summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-04-09 23:43:00 +0100
committerCarl Hetherington <cth@carlh.net>2013-04-09 23:43:00 +0100
commitb66010a281acd3e3e58ef7202bce55023fc29d7f (patch)
treee23ee83991adef3577caf8dd605f5ce06d00704c /src
parente94cd129dcd66a76210880bfdf19d27f7992651b (diff)
Merge ImageMagick and FFmpeg content into VideoContent list; remove seek_to_last hacks.
Diffstat (limited to 'src')
-rw-r--r--src/lib/decoder.cc11
-rw-r--r--src/lib/decoder.h1
-rw-r--r--src/lib/ffmpeg_decoder.cc16
-rw-r--r--src/lib/ffmpeg_decoder.h2
-rw-r--r--src/lib/film.cc3
-rw-r--r--src/lib/imagemagick_content.cc2
-rw-r--r--src/lib/imagemagick_decoder.cc10
-rw-r--r--src/lib/imagemagick_decoder.h1
-rw-r--r--src/lib/player.cc205
-rw-r--r--src/lib/player.h10
-rw-r--r--src/lib/playlist.cc178
-rw-r--r--src/lib/playlist.h24
-rw-r--r--src/lib/video_decoder.cc4
-rw-r--r--src/lib/video_decoder.h6
-rw-r--r--src/tools/dvdomatic.cc21
-rw-r--r--src/wx/film_viewer.cc2
16 files changed, 194 insertions, 302 deletions
diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc
index c40446919..082ad5076 100644
--- a/src/lib/decoder.cc
+++ b/src/lib/decoder.cc
@@ -41,7 +41,7 @@ Decoder::Decoder (shared_ptr<const Film> f)
_film_connection = f->Changed.connect (bind (&Decoder::film_changed, this, _1));
}
-/** Seek to a position as a source timestamp in seconds.
+/** Seek to a position as a content timestamp in seconds.
* @return true on error.
*/
bool
@@ -49,12 +49,3 @@ Decoder::seek (double)
{
throw DecodeError (N_("decoder does not support seek"));
}
-
-/** Seek so that the next frame we will produce is the same as the last one.
- * @return true on error.
- */
-bool
-Decoder::seek_to_last ()
-{
- throw DecodeError (N_("decoder does not support seek"));
-}
diff --git a/src/lib/decoder.h b/src/lib/decoder.h
index 34accf6c7..0fffef257 100644
--- a/src/lib/decoder.h
+++ b/src/lib/decoder.h
@@ -56,7 +56,6 @@ public:
virtual bool pass () = 0;
virtual bool seek (double);
- virtual bool seek_to_last ();
protected:
boost::shared_ptr<const Film> _film;
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index a0949f635..d0b1de748 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -518,22 +518,12 @@ FFmpegDecoder::filter_and_emit_video (AVFrame* frame)
bool
FFmpegDecoder::seek (double p)
{
- return do_seek (p, false);
-}
-
-bool
-FFmpegDecoder::seek_to_last ()
-{
- /* This AVSEEK_FLAG_BACKWARD in do_seek is a bit of a hack; without it, if we ask for a seek to the same place as last time
+ /* This use of AVSEEK_FLAG_BACKWARD is a bit of a hack; without it, if we ask for a seek to the same place as last time
(used when we change decoder parameters and want to re-fetch the frame) we end up going forwards rather than
staying in the same place.
*/
- return do_seek (last_source_time(), true);
-}
-
-bool
-FFmpegDecoder::do_seek (double p, bool backwards)
-{
+ bool const backwards = (p == last_content_time());
+
int64_t const vt = p / av_q2d (_format_context->streams[_video_stream]->time_base);
int const r = av_seek_frame (_format_context, _video_stream, vt, backwards ? AVSEEK_FLAG_BACKWARD : 0);
diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h
index cd37d20c6..f6a53874a 100644
--- a/src/lib/ffmpeg_decoder.h
+++ b/src/lib/ffmpeg_decoder.h
@@ -77,7 +77,6 @@ public:
}
bool seek (double);
- bool seek_to_last ();
bool pass ();
private:
@@ -86,7 +85,6 @@ private:
FFmpegDecoder (FFmpegDecoder const &);
FFmpegDecoder& operator= (FFmpegDecoder const &);
- bool do_seek (double p, bool);
PixelFormat pixel_format () const;
AVSampleFormat audio_sample_format () const;
int bytes_per_audio_sample () const;
diff --git a/src/lib/film.cc b/src/lib/film.cc
index b36dc8f9c..35a07b399 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -69,6 +69,7 @@ using std::setfill;
using std::min;
using std::make_pair;
using std::endl;
+using std::cout;
using std::list;
using boost::shared_ptr;
using boost::lexical_cast;
@@ -1084,7 +1085,6 @@ Film::move_content_earlier (shared_ptr<Content> c)
--j;
swap (*i, *j);
- _playlist->setup (_content);
}
signal_changed (CONTENT);
@@ -1107,7 +1107,6 @@ Film::move_content_later (shared_ptr<Content> c)
}
swap (*i, *j);
- _playlist->setup (_content);
}
signal_changed (CONTENT);
diff --git a/src/lib/imagemagick_content.cc b/src/lib/imagemagick_content.cc
index 59fde40bb..24f6d338d 100644
--- a/src/lib/imagemagick_content.cc
+++ b/src/lib/imagemagick_content.cc
@@ -32,7 +32,7 @@ ImageMagickContent::ImageMagickContent (boost::filesystem::path f)
: Content (f)
, VideoContent (f)
{
-
+
}
ImageMagickContent::ImageMagickContent (shared_ptr<const cxml::Node> node)
diff --git a/src/lib/imagemagick_decoder.cc b/src/lib/imagemagick_decoder.cc
index 6a2be1a7c..7049b7d6e 100644
--- a/src/lib/imagemagick_decoder.cc
+++ b/src/lib/imagemagick_decoder.cc
@@ -106,16 +106,6 @@ ImageMagickDecoder::pixel_format () const
}
bool
-ImageMagickDecoder::seek_to_last ()
-{
- if (_position > 0) {
- --_position;
- }
-
- return false;
-}
-
-bool
ImageMagickDecoder::seek (double t)
{
int const f = t * _imagemagick_content->video_frame_rate ();
diff --git a/src/lib/imagemagick_decoder.h b/src/lib/imagemagick_decoder.h
index cb524b44b..52c7bec18 100644
--- a/src/lib/imagemagick_decoder.h
+++ b/src/lib/imagemagick_decoder.h
@@ -50,7 +50,6 @@ public:
}
bool seek (double);
- bool seek_to_last ();
bool pass ();
protected:
diff --git a/src/lib/player.cc b/src/lib/player.cc
index 756c3b854..19899f6da 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -20,7 +20,9 @@
#include "player.h"
#include "film.h"
#include "ffmpeg_decoder.h"
+#include "ffmpeg_content.h"
#include "imagemagick_decoder.h"
+#include "imagemagick_content.h"
#include "sndfile_decoder.h"
#include "sndfile_content.h"
#include "playlist.h"
@@ -39,7 +41,6 @@ Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
, _audio (true)
, _subtitles (true)
, _have_valid_decoders (false)
- , _ffmpeg_decoder_done (false)
, _video_sync (true)
{
_playlist->Changed.connect (bind (&Player::playlist_changed, this));
@@ -74,25 +75,13 @@ Player::pass ()
bool done = true;
- if (_playlist->video_from() == Playlist::VIDEO_FFMPEG || _playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
- if (!_ffmpeg_decoder_done) {
- if (_ffmpeg_decoder->pass ()) {
- _ffmpeg_decoder_done = true;
- } else {
- done = false;
- }
+ if (_video_decoder != _video_decoders.end ()) {
+ if ((*_video_decoder)->pass ()) {
+ _video_decoder++;
}
- }
-
- if (_playlist->video_from() == Playlist::VIDEO_IMAGEMAGICK) {
- if (_imagemagick_decoder != _imagemagick_decoders.end ()) {
- if ((*_imagemagick_decoder)->pass ()) {
- _imagemagick_decoder++;
- }
-
- if (_imagemagick_decoder != _imagemagick_decoders.end ()) {
- done = false;
- }
+
+ if (_video_decoder != _video_decoders.end ()) {
+ done = false;
}
}
@@ -114,26 +103,18 @@ void
Player::set_progress (shared_ptr<Job> job)
{
/* Assume progress can be divined from how far through the video we are */
- switch (_playlist->video_from ()) {
- case Playlist::VIDEO_NONE:
- break;
- case Playlist::VIDEO_FFMPEG:
- if (_playlist->video_length ()) {
- job->set_progress (float(_ffmpeg_decoder->video_frame()) / _playlist->video_length ());
- }
- break;
- case Playlist::VIDEO_IMAGEMAGICK:
- {
- int n = 0;
- for (list<shared_ptr<ImageMagickDecoder> >::iterator i = _imagemagick_decoders.begin(); i != _imagemagick_decoders.end(); ++i) {
- if (_imagemagick_decoder == i) {
- job->set_progress (float (n) / _imagemagick_decoders.size ());
- }
- ++n;
- }
- break;
+
+ if (_video_decoder == _video_decoders.end() || !_playlist->video_length()) {
+ return;
}
+
+ ContentVideoFrame p = 0;
+ list<shared_ptr<VideoDecoder> >::iterator i = _video_decoders.begin ();
+ while (i != _video_decoders.end() && i != _video_decoder) {
+ p += (*i)->video_length ();
}
+
+ job->set_progress (float ((*_video_decoder)->video_frame ()) / _playlist->video_length ());
}
void
@@ -173,109 +154,67 @@ Player::seek (double t)
_have_valid_decoders = true;
}
- bool r = false;
-
- switch (_playlist->video_from()) {
- case Playlist::VIDEO_NONE:
- break;
- case Playlist::VIDEO_FFMPEG:
- if (!_ffmpeg_decoder || _ffmpeg_decoder->seek (t)) {
- r = true;
- }
- /* We're seeking, so all `all done' bets are off */
- _ffmpeg_decoder_done = false;
- break;
- case Playlist::VIDEO_IMAGEMAGICK:
- /* Find the decoder that contains this position */
- _imagemagick_decoder = _imagemagick_decoders.begin ();
- while (_imagemagick_decoder != _imagemagick_decoders.end ()) {
- double const this_length = (*_imagemagick_decoder)->video_length() / _film->video_frame_rate ();
- if (t < this_length) {
- break;
- }
- t -= this_length;
- ++_imagemagick_decoder;
+ /* Find the decoder that contains this position */
+ _video_decoder = _video_decoders.begin ();
+ while (_video_decoder != _video_decoders.end ()) {
+ double const this_length = (*_video_decoder)->video_length() / _film->video_frame_rate ();
+ if (t < this_length) {
+ break;
}
-
- if (_imagemagick_decoder != _imagemagick_decoders.end()) {
- (*_imagemagick_decoder)->seek (t);
- } else {
- r = true;
- }
- break;
- }
-
- /* XXX: don't seek audio because we don't need to... */
-
- return r;
-}
-
-bool
-Player::seek_to_last ()
-{
- if (!_have_valid_decoders) {
- setup_decoders ();
- _have_valid_decoders = true;
+ t -= this_length;
+ ++_video_decoder;
}
-
- bool r = false;
- switch (_playlist->video_from ()) {
- case Playlist::VIDEO_NONE:
- break;
- case Playlist::VIDEO_FFMPEG:
- if (!_ffmpeg_decoder || _ffmpeg_decoder->seek_to_last ()) {
- r = true;
- }
-
- /* We're seeking, so all `all done' bets are off */
- _ffmpeg_decoder_done = false;
- break;
- case Playlist::VIDEO_IMAGEMAGICK:
- if ((*_imagemagick_decoder)->seek_to_last ()) {
- r = true;
- }
- break;
+ if (_video_decoder != _video_decoders.end()) {
+ (*_video_decoder)->seek (t);
+ } else {
+ return true;
}
/* XXX: don't seek audio because we don't need to... */
- return r;
+ return false;
}
void
Player::setup_decoders ()
{
- if ((_video && _playlist->video_from() == Playlist::VIDEO_FFMPEG) || (_audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG)) {
- _ffmpeg_decoder.reset (
- new FFmpegDecoder (
- _film,
- _playlist->ffmpeg(),
- _video && _playlist->video_from() == Playlist::VIDEO_FFMPEG,
- _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG,
- _subtitles && _film->with_subtitles(),
- _video_sync
- )
- );
- }
-
- if (_video && _playlist->video_from() == Playlist::VIDEO_FFMPEG) {
- _ffmpeg_decoder->connect_video (shared_from_this ());
- }
+ if (_video) {
+ list<shared_ptr<const VideoContent> > vc = _playlist->video ();
+ for (list<shared_ptr<const VideoContent> >::iterator i = vc.begin(); i != vc.end(); ++i) {
+
+ shared_ptr<VideoDecoder> d;
+
+ /* XXX: into content? */
+
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
+ if (fc) {
+ shared_ptr<FFmpegDecoder> fd (
+ new FFmpegDecoder (
+ _film, fc, _video,
+ _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG,
+ _subtitles && _film->with_subtitles(),
+ _video_sync
+ )
+ );
+
+ if (_playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
+ fd->Audio.connect (bind (&Player::process_audio, this, fc, _1));
+ }
+
+ d = fd;
+ }
- if (_audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
- _ffmpeg_decoder->Audio.connect (bind (&Player::process_audio, this, _playlist->ffmpeg (), _1));
- }
+ shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> (*i);
+ if (ic) {
+ d.reset (new ImageMagickDecoder (_film, ic));
+ }
- if (_video && _playlist->video_from() == Playlist::VIDEO_IMAGEMAGICK) {
- list<shared_ptr<const ImageMagickContent> > ic = _playlist->imagemagick ();
- for (list<shared_ptr<const ImageMagickContent> >::iterator i = ic.begin(); i != ic.end(); ++i) {
- shared_ptr<ImageMagickDecoder> d (new ImageMagickDecoder (_film, *i));
- _imagemagick_decoders.push_back (d);
d->connect_video (shared_from_this ());
+ _video_decoders.push_back (d);
}
- _imagemagick_decoder = _imagemagick_decoders.begin ();
+ _video_decoder = _video_decoders.begin ();
}
if (_audio && _playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
@@ -297,23 +236,12 @@ Player::disable_video_sync ()
double
Player::last_video_time () const
{
- switch (_playlist->video_from ()) {
- case Playlist::VIDEO_NONE:
- return 0;
- case Playlist::VIDEO_FFMPEG:
- return _ffmpeg_decoder->last_source_time ();
- case Playlist::VIDEO_IMAGEMAGICK:
- {
- double t = 0;
- for (list<shared_ptr<ImageMagickDecoder> >::const_iterator i = _imagemagick_decoders.begin(); i != _imagemagick_decoder; ++i) {
- t += (*i)->video_length() / (*i)->video_frame_rate ();
- }
-
- return t + (*_imagemagick_decoder)->last_source_time ();
- }
+ double t = 0;
+ for (list<shared_ptr<VideoDecoder> >::const_iterator i = _video_decoders.begin(); i != _video_decoder; ++i) {
+ t += (*i)->video_length() / (*i)->video_frame_rate ();
}
- return 0;
+ return t + (*_video_decoder)->last_content_time ();
}
void
@@ -326,6 +254,7 @@ Player::content_changed (weak_ptr<Content> w, int p)
if (p == VideoContentProperty::VIDEO_LENGTH) {
if (dynamic_pointer_cast<FFmpegContent> (c)) {
+ /* FFmpeg content length changes are serious; we need new decoders */
_have_valid_decoders = false;
}
}
diff --git a/src/lib/player.h b/src/lib/player.h
index afc856316..8a82ab298 100644
--- a/src/lib/player.h
+++ b/src/lib/player.h
@@ -28,8 +28,7 @@
#include "video_sink.h"
#include "audio_sink.h"
-class FFmpegDecoder;
-class ImageMagickDecoder;
+class VideoDecoder;
class SndfileDecoder;
class Job;
class Film;
@@ -49,7 +48,6 @@ public:
bool pass ();
void set_progress (boost::shared_ptr<Job>);
bool seek (double);
- bool seek_to_last ();
double last_video_time () const;
@@ -68,10 +66,8 @@ private:
bool _subtitles;
bool _have_valid_decoders;
- boost::shared_ptr<FFmpegDecoder> _ffmpeg_decoder;
- bool _ffmpeg_decoder_done;
- std::list<boost::shared_ptr<ImageMagickDecoder> > _imagemagick_decoders;
- std::list<boost::shared_ptr<ImageMagickDecoder> >::iterator _imagemagick_decoder;
+ std::list<boost::shared_ptr<VideoDecoder> > _video_decoders;
+ std::list<boost::shared_ptr<VideoDecoder> >::iterator _video_decoder;
std::list<boost::shared_ptr<SndfileDecoder> > _sndfile_decoders;
boost::shared_ptr<AudioBuffers> _sndfile_buffers;
diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc
index 3f7905fa9..d26dae730 100644
--- a/src/lib/playlist.cc
+++ b/src/lib/playlist.cc
@@ -21,9 +21,9 @@
#include "playlist.h"
#include "sndfile_content.h"
#include "sndfile_decoder.h"
-#include "ffmpeg_content.h"
+#include "video_content.h"
#include "ffmpeg_decoder.h"
-#include "imagemagick_content.h"
+#include "ffmpeg_content.h"
#include "imagemagick_decoder.h"
#include "job.h"
@@ -31,13 +31,13 @@ using std::list;
using std::cout;
using std::vector;
using std::min;
+using std::max;
using boost::shared_ptr;
using boost::weak_ptr;
using boost::dynamic_pointer_cast;
Playlist::Playlist ()
- : _video_from (VIDEO_NONE)
- , _audio_from (AUDIO_NONE)
+ : _audio_from (AUDIO_FFMPEG)
{
}
@@ -45,11 +45,9 @@ Playlist::Playlist ()
void
Playlist::setup (ContentList content)
{
- _video_from = VIDEO_NONE;
- _audio_from = AUDIO_NONE;
+ _audio_from = AUDIO_FFMPEG;
- _ffmpeg.reset ();
- _imagemagick.clear ();
+ _video.clear ();
_sndfile.clear ();
for (list<boost::signals2::connection>::iterator i = _content_connections.begin(); i != _content_connections.end(); ++i) {
@@ -59,24 +57,11 @@ Playlist::setup (ContentList content)
_content_connections.clear ();
for (ContentList::const_iterator i = content.begin(); i != content.end(); ++i) {
- shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (*i);
- if (fc) {
- assert (!_ffmpeg);
- _ffmpeg = fc;
- _video_from = VIDEO_FFMPEG;
- if (_audio_from == AUDIO_NONE) {
- _audio_from = AUDIO_FFMPEG;
- }
+ shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (*i);
+ if (vc) {
+ _video.push_back (vc);
}
- shared_ptr<ImageMagickContent> ic = dynamic_pointer_cast<ImageMagickContent> (*i);
- if (ic) {
- _imagemagick.push_back (ic);
- if (_video_from == VIDEO_NONE) {
- _video_from = VIDEO_IMAGEMAGICK;
- }
- }
-
shared_ptr<SndfileContent> sc = dynamic_pointer_cast<SndfileContent> (*i);
if (sc) {
_sndfile.push_back (sc);
@@ -92,53 +77,65 @@ Playlist::setup (ContentList content)
ContentAudioFrame
Playlist::audio_length () const
{
+ ContentAudioFrame len = 0;
+
switch (_audio_from) {
- case AUDIO_NONE:
- return 0;
case AUDIO_FFMPEG:
- return _ffmpeg->audio_length ();
+ for (list<shared_ptr<const VideoContent> >::const_iterator i = _video.begin(); i != _video.end(); ++i) {
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
+ if (fc) {
+ len += fc->audio_length ();
+ }
+ }
+ break;
case AUDIO_SNDFILE:
- {
- ContentAudioFrame l = 0;
for (list<shared_ptr<const SndfileContent> >::const_iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) {
- l += (*i)->audio_length ();
+ len += (*i)->audio_length ();
}
- return l;
- }
+ break;
}
- return 0;
+ return len;
}
int
Playlist::audio_channels () const
{
+ int channels = 0;
+
switch (_audio_from) {
- case AUDIO_NONE:
- return 0;
case AUDIO_FFMPEG:
- return _ffmpeg->audio_channels ();
+ for (list<shared_ptr<const VideoContent> >::const_iterator i = _video.begin(); i != _video.end(); ++i) {
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
+ if (fc) {
+ channels = max (channels, fc->audio_channels ());
+ }
+ }
+ break;
case AUDIO_SNDFILE:
- {
- int c = 0;
for (list<shared_ptr<const SndfileContent> >::const_iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) {
- c += (*i)->audio_channels ();
+ channels += (*i)->audio_channels ();
}
- return c;
- }
+ break;
}
- return 0;
+ return channels;
}
int
Playlist::audio_frame_rate () const
{
+ /* XXX: assuming that all content has the same rate */
+
switch (_audio_from) {
- case AUDIO_NONE:
- return 0;
case AUDIO_FFMPEG:
- return _ffmpeg->audio_frame_rate ();
+ {
+ shared_ptr<const FFmpegContent> fc = first_ffmpeg ();
+ if (fc) {
+ return fc->audio_channels ();
+ }
+ break;
+ }
case AUDIO_SNDFILE:
return _sndfile.front()->audio_frame_rate ();
}
@@ -149,11 +146,17 @@ Playlist::audio_frame_rate () const
int64_t
Playlist::audio_channel_layout () const
{
+ /* XXX: assuming that all content has the same layout */
+
switch (_audio_from) {
- case AUDIO_NONE:
- return 0;
case AUDIO_FFMPEG:
- return _ffmpeg->audio_channel_layout ();
+ {
+ shared_ptr<const FFmpegContent> fc = first_ffmpeg ();
+ if (fc) {
+ return fc->audio_channel_layout ();
+ }
+ break;
+ }
case AUDIO_SNDFILE:
/* XXX */
return 0;
@@ -165,59 +168,41 @@ Playlist::audio_channel_layout () const
float
Playlist::video_frame_rate () const
{
- switch (_video_from) {
- case VIDEO_NONE:
+ if (_video.empty ()) {
return 0;
- case VIDEO_FFMPEG:
- return _ffmpeg->video_frame_rate ();
- case VIDEO_IMAGEMAGICK:
- return 24;
}
-
- return 0;
+
+ /* XXX: assuming all the same */
+ return _video.front()->video_frame_rate ();
}
libdcp::Size
Playlist::video_size () const
{
- switch (_video_from) {
- case VIDEO_NONE:
+ if (_video.empty ()) {
return libdcp::Size ();
- case VIDEO_FFMPEG:
- return _ffmpeg->video_size ();
- case VIDEO_IMAGEMAGICK:
- /* XXX */
- return _imagemagick.front()->video_size ();
}
- return libdcp::Size ();
+ /* XXX: assuming all the same */
+ return _video.front()->video_size ();
}
ContentVideoFrame
Playlist::video_length () const
{
- switch (_video_from) {
- case VIDEO_NONE:
- return 0;
- case VIDEO_FFMPEG:
- return _ffmpeg->video_length ();
- case VIDEO_IMAGEMAGICK:
- {
- ContentVideoFrame l = 0;
- for (list<shared_ptr<const ImageMagickContent> >::const_iterator i = _imagemagick.begin(); i != _imagemagick.end(); ++i) {
- l += (*i)->video_length ();
- }
- return l;
+ ContentVideoFrame len = 0;
+ for (list<shared_ptr<const VideoContent> >::const_iterator i = _video.begin(); i != _video.end(); ++i) {
+ len += (*i)->video_length ();
}
- }
-
- return 0;
+
+ return len;
}
bool
Playlist::has_audio () const
{
- return _audio_from != AUDIO_NONE;
+ /* XXX */
+ return true;
}
void
@@ -226,32 +211,51 @@ Playlist::content_changed (weak_ptr<Content> c, int p)
ContentChanged (c, p);
}
+shared_ptr<const FFmpegContent>
+Playlist::first_ffmpeg () const
+{
+ for (list<shared_ptr<const VideoContent> >::const_iterator i = _video.begin(); i != _video.end(); ++i) {
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
+ if (fc) {
+ return fc;
+ }
+ }
+
+ return shared_ptr<const FFmpegContent> ();
+}
+
+
AudioMapping
Playlist::default_audio_mapping () const
{
AudioMapping m;
switch (_audio_from) {
- case AUDIO_NONE:
- break;
case AUDIO_FFMPEG:
- if (_ffmpeg->audio_channels() == 1) {
+ {
+ shared_ptr<const FFmpegContent> fc = first_ffmpeg ();
+ if (!fc) {
+ break;
+ }
+
+ /* XXX: assumes all the same */
+ if (fc->audio_channels() == 1) {
/* Map mono sources to centre */
- m.add (AudioMapping::Channel (_ffmpeg, 0), libdcp::CENTRE);
+ m.add (AudioMapping::Channel (fc, 0), libdcp::CENTRE);
} else {
- int const N = min (_ffmpeg->audio_channels (), MAX_AUDIO_CHANNELS);
+ int const N = min (fc->audio_channels (), MAX_AUDIO_CHANNELS);
/* Otherwise just start with a 1:1 mapping */
for (int i = 0; i < N; ++i) {
- m.add (AudioMapping::Channel (_ffmpeg, i), (libdcp::Channel) i);
+ m.add (AudioMapping::Channel (fc, i), (libdcp::Channel) i);
}
}
break;
+ }
case AUDIO_SNDFILE:
{
int n = 0;
for (list<shared_ptr<const SndfileContent> >::const_iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) {
- cout << "sndfile " << (*i)->audio_channels() << "\n";
for (int j = 0; j < (*i)->audio_channels(); ++j) {
m.add (AudioMapping::Channel (*i, j), (libdcp::Channel) n);
++n;
diff --git a/src/lib/playlist.h b/src/lib/playlist.h
index 1d189cb07..4dd27f675 100644
--- a/src/lib/playlist.h
+++ b/src/lib/playlist.h
@@ -56,32 +56,17 @@ public:
AudioMapping default_audio_mapping () const;
- enum VideoFrom {
- VIDEO_NONE,
- VIDEO_FFMPEG,
- VIDEO_IMAGEMAGICK
- };
-
enum AudioFrom {
- AUDIO_NONE,
AUDIO_FFMPEG,
AUDIO_SNDFILE
};
- VideoFrom video_from () const {
- return _video_from;
- }
-
AudioFrom audio_from () const {
return _audio_from;
}
- boost::shared_ptr<const FFmpegContent> ffmpeg () const {
- return _ffmpeg;
- }
-
- std::list<boost::shared_ptr<const ImageMagickContent> > imagemagick () const {
- return _imagemagick;
+ std::list<boost::shared_ptr<const VideoContent> > video () const {
+ return _video;
}
std::list<boost::shared_ptr<const SndfileContent> > sndfile () const {
@@ -93,12 +78,11 @@ public:
private:
void content_changed (boost::weak_ptr<Content>, int);
+ boost::shared_ptr<const FFmpegContent> first_ffmpeg () const;
- VideoFrom _video_from;
AudioFrom _audio_from;
- boost::shared_ptr<const FFmpegContent> _ffmpeg;
- std::list<boost::shared_ptr<const ImageMagickContent> > _imagemagick;
+ std::list<boost::shared_ptr<const VideoContent> > _video;
std::list<boost::shared_ptr<const SndfileContent> > _sndfile;
std::list<boost::signals2::connection> _content_connections;
diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc
index fd2b28d7f..99d711693 100644
--- a/src/lib/video_decoder.cc
+++ b/src/lib/video_decoder.cc
@@ -32,7 +32,7 @@ using boost::optional;
VideoDecoder::VideoDecoder (shared_ptr<const Film> f)
: Decoder (f)
, _video_frame (0)
- , _last_source_time (0)
+ , _last_content_time (0)
{
}
@@ -88,7 +88,7 @@ VideoDecoder::signal_video (shared_ptr<Image> image, bool same, shared_ptr<Subti
_last_image = image;
_last_subtitle = sub;
- _last_source_time = t;
+ _last_content_time = t;
}
/** Set up the current subtitle. This will be put onto frames that
diff --git a/src/lib/video_decoder.h b/src/lib/video_decoder.h
index c04874342..05cf99a96 100644
--- a/src/lib/video_decoder.h
+++ b/src/lib/video_decoder.h
@@ -48,8 +48,8 @@ public:
return _video_frame;
}
- double last_source_time () const {
- return _last_source_time;
+ double last_content_time () const {
+ return _last_content_time;
}
protected:
@@ -65,7 +65,7 @@ private:
void signal_video (boost::shared_ptr<Image>, bool, boost::shared_ptr<Subtitle>, double);
int _video_frame;
- double _last_source_time;
+ double _last_content_time;
boost::shared_ptr<TimedSubtitle> _timed_subtitle;
diff --git a/src/tools/dvdomatic.cc b/src/tools/dvdomatic.cc
index 6c27892b0..239b4a517 100644
--- a/src/tools/dvdomatic.cc
+++ b/src/tools/dvdomatic.cc
@@ -59,6 +59,7 @@ static FilmViewer* film_viewer = 0;
static shared_ptr<Film> film;
static std::string log_level;
static std::string film_to_load;
+static std::string film_to_create;
static wxMenu* jobs_menu = 0;
static wxLocale* locale = 0;
@@ -439,13 +440,15 @@ private:
#if wxMINOR_VERSION == 9
static const wxCmdLineEntryDesc command_line_description[] = {
{ wxCMD_LINE_OPTION, "l", "log", "set log level (silent, verbose or timing)", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
- { wxCMD_LINE_PARAM, 0, 0, "film to load", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL },
+ { wxCMD_LINE_SWITCH, "n", "new", "create new film", wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
+ { wxCMD_LINE_PARAM, 0, 0, "film to load or create", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL },
{ wxCMD_LINE_NONE, "", "", "", wxCmdLineParamType (0), 0 }
};
#else
static const wxCmdLineEntryDesc command_line_description[] = {
{ wxCMD_LINE_OPTION, wxT("l"), wxT("log"), wxT("set log level (silent, verbose or timing)"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
- { wxCMD_LINE_PARAM, 0, 0, wxT("film to load"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL },
+ { wxCMD_LINE_SWITCH, wxT("n"), wxT("new"), wxT("create new film"), wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
+ { wxCMD_LINE_PARAM, 0, 0, wxT("film to load or create"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_PARAM_OPTIONAL },
{ wxCMD_LINE_NONE, wxT(""), wxT(""), wxT(""), wxCmdLineParamType (0), 0 }
};
#endif
@@ -525,6 +528,12 @@ class App : public wxApp
}
}
+ if (!film_to_create.empty ()) {
+ film.reset (new Film (film_to_create, false));
+ film->log()->set_level (log_level);
+ film->set_name (boost::filesystem::path (film_to_create).filename().generic_string ());
+ }
+
Frame* f = new Frame (_("DVD-o-matic"));
SetTopWindow (f);
f->Maximize ();
@@ -545,11 +554,15 @@ class App : public wxApp
bool OnCmdLineParsed (wxCmdLineParser& parser)
{
if (parser.GetParamCount() > 0) {
- film_to_load = wx_to_std (parser.GetParam(0));
+ if (parser.FoundSwitch (wxT ("new"))) {
+ film_to_create = wx_to_std (parser.GetParam (0));
+ } else {
+ film_to_load = wx_to_std (parser.GetParam(0));
+ }
}
wxString log;
- if (parser.Found(wxT("log"), &log)) {
+ if (parser.Found (wxT ("log"), &log)) {
log_level = wx_to_std (log);
}
diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc
index f8373d3fd..8fca8f370 100644
--- a/src/wx/film_viewer.cc
+++ b/src/wx/film_viewer.cc
@@ -157,7 +157,7 @@ FilmViewer::set_film (shared_ptr<Film> f)
void
FilmViewer::update_from_decoder ()
{
- if (!_player || _player->seek_to_last ()) {
+ if (!_player || _player->seek (_player->last_video_time ())) {
return;
}