From 9db7ed5f6499de903313a85d59bb70302e97e7ff Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 17 Jan 2013 00:24:13 +0000 Subject: shared_ptr is a bit excessive for DecodeOptions. --- src/lib/decoder.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/lib/decoder.h') diff --git a/src/lib/decoder.h b/src/lib/decoder.h index 3908afa2f..cc4c87373 100644 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@ -34,9 +34,9 @@ #include "video_source.h" #include "audio_source.h" #include "film.h" +#include "options.h" class Job; -class DecodeOptions; class Image; class Log; class DelayLine; @@ -54,7 +54,7 @@ class FilterGraph; class Decoder { public: - Decoder (boost::shared_ptr, boost::shared_ptr, Job *); + Decoder (boost::shared_ptr, DecodeOptions, Job *); virtual ~Decoder () {} virtual bool pass () = 0; @@ -66,8 +66,8 @@ public: protected: /** our Film */ boost::shared_ptr _film; - /** our options */ - boost::shared_ptr _opt; + /** our decode options */ + DecodeOptions _opt; /** associated Job, or 0 */ Job* _job; -- cgit v1.2.3 From 2e536ef0971edefea23810b99f7706881072783b Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Fri, 8 Feb 2013 13:07:16 +0000 Subject: Shuffle Job pointers around slightly. --- src/lib/ab_transcoder.cc | 8 +++++--- src/lib/audio_decoder.cc | 4 ++-- src/lib/audio_decoder.h | 2 +- src/lib/decoder.cc | 5 +---- src/lib/decoder.h | 5 +---- src/lib/decoder_factory.cc | 10 +++++----- src/lib/decoder_factory.h | 3 +-- src/lib/examine_content_job.cc | 4 ++-- src/lib/external_audio_decoder.cc | 6 +++--- src/lib/external_audio_decoder.h | 2 +- src/lib/ffmpeg_decoder.cc | 8 ++++---- src/lib/ffmpeg_decoder.h | 2 +- src/lib/film.cc | 4 ++-- src/lib/imagemagick_decoder.cc | 6 +++--- src/lib/imagemagick_decoder.h | 2 +- src/lib/transcoder.cc | 6 ++++-- src/lib/video_decoder.cc | 12 +++++++----- src/lib/video_decoder.h | 4 ++-- src/wx/film_viewer.cc | 2 +- 19 files changed, 47 insertions(+), 48 deletions(-) (limited to 'src/lib/decoder.h') diff --git a/src/lib/ab_transcoder.cc b/src/lib/ab_transcoder.cc index fc4fb8daa..f47a99fda 100644 --- a/src/lib/ab_transcoder.cc +++ b/src/lib/ab_transcoder.cc @@ -55,8 +55,8 @@ ABTranscoder::ABTranscoder ( , _job (j) , _encoder (e) { - _da = decoder_factory (_film_a, o, j); - _db = decoder_factory (_film_b, o, j); + _da = decoder_factory (_film_a, o); + _db = decoder_factory (_film_b, o); if (_film_a->audio_stream()) { shared_ptr st = _film_a->audio_stream(); @@ -98,7 +98,9 @@ ABTranscoder::go () bool const vb = _db.video->pass (); bool const a = _da.audio->pass (); - _da.video->set_progress (); + if (_job) { + _da.video->set_progress (_job); + } if (va && vb && a) { break; diff --git a/src/lib/audio_decoder.cc b/src/lib/audio_decoder.cc index a038dd2bb..a54c14843 100644 --- a/src/lib/audio_decoder.cc +++ b/src/lib/audio_decoder.cc @@ -23,8 +23,8 @@ using boost::optional; using boost::shared_ptr; -AudioDecoder::AudioDecoder (shared_ptr f, DecodeOptions o, Job* j) - : Decoder (f, o, j) +AudioDecoder::AudioDecoder (shared_ptr f, DecodeOptions o) + : Decoder (f, o) { } diff --git a/src/lib/audio_decoder.h b/src/lib/audio_decoder.h index 3bf585f4d..9bef8e0e7 100644 --- a/src/lib/audio_decoder.h +++ b/src/lib/audio_decoder.h @@ -34,7 +34,7 @@ class AudioDecoder : public AudioSource, public virtual Decoder { public: - AudioDecoder (boost::shared_ptr, DecodeOptions, Job *); + AudioDecoder (boost::shared_ptr, DecodeOptions); virtual void set_audio_stream (boost::shared_ptr); diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc index fd0abee41..30009460f 100644 --- a/src/lib/decoder.cc +++ b/src/lib/decoder.cc @@ -26,7 +26,6 @@ #include #include "film.h" #include "format.h" -#include "job.h" #include "options.h" #include "exceptions.h" #include "image.h" @@ -47,12 +46,10 @@ using boost::optional; /** @param f Film. * @param o Decode options. - * @param j Job that we are running within, or 0 */ -Decoder::Decoder (boost::shared_ptr f, DecodeOptions o, Job* j) +Decoder::Decoder (boost::shared_ptr f, DecodeOptions o) : _film (f) , _opt (o) - , _job (j) { _film_connection = f->Changed.connect (bind (&Decoder::film_changed, this, _1)); } diff --git a/src/lib/decoder.h b/src/lib/decoder.h index cc4c87373..f2f523516 100644 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@ -36,7 +36,6 @@ #include "film.h" #include "options.h" -class Job; class Image; class Log; class DelayLine; @@ -54,7 +53,7 @@ class FilterGraph; class Decoder { public: - Decoder (boost::shared_ptr, DecodeOptions, Job *); + Decoder (boost::shared_ptr, DecodeOptions); virtual ~Decoder () {} virtual bool pass () = 0; @@ -68,8 +67,6 @@ protected: boost::shared_ptr _film; /** our decode options */ DecodeOptions _opt; - /** associated Job, or 0 */ - Job* _job; private: virtual void film_changed (Film::Property) {} diff --git a/src/lib/decoder_factory.cc b/src/lib/decoder_factory.cc index c4d818f49..59e15722d 100644 --- a/src/lib/decoder_factory.cc +++ b/src/lib/decoder_factory.cc @@ -36,21 +36,21 @@ using boost::dynamic_pointer_cast; Decoders decoder_factory ( - shared_ptr f, DecodeOptions o, Job* j + shared_ptr f, DecodeOptions o ) { if (boost::filesystem::is_directory (f->content_path()) || f->content_type() == STILL) { /* A single image file, or a directory of them */ return Decoders ( - shared_ptr (new ImageMagickDecoder (f, o, j)), - shared_ptr (new ExternalAudioDecoder (f, o, j)) + shared_ptr (new ImageMagickDecoder (f, o)), + shared_ptr (new ExternalAudioDecoder (f, o)) ); } - shared_ptr fd (new FFmpegDecoder (f, o, j)); + shared_ptr fd (new FFmpegDecoder (f, o)); if (f->use_content_audio()) { return Decoders (fd, fd); } - return Decoders (fd, shared_ptr (new ExternalAudioDecoder (f, o, j))); + return Decoders (fd, shared_ptr (new ExternalAudioDecoder (f, o))); } diff --git a/src/lib/decoder_factory.h b/src/lib/decoder_factory.h index 445a1c8a2..8076b01c7 100644 --- a/src/lib/decoder_factory.h +++ b/src/lib/decoder_factory.h @@ -27,7 +27,6 @@ #include "options.h" class Film; -class Job; class VideoDecoder; class AudioDecoder; @@ -44,7 +43,7 @@ struct Decoders { }; extern Decoders decoder_factory ( - boost::shared_ptr, DecodeOptions, Job * + boost::shared_ptr, DecodeOptions ); #endif diff --git a/src/lib/examine_content_job.cc b/src/lib/examine_content_job.cc index 69a757e2b..94e5320fe 100644 --- a/src/lib/examine_content_job.cc +++ b/src/lib/examine_content_job.cc @@ -81,7 +81,7 @@ ExamineContentJob::run () DecodeOptions o; o.decode_audio = false; - Decoders decoders = decoder_factory (_film, o, this); + Decoders decoders = decoder_factory (_film, o); set_progress_unknown (); while (!decoders.video->pass()) { @@ -96,7 +96,7 @@ ExamineContentJob::run () /* Get a quick decoder to get the content's length from its header */ - Decoders d = decoder_factory (_film, DecodeOptions(), 0); + Decoders d = decoder_factory (_film, DecodeOptions()); _film->set_length (d.video->length()); _film->log()->log (String::compose ("Video length obtained from header as %1 frames", _film->length().get())); diff --git a/src/lib/external_audio_decoder.cc b/src/lib/external_audio_decoder.cc index 366051418..9c01bfb34 100644 --- a/src/lib/external_audio_decoder.cc +++ b/src/lib/external_audio_decoder.cc @@ -31,9 +31,9 @@ using std::cout; using boost::shared_ptr; using boost::optional; -ExternalAudioDecoder::ExternalAudioDecoder (shared_ptr f, DecodeOptions o, Job* j) - : Decoder (f, o, j) - , AudioDecoder (f, o, j) +ExternalAudioDecoder::ExternalAudioDecoder (shared_ptr f, DecodeOptions o) + : Decoder (f, o) + , AudioDecoder (f, o) { sf_count_t frames; vector sf = open_files (frames); diff --git a/src/lib/external_audio_decoder.h b/src/lib/external_audio_decoder.h index 37e53bca7..6f010abb1 100644 --- a/src/lib/external_audio_decoder.h +++ b/src/lib/external_audio_decoder.h @@ -44,7 +44,7 @@ private: class ExternalAudioDecoder : public AudioDecoder { public: - ExternalAudioDecoder (boost::shared_ptr, DecodeOptions, Job *); + ExternalAudioDecoder (boost::shared_ptr, DecodeOptions); bool pass (); diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 81f405644..1f11f70a0 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -60,10 +60,10 @@ using boost::optional; using boost::dynamic_pointer_cast; using libdcp::Size; -FFmpegDecoder::FFmpegDecoder (shared_ptr f, DecodeOptions o, Job* j) - : Decoder (f, o, j) - , VideoDecoder (f, o, j) - , AudioDecoder (f, o, j) +FFmpegDecoder::FFmpegDecoder (shared_ptr f, DecodeOptions o) + : Decoder (f, o) + , VideoDecoder (f, o) + , AudioDecoder (f, o) , _format_context (0) , _video_stream (-1) , _frame (0) diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index 9a4e65ebc..17308eb56 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -86,7 +86,7 @@ private: class FFmpegDecoder : public VideoDecoder, public AudioDecoder { public: - FFmpegDecoder (boost::shared_ptr, DecodeOptions, Job *); + FFmpegDecoder (boost::shared_ptr, DecodeOptions); ~FFmpegDecoder (); float frames_per_second () const; diff --git a/src/lib/film.cc b/src/lib/film.cc index 59f79e666..ff4d3b8f5 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -857,7 +857,7 @@ Film::set_content (string c) */ try { - Decoders d = decoder_factory (shared_from_this(), DecodeOptions(), 0); + Decoders d = decoder_factory (shared_from_this(), DecodeOptions()); set_size (d.video->native_size ()); set_frames_per_second (d.video->frames_per_second ()); @@ -1079,7 +1079,7 @@ Film::set_external_audio (vector a) _external_audio = a; } - shared_ptr decoder (new ExternalAudioDecoder (shared_from_this(), DecodeOptions(), 0)); + shared_ptr decoder (new ExternalAudioDecoder (shared_from_this(), DecodeOptions())); if (decoder->audio_stream()) { _external_audio_stream = decoder->audio_stream (); } diff --git a/src/lib/imagemagick_decoder.cc b/src/lib/imagemagick_decoder.cc index 99b9e1d34..42fe699d7 100644 --- a/src/lib/imagemagick_decoder.cc +++ b/src/lib/imagemagick_decoder.cc @@ -30,9 +30,9 @@ using boost::shared_ptr; using libdcp::Size; ImageMagickDecoder::ImageMagickDecoder ( - boost::shared_ptr f, DecodeOptions o, Job* j) - : Decoder (f, o, j) - , VideoDecoder (f, o, j) + boost::shared_ptr f, DecodeOptions o) + : Decoder (f, o) + , VideoDecoder (f, o) { if (boost::filesystem::is_directory (_film->content_path())) { for ( diff --git a/src/lib/imagemagick_decoder.h b/src/lib/imagemagick_decoder.h index 84a6f15f9..0e375f6e9 100644 --- a/src/lib/imagemagick_decoder.h +++ b/src/lib/imagemagick_decoder.h @@ -26,7 +26,7 @@ namespace Magick { class ImageMagickDecoder : public VideoDecoder { public: - ImageMagickDecoder (boost::shared_ptr, DecodeOptions, Job *); + ImageMagickDecoder (boost::shared_ptr, DecodeOptions); float frames_per_second () const { /* We don't know */ diff --git a/src/lib/transcoder.cc b/src/lib/transcoder.cc index 93963761e..959fac857 100644 --- a/src/lib/transcoder.cc +++ b/src/lib/transcoder.cc @@ -51,7 +51,7 @@ using boost::dynamic_pointer_cast; Transcoder::Transcoder (shared_ptr f, DecodeOptions o, Job* j, shared_ptr e) : _job (j) , _encoder (e) - , _decoders (decoder_factory (f, o, j)) + , _decoders (decoder_factory (f, o)) { assert (_encoder); @@ -96,7 +96,9 @@ Transcoder::go () while (1) { if (!done[0]) { done[0] = _decoders.video->pass (); - _decoders.video->set_progress (); + if (_job) { + _decoders.video->set_progress (_job); + } } if (!done[1] && _decoders.audio && dynamic_pointer_cast (_decoders.audio) != dynamic_pointer_cast (_decoders.video)) { diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc index c11b752ae..c1f48cb5e 100644 --- a/src/lib/video_decoder.cc +++ b/src/lib/video_decoder.cc @@ -28,8 +28,8 @@ using boost::shared_ptr; using boost::optional; -VideoDecoder::VideoDecoder (shared_ptr f, DecodeOptions o, Job* j) - : Decoder (f, o, j) +VideoDecoder::VideoDecoder (shared_ptr f, DecodeOptions o) + : Decoder (f, o) , _video_frame (0) , _last_source_time (0) { @@ -110,9 +110,11 @@ VideoDecoder::set_subtitle_stream (shared_ptr s) } void -VideoDecoder::set_progress () const +VideoDecoder::set_progress (Job* j) const { - if (_job && _film->length()) { - _job->set_progress (float (_video_frame) / _film->length().get()); + assert (j); + + if (_film->length()) { + j->set_progress (float (_video_frame) / _film->length().get()); } } diff --git a/src/lib/video_decoder.h b/src/lib/video_decoder.h index ef1ab041a..283ab5d88 100644 --- a/src/lib/video_decoder.h +++ b/src/lib/video_decoder.h @@ -27,7 +27,7 @@ class VideoDecoder : public VideoSource, public virtual Decoder { public: - VideoDecoder (boost::shared_ptr, DecodeOptions, Job *); + VideoDecoder (boost::shared_ptr, DecodeOptions); /** @return video frames per second, or 0 if unknown */ virtual float frames_per_second () const = 0; @@ -43,7 +43,7 @@ public: virtual void set_subtitle_stream (boost::shared_ptr); - void set_progress () const; + void set_progress (Job *) const; int video_frame () const { return _video_frame; diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 4e5f38300..4e779a693 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -101,7 +101,7 @@ FilmViewer::film_changed (Film::Property p) o.decode_audio = false; o.decode_subtitles = true; o.video_sync = false; - _decoders = decoder_factory (_film, o, 0); + _decoders = decoder_factory (_film, o); _decoders.video->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3)); _decoders.video->OutputChanged.connect (boost::bind (&FilmViewer::decoder_changed, this)); _decoders.video->set_subtitle_stream (_film->subtitle_stream()); -- cgit v1.2.3 From 127672223cca569986e35c91265e269ed5a6561c Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sun, 31 Mar 2013 15:09:49 +0100 Subject: Runs. --- doc/design/content.tex | 6 +- src/lib/ab_transcode_job.cc | 2 +- src/lib/ab_transcode_job.h | 3 +- src/lib/ab_transcoder.cc | 48 ++-- src/lib/ab_transcoder.h | 13 +- src/lib/analyse_audio_job.cc | 30 +-- src/lib/audio_content.cc | 7 + src/lib/audio_content.h | 13 +- src/lib/audio_decoder.cc | 9 +- src/lib/audio_decoder.h | 23 +- src/lib/content.cc | 20 ++ src/lib/content.h | 19 +- src/lib/decoder.cc | 15 +- src/lib/decoder.h | 8 +- src/lib/decoder_factory.cc | 19 +- src/lib/encoder.cc | 32 +-- src/lib/encoder.h | 4 +- src/lib/examine_content_job.cc | 67 +----- src/lib/examine_content_job.h | 17 +- src/lib/exceptions.h | 1 + src/lib/ffmpeg_content.cc | 156 +++++++++++++ src/lib/ffmpeg_content.h | 93 +++++++- src/lib/ffmpeg_decoder.cc | 143 +++--------- src/lib/ffmpeg_decoder.h | 51 ++-- src/lib/film.cc | 462 +++++++----------------------------- src/lib/film.h | 31 ++- src/lib/filter_graph.cc | 2 +- src/lib/filter_graph.h | 2 +- src/lib/format.cc | 19 +- src/lib/format.h | 16 +- src/lib/imagemagick_content.cc | 2 + src/lib/imagemagick_content.h | 3 +- src/lib/imagemagick_decoder.cc | 65 ++---- src/lib/imagemagick_decoder.h | 14 +- src/lib/job.cc | 2 - src/lib/job.h | 3 +- src/lib/playlist.cc | 266 +++++++++++++++++++++ src/lib/playlist.h | 56 ++++- src/lib/scp_dcp_job.h | 2 +- src/lib/sndfile_content.cc | 41 ++++ src/lib/sndfile_content.h | 6 + src/lib/sndfile_decoder.cc | 142 ++---------- src/lib/sndfile_decoder.h | 28 +-- src/lib/stream.cc | 92 -------- src/lib/stream.h | 121 ---------- src/lib/transcode_job.cc | 19 +- src/lib/transcode_job.h | 1 - src/lib/transcoder.cc | 51 ++-- src/lib/transcoder.h | 16 +- src/lib/util.cc | 6 +- src/lib/util.h | 4 +- src/lib/video_content.cc | 28 +++ src/lib/video_content.h | 39 ++++ src/lib/video_decoder.cc | 16 +- src/lib/video_decoder.h | 24 +- src/lib/writer.cc | 8 +- src/lib/writer.h | 4 +- src/lib/wscript | 8 +- src/tools/dvdomatic.cc | 3 - src/tools/makedcp.cc | 2 +- src/wx/audio_dialog.cc | 19 +- src/wx/audio_dialog.h | 2 + src/wx/film_editor.cc | 514 +++++++++++++++-------------------------- src/wx/film_editor.h | 51 ++-- src/wx/film_viewer.cc | 40 ++-- src/wx/properties_dialog.cc | 10 +- test/test.cc | 84 ++----- 67 files changed, 1361 insertions(+), 1762 deletions(-) create mode 100644 src/lib/audio_content.cc create mode 100644 src/lib/content.cc create mode 100644 src/lib/ffmpeg_content.cc create mode 100644 src/lib/imagemagick_content.cc create mode 100644 src/lib/playlist.cc create mode 100644 src/lib/sndfile_content.cc delete mode 100644 src/lib/stream.cc delete mode 100644 src/lib/stream.h create mode 100644 src/lib/video_content.cc (limited to 'src/lib/decoder.h') diff --git a/doc/design/content.tex b/doc/design/content.tex index a3c5c5835..0f5f17025 100644 --- a/doc/design/content.tex +++ b/doc/design/content.tex @@ -174,7 +174,7 @@ public: \end{verbatim} Then Film has a \texttt{Playlist} which has a -\texttt{vector}. And it can answer questions +\texttt{vector >}. It can answer questions about audio/video length, frame rate, audio channels and so on. \texttt{Playlist} can also be a source of video and audio, so clients can do: @@ -188,6 +188,8 @@ while (!p->pass ()) { } \end{verbatim} -Playlist could be created on-demand for all the difference it would make. +Playlist could be created on-demand for all the difference it would +make. And perhaps it should, since it will hold Decoders which are +probably run-once. \end{document} diff --git a/src/lib/ab_transcode_job.cc b/src/lib/ab_transcode_job.cc index 4ffdd9af6..f17d43916 100644 --- a/src/lib/ab_transcode_job.cc +++ b/src/lib/ab_transcode_job.cc @@ -54,7 +54,7 @@ ABTranscodeJob::run () { try { /* _film_b is the one with reference filters */ - ABTranscoder w (_film_b, _film, _decode_opt, this, shared_ptr (new Encoder (_film))); + ABTranscoder w (_film_b, _film, _decode_opt, shared_from_this ()); w.go (); set_progress (1); set_state (FINISHED_OK); diff --git a/src/lib/ab_transcode_job.h b/src/lib/ab_transcode_job.h index 8e3cbe2d8..5d029a18b 100644 --- a/src/lib/ab_transcode_job.h +++ b/src/lib/ab_transcode_job.h @@ -46,8 +46,7 @@ public: void run (); private: - DecodeOptions _decode_opt; - /** Copy of our Film using the reference filters and scaler */ boost::shared_ptr _film_b; + DecodeOptions _decode_opt; }; diff --git a/src/lib/ab_transcoder.cc b/src/lib/ab_transcoder.cc index 3a1cd83d7..0c687008d 100644 --- a/src/lib/ab_transcoder.cc +++ b/src/lib/ab_transcoder.cc @@ -21,13 +21,11 @@ #include #include "ab_transcoder.h" #include "film.h" -#include "video_decoder.h" -#include "audio_decoder.h" #include "encoder.h" #include "job.h" #include "options.h" #include "image.h" -#include "decoder_factory.h" +#include "playlist.h" #include "matcher.h" #include "delay_line.h" #include "gain.h" @@ -49,31 +47,23 @@ using boost::dynamic_pointer_cast; * @param e Encoder to use. */ -ABTranscoder::ABTranscoder ( - shared_ptr a, shared_ptr b, DecodeOptions o, Job* j, shared_ptr e) +ABTranscoder::ABTranscoder (shared_ptr a, shared_ptr b, DecodeOptions o, shared_ptr j) : _film_a (a) , _film_b (b) + , _playlist_a (_film_a->playlist ()) + , _playlist_b (_film_b->playlist ()) , _job (j) - , _encoder (e) + , _encoder (new Encoder (_film_a, _playlist_a)) , _combiner (new Combiner (a->log())) { - _da = decoder_factory (_film_a, o); - _db = decoder_factory (_film_b, o); - - if (_film_a->audio_stream()) { - shared_ptr st = _film_a->audio_stream(); - _matcher.reset (new Matcher (_film_a->log(), st->sample_rate(), _film_a->source_frame_rate())); - _delay_line.reset (new DelayLine (_film_a->log(), st->channels(), _film_a->audio_delay() * st->sample_rate() / 1000)); + if (_playlist_a->has_audio ()) { + _matcher.reset (new Matcher (_film_a->log(), _playlist_a->audio_frame_rate(), _playlist_a->video_frame_rate())); + _delay_line.reset (new DelayLine (_film_a->log(), _playlist_a->audio_channels(), _film_a->audio_delay() * _playlist_a->audio_frame_rate() / 1000)); _gain.reset (new Gain (_film_a->log(), _film_a->audio_gain())); } - /* Set up the decoder to use the film's set streams */ - _da.video->set_subtitle_stream (_film_a->subtitle_stream ()); - _db.video->set_subtitle_stream (_film_a->subtitle_stream ()); - _da.audio->set_audio_stream (_film_a->audio_stream ()); - - _da.video->Video.connect (bind (&Combiner::process_video, _combiner, _1, _2, _3)); - _db.video->Video.connect (bind (&Combiner::process_video_b, _combiner, _1, _2, _3)); + _playlist_a->Video.connect (bind (&Combiner::process_video, _combiner, _1, _2, _3)); + _playlist_b->Video.connect (bind (&Combiner::process_video_b, _combiner, _1, _2, _3)); if (_matcher) { _combiner->connect_video (_matcher); @@ -83,7 +73,7 @@ ABTranscoder::ABTranscoder ( } if (_matcher && _delay_line) { - _da.audio->connect_audio (_delay_line); + _playlist_a->connect_audio (_delay_line); _delay_line->connect_audio (_matcher); _matcher->connect_audio (_gain); _gain->connect_audio (_encoder); @@ -95,23 +85,17 @@ ABTranscoder::go () { _encoder->process_begin (); - bool done[3] = { false, false, false }; + bool done[2] = { false, false }; while (1) { - done[0] = _da.video->pass (); - done[1] = _db.video->pass (); - - if (!done[2] && _da.audio && dynamic_pointer_cast (_da.audio) != dynamic_pointer_cast (_da.video)) { - done[2] = _da.audio->pass (); - } else { - done[2] = true; - } + done[0] = _playlist_a->pass (); + done[1] = _playlist_b->pass (); if (_job) { - _da.video->set_progress (_job); + _playlist_a->set_progress (_job); } - if (done[0] && done[1] && done[2]) { + if (done[0] && done[1]) { break; } } diff --git a/src/lib/ab_transcoder.h b/src/lib/ab_transcoder.h index 58a08af04..14277c562 100644 --- a/src/lib/ab_transcoder.h +++ b/src/lib/ab_transcoder.h @@ -29,16 +29,14 @@ class Job; class Encoder; -class VideoDecoder; -class AudioDecoder; class Image; class Log; -class Subtitle; class Film; class Matcher; class DelayLine; class Gain; class Combiner; +class Playlist; /** @class ABTranscoder * @brief A transcoder which uses one Film for the left half of the screen, and a different one @@ -51,8 +49,7 @@ public: boost::shared_ptr a, boost::shared_ptr b, DecodeOptions o, - Job* j, - boost::shared_ptr e + boost::shared_ptr j ); void go (); @@ -60,10 +57,10 @@ public: private: boost::shared_ptr _film_a; boost::shared_ptr _film_b; - Job* _job; + boost::shared_ptr _playlist_a; + boost::shared_ptr _playlist_b; + boost::shared_ptr _job; boost::shared_ptr _encoder; - Decoders _da; - Decoders _db; boost::shared_ptr _combiner; boost::shared_ptr _matcher; boost::shared_ptr _delay_line; diff --git a/src/lib/analyse_audio_job.cc b/src/lib/analyse_audio_job.cc index 43eecbcbd..74491943b 100644 --- a/src/lib/analyse_audio_job.cc +++ b/src/lib/analyse_audio_job.cc @@ -22,8 +22,7 @@ #include "compose.hpp" #include "film.h" #include "options.h" -#include "decoder_factory.h" -#include "audio_decoder.h" +#include "playlist.h" #include "i18n.h" @@ -52,29 +51,18 @@ AnalyseAudioJob::name () const void AnalyseAudioJob::run () { - if (!_film->audio_stream () || !_film->length()) { - set_progress (1); - set_state (FINISHED_ERROR); - return; - } - - DecodeOptions options; - options.decode_video = false; - - Decoders decoders = decoder_factory (_film, options); - assert (decoders.audio); + shared_ptr playlist = _film->playlist (); + playlist->disable_video (); - decoders.audio->set_audio_stream (_film->audio_stream ()); - decoders.audio->Audio.connect (bind (&AnalyseAudioJob::audio, this, _1)); + playlist->Audio.connect (bind (&AnalyseAudioJob::audio, this, _1)); - int64_t total_audio_frames = video_frames_to_audio_frames (_film->length().get(), _film->audio_stream()->sample_rate(), _film->source_frame_rate()); - _samples_per_point = max (int64_t (1), total_audio_frames / _num_points); + _samples_per_point = max (int64_t (1), playlist->audio_length() / _num_points); - _current.resize (_film->audio_stream()->channels ()); - _analysis.reset (new AudioAnalysis (_film->audio_stream()->channels())); + _current.resize (playlist->audio_channels ()); + _analysis.reset (new AudioAnalysis (playlist->audio_channels())); - while (!decoders.audio->pass()) { - set_progress (float (_done) / total_audio_frames); + while (!playlist->pass()) { + set_progress (float (_done) / playlist->audio_length ()); } _analysis->write (_film->audio_analysis_path ()); diff --git a/src/lib/audio_content.cc b/src/lib/audio_content.cc new file mode 100644 index 000000000..e9eacfd79 --- /dev/null +++ b/src/lib/audio_content.cc @@ -0,0 +1,7 @@ +#include "audio_content.h" + +AudioContent::AudioContent (boost::filesystem::path f) + : Content (f) +{ + +} diff --git a/src/lib/audio_content.h b/src/lib/audio_content.h index 95fd681a7..e18d1082e 100644 --- a/src/lib/audio_content.h +++ b/src/lib/audio_content.h @@ -1,8 +1,19 @@ +#ifndef DVDOMATIC_AUDIO_CONTENT_H +#define DVDOMATIC_AUDIO_CONTENT_H + #include "content.h" +#include "util.h" class AudioContent : public virtual Content { public: - + AudioContent (boost::filesystem::path); + virtual int audio_channels () const = 0; + virtual ContentAudioFrame audio_length () const = 0; + virtual int audio_frame_rate () const = 0; + virtual int64_t audio_channel_layout () const = 0; + }; + +#endif diff --git a/src/lib/audio_decoder.cc b/src/lib/audio_decoder.cc index a54c14843..a72cf11bb 100644 --- a/src/lib/audio_decoder.cc +++ b/src/lib/audio_decoder.cc @@ -18,19 +18,12 @@ */ #include "audio_decoder.h" -#include "stream.h" using boost::optional; using boost::shared_ptr; -AudioDecoder::AudioDecoder (shared_ptr f, DecodeOptions o) +AudioDecoder::AudioDecoder (shared_ptr f, shared_ptr c, DecodeOptions o) : Decoder (f, o) { } - -void -AudioDecoder::set_audio_stream (shared_ptr s) -{ - _audio_stream = s; -} diff --git a/src/lib/audio_decoder.h b/src/lib/audio_decoder.h index 9bef8e0e7..7d2a2bb62 100644 --- a/src/lib/audio_decoder.h +++ b/src/lib/audio_decoder.h @@ -25,34 +25,17 @@ #define DVDOMATIC_AUDIO_DECODER_H #include "audio_source.h" -#include "stream.h" #include "decoder.h" +class AudioContent; + /** @class AudioDecoder. * @brief Parent class for audio decoders. */ class AudioDecoder : public AudioSource, public virtual Decoder { public: - AudioDecoder (boost::shared_ptr, DecodeOptions); - - virtual void set_audio_stream (boost::shared_ptr); - - /** @return Audio stream that we are using */ - boost::shared_ptr audio_stream () const { - return _audio_stream; - } - - /** @return All available audio streams */ - std::vector > audio_streams () const { - return _audio_streams; - } - -protected: - /** Audio stream that we are using */ - boost::shared_ptr _audio_stream; - /** All available audio streams */ - std::vector > _audio_streams; + AudioDecoder (boost::shared_ptr, boost::shared_ptr, DecodeOptions); }; #endif diff --git a/src/lib/content.cc b/src/lib/content.cc new file mode 100644 index 000000000..2fb94e959 --- /dev/null +++ b/src/lib/content.cc @@ -0,0 +1,20 @@ +#include +#include "content.h" +#include "util.h" + +using std::string; +using boost::shared_ptr; + +Content::Content (boost::filesystem::path f) + : _file (f) +{ + +} + +void +Content::examine (shared_ptr, shared_ptr, bool) +{ + string const d = md5_digest (_file); + boost::mutex::scoped_lock lm (_mutex); + _digest = d; +} diff --git a/src/lib/content.h b/src/lib/content.h index c848860aa..25c097424 100644 --- a/src/lib/content.h +++ b/src/lib/content.h @@ -1,17 +1,34 @@ +#ifndef DVDOMATIC_CONTENT_H +#define DVDOMATIC_CONTENT_H + #include +#include #include +class Job; +class Film; + class Content { public: + Content (boost::filesystem::path); + + virtual void examine (boost::shared_ptr, boost::shared_ptr, bool); + virtual std::string summary () const = 0; + boost::filesystem::path file () const { boost::mutex::scoped_lock lm (_mutex); return _file; } + boost::signals2::signal Changed; + protected: - boost::mutex _mutex; + mutable boost::mutex _mutex; private: boost::filesystem::path _file; + std::string _digest; }; + +#endif diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc index 52b22fa06..2fe265c14 100644 --- a/src/lib/decoder.cc +++ b/src/lib/decoder.cc @@ -22,34 +22,21 @@ */ #include -#include -#include #include "film.h" -#include "format.h" #include "options.h" #include "exceptions.h" -#include "image.h" #include "util.h" -#include "log.h" #include "decoder.h" -#include "delay_line.h" -#include "subtitle.h" -#include "filter_graph.h" #include "i18n.h" using std::string; -using std::stringstream; -using std::min; -using std::pair; -using std::list; using boost::shared_ptr; -using boost::optional; /** @param f Film. * @param o Decode options. */ -Decoder::Decoder (boost::shared_ptr f, DecodeOptions o) +Decoder::Decoder (shared_ptr f, DecodeOptions o) : _film (f) , _opt (o) { diff --git a/src/lib/decoder.h b/src/lib/decoder.h index f2f523516..50aa16dba 100644 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@ -30,7 +30,6 @@ #include #include #include "util.h" -#include "stream.h" #include "video_source.h" #include "audio_source.h" #include "film.h" @@ -53,7 +52,7 @@ class FilterGraph; class Decoder { public: - Decoder (boost::shared_ptr, DecodeOptions); + Decoder (boost::shared_ptr, DecodeOptions); virtual ~Decoder () {} virtual bool pass () = 0; @@ -63,14 +62,13 @@ public: boost::signals2::signal OutputChanged; protected: - /** our Film */ - boost::shared_ptr _film; + boost::shared_ptr _film; /** our decode options */ DecodeOptions _opt; private: virtual void film_changed (Film::Property) {} - + boost::signals2::scoped_connection _film_connection; }; diff --git a/src/lib/decoder_factory.cc b/src/lib/decoder_factory.cc index f7f9f4074..feaa1c7ef 100644 --- a/src/lib/decoder_factory.cc +++ b/src/lib/decoder_factory.cc @@ -39,22 +39,5 @@ decoder_factory ( shared_ptr f, DecodeOptions o ) { - if (f->content().empty()) { - return Decoders (); - } - - if (boost::filesystem::is_directory (f->content_path()) || f->content_type() == STILL) { - /* A single image file, or a directory of them */ - return Decoders ( - shared_ptr (new ImageMagickDecoder (f, o)), - shared_ptr (new SndfileDecoder (f, o)) - ); - } - - shared_ptr fd (new FFmpegDecoder (f, o)); - if (f->use_content_audio()) { - return Decoders (fd, fd); - } - - return Decoders (fd, shared_ptr (new SndfileDecoder (f, o))); + return Decoders (); } diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc index 7b338407e..970213793 100644 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@ -38,6 +38,7 @@ #include "format.h" #include "cross.h" #include "writer.h" +#include "playlist.h" #include "i18n.h" @@ -53,8 +54,9 @@ using namespace boost; int const Encoder::_history_size = 25; /** @param f Film that we are encoding */ -Encoder::Encoder (shared_ptr f) +Encoder::Encoder (shared_ptr f, shared_ptr p) : _film (f) + , _playlist (p) , _video_frames_in (0) , _video_frames_out (0) #ifdef HAVE_SWRESAMPLE @@ -77,22 +79,22 @@ Encoder::~Encoder () void Encoder::process_begin () { - if (_film->audio_stream() && _film->audio_stream()->sample_rate() != _film->target_audio_sample_rate()) { + if (_playlist->has_audio() && _playlist->audio_frame_rate() != _film->target_audio_sample_rate()) { #ifdef HAVE_SWRESAMPLE stringstream s; - s << String::compose (N_("Will resample audio from %1 to %2"), _film->audio_stream()->sample_rate(), _film->target_audio_sample_rate()); + s << String::compose (N_("Will resample audio from %1 to %2"), _playlist->audio_frame_rate(), _film->target_audio_sample_rate()); _film->log()->log (s.str ()); /* We will be using planar float data when we call the resampler */ _swr_context = swr_alloc_set_opts ( 0, - _film->audio_stream()->channel_layout(), + _playlist->audio_channel_layout(), AV_SAMPLE_FMT_FLTP, _film->target_audio_sample_rate(), - _film->audio_stream()->channel_layout(), + _playlist->audio_channel_layout(), AV_SAMPLE_FMT_FLTP, - _film->audio_stream()->sample_rate(), + _playlist->audio_frame_rate(), 0, 0 ); @@ -118,7 +120,7 @@ Encoder::process_begin () } } - _writer.reset (new Writer (_film)); + _writer.reset (new Writer (_film, _playlist)); } @@ -126,9 +128,9 @@ void Encoder::process_end () { #if HAVE_SWRESAMPLE - if (_film->audio_stream() && _film->audio_stream()->channels() && _swr_context) { + if (_playlist->has_audio() && _playlist->audio_channels() && _swr_context) { - shared_ptr out (new AudioBuffers (_film->audio_stream()->channels(), 256)); + shared_ptr out (new AudioBuffers (_playlist->audio_channels(), 256)); while (1) { int const frames = swr_convert (_swr_context, (uint8_t **) out->data(), 256, 0, 0); @@ -233,7 +235,7 @@ Encoder::frame_done () void Encoder::process_video (shared_ptr image, bool same, boost::shared_ptr sub) { - FrameRateConversion frc (_film->source_frame_rate(), _film->dcp_frame_rate()); + FrameRateConversion frc (_playlist->video_frame_rate(), _film->dcp_frame_rate()); if (frc.skip && (_video_frames_in % 2)) { ++_video_frames_in; @@ -271,7 +273,7 @@ Encoder::process_video (shared_ptr image, bool same, boost::shared_ptr ( new DCPVideoFrame ( - image, sub, _film->format()->dcp_size(), _film->format()->dcp_padding (_film), + image, sub, _film->format()->dcp_size(), _film->format()->dcp_padding (_playlist), _film->subtitle_offset(), _film->subtitle_scale(), _film->scaler(), _video_frames_out, _film->dcp_frame_rate(), s.second, _film->colour_lut(), _film->j2k_bandwidth(), @@ -301,9 +303,9 @@ Encoder::process_audio (shared_ptr data) if (_swr_context) { /* Compute the resampled frames count and add 32 for luck */ - int const max_resampled_frames = ceil ((int64_t) data->frames() * _film->target_audio_sample_rate() / _film->audio_stream()->sample_rate()) + 32; + int const max_resampled_frames = ceil ((int64_t) data->frames() * _film->target_audio_sample_rate() / _playlist->audio_frame_rate()) + 32; - shared_ptr resampled (new AudioBuffers (_film->audio_stream()->channels(), max_resampled_frames)); + shared_ptr resampled (new AudioBuffers (_playlist->audio_channels(), max_resampled_frames)); /* Resample audio */ int const resampled_frames = swr_convert ( @@ -425,8 +427,8 @@ Encoder::encoder_thread (ServerDescription* server) void Encoder::write_audio (shared_ptr data) { - AudioMapping m (_film->audio_channels ()); - if (m.dcp_channels() != _film->audio_channels()) { + AudioMapping m (_playlist->audio_channels ()); + if (m.dcp_channels() != _playlist->audio_channels()) { /* Remap (currently just for mono -> 5.1) */ diff --git a/src/lib/encoder.h b/src/lib/encoder.h index 86880bc34..c84ee027a 100644 --- a/src/lib/encoder.h +++ b/src/lib/encoder.h @@ -51,6 +51,7 @@ class ServerDescription; class DCPVideoFrame; class EncodedData; class Writer; +class Playlist; /** @class Encoder * @brief Encoder to J2K and WAV for DCP. @@ -62,7 +63,7 @@ class Writer; class Encoder : public VideoSink, public AudioSink { public: - Encoder (boost::shared_ptr f); + Encoder (boost::shared_ptr f, boost::shared_ptr); virtual ~Encoder (); /** Called to indicate that a processing run is about to begin */ @@ -95,6 +96,7 @@ private: /** Film that we are encoding */ boost::shared_ptr _film; + boost::shared_ptr _playlist; /** Mutex for _time_history and _last_frame */ mutable boost::mutex _history_mutex; diff --git a/src/lib/examine_content_job.cc b/src/lib/examine_content_job.cc index 4b30c9431..c600132c3 100644 --- a/src/lib/examine_content_job.cc +++ b/src/lib/examine_content_job.cc @@ -17,29 +17,21 @@ */ -/** @file src/examine_content_job.cc - * @brief A class to run through content at high speed to find its length. - */ - #include #include "examine_content_job.h" #include "options.h" -#include "decoder_factory.h" -#include "decoder.h" -#include "transcoder.h" #include "log.h" -#include "film.h" -#include "video_decoder.h" +#include "content.h" #include "i18n.h" using std::string; -using std::vector; -using std::pair; using boost::shared_ptr; -ExamineContentJob::ExamineContentJob (shared_ptr f) +ExamineContentJob::ExamineContentJob (shared_ptr f, shared_ptr c, bool q) : Job (f) + , _content (c) + , _quick (q) { } @@ -51,60 +43,13 @@ ExamineContentJob::~ExamineContentJob () string ExamineContentJob::name () const { - if (_film->name().empty ()) { - return _("Examine content"); - } - - return String::compose (_("Examine content of %1"), _film->name()); + return _("Examine content"); } void ExamineContentJob::run () { - descend (0.5); - _film->set_content_digest (md5_digest (_film->content_path ())); - ascend (); - - descend (0.5); - - /* Set the film's length to either - a) a length judged by running through the content or - b) the length from a decoder's header. - */ - if (!_film->trust_content_header()) { - /* Decode the content to get an accurate length */ - - /* We don't want to use any existing length here, as progress - will be messed up. - */ - _film->unset_length (); - _film->set_crop (Crop ()); - - DecodeOptions o; - o.decode_audio = false; - - Decoders decoders = decoder_factory (_film, o); - - set_progress_unknown (); - while (!decoders.video->pass()) { - /* keep going */ - } - - _film->set_length (decoders.video->video_frame()); - - _film->log()->log (String::compose (N_("Video length examined as %1 frames"), _film->length().get())); - - } else { - - /* Get a quick decoder to get the content's length from its header */ - - Decoders d = decoder_factory (_film, DecodeOptions()); - _film->set_length (d.video->length()); - - _film->log()->log (String::compose (N_("Video length obtained from header as %1 frames"), _film->length().get())); - } - - ascend (); + _content->examine (_film, shared_from_this (), _quick); set_progress (1); set_state (FINISHED_OK); } diff --git a/src/lib/examine_content_job.h b/src/lib/examine_content_job.h index 8ee4f0d60..dc0d53fff 100644 --- a/src/lib/examine_content_job.h +++ b/src/lib/examine_content_job.h @@ -17,22 +17,23 @@ */ -/** @file src/examine_content_job.h - * @brief A class to obtain the length and MD5 digest of a content file. - */ - +#include #include "job.h" -/** @class ExamineContentJob - * @brief A class to obtain the length and MD5 digest of a content file. - */ +class Content; +class Log; + class ExamineContentJob : public Job { public: - ExamineContentJob (boost::shared_ptr); + ExamineContentJob (boost::shared_ptr, boost::shared_ptr, bool); ~ExamineContentJob (); std::string name () const; void run (); + +private: + boost::shared_ptr _content; + bool _quick; }; diff --git a/src/lib/exceptions.h b/src/lib/exceptions.h index e45a62353..6920556e5 100644 --- a/src/lib/exceptions.h +++ b/src/lib/exceptions.h @@ -112,6 +112,7 @@ class OpenFileError : public FileError { public: /** @param f File that we were trying to open */ + /* XXX: should be boost::filesystem::path */ OpenFileError (std::string f); }; diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc new file mode 100644 index 000000000..25efb1ebf --- /dev/null +++ b/src/lib/ffmpeg_content.cc @@ -0,0 +1,156 @@ +#include "ffmpeg_content.h" +#include "ffmpeg_decoder.h" +#include "options.h" +#include "compose.hpp" +#include "job.h" +#include "util.h" +#include "log.h" + +#include "i18n.h" + +using std::string; +using boost::shared_ptr; + +int const FFmpegContentProperty::SUBTITLE_STREAMS = 100; +int const FFmpegContentProperty::SUBTITLE_STREAM = 101; +int const FFmpegContentProperty::AUDIO_STREAMS = 102; +int const FFmpegContentProperty::AUDIO_STREAM = 103; + +FFmpegContent::FFmpegContent (boost::filesystem::path f) + : Content (f) + , VideoContent (f) + , AudioContent (f) +{ + +} + +void +FFmpegContent::examine (shared_ptr film, shared_ptr job, bool quick) +{ + job->descend (0.5); + Content::examine (film, job, quick); + job->ascend (); + + job->set_progress_unknown (); + + DecodeOptions o; + o.decode_audio = false; + shared_ptr decoder (new FFmpegDecoder (film, shared_from_this (), o)); + + ContentVideoFrame video_length = 0; + if (quick) { + video_length = decoder->video_length (); + film->log()->log (String::compose ("Video length obtained from header as %1 frames", decoder->video_length ())); + } else { + while (!decoder->pass ()) { + /* keep going */ + } + + video_length = decoder->video_frame (); + film->log()->log (String::compose ("Video length examined as %1 frames", decoder->video_frame ())); + } + + { + boost::mutex::scoped_lock lm (_mutex); + + _video_length = video_length; + + _subtitle_streams = decoder->subtitle_streams (); + if (!_subtitle_streams.empty ()) { + _subtitle_stream = _subtitle_streams.front (); + } + + _audio_streams = decoder->audio_streams (); + if (!_audio_streams.empty ()) { + _audio_stream = _audio_streams.front (); + } + } + + take_from_video_decoder (decoder); + + Changed (VideoContentProperty::VIDEO_LENGTH); + Changed (FFmpegContentProperty::SUBTITLE_STREAMS); + Changed (FFmpegContentProperty::SUBTITLE_STREAM); + Changed (FFmpegContentProperty::AUDIO_STREAMS); + Changed (FFmpegContentProperty::AUDIO_STREAM); +} + +string +FFmpegContent::summary () const +{ + return String::compose (_("Movie: %1"), file().filename ()); +} + +void +FFmpegContent::set_subtitle_stream (FFmpegSubtitleStream s) +{ + { + boost::mutex::scoped_lock lm (_mutex); + _subtitle_stream = s; + } + + Changed (FFmpegContentProperty::SUBTITLE_STREAM); +} + +void +FFmpegContent::set_audio_stream (FFmpegAudioStream s) +{ + { + boost::mutex::scoped_lock lm (_mutex); + _audio_stream = s; + } + + Changed (FFmpegContentProperty::AUDIO_STREAM); +} + +ContentAudioFrame +FFmpegContent::audio_length () const +{ + if (!_audio_stream) { + return 0; + } + + return video_frames_to_audio_frames (_video_length, audio_frame_rate(), video_frame_rate()); +} + +int +FFmpegContent::audio_channels () const +{ + if (!_audio_stream) { + return 0; + } + + return _audio_stream->channels (); +} + +int +FFmpegContent::audio_frame_rate () const +{ + if (!_audio_stream) { + return 0; + } + + return _audio_stream->frame_rate; +} + +int64_t +FFmpegContent::audio_channel_layout () const +{ + if (!_audio_stream) { + return 0; + } + + return _audio_stream->channel_layout; +} + +bool +operator== (FFmpegSubtitleStream const & a, FFmpegSubtitleStream const & b) +{ + return a.id == b.id; +} + +bool +operator== (FFmpegAudioStream const & a, FFmpegAudioStream const & b) +{ + return a.id == b.id; +} diff --git a/src/lib/ffmpeg_content.h b/src/lib/ffmpeg_content.h index 8b3eca62d..83474ea66 100644 --- a/src/lib/ffmpeg_content.h +++ b/src/lib/ffmpeg_content.h @@ -1,8 +1,97 @@ -#include "content.h" +#ifndef DVDOMATIC_FFMPEG_CONTENT_H +#define DVDOMATIC_FFMPEG_CONTENT_H -class FFmpegContent : public VideoContent, public AudioContent +#include +#include "video_content.h" +#include "audio_content.h" + +class FFmpegAudioStream +{ +public: + FFmpegAudioStream (std::string n, int i, int f, int64_t c) + : name (n) + , id (i) + , frame_rate (f) + , channel_layout (c) + {} + + int channels () const { + return av_get_channel_layout_nb_channels (channel_layout); + } + + std::string name; + int id; + int frame_rate; + int64_t channel_layout; +}; + +extern bool operator== (FFmpegAudioStream const & a, FFmpegAudioStream const & b); + +class FFmpegSubtitleStream +{ +public: + FFmpegSubtitleStream (std::string n, int i) + : name (n) + , id (i) + {} + + std::string name; + int id; +}; + +extern bool operator== (FFmpegSubtitleStream const & a, FFmpegSubtitleStream const & b); + +class FFmpegContentProperty : public VideoContentProperty +{ +public: + static int const SUBTITLE_STREAMS; + static int const SUBTITLE_STREAM; + static int const AUDIO_STREAMS; + static int const AUDIO_STREAM; +}; + +class FFmpegContent : public VideoContent, public AudioContent, public boost::enable_shared_from_this { public: + FFmpegContent (boost::filesystem::path); + void examine (boost::shared_ptr, boost::shared_ptr, bool); + std::string summary () const; + /* AudioContent */ + int audio_channels () const; + ContentAudioFrame audio_length () const; + int audio_frame_rate () const; + int64_t audio_channel_layout () const; + + std::vector subtitle_streams () const { + boost::mutex::scoped_lock lm (_mutex); + return _subtitle_streams; + } + + boost::optional subtitle_stream () const { + boost::mutex::scoped_lock lm (_mutex); + return _subtitle_stream; + } + + std::vector audio_streams () const { + boost::mutex::scoped_lock lm (_mutex); + return _audio_streams; + } + + boost::optional audio_stream () const { + boost::mutex::scoped_lock lm (_mutex); + return _audio_stream; + } + + void set_subtitle_stream (FFmpegSubtitleStream); + void set_audio_stream (FFmpegAudioStream); + +private: + std::vector _subtitle_streams; + boost::optional _subtitle_stream; + std::vector _audio_streams; + boost::optional _audio_stream; }; + +#endif diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index ac25844e3..c8e46776f 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -62,10 +62,11 @@ using boost::optional; using boost::dynamic_pointer_cast; using libdcp::Size; -FFmpegDecoder::FFmpegDecoder (shared_ptr f, DecodeOptions o) +FFmpegDecoder::FFmpegDecoder (shared_ptr f, shared_ptr c, DecodeOptions o) : Decoder (f, o) - , VideoDecoder (f, o) - , AudioDecoder (f, o) + , VideoDecoder (f, c, o) + , AudioDecoder (f, c, o) + , _ffmpeg_content (c) , _format_context (0) , _video_stream (-1) , _frame (0) @@ -110,8 +111,8 @@ FFmpegDecoder::setup_general () { av_register_all (); - if (avformat_open_input (&_format_context, _film->content_path().c_str(), 0, 0) < 0) { - throw OpenFileError (_film->content_path ()); + if (avformat_open_input (&_format_context, _ffmpeg_content->file().string().c_str(), 0, 0) < 0) { + throw OpenFileError (_ffmpeg_content->file().string ()); } if (avformat_find_stream_info (_format_context, 0) < 0) { @@ -135,17 +136,11 @@ FFmpegDecoder::setup_general () } _audio_streams.push_back ( - shared_ptr ( - new FFmpegAudioStream (stream_name (s), i, s->codec->sample_rate, s->codec->channel_layout) - ) + FFmpegAudioStream (stream_name (s), i, s->codec->sample_rate, s->codec->channel_layout) ); } else if (s->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { - _subtitle_streams.push_back ( - shared_ptr ( - new SubtitleStream (stream_name (s), i) - ) - ); + _subtitle_streams.push_back (FFmpegSubtitleStream (stream_name (s), i)); } } @@ -177,14 +172,11 @@ FFmpegDecoder::setup_video () void FFmpegDecoder::setup_audio () { - if (!_audio_stream) { + if (!_ffmpeg_content->audio_stream ()) { return; } - shared_ptr ffa = dynamic_pointer_cast (_audio_stream); - assert (ffa); - - _audio_codec_context = _format_context->streams[ffa->id()]->codec; + _audio_codec_context = _format_context->streams[_ffmpeg_content->audio_stream()->id]->codec; _audio_codec = avcodec_find_decoder (_audio_codec_context->codec_id); if (_audio_codec == 0) { @@ -199,11 +191,11 @@ FFmpegDecoder::setup_audio () void FFmpegDecoder::setup_subtitle () { - if (!_subtitle_stream || _subtitle_stream->id() >= int (_format_context->nb_streams)) { + if (!_ffmpeg_content->subtitle_stream() || _ffmpeg_content->subtitle_stream()->id >= int (_format_context->nb_streams)) { return; } - _subtitle_codec_context = _format_context->streams[_subtitle_stream->id()]->codec; + _subtitle_codec_context = _format_context->streams[_ffmpeg_content->subtitle_stream()->id]->codec; _subtitle_codec = avcodec_find_decoder (_subtitle_codec_context->codec_id); if (_subtitle_codec == 0) { @@ -244,7 +236,7 @@ FFmpegDecoder::pass () } } - if (_audio_stream && _opt.decode_audio) { + if (_ffmpeg_content->audio_stream() && _opt.decode_audio) { decode_audio_packet (); } @@ -253,8 +245,6 @@ FFmpegDecoder::pass () avcodec_get_frame_defaults (_frame); - shared_ptr ffa = dynamic_pointer_cast (_audio_stream); - if (_packet.stream_index == _video_stream && _opt.decode_video) { int frame_finished; @@ -272,9 +262,9 @@ FFmpegDecoder::pass () } } - } else if (ffa && _packet.stream_index == ffa->id() && _opt.decode_audio) { + } else if (_ffmpeg_content->audio_stream() && _packet.stream_index == _ffmpeg_content->audio_stream()->id && _opt.decode_audio) { decode_audio_packet (); - } else if (_subtitle_stream && _packet.stream_index == _subtitle_stream->id() && _opt.decode_subtitles && _first_video) { + } else if (_ffmpeg_content->subtitle_stream() && _packet.stream_index == _ffmpeg_content->subtitle_stream()->id && _opt.decode_subtitles && _first_video) { int got_subtitle; AVSubtitle sub; @@ -306,19 +296,16 @@ FFmpegDecoder::pass () shared_ptr FFmpegDecoder::deinterleave_audio (uint8_t** data, int size) { - assert (_film->audio_channels()); + assert (_ffmpeg_content->audio_channels()); assert (bytes_per_audio_sample()); - shared_ptr ffa = dynamic_pointer_cast (_audio_stream); - assert (ffa); - /* Deinterleave and convert to float */ - assert ((size % (bytes_per_audio_sample() * ffa->channels())) == 0); + assert ((size % (bytes_per_audio_sample() * _ffmpeg_content->audio_channels())) == 0); int const total_samples = size / bytes_per_audio_sample(); - int const frames = total_samples / _film->audio_channels(); - shared_ptr audio (new AudioBuffers (ffa->channels(), frames)); + int const frames = total_samples / _ffmpeg_content->audio_channels(); + shared_ptr audio (new AudioBuffers (_ffmpeg_content->audio_channels(), frames)); switch (audio_sample_format()) { case AV_SAMPLE_FMT_S16: @@ -330,7 +317,7 @@ FFmpegDecoder::deinterleave_audio (uint8_t** data, int size) audio->data(channel)[sample] = float(*p++) / (1 << 15); ++channel; - if (channel == _film->audio_channels()) { + if (channel == _ffmpeg_content->audio_channels()) { channel = 0; ++sample; } @@ -341,7 +328,7 @@ FFmpegDecoder::deinterleave_audio (uint8_t** data, int size) case AV_SAMPLE_FMT_S16P: { int16_t** p = reinterpret_cast (data); - for (int i = 0; i < _film->audio_channels(); ++i) { + for (int i = 0; i < _ffmpeg_content->audio_channels(); ++i) { for (int j = 0; j < frames; ++j) { audio->data(i)[j] = static_cast(p[i][j]) / (1 << 15); } @@ -358,7 +345,7 @@ FFmpegDecoder::deinterleave_audio (uint8_t** data, int size) audio->data(channel)[sample] = static_cast(*p++) / (1 << 31); ++channel; - if (channel == _film->audio_channels()) { + if (channel == _ffmpeg_content->audio_channels()) { channel = 0; ++sample; } @@ -375,7 +362,7 @@ FFmpegDecoder::deinterleave_audio (uint8_t** data, int size) audio->data(channel)[sample] = *p++; ++channel; - if (channel == _film->audio_channels()) { + if (channel == _ffmpeg_content->audio_channels()) { channel = 0; ++sample; } @@ -386,7 +373,7 @@ FFmpegDecoder::deinterleave_audio (uint8_t** data, int size) case AV_SAMPLE_FMT_FLTP: { float** p = reinterpret_cast (data); - for (int i = 0; i < _film->audio_channels(); ++i) { + for (int i = 0; i < _ffmpeg_content->audio_channels(); ++i) { memcpy (audio->data(i), p[i], frames * sizeof(float)); } } @@ -488,21 +475,6 @@ FFmpegDecoder::bytes_per_audio_sample () const return av_get_bytes_per_sample (audio_sample_format ()); } -void -FFmpegDecoder::set_audio_stream (shared_ptr s) -{ - AudioDecoder::set_audio_stream (s); - setup_audio (); -} - -void -FFmpegDecoder::set_subtitle_stream (shared_ptr s) -{ - VideoDecoder::set_subtitle_stream (s); - setup_subtitle (); - OutputChanged (); -} - void FFmpegDecoder::filter_and_emit_video (AVFrame* frame) { @@ -561,58 +533,6 @@ FFmpegDecoder::do_seek (double p, bool backwards) return r < 0; } -shared_ptr -FFmpegAudioStream::create (string t, optional v) -{ - if (!v) { - /* version < 1; no type in the string, and there's only FFmpeg streams anyway */ - return shared_ptr (new FFmpegAudioStream (t, v)); - } - - stringstream s (t); - string type; - s >> type; - if (type != N_("ffmpeg")) { - return shared_ptr (); - } - - return shared_ptr (new FFmpegAudioStream (t, v)); -} - -FFmpegAudioStream::FFmpegAudioStream (string t, optional version) -{ - stringstream n (t); - - int name_index = 4; - if (!version) { - name_index = 2; - int channels; - n >> _id >> channels; - _channel_layout = av_get_default_channel_layout (channels); - _sample_rate = 0; - } else { - string type; - /* Current (marked version 1) */ - n >> type >> _id >> _sample_rate >> _channel_layout; - assert (type == N_("ffmpeg")); - } - - for (int i = 0; i < name_index; ++i) { - size_t const s = t.find (' '); - if (s != string::npos) { - t = t.substr (s + 1); - } - } - - _name = t; -} - -string -FFmpegAudioStream::to_string () const -{ - return String::compose (N_("ffmpeg %1 %2 %3 %4"), _id, _sample_rate, _channel_layout, _name); -} - void FFmpegDecoder::out_with_sync () { @@ -678,8 +598,8 @@ FFmpegDecoder::film_changed (Film::Property p) } /** @return Length (in video frames) according to our content's header */ -SourceFrame -FFmpegDecoder::length () const +ContentVideoFrame +FFmpegDecoder::video_length () const { return (double(_format_context->duration) / AV_TIME_BASE) * frames_per_second(); } @@ -693,9 +613,6 @@ FFmpegDecoder::frame_time () const void FFmpegDecoder::decode_audio_packet () { - shared_ptr ffa = dynamic_pointer_cast (_audio_stream); - assert (ffa); - /* Audio packets can contain multiple frames, so we may have to call avcodec_decode_audio4 several times. */ @@ -727,17 +644,17 @@ FFmpegDecoder::decode_audio_packet () */ /* frames of silence that we must push */ - int const s = rint ((_first_audio.get() - _first_video.get()) * ffa->sample_rate ()); + int const s = rint ((_first_audio.get() - _first_video.get()) * _ffmpeg_content->audio_frame_rate ()); _film->log()->log ( String::compose ( N_("First video at %1, first audio at %2, pushing %3 audio frames of silence for %4 channels (%5 bytes per sample)"), - _first_video.get(), _first_audio.get(), s, ffa->channels(), bytes_per_audio_sample() + _first_video.get(), _first_audio.get(), s, _ffmpeg_content->audio_channels(), bytes_per_audio_sample() ) ); if (s) { - shared_ptr audio (new AudioBuffers (ffa->channels(), s)); + shared_ptr audio (new AudioBuffers (_ffmpeg_content->audio_channels(), s)); audio->make_silent (); Audio (audio); } @@ -747,7 +664,7 @@ FFmpegDecoder::decode_audio_packet () 0, _audio_codec_context->channels, _frame->nb_samples, audio_sample_format (), 1 ); - assert (_audio_codec_context->channels == _film->audio_channels()); + assert (_audio_codec_context->channels == _ffmpeg_content->audio_channels()); Audio (deinterleave_audio (_frame->data, data_size)); } } diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index 1bb14ce9c..a0900d89f 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -36,6 +36,7 @@ extern "C" { #include "video_decoder.h" #include "audio_decoder.h" #include "film.h" +#include "ffmpeg_content.h" struct AVFilterGraph; struct AVCodecContext; @@ -50,62 +51,37 @@ class Options; class Image; class Log; -class FFmpegAudioStream : public AudioStream -{ -public: - FFmpegAudioStream (std::string n, int i, int s, int64_t c) - : AudioStream (s, c) - , _name (n) - , _id (i) - {} - - std::string to_string () const; - - std::string name () const { - return _name; - } - - int id () const { - return _id; - } - - static boost::shared_ptr create (std::string t, boost::optional v); - -private: - friend class stream_test; - - FFmpegAudioStream (std::string t, boost::optional v); - - std::string _name; - int _id; -}; - /** @class FFmpegDecoder * @brief A decoder using FFmpeg to decode content. */ class FFmpegDecoder : public VideoDecoder, public AudioDecoder { public: - FFmpegDecoder (boost::shared_ptr, DecodeOptions); + FFmpegDecoder (boost::shared_ptr, boost::shared_ptr, DecodeOptions); ~FFmpegDecoder (); float frames_per_second () const; libdcp::Size native_size () const; - SourceFrame length () const; + ContentVideoFrame video_length () const; int time_base_numerator () const; int time_base_denominator () const; int sample_aspect_ratio_numerator () const; int sample_aspect_ratio_denominator () const; - void set_audio_stream (boost::shared_ptr); - void set_subtitle_stream (boost::shared_ptr); + std::vector subtitle_streams () const { + return _subtitle_streams; + } + + std::vector audio_streams () const { + return _audio_streams; + } bool seek (double); bool seek_to_last (); + bool pass (); private: - bool pass (); bool do_seek (double p, bool); PixelFormat pixel_format () const; AVSampleFormat audio_sample_format () const; @@ -129,6 +105,8 @@ private: std::string stream_name (AVStream* s) const; + boost::shared_ptr _ffmpeg_content; + AVFormatContext* _format_context; int _video_stream; @@ -148,4 +126,7 @@ private: std::list > _filter_graphs; boost::mutex _filter_graphs_mutex; + + std::vector _subtitle_streams; + std::vector _audio_streams; }; diff --git a/src/lib/film.cc b/src/lib/film.cc index 0d969f16d..f69f63fd8 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -52,6 +52,7 @@ #include "audio_decoder.h" #include "sndfile_decoder.h" #include "analyse_audio_job.h" +#include "playlist.h" #include "i18n.h" @@ -135,8 +136,6 @@ Film::Film (string d, bool must_exist) } } - _sndfile_stream = SndfileStream::create (); - if (must_exist) { read_metadata (); } @@ -162,7 +161,6 @@ Film::Film (Film const & o) , _dcp_ab (o._dcp_ab) , _audio_gain (o._audio_gain) , _audio_delay (o._audio_delay) - , _still_duration (o._still_duration) , _with_subtitles (o._with_subtitles) , _subtitle_offset (o._subtitle_offset) , _subtitle_scale (o._subtitle_scale) @@ -186,6 +184,10 @@ Film::video_state_identifier () const { assert (format ()); + return "XXX"; + +#if 0 + pair f = Filter::ffmpeg_strings (filters()); stringstream s; @@ -204,6 +206,7 @@ Film::video_state_identifier () const } return s.str (); +#endif } /** @return The path to the directory to write video frame info files to */ @@ -234,7 +237,7 @@ Film::audio_analysis_path () const { boost::filesystem::path p; p /= "analysis"; - p /= content_digest(); + p /= "XXX";//content_digest(); return file (p.string ()); } @@ -256,12 +259,12 @@ Film::make_dcp () log()->log (String::compose ("Starting to make DCP on %1", buffer)); } - log()->log (String::compose ("Content is %1; type %2", content_path(), (content_type() == STILL ? _("still") : _("video")))); - if (length()) { - log()->log (String::compose ("Content length %1", length().get())); - } - log()->log (String::compose ("Content digest %1", content_digest())); - log()->log (String::compose ("Content at %1 fps, DCP at %2 fps", source_frame_rate(), dcp_frame_rate())); +// log()->log (String::compose ("Content is %1; type %2", content_path(), (content_type() == STILL ? _("still") : _("video")))); +// if (length()) { +// log()->log (String::compose ("Content length %1", length().get())); +// } +// log()->log (String::compose ("Content digest %1", content_digest())); +// log()->log (String::compose ("Content at %1 fps, DCP at %2 fps", source_frame_rate(), dcp_frame_rate())); log()->log (String::compose ("%1 threads", Config::instance()->num_local_encoding_threads())); log()->log (String::compose ("J2K bandwidth %1", j2k_bandwidth())); #ifdef DVDOMATIC_DEBUG @@ -318,17 +321,13 @@ Film::analyse_audio () JobManager::instance()->add (_analyse_audio_job); } -/** Start a job to examine our content file */ +/** Start a job to examine a piece of content */ void -Film::examine_content () +Film::examine_content (shared_ptr c) { - if (_examine_content_job) { - return; - } - - _examine_content_job.reset (new ExamineContentJob (shared_from_this())); - _examine_content_job->Finished.connect (bind (&Film::examine_content_finished, this)); - JobManager::instance()->add (_examine_content_job); + shared_ptr j (new ExamineContentJob (shared_from_this(), c, trust_content_header ())); + j->Finished.connect (bind (&Film::examine_content_finished, this)); + JobManager::instance()->add (j); } void @@ -346,7 +345,7 @@ Film::analyse_audio_finished () void Film::examine_content_finished () { - _examine_content_job.reset (); + /* XXX */ } /** Start a job to send our DCP to the configured TMS */ @@ -395,7 +394,7 @@ Film::write_metadata () const /* User stuff */ f << "name " << _name << endl; f << "use_dci_name " << _use_dci_name << endl; - f << "content " << _content << endl; +// f << "content " << _content << endl; f << "trust_content_header " << (_trust_content_header ? "1" : "0") << endl; if (_dcp_content_type) { f << "dcp_content_type " << _dcp_content_type->dci_name () << endl; @@ -414,19 +413,19 @@ Film::write_metadata () const f << "trim_start " << _trim_start << endl; f << "trim_end " << _trim_end << endl; f << "dcp_ab " << (_dcp_ab ? "1" : "0") << endl; - if (_content_audio_stream) { - f << "selected_content_audio_stream " << _content_audio_stream->to_string() << endl; - } - for (vector::const_iterator i = _external_audio.begin(); i != _external_audio.end(); ++i) { - f << "external_audio " << *i << endl; - } - f << "use_content_audio " << (_use_content_audio ? "1" : "0") << endl; +// if (_content_audio_stream) { +// f << "selected_content_audio_stream " << _content_audio_stream->to_string() << endl; +// } +// for (vector::const_iterator i = _external_audio.begin(); i != _external_audio.end(); ++i) { +// f << "external_audio " << *i << endl; +// } +// f << "use_content_audio " << (_use_content_audio ? "1" : "0") << endl; f << "audio_gain " << _audio_gain << endl; f << "audio_delay " << _audio_delay << endl; - f << "still_duration " << _still_duration << endl; - if (_subtitle_stream) { - f << "selected_subtitle_stream " << _subtitle_stream->to_string() << endl; - } +// f << "still_duration " << _still_duration << endl; +// if (_subtitle_stream) { +// f << "selected_subtitle_stream " << _subtitle_stream->to_string() << endl; +// } f << "with_subtitles " << _with_subtitles << endl; f << "subtitle_offset " << _subtitle_offset << endl; f << "subtitle_scale " << _subtitle_scale << endl; @@ -435,22 +434,22 @@ Film::write_metadata () const _dci_metadata.write (f); f << "dci_date " << boost::gregorian::to_iso_string (_dci_date) << endl; f << "dcp_frame_rate " << _dcp_frame_rate << endl; - f << "width " << _size.width << endl; - f << "height " << _size.height << endl; - f << "length " << _length.get_value_or(0) << endl; - f << "content_digest " << _content_digest << endl; +// f << "width " << _size.width << endl; +// f << "height " << _size.height << endl; +// f << "length " << _length.get_value_or(0) << endl; +// f << "content_digest " << _content_digest << endl; - for (vector >::const_iterator i = _content_audio_streams.begin(); i != _content_audio_streams.end(); ++i) { - f << "content_audio_stream " << (*i)->to_string () << endl; - } +// for (vector >::const_iterator i = _content_audio_streams.begin(); i != _content_audio_streams.end(); ++i) { +// f << "content_audio_stream " << (*i)->to_string () << endl; +// } - f << "external_audio_stream " << _sndfile_stream->to_string() << endl; +// f << "external_audio_stream " << _sndfile_stream->to_string() << endl; - for (vector >::const_iterator i = _subtitle_streams.begin(); i != _subtitle_streams.end(); ++i) { - f << "subtitle_stream " << (*i)->to_string () << endl; - } +// for (vector >::const_iterator i = _subtitle_streams.begin(); i != _subtitle_streams.end(); ++i) { +// f << "subtitle_stream " << (*i)->to_string () << endl; +// } - f << "source_frame_rate " << _source_frame_rate << endl; +// f << "source_frame_rate " << _source_frame_rate << endl; _dirty = false; } @@ -461,9 +460,9 @@ Film::read_metadata () { boost::mutex::scoped_lock lm (_state_mutex); - _external_audio.clear (); - _content_audio_streams.clear (); - _subtitle_streams.clear (); +// _external_audio.clear (); +// _content_audio_streams.clear (); +// _subtitle_streams.clear (); boost::optional version; @@ -499,7 +498,7 @@ Film::read_metadata () } else if (k == "use_dci_name") { _use_dci_name = (v == "1"); } else if (k == "content") { - _content = v; +// _content = v; } else if (k == "trust_content_header") { _trust_content_header = (v == "1"); } else if (k == "dcp_content_type") { @@ -532,23 +531,23 @@ Film::read_metadata () if (!version) { audio_stream_index = atoi (v.c_str ()); } else { - _content_audio_stream = audio_stream_factory (v, version); +// _content_audio_stream = audio_stream_factory (v, version); } } else if (k == "external_audio") { - _external_audio.push_back (v); +// _external_audio.push_back (v); } else if (k == "use_content_audio") { - _use_content_audio = (v == "1"); +// _use_content_audio = (v == "1"); } else if (k == "audio_gain") { _audio_gain = atof (v.c_str ()); } else if (k == "audio_delay") { _audio_delay = atoi (v.c_str ()); } else if (k == "still_duration") { - _still_duration = atoi (v.c_str ()); +// _still_duration = atoi (v.c_str ()); } else if (k == "selected_subtitle_stream") { if (!version) { subtitle_stream_index = atoi (v.c_str ()); } else { - _subtitle_stream = subtitle_stream_factory (v, version); +// _subtitle_stream = subtitle_stream_factory (v, version); } } else if (k == "with_subtitles") { _with_subtitles = (v == "1"); @@ -570,50 +569,31 @@ Film::read_metadata () /* Cached stuff */ if (k == "width") { - _size.width = atoi (v.c_str ()); +// _size.width = atoi (v.c_str ()); } else if (k == "height") { - _size.height = atoi (v.c_str ()); +// _size.height = atoi (v.c_str ()); } else if (k == "length") { int const vv = atoi (v.c_str ()); if (vv) { - _length = vv; +// _length = vv; } } else if (k == "content_digest") { - _content_digest = v; +// _content_digest = v; } else if (k == "content_audio_stream" || (!version && k == "audio_stream")) { - _content_audio_streams.push_back (audio_stream_factory (v, version)); +// _content_audio_streams.push_back (audio_stream_factory (v, version)); } else if (k == "external_audio_stream") { - _sndfile_stream = audio_stream_factory (v, version); +// _sndfile_stream = audio_stream_factory (v, version); } else if (k == "subtitle_stream") { - _subtitle_streams.push_back (subtitle_stream_factory (v, version)); +// _subtitle_streams.push_back (subtitle_stream_factory (v, version)); } else if (k == "source_frame_rate") { - _source_frame_rate = atof (v.c_str ()); +// _source_frame_rate = atof (v.c_str ()); } else if (version < 4 && k == "frames_per_second") { - _source_frame_rate = atof (v.c_str ()); +// _source_frame_rate = atof (v.c_str ()); /* Fill in what would have been used for DCP frame rate by the older version */ - _dcp_frame_rate = best_dcp_frame_rate (_source_frame_rate); +// _dcp_frame_rate = best_dcp_frame_rate (_source_frame_rate); } } - if (!version) { - if (audio_sample_rate) { - /* version < 1 didn't specify sample rate in the audio streams, so fill it in here */ - for (vector >::iterator i = _content_audio_streams.begin(); i != _content_audio_streams.end(); ++i) { - (*i)->set_sample_rate (audio_sample_rate.get()); - } - } - - /* also the selected stream was specified as an index */ - if (audio_stream_index && audio_stream_index.get() >= 0 && audio_stream_index.get() < (int) _content_audio_streams.size()) { - _content_audio_stream = _content_audio_streams[audio_stream_index.get()]; - } - - /* similarly the subtitle */ - if (subtitle_stream_index && subtitle_stream_index.get() >= 0 && subtitle_stream_index.get() < (int) _subtitle_streams.size()) { - _subtitle_stream = _subtitle_streams[subtitle_stream_index.get()]; - } - } - _dirty = false; } @@ -661,47 +641,21 @@ Film::file (string f) const return p.string (); } -/** @return full path of the content (actual video) file - * of the Film. - */ -string -Film::content_path () const -{ - boost::mutex::scoped_lock lm (_state_mutex); - if (boost::filesystem::path(_content).has_root_directory ()) { - return _content; - } - - return file (_content); -} - -ContentType -Film::content_type () const -{ - if (boost::filesystem::is_directory (_content)) { - /* Directory of images, we assume */ - return VIDEO; - } - - if (still_image_file (_content)) { - return STILL; - } - - return VIDEO; -} - /** @return The sampling rate that we will resample the audio to */ int Film::target_audio_sample_rate () const { - if (!audio_stream()) { + /* XXX: how often is this method called? */ + + boost::shared_ptr p = playlist (); + if (p->has_audio ()) { return 0; } /* Resample to a DCI-approved sample rate */ - double t = dcp_audio_sample_rate (audio_stream()->sample_rate()); + double t = dcp_audio_sample_rate (p->audio_frame_rate()); - FrameRateConversion frc (source_frame_rate(), dcp_frame_rate()); + FrameRateConversion frc (p->video_frame_rate(), dcp_frame_rate()); /* Compensate if the DCP is being run at a different frame rate to the source; that is, if the video is run such that it will @@ -710,18 +664,12 @@ Film::target_audio_sample_rate () const */ if (frc.change_speed) { - t *= source_frame_rate() * frc.factor() / dcp_frame_rate(); + t *= p->video_frame_rate() * frc.factor() / dcp_frame_rate(); } return rint (t); } -int -Film::still_duration_in_frames () const -{ - return still_duration() * source_frame_rate(); -} - /** @return a DCI-compliant name for a DCP of this film */ string Film::dci_name (bool if_created_now) const @@ -768,7 +716,8 @@ Film::dci_name (bool if_created_now) const } } - switch (audio_channels()) { + /* XXX */ + switch (2) { case 1: d << "_10"; break; @@ -846,98 +795,6 @@ Film::set_use_dci_name (bool u) signal_changed (USE_DCI_NAME); } -void -Film::set_content (string c) -{ - string check = directory (); - - boost::filesystem::path slash ("/"); - string platform_slash = slash.make_preferred().string (); - - if (!ends_with (check, platform_slash)) { - check += platform_slash; - } - - if (boost::filesystem::path(c).has_root_directory () && starts_with (c, check)) { - c = c.substr (_directory.length() + 1); - } - - string old_content; - - { - boost::mutex::scoped_lock lm (_state_mutex); - if (c == _content) { - return; - } - - old_content = _content; - _content = c; - } - - /* Reset streams here in case the new content doesn't have one or the other */ - _content_audio_stream = shared_ptr (); - _subtitle_stream = shared_ptr (); - - /* Start off using content audio */ - set_use_content_audio (true); - - /* Create a temporary decoder so that we can get information - about the content. - */ - - try { - Decoders d = decoder_factory (shared_from_this(), DecodeOptions()); - - set_size (d.video->native_size ()); - set_source_frame_rate (d.video->frames_per_second ()); - set_dcp_frame_rate (best_dcp_frame_rate (source_frame_rate ())); - set_subtitle_streams (d.video->subtitle_streams ()); - if (d.audio) { - set_content_audio_streams (d.audio->audio_streams ()); - } - - { - boost::mutex::scoped_lock lm (_state_mutex); - _content = c; - } - - signal_changed (CONTENT); - - /* Start off with the first audio and subtitle streams */ - if (d.audio && !d.audio->audio_streams().empty()) { - set_content_audio_stream (d.audio->audio_streams().front()); - } - - if (!d.video->subtitle_streams().empty()) { - set_subtitle_stream (d.video->subtitle_streams().front()); - } - - examine_content (); - - } catch (...) { - - boost::mutex::scoped_lock lm (_state_mutex); - _content = old_content; - throw; - - } - - /* Default format */ - switch (content_type()) { - case STILL: - set_format (Format::from_id ("var-185")); - break; - case VIDEO: - set_format (Format::from_id ("185")); - break; - } - - /* Still image DCPs must use external audio */ - if (content_type() == STILL) { - set_use_content_audio (false); - } -} - void Film::set_trust_content_header (bool t) { @@ -950,7 +807,8 @@ Film::set_trust_content_header (bool t) if (!_trust_content_header && !content().empty()) { /* We just said that we don't trust the content's header */ - examine_content (); + /* XXX */ +// examine_content (); } } @@ -1091,43 +949,6 @@ Film::set_dcp_ab (bool a) signal_changed (DCP_AB); } -void -Film::set_content_audio_stream (shared_ptr s) -{ - { - boost::mutex::scoped_lock lm (_state_mutex); - _content_audio_stream = s; - } - signal_changed (CONTENT_AUDIO_STREAM); -} - -void -Film::set_external_audio (vector a) -{ - { - boost::mutex::scoped_lock lm (_state_mutex); - _external_audio = a; - } - - shared_ptr decoder (new SndfileDecoder (shared_from_this(), DecodeOptions())); - if (decoder->audio_stream()) { - _sndfile_stream = decoder->audio_stream (); - } - - signal_changed (EXTERNAL_AUDIO); -} - -void -Film::set_use_content_audio (bool e) -{ - { - boost::mutex::scoped_lock lm (_state_mutex); - _use_content_audio = e; - } - - signal_changed (USE_CONTENT_AUDIO); -} - void Film::set_audio_gain (float g) { @@ -1148,26 +969,6 @@ Film::set_audio_delay (int d) signal_changed (AUDIO_DELAY); } -void -Film::set_still_duration (int d) -{ - { - boost::mutex::scoped_lock lm (_state_mutex); - _still_duration = d; - } - signal_changed (STILL_DURATION); -} - -void -Film::set_subtitle_stream (shared_ptr s) -{ - { - boost::mutex::scoped_lock lm (_state_mutex); - _subtitle_stream = s; - } - signal_changed (SUBTITLE_STREAM); -} - void Film::set_with_subtitles (bool w) { @@ -1239,76 +1040,6 @@ Film::set_dcp_frame_rate (int f) signal_changed (DCP_FRAME_RATE); } -void -Film::set_size (libdcp::Size s) -{ - { - boost::mutex::scoped_lock lm (_state_mutex); - _size = s; - } - signal_changed (SIZE); -} - -void -Film::set_length (SourceFrame l) -{ - { - boost::mutex::scoped_lock lm (_state_mutex); - _length = l; - } - signal_changed (LENGTH); -} - -void -Film::unset_length () -{ - { - boost::mutex::scoped_lock lm (_state_mutex); - _length = boost::none; - } - signal_changed (LENGTH); -} - -void -Film::set_content_digest (string d) -{ - { - boost::mutex::scoped_lock lm (_state_mutex); - _content_digest = d; - } - _dirty = true; -} - -void -Film::set_content_audio_streams (vector > s) -{ - { - boost::mutex::scoped_lock lm (_state_mutex); - _content_audio_streams = s; - } - signal_changed (CONTENT_AUDIO_STREAMS); -} - -void -Film::set_subtitle_streams (vector > s) -{ - { - boost::mutex::scoped_lock lm (_state_mutex); - _subtitle_streams = s; - } - signal_changed (SUBTITLE_STREAMS); -} - -void -Film::set_source_frame_rate (float f) -{ - { - boost::mutex::scoped_lock lm (_state_mutex); - _source_frame_rate = f; - } - signal_changed (SOURCE_FRAME_RATE); -} - void Film::signal_changed (Property p) { @@ -1322,33 +1053,12 @@ Film::signal_changed (Property p) } } -int -Film::audio_channels () const -{ - shared_ptr s = audio_stream (); - if (!s) { - return 0; - } - - return s->channels (); -} - void Film::set_dci_date_today () { _dci_date = boost::gregorian::day_clock::local_day (); } -boost::shared_ptr -Film::audio_stream () const -{ - if (use_content_audio()) { - return _content_audio_stream; - } - - return _sndfile_stream; -} - string Film::info_path (int f) const { @@ -1404,20 +1114,22 @@ Film::have_dcp () const return true; } -bool -Film::has_audio () const +shared_ptr +Film::playlist () const { - if (use_content_audio()) { - return audio_stream(); - } + boost::mutex::scoped_lock lm (_state_mutex); + return shared_ptr (new Playlist (shared_from_this (), _content)); +} - vector const e = external_audio (); - for (vector::const_iterator i = e.begin(); i != e.end(); ++i) { - if (!i->empty ()) { - return true; - } +void +Film::add_content (shared_ptr c) +{ + { + boost::mutex::scoped_lock lm (_state_mutex); + _content.push_back (c); } - return false; -} + signal_changed (CONTENT); + examine_content (c); +} diff --git a/src/lib/film.h b/src/lib/film.h index 2e05d64f4..afd57b7c2 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -37,7 +37,6 @@ extern "C" { } #include "dcp_content_type.h" #include "util.h" -#include "stream.h" #include "dci_metadata.h" class Format; @@ -48,6 +47,7 @@ class ExamineContentJob; class AnalyseAudioJob; class ExternalAudioStream; class Content; +class Playlist; /** @class Film * @brief A representation of a video, maybe with sound. @@ -69,7 +69,7 @@ public: std::string video_mxf_filename () const; std::string audio_analysis_path () const; - void examine_content (); + void examine_content (boost::shared_ptr); void analyse_audio (); void send_dcp_to_tms (); @@ -87,9 +87,6 @@ public: std::string file (std::string f) const; std::string dir (std::string d) const; - std::string content_path () const; - ContentType content_type () const; - int target_audio_sample_rate () const; void write_metadata () const; @@ -104,12 +101,12 @@ public: return _dirty; } - int audio_channels () const; - void set_dci_date_today (); bool have_dcp () const; + boost::shared_ptr playlist () const; + /** Identifiers for the parts of our state; used for signalling changes. */ @@ -118,6 +115,7 @@ public: NAME, USE_DCI_NAME, TRUST_CONTENT_HEADER, + CONTENT, DCP_CONTENT_TYPE, FORMAT, CROP, @@ -162,6 +160,11 @@ public: return _trust_content_header; } + std::list > content () const { + boost::mutex::scoped_lock lm (_state_mutex); + return _content; + } + DCPContentType const * dcp_content_type () const { boost::mutex::scoped_lock lm (_state_mutex); return _dcp_content_type; @@ -212,11 +215,6 @@ public: return _audio_delay; } - boost::shared_ptr subtitle_stream () const { - boost::mutex::scoped_lock lm (_state_mutex); - return _subtitle_stream; - } - bool with_subtitles () const { boost::mutex::scoped_lock lm (_state_mutex); return _with_subtitles; @@ -252,15 +250,13 @@ public: return _dcp_frame_rate; } - boost::shared_ptr audio_stream () const; - bool has_audio () const; - /* SET */ void set_directory (std::string); void set_name (std::string); void set_use_dci_name (bool); void set_trust_content_header (bool); + void add_content (boost::shared_ptr); void set_dcp_content_type (DCPContentType const *); void set_format (Format const *); void set_crop (Crop); @@ -297,8 +293,6 @@ private: /** Log to write to */ boost::shared_ptr _log; - /** Any running ExamineContentJob, or 0 */ - boost::shared_ptr _examine_content_job; /** Any running AnalyseAudioJob, or 0 */ boost::shared_ptr _analyse_audio_job; @@ -318,7 +312,8 @@ private: std::string _name; /** True if a auto-generated DCI-compliant name should be used for our DCP */ bool _use_dci_name; - std::list > _content; + typedef std::list > ContentList; + ContentList _content; /** If this is true, we will believe the length specified by the content * file's header; if false, we will run through the whole content file * the first time we see it in order to obtain the length. diff --git a/src/lib/filter_graph.cc b/src/lib/filter_graph.cc index 045cbaa6a..a52c030fe 100644 --- a/src/lib/filter_graph.cc +++ b/src/lib/filter_graph.cc @@ -57,7 +57,7 @@ using libdcp::Size; * @param s Size of the images to process. * @param p Pixel format of the images to process. */ -FilterGraph::FilterGraph (shared_ptr film, FFmpegDecoder* decoder, libdcp::Size s, AVPixelFormat p) +FilterGraph::FilterGraph (shared_ptr film, FFmpegDecoder* decoder, libdcp::Size s, AVPixelFormat p) : _buffer_src_context (0) , _buffer_sink_context (0) , _size (s) diff --git a/src/lib/filter_graph.h b/src/lib/filter_graph.h index 7e4e8422b..db86a677d 100644 --- a/src/lib/filter_graph.h +++ b/src/lib/filter_graph.h @@ -37,7 +37,7 @@ class FFmpegDecoder; class FilterGraph { public: - FilterGraph (boost::shared_ptr film, FFmpegDecoder* decoder, libdcp::Size s, AVPixelFormat p); + FilterGraph (boost::shared_ptr, FFmpegDecoder* decoder, libdcp::Size s, AVPixelFormat p); bool can_process (libdcp::Size s, AVPixelFormat p) const; std::list > process (AVFrame const * frame); diff --git a/src/lib/format.cc b/src/lib/format.cc index b506c7000..05b71f2e5 100644 --- a/src/lib/format.cc +++ b/src/lib/format.cc @@ -29,6 +29,7 @@ #include #include "format.h" #include "film.h" +#include "playlist.h" #include "i18n.h" @@ -206,16 +207,16 @@ FixedFormat::FixedFormat (int r, libdcp::Size dcp, string id, string n, string d * (so there are dcp_padding() pixels on the left and dcp_padding() on the right) */ int -Format::dcp_padding (shared_ptr f) const +Format::dcp_padding (shared_ptr p) const { - int p = rint ((_dcp_size.width - (_dcp_size.height * ratio_as_integer(f) / 100.0)) / 2.0); + int pad = rint ((_dcp_size.width - (_dcp_size.height * ratio_as_integer(p) / 100.0)) / 2.0); /* This comes out -ve for Scope; bodge it */ - if (p < 0) { - p = 0; + if (pad < 0) { + pad = 0; } - return p; + return pad; } float @@ -231,15 +232,15 @@ VariableFormat::VariableFormat (libdcp::Size dcp, string id, string n, string d, } int -VariableFormat::ratio_as_integer (shared_ptr f) const +VariableFormat::ratio_as_integer (shared_ptr p) const { - return rint (ratio_as_float (f) * 100); + return rint (ratio_as_float (p) * 100); } float -VariableFormat::ratio_as_float (shared_ptr f) const +VariableFormat::ratio_as_float (shared_ptr p) const { - return float (f->size().width) / f->size().height; + return float (p->video_size().width) / p->video_size().height; } /** @return A name to be presented to the user */ diff --git a/src/lib/format.h b/src/lib/format.h index 305524628..94c2253de 100644 --- a/src/lib/format.h +++ b/src/lib/format.h @@ -26,7 +26,7 @@ #include #include "util.h" -class Film; +class Playlist; class Format { @@ -42,15 +42,15 @@ public: /** @return the aspect ratio multiplied by 100 * (e.g. 239 for Cinemascope 2.39:1) */ - virtual int ratio_as_integer (boost::shared_ptr f) const = 0; + virtual int ratio_as_integer (boost::shared_ptr f) const = 0; /** @return the ratio as a floating point number */ - virtual float ratio_as_float (boost::shared_ptr f) const = 0; + virtual float ratio_as_float (boost::shared_ptr f) const = 0; /** @return the ratio of the container (including any padding) as a floating point number */ float container_ratio_as_float () const; - int dcp_padding (boost::shared_ptr f) const; + int dcp_padding (boost::shared_ptr) const; /** @return size in pixels of the images that we should * put in a DCP for this ratio. This size will not correspond @@ -115,11 +115,11 @@ class FixedFormat : public Format public: FixedFormat (int, libdcp::Size, std::string, std::string, std::string, std::string); - int ratio_as_integer (boost::shared_ptr) const { + int ratio_as_integer (boost::shared_ptr) const { return _ratio; } - float ratio_as_float (boost::shared_ptr) const { + float ratio_as_float (boost::shared_ptr) const { return _ratio / 100.0; } @@ -136,8 +136,8 @@ class VariableFormat : public Format public: VariableFormat (libdcp::Size, std::string, std::string, std::string, std::string); - int ratio_as_integer (boost::shared_ptr f) const; - float ratio_as_float (boost::shared_ptr f) const; + int ratio_as_integer (boost::shared_ptr f) const; + float ratio_as_float (boost::shared_ptr f) const; std::string name () const; }; diff --git a/src/lib/imagemagick_content.cc b/src/lib/imagemagick_content.cc new file mode 100644 index 000000000..d0887c0aa --- /dev/null +++ b/src/lib/imagemagick_content.cc @@ -0,0 +1,2 @@ +#include "imagemagick_content.h" + diff --git a/src/lib/imagemagick_content.h b/src/lib/imagemagick_content.h index 2a8197b69..985aa0e8d 100644 --- a/src/lib/imagemagick_content.h +++ b/src/lib/imagemagick_content.h @@ -2,5 +2,6 @@ class ImageMagickContent : public VideoContent { - +public: + ImageMagickContent (boost::filesystem::path); }; diff --git a/src/lib/imagemagick_decoder.cc b/src/lib/imagemagick_decoder.cc index 5dc0b7b06..aa3c64f93 100644 --- a/src/lib/imagemagick_decoder.cc +++ b/src/lib/imagemagick_decoder.cc @@ -20,6 +20,7 @@ #include #include #include +#include "imagemagick_content.h" #include "imagemagick_decoder.h" #include "image.h" #include "film.h" @@ -32,37 +33,20 @@ using boost::shared_ptr; using libdcp::Size; ImageMagickDecoder::ImageMagickDecoder ( - boost::shared_ptr f, DecodeOptions o) + shared_ptr f, shared_ptr c, DecodeOptions o) : Decoder (f, o) - , VideoDecoder (f, o) + , VideoDecoder (f, c, o) + , _imagemagick_content (c) + , _position (0) { - if (boost::filesystem::is_directory (_film->content_path())) { - for ( - boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator (_film->content_path()); - i != boost::filesystem::directory_iterator(); - ++i) { - - if (still_image_file (i->path().string())) { - _files.push_back (i->path().string()); - } - } - } else { - _files.push_back (_film->content_path ()); - } - - _iter = _files.begin (); + } libdcp::Size ImageMagickDecoder::native_size () const { - if (_files.empty ()) { - throw DecodeError (_("no still image files found")); - } - - /* Look at the first file and assume its size holds for all */ using namespace MagickCore; - Magick::Image* image = new Magick::Image (_film->content_path ()); + Magick::Image* image = new Magick::Image (_imagemagick_content->file().string()); libdcp::Size const s = libdcp::Size (image->columns(), image->rows()); delete image; @@ -72,16 +56,15 @@ ImageMagickDecoder::native_size () const bool ImageMagickDecoder::pass () { - if (_iter == _files.end()) { - if (video_frame() >= _film->still_duration_in_frames()) { - return true; - } - + if (_position > 0 && _position < _imagemagick_content->video_length ()) { repeat_last_video (); + _position++; return false; + } else if (_position >= _imagemagick_content->video_length ()) { + return true; } - Magick::Image* magick_image = new Magick::Image (_film->content_path ()); + Magick::Image* magick_image = new Magick::Image (_imagemagick_content->file().string ()); libdcp::Size size = native_size (); shared_ptr image (new SimpleImage (PIX_FMT_RGB24, size, false)); @@ -104,7 +87,7 @@ ImageMagickDecoder::pass () emit_video (image, 0); - ++_iter; + ++_position; return false; } @@ -118,10 +101,8 @@ ImageMagickDecoder::pixel_format () const bool ImageMagickDecoder::seek_to_last () { - if (_iter == _files.end()) { - _iter = _files.begin(); - } else { - --_iter; + if (_position > 0) { + --_position; } return false; @@ -130,16 +111,14 @@ ImageMagickDecoder::seek_to_last () bool ImageMagickDecoder::seek (double t) { - int const f = t * frames_per_second(); - - _iter = _files.begin (); - for (int i = 0; i < f; ++i) { - if (_iter == _files.end()) { - return true; - } - ++_iter; + int const f = t * _imagemagick_content->video_frame_rate (); + + if (f >= _imagemagick_content->video_length()) { + _position = 0; + return true; } - + + _position = f; return false; } diff --git a/src/lib/imagemagick_decoder.h b/src/lib/imagemagick_decoder.h index 2f4e2c967..b04bd88b1 100644 --- a/src/lib/imagemagick_decoder.h +++ b/src/lib/imagemagick_decoder.h @@ -23,10 +23,12 @@ namespace Magick { class Image; } +class ImageMagickContent; + class ImageMagickDecoder : public VideoDecoder { public: - ImageMagickDecoder (boost::shared_ptr, DecodeOptions); + ImageMagickDecoder (boost::shared_ptr, boost::shared_ptr, DecodeOptions); float frames_per_second () const { /* We don't know */ @@ -35,7 +37,7 @@ public: libdcp::Size native_size () const; - SourceFrame length () const { + ContentVideoFrame video_length () const { /* We don't know */ return 0; } @@ -54,9 +56,9 @@ public: bool seek (double); bool seek_to_last (); + bool pass (); protected: - bool pass (); PixelFormat pixel_format () const; int time_base_numerator () const { @@ -79,7 +81,7 @@ protected: private: void film_changed (Film::Property); - - std::list _files; - std::list::iterator _iter; + + boost::shared_ptr _imagemagick_content; + ContentVideoFrame _position; }; diff --git a/src/lib/job.cc b/src/lib/job.cc index ace02b8b3..ff0332d6d 100644 --- a/src/lib/job.cc +++ b/src/lib/job.cc @@ -34,8 +34,6 @@ using std::list; using std::stringstream; using boost::shared_ptr; -/** @param s Film that we are operating on. - */ Job::Job (shared_ptr f) : _film (f) , _thread (0) diff --git a/src/lib/job.h b/src/lib/job.h index fd036bce2..f5175c525 100644 --- a/src/lib/job.h +++ b/src/lib/job.h @@ -38,7 +38,7 @@ class Film; class Job : public boost::enable_shared_from_this { public: - Job (boost::shared_ptr s); + Job (boost::shared_ptr); virtual ~Job() {} /** @return user-readable name of this job */ @@ -87,7 +87,6 @@ protected: void set_state (State); void set_error (std::string s, std::string d); - /** Film for this job */ boost::shared_ptr _film; private: diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc new file mode 100644 index 000000000..17ecd2f37 --- /dev/null +++ b/src/lib/playlist.cc @@ -0,0 +1,266 @@ +/* + Copyright (C) 2013 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include "playlist.h" +#include "sndfile_content.h" +#include "sndfile_decoder.h" +#include "ffmpeg_content.h" +#include "ffmpeg_decoder.h" +#include "imagemagick_content.h" +#include "imagemagick_decoder.h" + +using std::list; +using boost::shared_ptr; +using boost::dynamic_pointer_cast; + +Playlist::Playlist (shared_ptr f, list > c) + : _video_from (VIDEO_NONE) + , _audio_from (AUDIO_NONE) + , _ffmpeg_decoder_done (false) +{ + for (list >::const_iterator i = c.begin(); i != c.end(); ++i) { + shared_ptr fc = dynamic_pointer_cast (*i); + if (fc) { + assert (!_ffmpeg); + _ffmpeg = fc; + _video_from = VIDEO_FFMPEG; + if (_audio_from == AUDIO_NONE) { + _audio_from = AUDIO_FFMPEG; + } + } + + shared_ptr ic = dynamic_pointer_cast (*i); + if (ic) { + _imagemagick.push_back (ic); + if (_video_from == VIDEO_NONE) { + _video_from = VIDEO_IMAGEMAGICK; + } + } + + shared_ptr sc = dynamic_pointer_cast (*i); + if (sc) { + _sndfile.push_back (sc); + _audio_from = AUDIO_SNDFILE; + } + } + + if (_video_from == VIDEO_FFMPEG || _audio_from == AUDIO_FFMPEG) { + DecodeOptions o; + /* XXX: decodeoptions */ + _ffmpeg_decoder.reset (new FFmpegDecoder (f, _ffmpeg, o)); + } + + if (_video_from == VIDEO_FFMPEG) { + _ffmpeg_decoder->connect_video (shared_from_this ()); + } + + if (_audio_from == AUDIO_FFMPEG) { + _ffmpeg_decoder->connect_audio (shared_from_this ()); + } + + if (_video_from == VIDEO_IMAGEMAGICK) { + for (list >::iterator i = _imagemagick.begin(); i != _imagemagick.end(); ++i) { + DecodeOptions o; + /* XXX: decodeoptions */ + shared_ptr d (new ImageMagickDecoder (f, *i, o)); + _imagemagick_decoders.push_back (d); + d->connect_video (shared_from_this ()); + } + + _imagemagick_decoder = _imagemagick_decoders.begin (); + } + + if (_audio_from == AUDIO_SNDFILE) { + for (list >::iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) { + DecodeOptions o; + /* XXX: decodeoptions */ + shared_ptr d (new SndfileDecoder (f, *i, o)); + _sndfile_decoders.push_back (d); + d->connect_audio (shared_from_this ()); + } + } +} + +ContentAudioFrame +Playlist::audio_length () const +{ + switch (_audio_from) { + case AUDIO_NONE: + return 0; + case AUDIO_FFMPEG: + return _ffmpeg->audio_length (); + case AUDIO_SNDFILE: + { + ContentAudioFrame l = 0; + for (list >::const_iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) { + l += (*i)->audio_length (); + } + return l; + } + } + + return 0; +} + +int +Playlist::audio_channels () const +{ + switch (_audio_from) { + case AUDIO_NONE: + return 0; + case AUDIO_FFMPEG: + return _ffmpeg->audio_channels (); + case AUDIO_SNDFILE: + { + int c = 0; + for (list >::const_iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) { + c += (*i)->audio_channels (); + } + return c; + } + } + + return 0; +} + +int +Playlist::audio_frame_rate () const +{ + switch (_audio_from) { + case AUDIO_NONE: + return 0; + case AUDIO_FFMPEG: + return _ffmpeg->audio_frame_rate (); + case AUDIO_SNDFILE: + return _sndfile.front()->audio_frame_rate (); + } + + return 0; +} + +int64_t +Playlist::audio_channel_layout () const +{ + switch (_audio_from) { + case AUDIO_NONE: + return 0; + case AUDIO_FFMPEG: + return _ffmpeg->audio_channel_layout (); + case AUDIO_SNDFILE: + /* XXX */ + return 0; + } + + return 0; +} + +float +Playlist::video_frame_rate () const +{ + switch (_video_from) { + case VIDEO_NONE: + return 0; + case VIDEO_FFMPEG: + return _ffmpeg->video_frame_rate (); + case VIDEO_IMAGEMAGICK: + return 24; + } + + return 0; +} + +libdcp::Size +Playlist::video_size () const +{ + switch (_video_from) { + case VIDEO_NONE: + return libdcp::Size (); + case VIDEO_FFMPEG: + return _ffmpeg->video_size (); + case VIDEO_IMAGEMAGICK: + /* XXX */ + return _imagemagick.front()->video_size (); + } + + return libdcp::Size (); +} + +bool +Playlist::has_audio () const +{ + return _audio_from != AUDIO_NONE; +} + +void +Playlist::disable_video () +{ + _video_from = VIDEO_NONE; +} + +bool +Playlist::pass () +{ + bool done = true; + + if (_video_from == VIDEO_FFMPEG || _audio_from == AUDIO_FFMPEG) { + if (!_ffmpeg_decoder_done) { + if (_ffmpeg_decoder->pass ()) { + _ffmpeg_decoder_done = true; + } else { + done = false; + } + } + } + + if (_video_from == VIDEO_IMAGEMAGICK) { + if (_imagemagick_decoder != _imagemagick_decoders.end ()) { + if ((*_imagemagick_decoder)->pass ()) { + _imagemagick_decoder++; + } + + if (_imagemagick_decoder != _imagemagick_decoders.end ()) { + done = false; + } + } + } + + /* XXX: sndfile */ + + return done; +} + +void +Playlist::set_progress (shared_ptr job) +{ + /* XXX */ +} + +void +Playlist::process_video (shared_ptr i, bool same, shared_ptr s) +{ + Video (i, same, s); +} + +void +Playlist::process_audio (shared_ptr b) +{ + Audio (b); +} + diff --git a/src/lib/playlist.h b/src/lib/playlist.h index 4add76344..b42d46036 100644 --- a/src/lib/playlist.h +++ b/src/lib/playlist.h @@ -17,14 +17,66 @@ */ +#include #include +#include #include "video_source.h" +#include "audio_source.h" #include "video_sink.h" +#include "audio_sink.h" class Content; +class FFmpegContent; +class FFmpegDecoder; +class ImageMagickContent; +class ImageMagickDecoder; +class SndfileContent; +class SndfileDecoder; +class Job; +class Film; -class Playlist : public VideoSource, public AudioSource +class Playlist : public VideoSource, public AudioSource, public VideoSink, public AudioSink, public boost::enable_shared_from_this { public: - Playlist (std::list >); + Playlist (boost::shared_ptr, std::list >); + + ContentAudioFrame audio_length () const; + int audio_channels () const; + int audio_frame_rate () const; + int64_t audio_channel_layout () const; + bool has_audio () const; + + float video_frame_rate () const; + libdcp::Size video_size () const; + + void disable_video (); + + bool pass (); + void set_progress (boost::shared_ptr); + +private: + void process_video (boost::shared_ptr i, bool same, boost::shared_ptr s); + void process_audio (boost::shared_ptr); + + enum { + VIDEO_NONE, + VIDEO_FFMPEG, + VIDEO_IMAGEMAGICK + } _video_from; + + enum { + AUDIO_NONE, + AUDIO_FFMPEG, + AUDIO_SNDFILE + } _audio_from; + + boost::shared_ptr _ffmpeg; + std::list > _imagemagick; + std::list > _sndfile; + + boost::shared_ptr _ffmpeg_decoder; + bool _ffmpeg_decoder_done; + std::list > _imagemagick_decoders; + std::list >::iterator _imagemagick_decoder; + std::list > _sndfile_decoders; }; diff --git a/src/lib/scp_dcp_job.h b/src/lib/scp_dcp_job.h index 08d8e2c78..8c16d53fb 100644 --- a/src/lib/scp_dcp_job.h +++ b/src/lib/scp_dcp_job.h @@ -34,7 +34,7 @@ public: private: void set_status (std::string); - + mutable boost::mutex _status_mutex; std::string _status; }; diff --git a/src/lib/sndfile_content.cc b/src/lib/sndfile_content.cc new file mode 100644 index 000000000..8f5b28901 --- /dev/null +++ b/src/lib/sndfile_content.cc @@ -0,0 +1,41 @@ +#include "sndfile_content.h" +#include "compose.hpp" + +#include "i18n.h" + +using namespace std; + +string +SndfileContent::summary () const +{ + return String::compose (_("Sound file: %1"), file().filename ()); +} + +int +SndfileContent::audio_channels () const +{ + /* XXX */ + return 0; +} + +ContentAudioFrame +SndfileContent::audio_length () const +{ + /* XXX */ + return 0; +} + +int +SndfileContent::audio_frame_rate () const +{ + /* XXX */ + return 0; +} + +int64_t +SndfileContent::audio_channel_layout () const +{ + /* XXX */ + return 0; +} + diff --git a/src/lib/sndfile_content.h b/src/lib/sndfile_content.h index 382e55c40..e84617ed3 100644 --- a/src/lib/sndfile_content.h +++ b/src/lib/sndfile_content.h @@ -3,5 +3,11 @@ class SndfileContent : public AudioContent { public: + std::string summary () const; + /* AudioDecoder */ + int audio_channels () const; + ContentAudioFrame audio_length () const; + int audio_frame_rate () const; + int64_t audio_channel_layout () const; }; diff --git a/src/lib/sndfile_decoder.cc b/src/lib/sndfile_decoder.cc index 0e3e5e234..8848ff4f8 100644 --- a/src/lib/sndfile_decoder.cc +++ b/src/lib/sndfile_decoder.cc @@ -19,6 +19,7 @@ #include #include +#include "sndfile_content.h" #include "sndfile_decoder.h" #include "film.h" #include "exceptions.h" @@ -33,156 +34,53 @@ using std::cout; using boost::shared_ptr; using boost::optional; -SndfileDecoder::SndfileDecoder (shared_ptr f, DecodeOptions o) +/* XXX */ + +SndfileDecoder::SndfileDecoder (shared_ptr f, shared_ptr c, DecodeOptions o) : Decoder (f, o) - , AudioDecoder (f, o) + , AudioDecoder (f, c, o) { sf_count_t frames; - vector sf = open_files (frames); - close_files (sf); + SNDFILE* sf = open_file (frames); + sf_close (sf); } -vector -SndfileDecoder::open_files (sf_count_t & frames) +SNDFILE* +SndfileDecoder::open_file (sf_count_t & frames) { - vector const files = _film->external_audio (); - - int N = 0; - for (size_t i = 0; i < files.size(); ++i) { - if (!files[i].empty()) { - N = i + 1; - } - } - - if (N == 0) { - return vector (); - } - - bool first = true; frames = 0; - vector sndfiles; - for (size_t i = 0; i < (size_t) N; ++i) { - if (files[i].empty ()) { - sndfiles.push_back (0); - } else { - SF_INFO info; - SNDFILE* s = sf_open (files[i].c_str(), SFM_READ, &info); - if (!s) { - throw DecodeError (_("could not open external audio file for reading")); - } - - if (info.channels != 1) { - throw DecodeError (_("external audio files must be mono")); - } - - sndfiles.push_back (s); - - if (first) { - shared_ptr st ( - new SndfileStream ( - info.samplerate, av_get_default_channel_layout (N) - ) - ); - - _audio_streams.push_back (st); - _audio_stream = st; - frames = info.frames; - first = false; - } else { - if (info.frames != frames) { - throw DecodeError (_("external audio files have differing lengths")); - } - } - } + SF_INFO info; + SNDFILE* s = sf_open (_sndfile_content->file().string().c_str(), SFM_READ, &info); + if (!s) { + throw DecodeError (_("could not open external audio file for reading")); } - return sndfiles; + frames = info.frames; + return s; } bool SndfileDecoder::pass () { sf_count_t frames; - vector sndfiles = open_files (frames); - if (sndfiles.empty()) { - return true; - } + SNDFILE* sndfile = open_file (frames); /* Do things in half second blocks as I think there may be limits to what FFmpeg (and in particular the resampler) can cope with. */ - sf_count_t const block = _audio_stream->sample_rate() / 2; + sf_count_t const block = _sndfile_content->audio_frame_rate() / 2; - shared_ptr audio (new AudioBuffers (_audio_stream->channels(), block)); + shared_ptr audio (new AudioBuffers (_sndfile_content->audio_channels(), block)); while (frames > 0) { sf_count_t const this_time = min (block, frames); - for (size_t i = 0; i < sndfiles.size(); ++i) { - if (!sndfiles[i]) { - audio->make_silent (i); - } else { - sf_read_float (sndfiles[i], audio->data(i), block); - } - } - + sf_read_float (sndfile, audio->data(0), this_time); audio->set_frames (this_time); Audio (audio); frames -= this_time; } - close_files (sndfiles); + sf_close (sndfile); return true; } - -void -SndfileDecoder::close_files (vector const & sndfiles) -{ - for (size_t i = 0; i < sndfiles.size(); ++i) { - sf_close (sndfiles[i]); - } -} - -shared_ptr -SndfileStream::create () -{ - return shared_ptr (new SndfileStream); -} - -shared_ptr -SndfileStream::create (string t, optional v) -{ - if (!v) { - /* version < 1; no type in the string, and there's only FFmpeg streams anyway */ - return shared_ptr (); - } - - stringstream s (t); - string type; - s >> type; - if (type != N_("external")) { - return shared_ptr (); - } - - return shared_ptr (new SndfileStream (t, v)); -} - -SndfileStream::SndfileStream (string t, optional v) -{ - assert (v); - - stringstream s (t); - string type; - s >> type >> _sample_rate >> _channel_layout; -} - -SndfileStream::SndfileStream () -{ - -} - -string -SndfileStream::to_string () const -{ - return String::compose (N_("external %1 %2"), _sample_rate, _channel_layout); -} diff --git a/src/lib/sndfile_decoder.h b/src/lib/sndfile_decoder.h index e16eab673..c06b97a60 100644 --- a/src/lib/sndfile_decoder.h +++ b/src/lib/sndfile_decoder.h @@ -20,35 +20,19 @@ #include #include "decoder.h" #include "audio_decoder.h" -#include "stream.h" -class SndfileStream : public AudioStream -{ -public: - SndfileStream (int sample_rate, int64_t layout) - : AudioStream (sample_rate, layout) - {} - - std::string to_string () const; - - static boost::shared_ptr create (); - static boost::shared_ptr create (std::string t, boost::optional v); - -private: - friend class stream_test; - - SndfileStream (); - SndfileStream (std::string t, boost::optional v); -}; +class SndfileContent; class SndfileDecoder : public AudioDecoder { public: - SndfileDecoder (boost::shared_ptr, DecodeOptions); + SndfileDecoder (boost::shared_ptr, boost::shared_ptr, DecodeOptions); bool pass (); private: - std::vector open_files (sf_count_t &); - void close_files (std::vector const &); + SNDFILE* open_file (sf_count_t &); + void close_file (SNDFILE*); + + boost::shared_ptr _sndfile_content; }; diff --git a/src/lib/stream.cc b/src/lib/stream.cc deleted file mode 100644 index bfe7b5eb4..000000000 --- a/src/lib/stream.cc +++ /dev/null @@ -1,92 +0,0 @@ -/* - Copyright (C) 2012 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include "compose.hpp" -#include "stream.h" -#include "ffmpeg_decoder.h" -#include "sndfile_decoder.h" - -#include "i18n.h" - -using std::string; -using std::stringstream; -using boost::shared_ptr; -using boost::optional; - -/** Construct a SubtitleStream from a value returned from to_string(). - * @param t String returned from to_string(). - * @param v State file version. - */ -SubtitleStream::SubtitleStream (string t, boost::optional) -{ - stringstream n (t); - n >> _id; - - size_t const s = t.find (' '); - if (s != string::npos) { - _name = t.substr (s + 1); - } -} - -/** @return A canonical string representation of this stream */ -string -SubtitleStream::to_string () const -{ - return String::compose (N_("%1 %2"), _id, _name); -} - -/** Create a SubtitleStream from a value returned from to_string(). - * @param t String returned from to_string(). - * @param v State file version. - */ -shared_ptr -SubtitleStream::create (string t, optional v) -{ - return shared_ptr (new SubtitleStream (t, v)); -} - -/** Create an AudioStream from a string returned from to_string(). - * @param t String returned from to_string(). - * @param v State file version. - * @return AudioStream, or 0. - */ -shared_ptr -audio_stream_factory (string t, optional v) -{ - shared_ptr s; - - s = FFmpegAudioStream::create (t, v); - if (!s) { - s = SndfileStream::create (t, v); - } - - return s; -} - -/** Create a SubtitleStream from a string returned from to_string(). - * @param t String returned from to_string(). - * @param v State file version. - * @return SubtitleStream, or 0. - */ -shared_ptr -subtitle_stream_factory (string t, optional v) -{ - return SubtitleStream::create (t, v); -} diff --git a/src/lib/stream.h b/src/lib/stream.h deleted file mode 100644 index 16b06e4bc..000000000 --- a/src/lib/stream.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - Copyright (C) 2012 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** @file src/lib/stream.h - * @brief Representations of audio and subtitle streams. - * - * Some content may have multiple `streams' of audio and/or subtitles; perhaps - * for multiple languages, or for stereo / surround mixes. These classes represent - * those streams, and know about their details. - */ - -#ifndef DVDOMATIC_STREAM_H -#define DVDOMATIC_STREAM_H - -#include -#include -#include -extern "C" { -#include -} - -/** @class Stream - * @brief Parent class for streams. - */ -class Stream -{ -public: - virtual ~Stream () {} - virtual std::string to_string () const = 0; -}; - -/** @class AudioStream - * @brief A stream of audio data. - */ -struct AudioStream : public Stream -{ -public: - AudioStream (int r, int64_t l) - : _sample_rate (r) - , _channel_layout (l) - {} - - /* Only used for backwards compatibility for state file version < 1 */ - void set_sample_rate (int s) { - _sample_rate = s; - } - - int channels () const { - return av_get_channel_layout_nb_channels (_channel_layout); - } - - int sample_rate () const { - return _sample_rate; - } - - int64_t channel_layout () const { - return _channel_layout; - } - -protected: - AudioStream () - : _sample_rate (0) - , _channel_layout (0) - {} - - int _sample_rate; - int64_t _channel_layout; -}; - -/** @class SubtitleStream - * @brief A stream of subtitle data. - */ -class SubtitleStream : public Stream -{ -public: - SubtitleStream (std::string n, int i) - : _name (n) - , _id (i) - {} - - std::string to_string () const; - - std::string name () const { - return _name; - } - - int id () const { - return _id; - } - - static boost::shared_ptr create (std::string t, boost::optional v); - -private: - friend class stream_test; - - SubtitleStream (std::string t, boost::optional v); - - std::string _name; - int _id; -}; - -boost::shared_ptr audio_stream_factory (std::string t, boost::optional version); -boost::shared_ptr subtitle_stream_factory (std::string t, boost::optional version); - -#endif diff --git a/src/lib/transcode_job.cc b/src/lib/transcode_job.cc index 234ebe051..f8810975b 100644 --- a/src/lib/transcode_job.cc +++ b/src/lib/transcode_job.cc @@ -62,8 +62,7 @@ TranscodeJob::run () _film->log()->log (N_("Transcode job starting")); _film->log()->log (String::compose (N_("Audio delay is %1ms"), _film->audio_delay())); - _encoder.reset (new Encoder (_film)); - Transcoder w (_film, _decode_opt, this, _encoder); + Transcoder w (_film, _decode_opt, shared_from_this ()); w.go (); set_progress (1); set_state (FINISHED_OK); @@ -83,11 +82,13 @@ TranscodeJob::run () string TranscodeJob::status () const { - if (!_encoder) { - return _("0%"); - } +// if (!_encoder) { +// return _("0%"); +// } - float const fps = _encoder->current_frames_per_second (); + /* XXX */ +// float const fps = _encoder->current_frames_per_second (); + float const fps = 0; if (fps == 0) { return Job::status (); } @@ -106,12 +107,15 @@ TranscodeJob::status () const int TranscodeJob::remaining_time () const { + return 0; +#if 0 + XXX float fps = _encoder->current_frames_per_second (); if (fps == 0) { return 0; } - if (!_film->length()) { + if (!_video->length()) { return 0; } @@ -126,4 +130,5 @@ TranscodeJob::remaining_time () const /* We assume that dcp_length() is valid, if it is set */ int const left = length - _encoder->video_frames_out(); return left / fps; +#endif } diff --git a/src/lib/transcode_job.h b/src/lib/transcode_job.h index 9b69e4e65..a409ec97e 100644 --- a/src/lib/transcode_job.h +++ b/src/lib/transcode_job.h @@ -44,5 +44,4 @@ protected: private: DecodeOptions _decode_opt; - boost::shared_ptr _encoder; }; diff --git a/src/lib/transcoder.cc b/src/lib/transcoder.cc index e0f3a03a2..19d067149 100644 --- a/src/lib/transcoder.cc +++ b/src/lib/transcoder.cc @@ -36,6 +36,7 @@ #include "gain.h" #include "video_decoder.h" #include "audio_decoder.h" +#include "playlist.h" using std::string; using boost::shared_ptr; @@ -47,68 +48,42 @@ using boost::dynamic_pointer_cast; * @param j Job that we are running under, or 0. * @param e Encoder to use. */ -Transcoder::Transcoder (shared_ptr f, DecodeOptions o, Job* j, shared_ptr e) +Transcoder::Transcoder (shared_ptr f, DecodeOptions o, shared_ptr j) : _job (j) - , _encoder (e) - , _decoders (decoder_factory (f, o)) + , _playlist (f->playlist ()) + , _encoder (new Encoder (f, _playlist)) { - assert (_encoder); - - if (f->audio_stream()) { - shared_ptr st = f->audio_stream(); - _matcher.reset (new Matcher (f->log(), st->sample_rate(), f->source_frame_rate())); - _delay_line.reset (new DelayLine (f->log(), st->channels(), f->audio_delay() * st->sample_rate() / 1000)); + if (_playlist->has_audio ()) { + _matcher.reset (new Matcher (f->log(), _playlist->audio_frame_rate(), _playlist->video_frame_rate())); + _delay_line.reset (new DelayLine (f->log(), _playlist->audio_channels(), f->audio_delay() * _playlist->audio_frame_rate() / 1000)); _gain.reset (new Gain (f->log(), f->audio_gain())); } - /* Set up the decoder to use the film's set streams */ - _decoders.video->set_subtitle_stream (f->subtitle_stream ()); - if (_decoders.audio) { - _decoders.audio->set_audio_stream (f->audio_stream ()); - } - if (_matcher) { - _decoders.video->connect_video (_matcher); + _playlist->connect_video (_matcher); _matcher->connect_video (_encoder); } else { - _decoders.video->connect_video (_encoder); + _playlist->connect_video (_encoder); } - if (_matcher && _delay_line && _decoders.audio) { - _decoders.audio->connect_audio (_delay_line); + if (_matcher && _delay_line && _playlist->has_audio ()) { + _playlist->connect_audio (_delay_line); _delay_line->connect_audio (_matcher); _matcher->connect_audio (_gain); _gain->connect_audio (_encoder); } } -/** Run the decoder, passing its output to the encoder, until the decoder - * has no more data to present. - */ void Transcoder::go () { _encoder->process_begin (); try { - bool done[2] = { false, false }; - while (1) { - if (!done[0]) { - done[0] = _decoders.video->pass (); - if (_job) { - _decoders.video->set_progress (_job); - } - } - - if (!done[1] && _decoders.audio && dynamic_pointer_cast (_decoders.audio) != dynamic_pointer_cast (_decoders.video)) { - done[1] = _decoders.audio->pass (); - } else { - done[1] = true; - } - - if (done[0] && done[1]) { + if (_playlist->pass ()) { break; } + _playlist->set_progress (_job); } } catch (...) { diff --git a/src/lib/transcoder.h b/src/lib/transcoder.h index b0c263d07..8d34af948 100644 --- a/src/lib/transcoder.h +++ b/src/lib/transcoder.h @@ -32,9 +32,8 @@ class Encoder; class Matcher; class VideoFilter; class Gain; -class VideoDecoder; -class AudioDecoder; class DelayLine; +class Playlist; /** @class Transcoder * @brief A class which takes a Film and some Options, then uses those to transcode the film. @@ -48,23 +47,16 @@ public: Transcoder ( boost::shared_ptr f, DecodeOptions o, - Job* j, - boost::shared_ptr e + boost::shared_ptr j ); void go (); - boost::shared_ptr video_decoder () const { - return _decoders.video; - } - protected: /** A Job that is running this Transcoder, or 0 */ - Job* _job; - /** The encoder that we will use */ + boost::shared_ptr _job; + boost::shared_ptr _playlist; boost::shared_ptr _encoder; - /** The decoders that we will use */ - Decoders _decoders; boost::shared_ptr _matcher; boost::shared_ptr _delay_line; boost::shared_ptr _gain; diff --git a/src/lib/util.cc b/src/lib/util.cc index 48cb17c26..024740867 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -347,11 +347,11 @@ md5_digest (void const * data, int size) * @return MD5 digest of file's contents. */ string -md5_digest (string file) +md5_digest (boost::filesystem::path file) { - ifstream f (file.c_str(), ios::binary); + ifstream f (file.string().c_str(), ios::binary); if (!f.good ()) { - throw OpenFileError (file); + throw OpenFileError (file.string()); } f.seekg (0, ios::end); diff --git a/src/lib/util.h b/src/lib/util.h index 3d251cf06..87274cfff 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -57,7 +57,7 @@ extern double seconds (struct timeval); extern void dvdomatic_setup (); extern void dvdomatic_setup_i18n (std::string); extern std::vector split_at_spaces_considering_quotes (std::string); -extern std::string md5_digest (std::string); +extern std::string md5_digest (boost::filesystem::path); extern std::string md5_digest (void const *, int); extern void ensure_ui_thread (); extern std::string audio_channel_name (int); @@ -66,6 +66,8 @@ extern boost::filesystem::path mo_path (); #endif typedef int SourceFrame; +typedef int64_t ContentAudioFrame; +typedef int ContentVideoFrame; struct FrameRateConversion { diff --git a/src/lib/video_content.cc b/src/lib/video_content.cc new file mode 100644 index 000000000..9fc5cf1a2 --- /dev/null +++ b/src/lib/video_content.cc @@ -0,0 +1,28 @@ +#include "video_content.h" +#include "video_decoder.h" + +int const VideoContentProperty::VIDEO_LENGTH = 0; +int const VideoContentProperty::VIDEO_SIZE = 1; +int const VideoContentProperty::VIDEO_FRAME_RATE = 2; + +using boost::shared_ptr; + +VideoContent::VideoContent (boost::filesystem::path f) + : Content (f) + , _video_length (0) +{ + +} + +void +VideoContent::take_from_video_decoder (shared_ptr d) +{ + { + boost::mutex::scoped_lock lm (_mutex); + _video_size = d->native_size (); + _video_frame_rate = d->frames_per_second (); + } + + Changed (VideoContentProperty::VIDEO_SIZE); + Changed (VideoContentProperty::VIDEO_FRAME_RATE); +} diff --git a/src/lib/video_content.h b/src/lib/video_content.h index ee4a64fc4..219130668 100644 --- a/src/lib/video_content.h +++ b/src/lib/video_content.h @@ -1,8 +1,47 @@ +#ifndef DVDOMATIC_VIDEO_CONTENT_H +#define DVDOMATIC_VIDEO_CONTENT_H + #include "content.h" +#include "util.h" + +class VideoDecoder; + +class VideoContentProperty +{ +public: + static int const VIDEO_LENGTH; + static int const VIDEO_SIZE; + static int const VIDEO_FRAME_RATE; +}; class VideoContent : public virtual Content { public: + VideoContent (boost::filesystem::path); + + ContentVideoFrame video_length () const { + boost::mutex::scoped_lock lm (_mutex); + return _video_length; + } + + libdcp::Size video_size () const { + boost::mutex::scoped_lock lm (_mutex); + return _video_size; + } + float video_frame_rate () const { + boost::mutex::scoped_lock lm (_mutex); + return _video_frame_rate; + } + +protected: + void take_from_video_decoder (boost::shared_ptr); + ContentVideoFrame _video_length; + +private: + libdcp::Size _video_size; + float _video_frame_rate; }; + +#endif diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc index 891720f6b..ca1e7ab56 100644 --- a/src/lib/video_decoder.cc +++ b/src/lib/video_decoder.cc @@ -30,7 +30,7 @@ using boost::shared_ptr; using boost::optional; -VideoDecoder::VideoDecoder (shared_ptr f, DecodeOptions o) +VideoDecoder::VideoDecoder (shared_ptr f, shared_ptr c, DecodeOptions o) : Decoder (f, o) , _video_frame (0) , _last_source_time (0) @@ -102,21 +102,15 @@ VideoDecoder::emit_subtitle (shared_ptr s) } } -/** Set which stream of subtitles we should use from our source. - * @param s Stream to use. - */ -void -VideoDecoder::set_subtitle_stream (shared_ptr s) -{ - _subtitle_stream = s; -} - void VideoDecoder::set_progress (Job* j) const { assert (j); - + +#if 0 + XXX if (_film->length()) { j->set_progress (float (_video_frame) / _film->length().get()); } +#endif } diff --git a/src/lib/video_decoder.h b/src/lib/video_decoder.h index 283ab5d88..a52e5448a 100644 --- a/src/lib/video_decoder.h +++ b/src/lib/video_decoder.h @@ -21,42 +21,33 @@ #define DVDOMATIC_VIDEO_DECODER_H #include "video_source.h" -#include "stream.h" #include "decoder.h" +class VideoContent; + class VideoDecoder : public VideoSource, public virtual Decoder { public: - VideoDecoder (boost::shared_ptr, DecodeOptions); + VideoDecoder (boost::shared_ptr, boost::shared_ptr, DecodeOptions); /** @return video frames per second, or 0 if unknown */ virtual float frames_per_second () const = 0; /** @return native size in pixels */ virtual libdcp::Size native_size () const = 0; - /** @return length (in source video frames), according to our content's header */ - virtual SourceFrame length () const = 0; + /** @return length according to our content's header */ + virtual ContentVideoFrame video_length () const = 0; virtual int time_base_numerator () const = 0; virtual int time_base_denominator () const = 0; virtual int sample_aspect_ratio_numerator () const = 0; virtual int sample_aspect_ratio_denominator () const = 0; - virtual void set_subtitle_stream (boost::shared_ptr); - void set_progress (Job *) const; int video_frame () const { return _video_frame; } - boost::shared_ptr subtitle_stream () const { - return _subtitle_stream; - } - - std::vector > subtitle_streams () const { - return _subtitle_streams; - } - double last_source_time () const { return _last_source_time; } @@ -69,11 +60,6 @@ protected: void emit_subtitle (boost::shared_ptr); void repeat_last_video (); - /** Subtitle stream to use when decoding */ - boost::shared_ptr _subtitle_stream; - /** Subtitle streams that this decoder's content has */ - std::vector > _subtitle_streams; - private: void signal_video (boost::shared_ptr, bool, boost::shared_ptr); diff --git a/src/lib/writer.cc b/src/lib/writer.cc index 2d7ee9ba3..5f5dae98f 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -28,6 +28,7 @@ #include "format.h" #include "log.h" #include "dcp_video_frame.h" +#include "playlist.h" #include "i18n.h" @@ -41,8 +42,9 @@ using boost::shared_ptr; int const Writer::_maximum_frames_in_memory = 8; -Writer::Writer (shared_ptr f) +Writer::Writer (shared_ptr f, shared_ptr p) : _film (f) + , _playlist (p) , _first_nonexistant_frame (0) , _thread (0) , _finish (false) @@ -74,7 +76,7 @@ Writer::Writer (shared_ptr f) _picture_asset_writer = _picture_asset->start_write (_first_nonexistant_frame > 0); - AudioMapping m (_film->audio_channels ()); + AudioMapping m (_playlist->audio_channels ()); if (m.dcp_channels() > 0) { _sound_asset.reset ( @@ -83,7 +85,7 @@ Writer::Writer (shared_ptr f) N_("audio.mxf"), _film->dcp_frame_rate (), m.dcp_channels (), - dcp_audio_sample_rate (_film->audio_stream()->sample_rate()) + dcp_audio_sample_rate (_playlist->audio_frame_rate()) ) ); diff --git a/src/lib/writer.h b/src/lib/writer.h index beb16c7b9..920f592b6 100644 --- a/src/lib/writer.h +++ b/src/lib/writer.h @@ -26,6 +26,7 @@ class Film; class EncodedData; class AudioBuffers; +class Playlist; namespace libdcp { class MonoPictureAsset; @@ -63,7 +64,7 @@ bool operator== (QueueItem const & a, QueueItem const & b); class Writer : public ExceptionStore { public: - Writer (boost::shared_ptr); + Writer (boost::shared_ptr, boost::shared_ptr); bool can_fake_write (int) const; @@ -80,6 +81,7 @@ private: /** our Film */ boost::shared_ptr _film; + boost::shared_ptr _playlist; /** the first frame index that does not already exist in our MXF */ int _first_nonexistant_frame; diff --git a/src/lib/wscript b/src/lib/wscript index 5d9f5626a..5510d48a8 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -6,10 +6,12 @@ sources = """ ab_transcoder.cc analyse_audio_job.cc audio_analysis.cc + audio_content.cc audio_decoder.cc audio_source.cc config.cc combiner.cc + content.cc cross.cc dci_metadata.cc dcp_content_type.cc @@ -23,24 +25,27 @@ sources = """ exceptions.cc filter_graph.cc ffmpeg_compatibility.cc + ffmpeg_content.cc ffmpeg_decoder.cc film.cc filter.cc format.cc gain.cc image.cc + imagemagick_content.cc imagemagick_decoder.cc job.cc job_manager.cc log.cc lut.cc matcher.cc + playlist.cc scp_dcp_job.cc scaler.cc server.cc + sndfile_content.cc sndfile_decoder.cc sound_processor.cc - stream.cc subtitle.cc timer.cc transcode_job.cc @@ -48,6 +53,7 @@ sources = """ ui_signaller.cc util.cc version.cc + video_content.cc video_decoder.cc video_source.cc writer.cc diff --git a/src/tools/dvdomatic.cc b/src/tools/dvdomatic.cc index 87c079bee..a78d03794 100644 --- a/src/tools/dvdomatic.cc +++ b/src/tools/dvdomatic.cc @@ -236,9 +236,6 @@ public: set_menu_sensitivity (); - /* XXX: calling these here is a bit of a hack */ - film_editor->setup_visibility (); - film_editor->FileChanged.connect (bind (&Frame::file_changed, this, _1)); if (film) { file_changed (film->directory ()); diff --git a/src/tools/makedcp.cc b/src/tools/makedcp.cc index 0c6390771..226cde113 100644 --- a/src/tools/makedcp.cc +++ b/src/tools/makedcp.cc @@ -151,7 +151,7 @@ main (int argc, char* argv[]) } cout << "DCP for " << film->name() << "\n"; cout << "Test mode: " << (test_mode ? "yes" : "no") << "\n"; - cout << "Content: " << film->content() << "\n"; +// cout << "Content: " << film->content() << "\n"; pair const f = Filter::ffmpeg_strings (film->filters ()); cout << "Filters: " << f.first << " " << f.second << "\n"; diff --git a/src/wx/audio_dialog.cc b/src/wx/audio_dialog.cc index 3d17988b6..b7384fd14 100644 --- a/src/wx/audio_dialog.cc +++ b/src/wx/audio_dialog.cc @@ -18,10 +18,11 @@ */ #include +#include "lib/audio_analysis.h" +#include "lib/film.h" +#include "lib/playlist.h" #include "audio_dialog.h" #include "audio_plot.h" -#include "audio_analysis.h" -#include "film.h" #include "wx_util.h" using boost::shared_ptr; @@ -90,6 +91,7 @@ AudioDialog::set_film (boost::shared_ptr f) _film_audio_analysis_succeeded_connection.disconnect (); _film = f; + _playlist = _film->playlist (); try_to_load_analysis (); setup_channels (); @@ -104,11 +106,11 @@ AudioDialog::set_film (boost::shared_ptr f) void AudioDialog::setup_channels () { - if (!_film->audio_stream()) { + if (!_playlist->has_audio()) { return; } - AudioMapping m (_film->audio_stream()->channels ()); + AudioMapping m (_playlist->audio_channels ()); for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) { if (m.dcp_to_source(static_cast(i))) { @@ -134,7 +136,7 @@ AudioDialog::try_to_load_analysis () _plot->set_analysis (a); - AudioMapping m (_film->audio_stream()->channels ()); + AudioMapping m (_playlist->audio_channels ()); optional c = m.source_to_dcp (0); if (c) { _channel_checkbox[c.get()]->SetValue (true); @@ -157,7 +159,7 @@ AudioDialog::channel_clicked (wxCommandEvent& ev) assert (c < MAX_AUDIO_CHANNELS); - AudioMapping m (_film->audio_stream()->channels ()); + AudioMapping m (_playlist->audio_channels ()); optional s = m.dcp_to_source (static_cast (c)); if (s) { _plot->set_channel_visible (s.get(), _channel_checkbox[c]->GetValue ()); @@ -171,9 +173,8 @@ AudioDialog::film_changed (Film::Property p) case Film::AUDIO_GAIN: _plot->set_gain (_film->audio_gain ()); break; - case Film::CONTENT_AUDIO_STREAM: - case Film::EXTERNAL_AUDIO: - case Film::USE_CONTENT_AUDIO: + case Film::CONTENT: + _playlist = _film->playlist (); setup_channels (); break; default: diff --git a/src/wx/audio_dialog.h b/src/wx/audio_dialog.h index 514faeea0..3cb9c1726 100644 --- a/src/wx/audio_dialog.h +++ b/src/wx/audio_dialog.h @@ -25,6 +25,7 @@ class AudioPlot; class Film; +class Playlist; class AudioDialog : public wxDialog { @@ -42,6 +43,7 @@ private: void setup_channels (); boost::shared_ptr _film; + boost::shared_ptr _playlist; AudioPlot* _plot; wxCheckBox* _channel_checkbox[MAX_AUDIO_CHANNELS]; wxCheckBox* _type_checkbox[AudioPoint::COUNT]; diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index c1d679665..7dfbf6c50 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -65,12 +66,13 @@ FilmEditor::FilmEditor (shared_ptr f, wxWindow* parent) , _audio_dialog (0) { wxBoxSizer* s = new wxBoxSizer (wxVERTICAL); - SetSizer (s); _notebook = new wxNotebook (this, wxID_ANY); s->Add (_notebook, 1); make_film_panel (); _notebook->AddPage (_film_panel, _("Film"), true); + make_content_panel (); + _notebook->AddPage (_content_panel, _("Content"), false); make_video_panel (); _notebook->AddPage (_video_panel, _("Video"), false); make_audio_panel (); @@ -85,8 +87,9 @@ FilmEditor::FilmEditor (shared_ptr f, wxWindow* parent) bind (&FilmEditor::active_jobs_changed, this, _1) ); - setup_visibility (); setup_formats (); + + SetSizerAndFit (s); } void @@ -117,13 +120,7 @@ FilmEditor::make_film_panel () grid->Add (_edit_dci_button, wxGBPosition (r, 1), wxDefaultSpan); ++r; - add_label_to_grid_bag_sizer (grid, _film_panel, _("Content"), wxGBPosition (r, 0)); - _content = new wxFilePickerCtrl (_film_panel, wxID_ANY, wxT (""), _("Select Content File"), wxT("*.*")); - grid->Add (_content, wxGBPosition (r, 1), wxDefaultSpan, wxEXPAND); - ++r; - _trust_content_header = new wxCheckBox (_film_panel, wxID_ANY, _("Trust content's header")); - video_control (_trust_content_header); grid->Add (_trust_content_header, wxGBPosition (r, 0), wxGBSpan(1, 2)); ++r; @@ -132,9 +129,9 @@ FilmEditor::make_film_panel () grid->Add (_dcp_content_type, wxGBPosition (r, 1)); ++r; - video_control (add_label_to_grid_bag_sizer (grid, _film_panel, _("Original Frame Rate"), wxGBPosition (r, 0))); + add_label_to_grid_bag_sizer (grid, _film_panel, _("Original Frame Rate"), wxGBPosition (r, 0)); _source_frame_rate = new wxStaticText (_film_panel, wxID_ANY, wxT ("")); - grid->Add (video_control (_source_frame_rate), wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL); + grid->Add (_source_frame_rate, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL); ++r; { @@ -149,56 +146,42 @@ FilmEditor::make_film_panel () ++r; _frame_rate_description = new wxStaticText (_film_panel, wxID_ANY, wxT (" \n "), wxDefaultPosition, wxDefaultSize); - grid->Add (video_control (_frame_rate_description), wxGBPosition (r, 0), wxGBSpan (1, 2), wxEXPAND | wxALIGN_CENTER_VERTICAL | wxALL, 6); + grid->Add (_frame_rate_description, wxGBPosition (r, 0), wxGBSpan (1, 2), wxEXPAND | wxALIGN_CENTER_VERTICAL | wxALL, 6); wxFont font = _frame_rate_description->GetFont(); font.SetStyle(wxFONTSTYLE_ITALIC); font.SetPointSize(font.GetPointSize() - 1); _frame_rate_description->SetFont(font); ++r; - video_control (add_label_to_grid_bag_sizer (grid, _film_panel, _("Original Size"), wxGBPosition (r, 0))); + add_label_to_grid_bag_sizer (grid, _film_panel, _("Original Size"), wxGBPosition (r, 0)); _original_size = new wxStaticText (_film_panel, wxID_ANY, wxT ("")); - grid->Add (video_control (_original_size), wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL); + grid->Add (_original_size, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL); ++r; - video_control (add_label_to_grid_bag_sizer (grid, _film_panel, _("Length"), wxGBPosition (r, 0))); + add_label_to_grid_bag_sizer (grid, _film_panel, _("Length"), wxGBPosition (r, 0)); _length = new wxStaticText (_film_panel, wxID_ANY, wxT ("")); - grid->Add (video_control (_length), wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL); + grid->Add (_length, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL); ++r; { - video_control (add_label_to_grid_bag_sizer (grid, _film_panel, _("Trim frames"), wxGBPosition (r, 0))); + add_label_to_grid_bag_sizer (grid, _film_panel, _("Trim frames"), wxGBPosition (r, 0)); wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); - video_control (add_label_to_sizer (s, _film_panel, _("Start"))); + add_label_to_sizer (s, _film_panel, _("Start")); _trim_start = new wxSpinCtrl (_film_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)); - s->Add (video_control (_trim_start)); - video_control (add_label_to_sizer (s, _film_panel, _("End"))); + s->Add (_trim_start); + add_label_to_sizer (s, _film_panel, _("End")); _trim_end = new wxSpinCtrl (_film_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (64, -1)); - s->Add (video_control (_trim_end)); + s->Add (_trim_end); grid->Add (s, wxGBPosition (r, 1)); } ++r; _dcp_ab = new wxCheckBox (_film_panel, wxID_ANY, _("A/B")); - video_control (_dcp_ab); grid->Add (_dcp_ab, wxGBPosition (r, 0)); ++r; - /* STILL-only stuff */ - { - still_control (add_label_to_grid_bag_sizer (grid, _film_panel, _("Duration"), wxGBPosition (r, 0))); - wxSizer* s = new wxBoxSizer (wxHORIZONTAL); - _still_duration = new wxSpinCtrl (_film_panel); - still_control (_still_duration); - s->Add (_still_duration, 1, wxEXPAND); - /// TRANSLATORS: `s' here is an abbreviation for seconds, the unit of time - still_control (add_label_to_sizer (s, _film_panel, _("s"))); - grid->Add (s, wxGBPosition (r, 1)); - } - ++r; - vector const ct = DCPContentType::all (); for (vector::const_iterator i = ct.begin(); i != ct.end(); ++i) { _dcp_content_type->Append (std_to_wx ((*i)->pretty_name ())); @@ -217,7 +200,6 @@ FilmEditor::connect_to_widgets () _use_dci_name->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::use_dci_name_toggled), 0, this); _edit_dci_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_dci_button_clicked), 0, this); _format->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::format_changed), 0, this); - _content->Connect (wxID_ANY, wxEVT_COMMAND_FILEPICKER_CHANGED, wxCommandEventHandler (FilmEditor::content_changed), 0, this); _trust_content_header->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::trust_content_header_changed), 0, this); _left_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::left_crop_changed), 0, this); _right_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::right_crop_changed), 0, this); @@ -229,7 +211,6 @@ FilmEditor::connect_to_widgets () _dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_frame_rate_changed), 0, this); _best_dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::best_dcp_frame_rate_clicked), 0, this); _dcp_ab->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::dcp_ab_toggled), 0, this); - _still_duration->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::still_duration_changed), 0, this); _trim_start->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_start_changed), 0, this); _trim_end->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_end_changed), 0, this); _with_subtitles->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::with_subtitles_toggled), 0, this); @@ -237,21 +218,14 @@ FilmEditor::connect_to_widgets () _subtitle_scale->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_scale_changed), 0, this); _colour_lut->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::colour_lut_changed), 0, this); _j2k_bandwidth->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::j2k_bandwidth_changed), 0, this); - _subtitle_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::subtitle_stream_changed), 0, this); - _audio_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::audio_stream_changed), 0, this); +// _ffmpeg_subtitle_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::ffmpeg_subtitle_stream_changed), 0, this); +// _ffmpeg_audio_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::ffmpeg_audio_stream_changed), 0, this); _audio_gain->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_gain_changed), 0, this); _audio_gain_calculate_button->Connect ( wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::audio_gain_calculate_button_clicked), 0, this ); _show_audio->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::show_audio_clicked), 0, this); _audio_delay->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_delay_changed), 0, this); - _use_content_audio->Connect (wxID_ANY, wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler (FilmEditor::use_audio_changed), 0, this); - _use_external_audio->Connect (wxID_ANY, wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler (FilmEditor::use_audio_changed), 0, this); - for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) { - _external_audio[i]->Connect ( - wxID_ANY, wxEVT_COMMAND_FILEPICKER_CHANGED, wxCommandEventHandler (FilmEditor::external_audio_changed), 0, this - ); - } } void @@ -300,21 +274,19 @@ FilmEditor::make_video_panel () /* VIDEO-only stuff */ { - video_control (add_label_to_grid_bag_sizer (grid, _video_panel, _("Filters"), wxGBPosition (r, 0))); + add_label_to_grid_bag_sizer (grid, _video_panel, _("Filters"), wxGBPosition (r, 0)); wxSizer* s = new wxBoxSizer (wxHORIZONTAL); _filters = new wxStaticText (_video_panel, wxID_ANY, _("None")); - video_control (_filters); s->Add (_filters, 1, wxEXPAND | wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM | wxRIGHT, 6); _filters_button = new wxButton (_video_panel, wxID_ANY, _("Edit...")); - video_control (_filters_button); s->Add (_filters_button, 0); grid->Add (s, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL); } ++r; - video_control (add_label_to_grid_bag_sizer (grid, _video_panel, _("Scaler"), wxGBPosition (r, 0))); + add_label_to_grid_bag_sizer (grid, _video_panel, _("Scaler"), wxGBPosition (r, 0)); _scaler = new wxChoice (_video_panel, wxID_ANY); - grid->Add (video_control (_scaler), wxGBPosition (r, 1)); + grid->Add (_scaler, wxGBPosition (r, 1)); ++r; vector const sc = Scaler::all (); @@ -345,12 +317,48 @@ FilmEditor::make_video_panel () _top_crop->SetRange (0, 1024); _right_crop->SetRange (0, 1024); _bottom_crop->SetRange (0, 1024); - _still_duration->SetRange (1, 60 * 60); _trim_start->SetRange (0, 100); _trim_end->SetRange (0, 100); _j2k_bandwidth->SetRange (50, 250); } +void +FilmEditor::make_content_panel () +{ + _content_panel = new wxPanel (_notebook); + _content_sizer = new wxBoxSizer (wxVERTICAL); + _content_panel->SetSizer (_content_sizer); + + wxGridBagSizer* grid = new wxGridBagSizer (4, 4); + _content_sizer->Add (grid, 0, wxALL, 8); + + int r = 0; + + { + wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); + + _content = new wxListCtrl (_content_panel, wxID_ANY, wxDefaultPosition, wxSize (320, 160), wxLC_REPORT | wxLC_NO_HEADER | wxLC_SINGLE_SEL); + s->Add (_content, 1, wxEXPAND | wxTOP | wxBOTTOM, 6); + + _content->InsertColumn (0, ""); + + wxBoxSizer* b = new wxBoxSizer (wxVERTICAL); + _content_add = new wxButton (_content_panel, wxID_ANY, _("Add...")); + b->Add (_content_add); + _content_remove = new wxButton (_content_panel, wxID_ANY, _("Remove")); + b->Add (_content_remove); + _content_earlier = new wxButton (_content_panel, wxID_ANY, _("Earlier")); + b->Add (_content_earlier); + _content_later = new wxButton (_content_panel, wxID_ANY, _("Later")); + b->Add (_content_later); + + s->Add (b, 0, wxALL, 4); + + grid->Add (s, wxGBPosition (r, 0), wxGBSpan (1, 2), wxEXPAND); + ++r; + } +} + void FilmEditor::make_audio_panel () { @@ -366,48 +374,26 @@ FilmEditor::make_audio_panel () grid->AddSpacer (0); { - video_control (add_label_to_sizer (grid, _audio_panel, _("Audio Gain"))); + add_label_to_sizer (grid, _audio_panel, _("Audio Gain")); wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); _audio_gain = new wxSpinCtrl (_audio_panel); - s->Add (video_control (_audio_gain), 1); - video_control (add_label_to_sizer (s, _audio_panel, _("dB"))); + s->Add (_audio_gain, 1); + add_label_to_sizer (s, _audio_panel, _("dB")); _audio_gain_calculate_button = new wxButton (_audio_panel, wxID_ANY, _("Calculate...")); - video_control (_audio_gain_calculate_button); s->Add (_audio_gain_calculate_button, 1, wxEXPAND); grid->Add (s); } { - video_control (add_label_to_sizer (grid, _audio_panel, _("Audio Delay"))); + add_label_to_sizer (grid, _audio_panel, _("Audio Delay")); wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); _audio_delay = new wxSpinCtrl (_audio_panel); - s->Add (video_control (_audio_delay), 1); + s->Add (_audio_delay, 1); /// TRANSLATORS: this is an abbreviation for milliseconds, the unit of time - video_control (add_label_to_sizer (s, _audio_panel, _("ms"))); + add_label_to_sizer (s, _audio_panel, _("ms")); grid->Add (s); } - { - _use_content_audio = new wxRadioButton (_audio_panel, wxID_ANY, _("Use content's audio"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP); - grid->Add (video_control (_use_content_audio)); - wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); - _audio_stream = new wxChoice (_audio_panel, wxID_ANY); - s->Add (video_control (_audio_stream), 1); - _audio = new wxStaticText (_audio_panel, wxID_ANY, wxT ("")); - s->Add (video_control (_audio), 1, wxALIGN_CENTER_VERTICAL | wxLEFT, 8); - grid->Add (s, 1, wxEXPAND); - } - - _use_external_audio = new wxRadioButton (_audio_panel, wxID_ANY, _("Use external audio")); - grid->Add (_use_external_audio); - grid->AddSpacer (0); - - for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) { - add_label_to_sizer (grid, _audio_panel, std_to_wx (audio_channel_name (i))); - _external_audio[i] = new wxFilePickerCtrl (_audio_panel, wxID_ANY, wxT (""), _("Select Audio File"), wxT ("*.wav")); - grid->Add (_external_audio[i], 1, wxEXPAND); - } - _audio_gain->SetRange (-60, 60); _audio_delay->SetRange (-1000, 1000); } @@ -422,22 +408,21 @@ FilmEditor::make_subtitle_panel () _subtitle_sizer->Add (grid, 0, wxALL, 8); _with_subtitles = new wxCheckBox (_subtitle_panel, wxID_ANY, _("With Subtitles")); - video_control (_with_subtitles); grid->Add (_with_subtitles, 1); - _subtitle_stream = new wxChoice (_subtitle_panel, wxID_ANY); - grid->Add (video_control (_subtitle_stream)); + _ffmpeg_subtitle_stream = new wxChoice (_subtitle_panel, wxID_ANY); + grid->Add (_ffmpeg_subtitle_stream); - video_control (add_label_to_sizer (grid, _subtitle_panel, _("Subtitle Offset"))); + add_label_to_sizer (grid, _subtitle_panel, _("Subtitle Offset")); _subtitle_offset = new wxSpinCtrl (_subtitle_panel); - grid->Add (video_control (_subtitle_offset), 1); + grid->Add (_subtitle_offset, 1); { - video_control (add_label_to_sizer (grid, _subtitle_panel, _("Subtitle Scale"))); + add_label_to_sizer (grid, _subtitle_panel, _("Subtitle Scale")); wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); _subtitle_scale = new wxSpinCtrl (_subtitle_panel); - s->Add (video_control (_subtitle_scale)); - video_control (add_label_to_sizer (s, _subtitle_panel, _("%"))); + s->Add (_subtitle_scale); + add_label_to_sizer (s, _subtitle_panel, _("%")); grid->Add (s); } @@ -489,22 +474,6 @@ FilmEditor::bottom_crop_changed (wxCommandEvent &) _film->set_bottom_crop (_bottom_crop->GetValue ()); } -/** Called when the content filename has been changed */ -void -FilmEditor::content_changed (wxCommandEvent &) -{ - if (!_film) { - return; - } - - try { - _film->set_content (wx_to_std (_content->GetPath ())); - } catch (std::exception& e) { - _content->SetPath (std_to_wx (_film->directory ())); - error_dialog (this, wxString::Format (_("Could not set content: %s"), std_to_wx (e.what()).data())); - } -} - void FilmEditor::trust_content_header_changed (wxCommandEvent &) { @@ -611,8 +580,7 @@ FilmEditor::film_changed (Film::Property p) case Film::NONE: break; case Film::CONTENT: - checked_set (_content, _film->content ()); - setup_visibility (); + setup_content (); setup_formats (); setup_subtitle_control_sensitivity (); setup_streams (); @@ -621,14 +589,14 @@ FilmEditor::film_changed (Film::Property p) case Film::TRUST_CONTENT_HEADER: checked_set (_trust_content_header, _film->trust_content_header ()); break; - case Film::SUBTITLE_STREAMS: - setup_subtitle_control_sensitivity (); - setup_streams (); - break; - case Film::CONTENT_AUDIO_STREAMS: - setup_streams (); - setup_show_audio_sensitivity (); - break; +// case Film::SUBTITLE_STREAMS: +// setup_subtitle_control_sensitivity (); +// setup_streams (); +// break; +// case Film::CONTENT_AUDIO_STREAMS: +// setup_streams (); +// setup_show_audio_sensitivity (); +// break; case Film::FORMAT: { int n = 0; @@ -673,32 +641,32 @@ FilmEditor::film_changed (Film::Property p) checked_set (_name, _film->name()); setup_dcp_name (); break; - case Film::SOURCE_FRAME_RATE: - s << fixed << setprecision(2) << _film->source_frame_rate(); - _source_frame_rate->SetLabel (std_to_wx (s.str ())); - break; - case Film::SIZE: - if (_film->size().width == 0 && _film->size().height == 0) { - _original_size->SetLabel (wxT ("")); - } else { - s << _film->size().width << " x " << _film->size().height; - _original_size->SetLabel (std_to_wx (s.str ())); - } - break; - case Film::LENGTH: - if (_film->source_frame_rate() > 0 && _film->length()) { - s << _film->length().get() << " " - << wx_to_std (_("frames")) << "; " << seconds_to_hms (_film->length().get() / _film->source_frame_rate()); - } else if (_film->length()) { - s << _film->length().get() << " " - << wx_to_std (_("frames")); - } - _length->SetLabel (std_to_wx (s.str ())); - if (_film->length()) { - _trim_start->SetRange (0, _film->length().get()); - _trim_end->SetRange (0, _film->length().get()); - } - break; +// case Film::SOURCE_FRAME_RATE: +// s << fixed << setprecision(2) << _film->source_frame_rate(); +// _source_frame_rate->SetLabel (std_to_wx (s.str ())); +// break; +// case Film::SIZE: +// if (_film->size().width == 0 && _film->size().height == 0) { +// _original_size->SetLabel (wxT ("")); +// } else { +// s << _film->size().width << " x " << _film->size().height; +// _original_size->SetLabel (std_to_wx (s.str ())); +// } +// break; +// case Film::LENGTH: +// if (_film->source_frame_rate() > 0 && _film->length()) { +// s << _film->length().get() << " " +// << wx_to_std (_("frames")) << "; " << seconds_to_hms (_film->length().get() / _film->source_frame_rate()); +// } else if (_film->length()) { +// s << _film->length().get() << " " +// << wx_to_std (_("frames")); +// } +// _length->SetLabel (std_to_wx (s.str ())); +// if (_film->length()) { +// _trim_start->SetRange (0, _film->length().get()); +// _trim_end->SetRange (0, _film->length().get()); +// } +// break; case Film::DCP_CONTENT_TYPE: checked_set (_dcp_content_type, DCPContentType::as_index (_film->dcp_content_type ())); setup_dcp_name (); @@ -721,9 +689,6 @@ FilmEditor::film_changed (Film::Property p) case Film::AUDIO_DELAY: checked_set (_audio_delay, _film->audio_delay ()); break; - case Film::STILL_DURATION: - checked_set (_still_duration, _film->still_duration ()); - break; case Film::WITH_SUBTITLES: checked_set (_with_subtitles, _film->with_subtitles ()); setup_subtitle_control_sensitivity (); @@ -748,55 +713,36 @@ FilmEditor::film_changed (Film::Property p) case Film::DCI_METADATA: setup_dcp_name (); break; - case Film::CONTENT_AUDIO_STREAM: - if (_film->content_audio_stream()) { - checked_set (_audio_stream, _film->content_audio_stream()->to_string()); - } - setup_dcp_name (); - setup_audio_details (); - setup_audio_control_sensitivity (); - setup_show_audio_sensitivity (); - break; - case Film::USE_CONTENT_AUDIO: - checked_set (_use_content_audio, _film->use_content_audio()); - checked_set (_use_external_audio, !_film->use_content_audio()); - setup_dcp_name (); - setup_audio_details (); - setup_audio_control_sensitivity (); - setup_show_audio_sensitivity (); - break; - case Film::SUBTITLE_STREAM: - if (_film->subtitle_stream()) { - checked_set (_subtitle_stream, _film->subtitle_stream()->to_string()); - } - break; - case Film::EXTERNAL_AUDIO: - { - vector a = _film->external_audio (); - for (size_t i = 0; i < a.size() && i < MAX_AUDIO_CHANNELS; ++i) { - checked_set (_external_audio[i], a[i]); - } - setup_audio_details (); - setup_show_audio_sensitivity (); - break; - } - case Film::DCP_FRAME_RATE: - for (unsigned int i = 0; i < _dcp_frame_rate->GetCount(); ++i) { - if (wx_to_std (_dcp_frame_rate->GetString(i)) == boost::lexical_cast (_film->dcp_frame_rate())) { - if (_dcp_frame_rate->GetSelection() != int(i)) { - _dcp_frame_rate->SetSelection (i); - break; - } - } - } - - if (_film->source_frame_rate()) { - _frame_rate_description->SetLabel (std_to_wx (FrameRateConversion (_film->source_frame_rate(), _film->dcp_frame_rate()).description)); - _best_dcp_frame_rate->Enable (best_dcp_frame_rate (_film->source_frame_rate ()) != _film->dcp_frame_rate ()); - } else { - _frame_rate_description->SetLabel (wxT ("")); - _best_dcp_frame_rate->Disable (); - } +// case Film::CONTENT_AUDIO_STREAM: +// if (_film->content_audio_stream()) { +// checked_set (_audio_stream, _film->content_audio_stream()->to_string()); +// } +// setup_dcp_name (); +// setup_audio_details (); +// setup_show_audio_sensitivity (); +// break; +// case Film::SUBTITLE_STREAM: +// if (_film->subtitle_stream()) { +// checked_set (_subtitle_stream, _film->subtitle_stream()->to_string()); +// } +// break; +// case Film::DCP_FRAME_RATE: +// for (unsigned int i = 0; i < _dcp_frame_rate->GetCount(); ++i) { +// if (wx_to_std (_dcp_frame_rate->GetString(i)) == boost::lexical_cast (_film->dcp_frame_rate())) { +// if (_dcp_frame_rate->GetSelection() != int(i)) { +// _dcp_frame_rate->SetSelection (i); +// break; +// } +// } +// } + +// if (_film->source_frame_rate()) { +// _frame_rate_description->SetLabel (std_to_wx (FrameRateConversion (_film->source_frame_rate(), _film->dcp_frame_rate()).description)); +// _best_dcp_frame_rate->Enable (best_dcp_frame_rate (_film->source_frame_rate ()) != _film->dcp_frame_rate ()); +// } else { +// _frame_rate_description->SetLabel (wxT ("")); +// _best_dcp_frame_rate->Disable (); +// } } } @@ -863,23 +809,14 @@ FilmEditor::set_film (shared_ptr f) film_changed (Film::TRIM_START); film_changed (Film::TRIM_END); film_changed (Film::DCP_AB); - film_changed (Film::CONTENT_AUDIO_STREAM); - film_changed (Film::EXTERNAL_AUDIO); - film_changed (Film::USE_CONTENT_AUDIO); film_changed (Film::AUDIO_GAIN); film_changed (Film::AUDIO_DELAY); - film_changed (Film::STILL_DURATION); film_changed (Film::WITH_SUBTITLES); film_changed (Film::SUBTITLE_OFFSET); film_changed (Film::SUBTITLE_SCALE); film_changed (Film::COLOUR_LUT); film_changed (Film::J2K_BANDWIDTH); film_changed (Film::DCI_METADATA); - film_changed (Film::SIZE); - film_changed (Film::LENGTH); - film_changed (Film::CONTENT_AUDIO_STREAMS); - film_changed (Film::SUBTITLE_STREAMS); - film_changed (Film::SOURCE_FRAME_RATE); film_changed (Film::DCP_FRAME_RATE); } @@ -903,7 +840,7 @@ FilmEditor::set_things_sensitive (bool s) _bottom_crop->Enable (s); _filters_button->Enable (s); _scaler->Enable (s); - _audio_stream->Enable (s); +// _ffmpeg_audio_stream->Enable (s); _dcp_content_type->Enable (s); _dcp_frame_rate->Enable (s); _trim_start->Enable (s); @@ -915,10 +852,8 @@ FilmEditor::set_things_sensitive (bool s) _audio_gain_calculate_button->Enable (s); _show_audio->Enable (s); _audio_delay->Enable (s); - _still_duration->Enable (s); setup_subtitle_control_sensitivity (); - setup_audio_control_sensitivity (); setup_show_audio_sensitivity (); } @@ -966,62 +901,6 @@ FilmEditor::audio_delay_changed (wxCommandEvent &) _film->set_audio_delay (_audio_delay->GetValue ()); } -wxControl * -FilmEditor::video_control (wxControl* c) -{ - _video_controls.push_back (c); - return c; -} - -wxControl * -FilmEditor::still_control (wxControl* c) -{ - _still_controls.push_back (c); - return c; -} - -void -FilmEditor::setup_visibility () -{ - ContentType c = VIDEO; - - if (_film) { - c = _film->content_type (); - } - - for (list::iterator i = _video_controls.begin(); i != _video_controls.end(); ++i) { - (*i)->Show (c == VIDEO); - } - - for (list::iterator i = _still_controls.begin(); i != _still_controls.end(); ++i) { - (*i)->Show (c == STILL); - } - - _notebook->InvalidateBestSize (); - - _film_sizer->Layout (); - _film_sizer->SetSizeHints (_film_panel); - _video_sizer->Layout (); - _video_sizer->SetSizeHints (_video_panel); - _audio_sizer->Layout (); - _audio_sizer->SetSizeHints (_audio_panel); - _subtitle_sizer->Layout (); - _subtitle_sizer->SetSizeHints (_subtitle_panel); - - _notebook->Fit (); - Fit (); -} - -void -FilmEditor::still_duration_changed (wxCommandEvent &) -{ - if (!_film) { - return; - } - - _film->set_still_duration (_still_duration->GetValue ()); -} - void FilmEditor::trim_start_changed (wxCommandEvent &) { @@ -1072,20 +951,7 @@ FilmEditor::audio_gain_calculate_button_clicked (wxCommandEvent &) void FilmEditor::setup_formats () { - ContentType c = VIDEO; - - if (_film) { - c = _film->content_type (); - } - - _formats.clear (); - - vector fmt = Format::all (); - for (vector::iterator i = fmt.begin(); i != fmt.end(); ++i) { - if (c == VIDEO || (c == STILL && dynamic_cast (*i))) { - _formats.push_back (*i); - } - } + _formats = Format::all (); _format->Clear (); for (vector::iterator i = _formats.begin(); i != _formats.end(); ++i) { @@ -1110,7 +976,7 @@ FilmEditor::setup_subtitle_control_sensitivity () { bool h = false; if (_generally_sensitive && _film) { - h = !_film->subtitle_streams().empty(); +// h = !_film->subtitle_streams().empty(); } _with_subtitles->Enable (h); @@ -1120,26 +986,11 @@ FilmEditor::setup_subtitle_control_sensitivity () j = _film->with_subtitles (); } - _subtitle_stream->Enable (j); + _ffmpeg_subtitle_stream->Enable (j); _subtitle_offset->Enable (j); _subtitle_scale->Enable (j); } -void -FilmEditor::setup_audio_control_sensitivity () -{ - _use_content_audio->Enable (_generally_sensitive && _film && !_film->content_audio_streams().empty()); - _use_external_audio->Enable (_generally_sensitive); - - bool const source = _generally_sensitive && _use_content_audio->GetValue(); - bool const external = _generally_sensitive && _use_external_audio->GetValue(); - - _audio_stream->Enable (source); - for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) { - _external_audio[i]->Enable (external); - } -} - void FilmEditor::use_dci_name_toggled (wxCommandEvent &) { @@ -1166,63 +1017,66 @@ FilmEditor::edit_dci_button_clicked (wxCommandEvent &) void FilmEditor::setup_streams () { - _audio_stream->Clear (); - vector > a = _film->content_audio_streams (); - for (vector >::iterator i = a.begin(); i != a.end(); ++i) { - shared_ptr ffa = dynamic_pointer_cast (*i); - assert (ffa); - _audio_stream->Append (std_to_wx (ffa->name()), new wxStringClientData (std_to_wx (ffa->to_string ()))); - } +// _ffmpeg_audio_stream->Clear (); + vector a;// = _film->content_audio_streams (); +// for (vector::iterator i = a.begin(); i != a.end(); ++i) { +// _audio_stream->Append (std_to_wx (ffa->name()), new wxStringClientData (std_to_wx (i->to_string ()))); +// } - if (_film->use_content_audio() && _film->audio_stream()) { - checked_set (_audio_stream, _film->audio_stream()->to_string()); - } - - _subtitle_stream->Clear (); - vector > s = _film->subtitle_streams (); - for (vector >::iterator i = s.begin(); i != s.end(); ++i) { - _subtitle_stream->Append (std_to_wx ((*i)->name()), new wxStringClientData (std_to_wx ((*i)->to_string ()))); - } - if (_film->subtitle_stream()) { - checked_set (_subtitle_stream, _film->subtitle_stream()->to_string()); - } else { - _subtitle_stream->SetSelection (wxNOT_FOUND); - } +// if (_film->use_content_audio() && _film->audio_stream()) { +// checked_set (_audio_stream, _film->audio_stream()->to_string()); +// } + + _ffmpeg_subtitle_stream->Clear (); +// vector > s = _film->subtitle_streams (); +// for (vector >::iterator i = s.begin(); i != s.end(); ++i) { +// _subtitle_stream->Append (std_to_wx ((*i)->name()), new wxStringClientData (std_to_wx ((*i)->to_string ()))); +// } +// if (_film->subtitle_stream()) { +// checked_set (_subtitle_stream, _film->subtitle_stream()->to_string()); +// } else { +// _subtitle_stream->SetSelection (wxNOT_FOUND); +// } } void -FilmEditor::audio_stream_changed (wxCommandEvent &) +FilmEditor::ffmpeg_audio_stream_changed (wxCommandEvent &) { if (!_film) { return; } +#if 0 _film->set_content_audio_stream ( audio_stream_factory ( string_client_data (_audio_stream->GetClientObject (_audio_stream->GetSelection ())), Film::state_version ) ); +#endif } void -FilmEditor::subtitle_stream_changed (wxCommandEvent &) +FilmEditor::ffmpeg_subtitle_stream_changed (wxCommandEvent &) { if (!_film) { return; } +#if 0 _film->set_subtitle_stream ( subtitle_stream_factory ( string_client_data (_subtitle_stream->GetClientObject (_subtitle_stream->GetSelection ())), Film::state_version ) ); +#endif } void FilmEditor::setup_audio_details () { +#if 0 if (!_film->content_audio_stream()) { _audio->SetLabel (wxT ("")); } else { @@ -1235,6 +1089,7 @@ FilmEditor::setup_audio_details () s << ", " << _film->audio_stream()->sample_rate() << wx_to_std (_("Hz")); _audio->SetLabel (std_to_wx (s.str ())); } +#endif } void @@ -1243,23 +1098,6 @@ FilmEditor::active_jobs_changed (bool a) set_things_sensitive (!a); } -void -FilmEditor::use_audio_changed (wxCommandEvent &) -{ - _film->set_use_content_audio (_use_content_audio->GetValue()); -} - -void -FilmEditor::external_audio_changed (wxCommandEvent &) -{ - vector a; - for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) { - a.push_back (wx_to_std (_external_audio[i]->GetPath())); - } - - _film->set_external_audio (a); -} - void FilmEditor::setup_dcp_name () { @@ -1292,11 +1130,23 @@ FilmEditor::best_dcp_frame_rate_clicked (wxCommandEvent &) return; } - _film->set_dcp_frame_rate (best_dcp_frame_rate (_film->source_frame_rate ())); +// _film->set_dcp_frame_rate (best_dcp_frame_rate (_film->source_frame_rate ())); } void FilmEditor::setup_show_audio_sensitivity () { - _show_audio->Enable (_film && _film->has_audio ()); +// _show_audio->Enable (_film && _film->has_audio ()); +} + +void +FilmEditor::setup_content () +{ + _content->DeleteAllItems (); + + list > content = _film->content (); + for (list >::iterator i = content.begin(); i != content.end(); ++i) { + _content->InsertItem (_content->GetItemCount(), std_to_wx ((*i)->summary ())); + } } + diff --git a/src/wx/film_editor.h b/src/wx/film_editor.h index e5b619886..6b1d98ea6 100644 --- a/src/wx/film_editor.h +++ b/src/wx/film_editor.h @@ -29,6 +29,7 @@ #include "lib/film.h" class wxNotebook; +class wxListCtrl; class Film; class AudioDialog; @@ -41,12 +42,12 @@ public: FilmEditor (boost::shared_ptr, wxWindow *); void set_film (boost::shared_ptr); - void setup_visibility (); boost::signals2::signal FileChanged; private: void make_film_panel (); + void make_content_panel (); void make_video_panel (); void make_audio_panel (); void make_subtitle_panel (); @@ -60,7 +61,6 @@ private: void right_crop_changed (wxCommandEvent &); void top_crop_changed (wxCommandEvent &); void bottom_crop_changed (wxCommandEvent &); - void content_changed (wxCommandEvent &); void trust_content_header_changed (wxCommandEvent &); void format_changed (wxCommandEvent &); void trim_start_changed (wxCommandEvent &); @@ -77,11 +77,8 @@ private: void subtitle_scale_changed (wxCommandEvent &); void colour_lut_changed (wxCommandEvent &); void j2k_bandwidth_changed (wxCommandEvent &); - void still_duration_changed (wxCommandEvent &); - void audio_stream_changed (wxCommandEvent &); - void subtitle_stream_changed (wxCommandEvent &); - void use_audio_changed (wxCommandEvent &); - void external_audio_changed (wxCommandEvent &); + void ffmpeg_audio_stream_changed (wxCommandEvent &); + void ffmpeg_subtitle_stream_changed (wxCommandEvent &); void dcp_frame_rate_changed (wxCommandEvent &); void best_dcp_frame_rate_clicked (wxCommandEvent &); @@ -94,20 +91,19 @@ private: void set_things_sensitive (bool); void setup_formats (); void setup_subtitle_control_sensitivity (); - void setup_audio_control_sensitivity (); void setup_streams (); void setup_audio_details (); void setup_dcp_name (); void setup_show_audio_sensitivity (); + void setup_content (); - wxControl* video_control (wxControl *); - wxControl* still_control (wxControl *); - void active_jobs_changed (bool); wxNotebook* _notebook; wxPanel* _film_panel; wxSizer* _film_sizer; + wxPanel* _content_panel; + wxSizer* _content_sizer; wxPanel* _video_panel; wxSizer* _video_sizer; wxPanel* _audio_panel; @@ -121,68 +117,47 @@ private: wxTextCtrl* _name; wxStaticText* _dcp_name; wxCheckBox* _use_dci_name; + wxListCtrl* _content; + wxButton* _content_add; + wxButton* _content_remove; + wxButton* _content_earlier; + wxButton* _content_later; wxButton* _edit_dci_button; - /** The Film's format */ wxChoice* _format; wxStaticText* _format_description; - /** The Film's content file */ - wxFilePickerCtrl* _content; wxCheckBox* _trust_content_header; - /** The Film's left crop */ wxSpinCtrl* _left_crop; - /** The Film's right crop */ wxSpinCtrl* _right_crop; - /** The Film's top crop */ wxSpinCtrl* _top_crop; - /** The Film's bottom crop */ wxSpinCtrl* _bottom_crop; - /** Currently-applied filters */ wxStaticText* _filters; - /** Button to open the filters dialogue */ wxButton* _filters_button; - /** The Film's scaler */ wxChoice* _scaler; - wxRadioButton* _use_content_audio; - wxChoice* _audio_stream; - wxRadioButton* _use_external_audio; - wxFilePickerCtrl* _external_audio[MAX_AUDIO_CHANNELS]; - /** The Film's audio gain */ wxSpinCtrl* _audio_gain; - /** A button to open the gain calculation dialogue */ wxButton* _audio_gain_calculate_button; wxButton* _show_audio; - /** The Film's audio delay */ wxSpinCtrl* _audio_delay; wxCheckBox* _with_subtitles; - wxChoice* _subtitle_stream; + wxChoice* _ffmpeg_subtitle_stream; wxSpinCtrl* _subtitle_offset; wxSpinCtrl* _subtitle_scale; wxChoice* _colour_lut; wxSpinCtrl* _j2k_bandwidth; - /** The Film's DCP content type */ wxChoice* _dcp_content_type; - /** The Film's source frame rate */ wxStaticText* _source_frame_rate; wxChoice* _dcp_frame_rate; wxButton* _best_dcp_frame_rate; wxStaticText* _frame_rate_description; - /** The Film's original size */ wxStaticText* _original_size; - /** The Film's length */ wxStaticText* _length; /** The Film's audio details */ wxStaticText* _audio; - /** The Film's duration for still sources */ - wxSpinCtrl* _still_duration; wxSpinCtrl* _trim_start; wxSpinCtrl* _trim_end; /** Selector to generate an A/B comparison DCP */ wxCheckBox* _dcp_ab; - std::list _video_controls; - std::list _still_controls; - std::vector _formats; bool _generally_sensitive; diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 08eade4d0..1e2a74be9 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -114,12 +114,10 @@ FilmViewer::film_changed (Film::Property p) } _decoders.video->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3)); _decoders.video->OutputChanged.connect (boost::bind (&FilmViewer::decoder_changed, this)); - _decoders.video->set_subtitle_stream (_film->subtitle_stream()); +// _decoders.video->set_subtitle_stream (_film->subtitle_stream()); calculate_sizes (); get_frame (); _panel->Refresh (); - _slider->Show (_film->content_type() == VIDEO); - _play_button->Show (_film->content_type() == VIDEO); _v_sizer->Layout (); break; } @@ -132,7 +130,7 @@ FilmViewer::film_changed (Film::Property p) break; case Film::SUBTITLE_STREAM: if (_decoders.video) { - _decoders.video->set_subtitle_stream (_film->subtitle_stream ()); +// _decoders.video->set_subtitle_stream (_film->subtitle_stream ()); } break; default: @@ -187,12 +185,12 @@ FilmViewer::timer (wxTimerEvent &) get_frame (); - if (_film->length()) { - int const new_slider_position = 4096 * _decoders.video->last_source_time() / (_film->length().get() / _film->source_frame_rate()); - if (new_slider_position != _slider->GetValue()) { - _slider->SetValue (new_slider_position); - } - } +// if (_film->length()) { +// int const new_slider_position = 4096 * _decoders.video->last_source_time() / (_film->length().get() / _film->source_frame_rate()); +// if (new_slider_position != _slider->GetValue()) { +// _slider->SetValue (new_slider_position); +// } +// } } @@ -233,13 +231,13 @@ FilmViewer::paint_panel (wxPaintEvent &) void FilmViewer::slider_moved (wxScrollEvent &) { - if (!_film || !_film->length() || !_decoders.video) { - return; - } +// if (!_film || !_film->length() || !_decoders.video) { +// return; +// } - if (_decoders.video->seek (_slider->GetValue() * _film->length().get() / (4096 * _film->source_frame_rate()))) { - return; - } +// if (_decoders.video->seek (_slider->GetValue() * _film->length().get() / (4096 * _film->source_frame_rate()))) { +// return; +// } get_frame (); _panel->Refresh (); @@ -294,6 +292,7 @@ FilmViewer::raw_to_display () _clear_required = true; } +#if 0 if (_raw_sub) { /* Our output is already cropped by the decoder, so we need to account for that @@ -314,6 +313,7 @@ FilmViewer::raw_to_display () } else { _display_sub.reset (); } +#endif } void @@ -342,9 +342,9 @@ FilmViewer::calculate_sizes () of our _display_frame. */ _display_frame_x = 0; - if (format) { - _display_frame_x = static_cast (format->dcp_padding (_film)) * _out_size.width / format->dcp_size().width; - } +// if (format) { +// _display_frame_x = static_cast (format->dcp_padding (_film)) * _out_size.width / format->dcp_size().width; +// } _film_size = _out_size; _film_size.width -= _display_frame_x * 2; @@ -369,7 +369,7 @@ FilmViewer::check_play_state () } if (_play_button->GetValue()) { - _timer.Start (1000 / _film->source_frame_rate()); +// _timer.Start (1000 / _film->source_frame_rate()); } else { _timer.Stop (); } diff --git a/src/wx/properties_dialog.cc b/src/wx/properties_dialog.cc index 44a713dc3..06e245832 100644 --- a/src/wx/properties_dialog.cc +++ b/src/wx/properties_dialog.cc @@ -50,6 +50,7 @@ PropertiesDialog::PropertiesDialog (wxWindow* parent, shared_ptr film) _encoded = new ThreadedStaticText (this, _("counting..."), boost::bind (&PropertiesDialog::frames_already_encoded, this)); table->Add (_encoded, 1, wxALIGN_CENTER_VERTICAL); +#if 0 if (_film->length()) { _frames->SetLabel (std_to_wx (lexical_cast (_film->length().get()))); FrameRateConversion frc (_film->source_frame_rate(), _film->dcp_frame_rate()); @@ -62,6 +63,7 @@ PropertiesDialog::PropertiesDialog (wxWindow* parent, shared_ptr film) _frames->SetLabel (_("unknown")); _disk->SetLabel (_("unknown")); } +#endif wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL); overall_sizer->Add (table, 0, wxALL, 6); @@ -85,9 +87,9 @@ PropertiesDialog::frames_already_encoded () const return ""; } - if (_film->length()) { - /* XXX: encoded_frames() should check which frames have been encoded */ - u << " (" << (_film->encoded_frames() * 100 / _film->length().get()) << "%)"; - } +// if (_film->length()) { +// /* XXX: encoded_frames() should check which frames have been encoded */ +// u << " (" << (_film->encoded_frames() * 100 / _film->length().get()) << "%)"; +// } return u.str (); } diff --git a/test/test.cc b/test/test.cc index 61e192058..efa4848f6 100644 --- a/test/test.cc +++ b/test/test.cc @@ -142,7 +142,7 @@ BOOST_AUTO_TEST_CASE (film_metadata_test) BOOST_CHECK (f->filters ().empty()); f->set_name ("fred"); - BOOST_CHECK_THROW (f->set_content ("jim"), OpenFileError); +// BOOST_CHECK_THROW (f->set_content ("jim"), OpenFileError); f->set_dcp_content_type (DCPContentType::from_pretty_name ("Short")); f->set_format (Format::from_nickname ("Flat")); f->set_left_crop (1); @@ -183,50 +183,17 @@ BOOST_AUTO_TEST_CASE (film_metadata_test) BOOST_CHECK_EQUAL (::system (s.str().c_str ()), 0); } -BOOST_AUTO_TEST_CASE (stream_test) -{ - FFmpegAudioStream a ("ffmpeg 4 44100 1 hello there world", boost::optional (1)); - BOOST_CHECK_EQUAL (a.id(), 4); - BOOST_CHECK_EQUAL (a.sample_rate(), 44100); - BOOST_CHECK_EQUAL (a.channel_layout(), 1); - BOOST_CHECK_EQUAL (a.name(), "hello there world"); - BOOST_CHECK_EQUAL (a.to_string(), "ffmpeg 4 44100 1 hello there world"); - - SndfileStream e ("external 44100 1", boost::optional (1)); - BOOST_CHECK_EQUAL (e.sample_rate(), 44100); - BOOST_CHECK_EQUAL (e.channel_layout(), 1); - BOOST_CHECK_EQUAL (e.to_string(), "external 44100 1"); - - SubtitleStream s ("5 a b c", boost::optional (1)); - BOOST_CHECK_EQUAL (s.id(), 5); - BOOST_CHECK_EQUAL (s.name(), "a b c"); - - shared_ptr ff = audio_stream_factory ("ffmpeg 4 44100 1 hello there world", boost::optional (1)); - shared_ptr cff = dynamic_pointer_cast (ff); - BOOST_CHECK (cff); - BOOST_CHECK_EQUAL (cff->id(), 4); - BOOST_CHECK_EQUAL (cff->sample_rate(), 44100); - BOOST_CHECK_EQUAL (cff->channel_layout(), 1); - BOOST_CHECK_EQUAL (cff->name(), "hello there world"); - BOOST_CHECK_EQUAL (cff->to_string(), "ffmpeg 4 44100 1 hello there world"); - - shared_ptr fe = audio_stream_factory ("external 44100 1", boost::optional (1)); - BOOST_CHECK_EQUAL (fe->sample_rate(), 44100); - BOOST_CHECK_EQUAL (fe->channel_layout(), 1); - BOOST_CHECK_EQUAL (fe->to_string(), "external 44100 1"); -} - BOOST_AUTO_TEST_CASE (format_test) { Format::setup_formats (); Format const * f = Format::from_nickname ("Flat"); BOOST_CHECK (f); - BOOST_CHECK_EQUAL (f->ratio_as_integer(shared_ptr ()), 185); +// BOOST_CHECK_EQUAL (f->ratio_as_integer(shared_ptr ()), 185); f = Format::from_nickname ("Scope"); BOOST_CHECK (f); - BOOST_CHECK_EQUAL (f->ratio_as_integer(shared_ptr ()), 239); +// BOOST_CHECK_EQUAL (f->ratio_as_integer(shared_ptr ()), 239); } BOOST_AUTO_TEST_CASE (util_test) @@ -355,17 +322,6 @@ BOOST_AUTO_TEST_CASE (md5_digest_test) BOOST_CHECK_THROW (md5_digest ("foobar"), OpenFileError); } -BOOST_AUTO_TEST_CASE (paths_test) -{ - shared_ptr f = new_test_film ("paths_test"); - f->set_directory ("build/test/a/b/c/d/e"); - - f->_content = "/foo/bar/baz"; - BOOST_CHECK_EQUAL (f->content_path(), "/foo/bar/baz"); - f->_content = "foo/bar/baz"; - BOOST_CHECK_EQUAL (f->content_path(), "build/test/a/b/c/d/e/foo/bar/baz"); -} - void do_remote_encode (shared_ptr frame, ServerDescription* description, shared_ptr locally_encoded) { @@ -457,7 +413,7 @@ BOOST_AUTO_TEST_CASE (make_dcp_test) { shared_ptr film = new_test_film ("make_dcp_test"); film->set_name ("test_film2"); - film->set_content ("../../../test/test.mp4"); +// film->set_content ("../../../test/test.mp4"); film->set_format (Format::from_nickname ("Flat")); film->set_dcp_content_type (DCPContentType::from_pretty_name ("Test")); film->make_dcp (); @@ -487,8 +443,8 @@ BOOST_AUTO_TEST_CASE (make_dcp_with_range_test) { shared_ptr film = new_test_film ("make_dcp_with_range_test"); film->set_name ("test_film3"); - film->set_content ("../../../test/test.mp4"); - film->examine_content (); +// film->set_content ("../../../test/test.mp4"); +// film->examine_content (); film->set_format (Format::from_nickname ("Flat")); film->set_dcp_content_type (DCPContentType::from_pretty_name ("Test")); film->set_trim_end (42); @@ -649,44 +605,44 @@ BOOST_AUTO_TEST_CASE (audio_sampling_rate_test) Config::instance()->set_allowed_dcp_frame_rates (afr); shared_ptr f = new_test_film ("audio_sampling_rate_test"); - f->set_source_frame_rate (24); +// f->set_source_frame_rate (24); f->set_dcp_frame_rate (24); - f->set_content_audio_stream (shared_ptr (new FFmpegAudioStream ("a", 42, 48000, 0))); +// f->set_content_audio_stream (shared_ptr (new FFmpegAudioStream ("a", 42, 48000, 0))); BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 48000); - f->set_content_audio_stream (shared_ptr (new FFmpegAudioStream ("a", 42, 44100, 0))); +// f->set_content_audio_stream (shared_ptr (new FFmpegAudioStream ("a", 42, 44100, 0))); BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 48000); - f->set_content_audio_stream (shared_ptr (new FFmpegAudioStream ("a", 42, 80000, 0))); +// f->set_content_audio_stream (shared_ptr (new FFmpegAudioStream ("a", 42, 80000, 0))); BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 96000); - f->set_source_frame_rate (23.976); +// f->set_source_frame_rate (23.976); f->set_dcp_frame_rate (best_dcp_frame_rate (23.976)); - f->set_content_audio_stream (shared_ptr (new FFmpegAudioStream ("a", 42, 48000, 0))); +// f->set_content_audio_stream (shared_ptr (new FFmpegAudioStream ("a", 42, 48000, 0))); BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 47952); - f->set_source_frame_rate (29.97); +// f->set_source_frame_rate (29.97); f->set_dcp_frame_rate (best_dcp_frame_rate (29.97)); BOOST_CHECK_EQUAL (f->dcp_frame_rate (), 30); - f->set_content_audio_stream (shared_ptr (new FFmpegAudioStream ("a", 42, 48000, 0))); +// f->set_content_audio_stream (shared_ptr (new FFmpegAudioStream ("a", 42, 48000, 0))); BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 47952); - f->set_source_frame_rate (25); +// f->set_source_frame_rate (25); f->set_dcp_frame_rate (24); - f->set_content_audio_stream (shared_ptr (new FFmpegAudioStream ("a", 42, 48000, 0))); +// f->set_content_audio_stream (shared_ptr (new FFmpegAudioStream ("a", 42, 48000, 0))); BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 50000); - f->set_source_frame_rate (25); +// f->set_source_frame_rate (25); f->set_dcp_frame_rate (24); - f->set_content_audio_stream (shared_ptr (new FFmpegAudioStream ("a", 42, 44100, 0))); +// f->set_content_audio_stream (shared_ptr (new FFmpegAudioStream ("a", 42, 44100, 0))); BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 50000); /* Check some out-there conversions (not the best) */ - f->set_source_frame_rate (14.99); +// f->set_source_frame_rate (14.99); f->set_dcp_frame_rate (25); - f->set_content_audio_stream (shared_ptr (new FFmpegAudioStream ("a", 42, 16000, 0))); +// f->set_content_audio_stream (shared_ptr (new FFmpegAudioStream ("a", 42, 16000, 0))); /* The FrameRateConversion within target_audio_sample_rate should choose to double-up the 14.99 fps video to 30 and then run it slow at 25. */ -- cgit v1.2.3 From a054c067ab2cbf6c5abc5df4caa08ffaac206f0b Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sun, 31 Mar 2013 16:04:10 +0100 Subject: Content can be added and previewed. --- src/lib/ab_transcode_job.cc | 6 +- src/lib/ab_transcode_job.h | 5 +- src/lib/ab_transcoder.cc | 3 +- src/lib/ab_transcoder.h | 1 - src/lib/analyse_audio_job.cc | 1 - src/lib/audio_decoder.cc | 4 +- src/lib/audio_decoder.h | 2 +- src/lib/dcp_video_frame.cc | 1 - src/lib/decoder.cc | 4 +- src/lib/decoder.h | 5 +- src/lib/decoder_factory.cc | 2 +- src/lib/decoder_factory.h | 4 +- src/lib/encoder.cc | 1 - src/lib/examine_content_job.cc | 1 - src/lib/ffmpeg_content.cc | 5 +- src/lib/ffmpeg_decoder.cc | 31 ++++---- src/lib/ffmpeg_decoder.h | 7 +- src/lib/film.cc | 8 +- src/lib/imagemagick_decoder.cc | 7 +- src/lib/imagemagick_decoder.h | 2 +- src/lib/options.h | 43 ----------- src/lib/playlist.cc | 172 ++++++++++++++++++++++++++++++++--------- src/lib/playlist.h | 12 +++ src/lib/sndfile_decoder.cc | 6 +- src/lib/sndfile_decoder.h | 2 +- src/lib/transcode_job.cc | 6 +- src/lib/transcode_job.h | 6 +- src/lib/transcoder.cc | 4 +- src/lib/transcoder.h | 3 - src/lib/video_decoder.cc | 5 +- src/lib/video_decoder.h | 2 +- src/tools/servomatictest.cc | 11 ++- src/wx/film_editor.cc | 1 + src/wx/film_viewer.cc | 63 +++++++-------- src/wx/film_viewer.h | 2 +- 35 files changed, 232 insertions(+), 206 deletions(-) delete mode 100644 src/lib/options.h (limited to 'src/lib/decoder.h') diff --git a/src/lib/ab_transcode_job.cc b/src/lib/ab_transcode_job.cc index f17d43916..2bdff47de 100644 --- a/src/lib/ab_transcode_job.cc +++ b/src/lib/ab_transcode_job.cc @@ -32,11 +32,9 @@ using std::string; using boost::shared_ptr; /** @param f Film to compare. - * @param o Decode options. */ -ABTranscodeJob::ABTranscodeJob (shared_ptr f, DecodeOptions o) +ABTranscodeJob::ABTranscodeJob (shared_ptr f) : Job (f) - , _decode_opt (o) { _film_b.reset (new Film (*_film)); _film_b->set_scaler (Config::instance()->reference_scaler ()); @@ -54,7 +52,7 @@ ABTranscodeJob::run () { try { /* _film_b is the one with reference filters */ - ABTranscoder w (_film_b, _film, _decode_opt, shared_from_this ()); + ABTranscoder w (_film_b, _film, shared_from_this ()); w.go (); set_progress (1); set_state (FINISHED_OK); diff --git a/src/lib/ab_transcode_job.h b/src/lib/ab_transcode_job.h index 5d029a18b..cd82d4247 100644 --- a/src/lib/ab_transcode_job.h +++ b/src/lib/ab_transcode_job.h @@ -23,7 +23,6 @@ #include #include "job.h" -#include "options.h" class Film; @@ -38,8 +37,7 @@ class ABTranscodeJob : public Job { public: ABTranscodeJob ( - boost::shared_ptr f, - DecodeOptions o + boost::shared_ptr f ); std::string name () const; @@ -48,5 +46,4 @@ public: private: /** Copy of our Film using the reference filters and scaler */ boost::shared_ptr _film_b; - DecodeOptions _decode_opt; }; diff --git a/src/lib/ab_transcoder.cc b/src/lib/ab_transcoder.cc index 0c687008d..6fc438ee8 100644 --- a/src/lib/ab_transcoder.cc +++ b/src/lib/ab_transcoder.cc @@ -23,7 +23,6 @@ #include "film.h" #include "encoder.h" #include "job.h" -#include "options.h" #include "image.h" #include "playlist.h" #include "matcher.h" @@ -47,7 +46,7 @@ using boost::dynamic_pointer_cast; * @param e Encoder to use. */ -ABTranscoder::ABTranscoder (shared_ptr a, shared_ptr b, DecodeOptions o, shared_ptr j) +ABTranscoder::ABTranscoder (shared_ptr a, shared_ptr b, shared_ptr j) : _film_a (a) , _film_b (b) , _playlist_a (_film_a->playlist ()) diff --git a/src/lib/ab_transcoder.h b/src/lib/ab_transcoder.h index 14277c562..090c26fb7 100644 --- a/src/lib/ab_transcoder.h +++ b/src/lib/ab_transcoder.h @@ -48,7 +48,6 @@ public: ABTranscoder ( boost::shared_ptr a, boost::shared_ptr b, - DecodeOptions o, boost::shared_ptr j ); diff --git a/src/lib/analyse_audio_job.cc b/src/lib/analyse_audio_job.cc index 74491943b..6e6dda886 100644 --- a/src/lib/analyse_audio_job.cc +++ b/src/lib/analyse_audio_job.cc @@ -21,7 +21,6 @@ #include "analyse_audio_job.h" #include "compose.hpp" #include "film.h" -#include "options.h" #include "playlist.h" #include "i18n.h" diff --git a/src/lib/audio_decoder.cc b/src/lib/audio_decoder.cc index a72cf11bb..e2006a795 100644 --- a/src/lib/audio_decoder.cc +++ b/src/lib/audio_decoder.cc @@ -22,8 +22,8 @@ using boost::optional; using boost::shared_ptr; -AudioDecoder::AudioDecoder (shared_ptr f, shared_ptr c, DecodeOptions o) - : Decoder (f, o) +AudioDecoder::AudioDecoder (shared_ptr f, shared_ptr c) + : Decoder (f) { } diff --git a/src/lib/audio_decoder.h b/src/lib/audio_decoder.h index 7d2a2bb62..cbb84b52d 100644 --- a/src/lib/audio_decoder.h +++ b/src/lib/audio_decoder.h @@ -35,7 +35,7 @@ class AudioContent; class AudioDecoder : public AudioSource, public virtual Decoder { public: - AudioDecoder (boost::shared_ptr, boost::shared_ptr, DecodeOptions); + AudioDecoder (boost::shared_ptr, boost::shared_ptr); }; #endif diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc index d674393a9..e9499871a 100644 --- a/src/lib/dcp_video_frame.cc +++ b/src/lib/dcp_video_frame.cc @@ -47,7 +47,6 @@ #include "dcp_video_frame.h" #include "lut.h" #include "config.h" -#include "options.h" #include "exceptions.h" #include "server.h" #include "util.h" diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc index 2fe265c14..c40446919 100644 --- a/src/lib/decoder.cc +++ b/src/lib/decoder.cc @@ -23,7 +23,6 @@ #include #include "film.h" -#include "options.h" #include "exceptions.h" #include "util.h" #include "decoder.h" @@ -36,9 +35,8 @@ using boost::shared_ptr; /** @param f Film. * @param o Decode options. */ -Decoder::Decoder (shared_ptr f, DecodeOptions o) +Decoder::Decoder (shared_ptr f) : _film (f) - , _opt (o) { _film_connection = f->Changed.connect (bind (&Decoder::film_changed, this, _1)); } diff --git a/src/lib/decoder.h b/src/lib/decoder.h index 50aa16dba..4ccdc046f 100644 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@ -33,7 +33,6 @@ #include "video_source.h" #include "audio_source.h" #include "film.h" -#include "options.h" class Image; class Log; @@ -52,7 +51,7 @@ class FilterGraph; class Decoder { public: - Decoder (boost::shared_ptr, DecodeOptions); + Decoder (boost::shared_ptr); virtual ~Decoder () {} virtual bool pass () = 0; @@ -63,8 +62,6 @@ public: protected: boost::shared_ptr _film; - /** our decode options */ - DecodeOptions _opt; private: virtual void film_changed (Film::Property) {} diff --git a/src/lib/decoder_factory.cc b/src/lib/decoder_factory.cc index feaa1c7ef..7940edc2e 100644 --- a/src/lib/decoder_factory.cc +++ b/src/lib/decoder_factory.cc @@ -36,7 +36,7 @@ using boost::dynamic_pointer_cast; Decoders decoder_factory ( - shared_ptr f, DecodeOptions o + shared_ptr f ) { return Decoders (); diff --git a/src/lib/decoder_factory.h b/src/lib/decoder_factory.h index 8076b01c7..3fd91f876 100644 --- a/src/lib/decoder_factory.h +++ b/src/lib/decoder_factory.h @@ -24,8 +24,6 @@ * @brief A method to create appropriate decoders for some content. */ -#include "options.h" - class Film; class VideoDecoder; class AudioDecoder; @@ -43,7 +41,7 @@ struct Decoders { }; extern Decoders decoder_factory ( - boost::shared_ptr, DecodeOptions + boost::shared_ptr ); #endif diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc index 970213793..00807f863 100644 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@ -27,7 +27,6 @@ #include #include "encoder.h" #include "util.h" -#include "options.h" #include "film.h" #include "log.h" #include "exceptions.h" diff --git a/src/lib/examine_content_job.cc b/src/lib/examine_content_job.cc index c600132c3..aad7f265e 100644 --- a/src/lib/examine_content_job.cc +++ b/src/lib/examine_content_job.cc @@ -19,7 +19,6 @@ #include #include "examine_content_job.h" -#include "options.h" #include "log.h" #include "content.h" diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc index 25efb1ebf..6109b7212 100644 --- a/src/lib/ffmpeg_content.cc +++ b/src/lib/ffmpeg_content.cc @@ -1,6 +1,5 @@ #include "ffmpeg_content.h" #include "ffmpeg_decoder.h" -#include "options.h" #include "compose.hpp" #include "job.h" #include "util.h" @@ -33,9 +32,7 @@ FFmpegContent::examine (shared_ptr film, shared_ptr job, bool quick) job->set_progress_unknown (); - DecodeOptions o; - o.decode_audio = false; - shared_ptr decoder (new FFmpegDecoder (film, shared_from_this (), o)); + shared_ptr decoder (new FFmpegDecoder (film, shared_from_this (), true, false, false, true)); ContentVideoFrame video_length = 0; if (quick) { diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index c8e46776f..7b56a5971 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -41,7 +41,6 @@ extern "C" { #include "transcoder.h" #include "job.h" #include "filter.h" -#include "options.h" #include "exceptions.h" #include "image.h" #include "util.h" @@ -62,10 +61,10 @@ using boost::optional; using boost::dynamic_pointer_cast; using libdcp::Size; -FFmpegDecoder::FFmpegDecoder (shared_ptr f, shared_ptr c, DecodeOptions o) - : Decoder (f, o) - , VideoDecoder (f, c, o) - , AudioDecoder (f, c, o) +FFmpegDecoder::FFmpegDecoder (shared_ptr f, shared_ptr c, bool video, bool audio, bool subtitles, bool video_sync) + : Decoder (f) + , VideoDecoder (f, c) + , AudioDecoder (f, c) , _ffmpeg_content (c) , _format_context (0) , _video_stream (-1) @@ -76,13 +75,17 @@ FFmpegDecoder::FFmpegDecoder (shared_ptr f, shared_ptr= 0 && frame_finished) { filter_and_emit_video (_frame); } } - if (_ffmpeg_content->audio_stream() && _opt.decode_audio) { + if (_ffmpeg_content->audio_stream() && _decode_audio) { decode_audio_packet (); } @@ -245,7 +248,7 @@ FFmpegDecoder::pass () avcodec_get_frame_defaults (_frame); - if (_packet.stream_index == _video_stream && _opt.decode_video) { + if (_packet.stream_index == _video_stream && _decode_video) { int frame_finished; int const r = avcodec_decode_video2 (_video_codec_context, _frame, &frame_finished, &_packet); @@ -255,16 +258,16 @@ FFmpegDecoder::pass () _film->log()->log (String::compose (N_("Used only %1 bytes of %2 in packet"), r, _packet.size)); } - if (_opt.video_sync) { + if (_video_sync) { out_with_sync (); } else { filter_and_emit_video (_frame); } } - } else if (_ffmpeg_content->audio_stream() && _packet.stream_index == _ffmpeg_content->audio_stream()->id && _opt.decode_audio) { + } else if (_ffmpeg_content->audio_stream() && _packet.stream_index == _ffmpeg_content->audio_stream()->id && _decode_audio) { decode_audio_packet (); - } else if (_ffmpeg_content->subtitle_stream() && _packet.stream_index == _ffmpeg_content->subtitle_stream()->id && _opt.decode_subtitles && _first_video) { + } else if (_ffmpeg_content->subtitle_stream() && _packet.stream_index == _ffmpeg_content->subtitle_stream()->id && _decode_subtitles && _first_video) { int got_subtitle; AVSubtitle sub; @@ -633,9 +636,9 @@ FFmpegDecoder::decode_audio_packet () was before this packet. Until then audio is thrown away. */ - if ((_first_video && _first_video.get() <= source_pts_seconds) || !_opt.decode_video) { + if ((_first_video && _first_video.get() <= source_pts_seconds) || !_decode_video) { - if (!_first_audio && _opt.decode_video) { + if (!_first_audio && _decode_video) { _first_audio = source_pts_seconds; /* This is our first audio frame, and if we've arrived here we must have had our diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index a0900d89f..ef66f09d9 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -57,7 +57,7 @@ class Log; class FFmpegDecoder : public VideoDecoder, public AudioDecoder { public: - FFmpegDecoder (boost::shared_ptr, boost::shared_ptr, DecodeOptions); + FFmpegDecoder (boost::shared_ptr, boost::shared_ptr, bool video, bool audio, bool subtitles, bool video_sync); ~FFmpegDecoder (); float frames_per_second () const; @@ -129,4 +129,9 @@ private: std::vector _subtitle_streams; std::vector _audio_streams; + + bool _decode_video; + bool _decode_audio; + bool _decode_subtitles; + bool _video_sync; }; diff --git a/src/lib/film.cc b/src/lib/film.cc index f69f63fd8..0e57cf8eb 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -40,7 +40,6 @@ #include "transcode_job.h" #include "scp_dcp_job.h" #include "log.h" -#include "options.h" #include "exceptions.h" #include "examine_content_job.h" #include "scaler.h" @@ -296,15 +295,12 @@ Film::make_dcp () throw MissingSettingError (_("name")); } - DecodeOptions od; - od.decode_subtitles = with_subtitles (); - shared_ptr r; if (dcp_ab()) { - r = JobManager::instance()->add (shared_ptr (new ABTranscodeJob (shared_from_this(), od))); + r = JobManager::instance()->add (shared_ptr (new ABTranscodeJob (shared_from_this()))); } else { - r = JobManager::instance()->add (shared_ptr (new TranscodeJob (shared_from_this(), od))); + r = JobManager::instance()->add (shared_ptr (new TranscodeJob (shared_from_this()))); } } diff --git a/src/lib/imagemagick_decoder.cc b/src/lib/imagemagick_decoder.cc index aa3c64f93..c3723f610 100644 --- a/src/lib/imagemagick_decoder.cc +++ b/src/lib/imagemagick_decoder.cc @@ -32,10 +32,9 @@ using std::cout; using boost::shared_ptr; using libdcp::Size; -ImageMagickDecoder::ImageMagickDecoder ( - shared_ptr f, shared_ptr c, DecodeOptions o) - : Decoder (f, o) - , VideoDecoder (f, c, o) +ImageMagickDecoder::ImageMagickDecoder (shared_ptr f, shared_ptr c) + : Decoder (f) + , VideoDecoder (f, c) , _imagemagick_content (c) , _position (0) { diff --git a/src/lib/imagemagick_decoder.h b/src/lib/imagemagick_decoder.h index b04bd88b1..a26e283c0 100644 --- a/src/lib/imagemagick_decoder.h +++ b/src/lib/imagemagick_decoder.h @@ -28,7 +28,7 @@ class ImageMagickContent; class ImageMagickDecoder : public VideoDecoder { public: - ImageMagickDecoder (boost::shared_ptr, boost::shared_ptr, DecodeOptions); + ImageMagickDecoder (boost::shared_ptr, boost::shared_ptr); float frames_per_second () const { /* We don't know */ diff --git a/src/lib/options.h b/src/lib/options.h deleted file mode 100644 index 0d2c07fd5..000000000 --- a/src/lib/options.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - Copyright (C) 2012 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef DVDOMATIC_OPTIONS_H -#define DVDOMATIC_OPTIONS_H - -/** @file src/options.h - * @brief Options for a decoding operation. - */ - -class DecodeOptions -{ -public: - DecodeOptions () - : decode_video (true) - , decode_audio (true) - , decode_subtitles (false) - , video_sync (true) - {} - - bool decode_video; - bool decode_audio; - bool decode_subtitles; - bool video_sync; -}; - -#endif diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc index 17ecd2f37..fc9edac48 100644 --- a/src/lib/playlist.cc +++ b/src/lib/playlist.cc @@ -31,9 +31,12 @@ using boost::shared_ptr; using boost::dynamic_pointer_cast; Playlist::Playlist (shared_ptr f, list > c) - : _video_from (VIDEO_NONE) + : _film (f) + , _video_from (VIDEO_NONE) , _audio_from (AUDIO_NONE) + , _have_setup_decoders (false) , _ffmpeg_decoder_done (false) + , _video_sync (true) { for (list >::const_iterator i = c.begin(); i != c.end(); ++i) { shared_ptr fc = dynamic_pointer_cast (*i); @@ -60,42 +63,6 @@ Playlist::Playlist (shared_ptr f, list > c) _audio_from = AUDIO_SNDFILE; } } - - if (_video_from == VIDEO_FFMPEG || _audio_from == AUDIO_FFMPEG) { - DecodeOptions o; - /* XXX: decodeoptions */ - _ffmpeg_decoder.reset (new FFmpegDecoder (f, _ffmpeg, o)); - } - - if (_video_from == VIDEO_FFMPEG) { - _ffmpeg_decoder->connect_video (shared_from_this ()); - } - - if (_audio_from == AUDIO_FFMPEG) { - _ffmpeg_decoder->connect_audio (shared_from_this ()); - } - - if (_video_from == VIDEO_IMAGEMAGICK) { - for (list >::iterator i = _imagemagick.begin(); i != _imagemagick.end(); ++i) { - DecodeOptions o; - /* XXX: decodeoptions */ - shared_ptr d (new ImageMagickDecoder (f, *i, o)); - _imagemagick_decoders.push_back (d); - d->connect_video (shared_from_this ()); - } - - _imagemagick_decoder = _imagemagick_decoders.begin (); - } - - if (_audio_from == AUDIO_SNDFILE) { - for (list >::iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) { - DecodeOptions o; - /* XXX: decodeoptions */ - shared_ptr d (new SndfileDecoder (f, *i, o)); - _sndfile_decoders.push_back (d); - d->connect_audio (shared_from_this ()); - } - } } ContentAudioFrame @@ -202,6 +169,27 @@ Playlist::video_size () const return libdcp::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 >::const_iterator i = _imagemagick.begin(); i != _imagemagick.end(); ++i) { + l += (*i)->video_length (); + } + return l; + } + } + + return 0; +} + bool Playlist::has_audio () const { @@ -214,9 +202,26 @@ Playlist::disable_video () _video_from = VIDEO_NONE; } +void +Playlist::disable_audio () +{ + _audio_from = AUDIO_NONE; +} + +void +Playlist::disable_subtitles () +{ + /* XXX */ +} + bool Playlist::pass () { + if (!_have_setup_decoders) { + setup_decoders (); + _have_setup_decoders = true; + } + bool done = true; if (_video_from == VIDEO_FFMPEG || _audio_from == AUDIO_FFMPEG) { @@ -264,3 +269,96 @@ Playlist::process_audio (shared_ptr b) Audio (b); } +bool +Playlist::seek (double t) +{ + bool r = false; + + switch (_video_from) { + case VIDEO_NONE: + break; + case VIDEO_FFMPEG: + if (_ffmpeg_decoder->seek (t)) { + r = true; + } + break; + case VIDEO_IMAGEMAGICK: + if ((*_imagemagick_decoder)->seek (t)) { + r = true; + } + break; + } + + /* XXX: don't seek audio because we don't need to... */ + + return r; +} + +bool +Playlist::seek_to_last () +{ + bool r = false; + + switch (_video_from) { + case VIDEO_NONE: + break; + case VIDEO_FFMPEG: + if (_ffmpeg_decoder->seek_to_last ()) { + r = true; + } + break; + case VIDEO_IMAGEMAGICK: + if ((*_imagemagick_decoder)->seek_to_last ()) { + r = true; + } + break; + } + + /* XXX: don't seek audio because we don't need to... */ + + return r; +} + +void +Playlist::setup_decoders () +{ + if (_video_from == VIDEO_FFMPEG || _audio_from == AUDIO_FFMPEG) { + _ffmpeg_decoder.reset ( + new FFmpegDecoder ( + _film, _ffmpeg, _video_from == VIDEO_FFMPEG, _audio_from == AUDIO_FFMPEG, _film->with_subtitles(), _video_sync + ) + ); + } + + if (_video_from == VIDEO_FFMPEG) { + _ffmpeg_decoder->connect_video (shared_from_this ()); + } + + if (_audio_from == AUDIO_FFMPEG) { + _ffmpeg_decoder->connect_audio (shared_from_this ()); + } + + if (_video_from == VIDEO_IMAGEMAGICK) { + for (list >::iterator i = _imagemagick.begin(); i != _imagemagick.end(); ++i) { + shared_ptr d (new ImageMagickDecoder (_film, *i)); + _imagemagick_decoders.push_back (d); + d->connect_video (shared_from_this ()); + } + + _imagemagick_decoder = _imagemagick_decoders.begin (); + } + + if (_audio_from == AUDIO_SNDFILE) { + for (list >::iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) { + shared_ptr d (new SndfileDecoder (_film, *i)); + _sndfile_decoders.push_back (d); + d->connect_audio (shared_from_this ()); + } + } +} + +void +Playlist::disable_video_sync () +{ + _video_sync = false; +} diff --git a/src/lib/playlist.h b/src/lib/playlist.h index b42d46036..d374dc98c 100644 --- a/src/lib/playlist.h +++ b/src/lib/playlist.h @@ -48,16 +48,25 @@ public: float video_frame_rate () const; libdcp::Size video_size () const; + ContentVideoFrame video_length () const; void disable_video (); + void disable_audio (); + void disable_subtitles (); + void disable_video_sync (); bool pass (); void set_progress (boost::shared_ptr); + bool seek (double); + bool seek_to_last (); private: void process_video (boost::shared_ptr i, bool same, boost::shared_ptr s); void process_audio (boost::shared_ptr); + void setup_decoders (); + boost::shared_ptr _film; + enum { VIDEO_NONE, VIDEO_FFMPEG, @@ -74,9 +83,12 @@ private: std::list > _imagemagick; std::list > _sndfile; + bool _have_setup_decoders; boost::shared_ptr _ffmpeg_decoder; bool _ffmpeg_decoder_done; std::list > _imagemagick_decoders; std::list >::iterator _imagemagick_decoder; std::list > _sndfile_decoders; + + bool _video_sync; }; diff --git a/src/lib/sndfile_decoder.cc b/src/lib/sndfile_decoder.cc index 8848ff4f8..daa363c5e 100644 --- a/src/lib/sndfile_decoder.cc +++ b/src/lib/sndfile_decoder.cc @@ -36,9 +36,9 @@ using boost::optional; /* XXX */ -SndfileDecoder::SndfileDecoder (shared_ptr f, shared_ptr c, DecodeOptions o) - : Decoder (f, o) - , AudioDecoder (f, c, o) +SndfileDecoder::SndfileDecoder (shared_ptr f, shared_ptr c) + : Decoder (f) + , AudioDecoder (f, c) { sf_count_t frames; SNDFILE* sf = open_file (frames); diff --git a/src/lib/sndfile_decoder.h b/src/lib/sndfile_decoder.h index c06b97a60..9a3ef49b0 100644 --- a/src/lib/sndfile_decoder.h +++ b/src/lib/sndfile_decoder.h @@ -26,7 +26,7 @@ class SndfileContent; class SndfileDecoder : public AudioDecoder { public: - SndfileDecoder (boost::shared_ptr, boost::shared_ptr, DecodeOptions); + SndfileDecoder (boost::shared_ptr, boost::shared_ptr); bool pass (); diff --git a/src/lib/transcode_job.cc b/src/lib/transcode_job.cc index f8810975b..8b74f7766 100644 --- a/src/lib/transcode_job.cc +++ b/src/lib/transcode_job.cc @@ -39,11 +39,9 @@ using std::setprecision; using boost::shared_ptr; /** @param s Film to use. - * @param o Decode options. */ -TranscodeJob::TranscodeJob (shared_ptr f, DecodeOptions o) +TranscodeJob::TranscodeJob (shared_ptr f) : Job (f) - , _decode_opt (o) { } @@ -62,7 +60,7 @@ TranscodeJob::run () _film->log()->log (N_("Transcode job starting")); _film->log()->log (String::compose (N_("Audio delay is %1ms"), _film->audio_delay())); - Transcoder w (_film, _decode_opt, shared_from_this ()); + Transcoder w (_film, shared_from_this ()); w.go (); set_progress (1); set_state (FINISHED_OK); diff --git a/src/lib/transcode_job.h b/src/lib/transcode_job.h index a409ec97e..def545958 100644 --- a/src/lib/transcode_job.h +++ b/src/lib/transcode_job.h @@ -23,7 +23,6 @@ #include #include "job.h" -#include "options.h" class Encoder; @@ -33,7 +32,7 @@ class Encoder; class TranscodeJob : public Job { public: - TranscodeJob (boost::shared_ptr f, DecodeOptions od); + TranscodeJob (boost::shared_ptr f); std::string name () const; void run (); @@ -41,7 +40,4 @@ public: protected: int remaining_time () const; - -private: - DecodeOptions _decode_opt; }; diff --git a/src/lib/transcoder.cc b/src/lib/transcoder.cc index 19d067149..070258008 100644 --- a/src/lib/transcoder.cc +++ b/src/lib/transcoder.cc @@ -32,7 +32,6 @@ #include "film.h" #include "matcher.h" #include "delay_line.h" -#include "options.h" #include "gain.h" #include "video_decoder.h" #include "audio_decoder.h" @@ -44,11 +43,10 @@ using boost::dynamic_pointer_cast; /** Construct a transcoder using a Decoder that we create and a supplied Encoder. * @param f Film that we are transcoding. - * @param o Decode options. * @param j Job that we are running under, or 0. * @param e Encoder to use. */ -Transcoder::Transcoder (shared_ptr f, DecodeOptions o, shared_ptr j) +Transcoder::Transcoder (shared_ptr f, shared_ptr j) : _job (j) , _playlist (f->playlist ()) , _encoder (new Encoder (f, _playlist)) diff --git a/src/lib/transcoder.h b/src/lib/transcoder.h index 8d34af948..3c47b0c7e 100644 --- a/src/lib/transcoder.h +++ b/src/lib/transcoder.h @@ -18,7 +18,6 @@ */ /** @file src/transcoder.h - * @brief A class which takes a Film and some Options, then uses those to transcode the film. * * A decoder is selected according to the content type, and the encoder can be specified * as a parameter to the constructor. @@ -36,7 +35,6 @@ class DelayLine; class Playlist; /** @class Transcoder - * @brief A class which takes a Film and some Options, then uses those to transcode the film. * * A decoder is selected according to the content type, and the encoder can be specified * as a parameter to the constructor. @@ -46,7 +44,6 @@ class Transcoder public: Transcoder ( boost::shared_ptr f, - DecodeOptions o, boost::shared_ptr j ); diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc index ca1e7ab56..33dd433ea 100644 --- a/src/lib/video_decoder.cc +++ b/src/lib/video_decoder.cc @@ -22,7 +22,6 @@ #include "film.h" #include "image.h" #include "log.h" -#include "options.h" #include "job.h" #include "i18n.h" @@ -30,8 +29,8 @@ using boost::shared_ptr; using boost::optional; -VideoDecoder::VideoDecoder (shared_ptr f, shared_ptr c, DecodeOptions o) - : Decoder (f, o) +VideoDecoder::VideoDecoder (shared_ptr f, shared_ptr c) + : Decoder (f) , _video_frame (0) , _last_source_time (0) { diff --git a/src/lib/video_decoder.h b/src/lib/video_decoder.h index a52e5448a..03dc4777a 100644 --- a/src/lib/video_decoder.h +++ b/src/lib/video_decoder.h @@ -28,7 +28,7 @@ class VideoContent; class VideoDecoder : public VideoSource, public virtual Decoder { public: - VideoDecoder (boost::shared_ptr, boost::shared_ptr, DecodeOptions); + VideoDecoder (boost::shared_ptr, boost::shared_ptr); /** @return video frames per second, or 0 if unknown */ virtual float frames_per_second () const = 0; diff --git a/src/tools/servomatictest.cc b/src/tools/servomatictest.cc index f5756c693..d08fefa90 100644 --- a/src/tools/servomatictest.cc +++ b/src/tools/servomatictest.cc @@ -28,7 +28,6 @@ #include "scaler.h" #include "server.h" #include "dcp_video_frame.h" -#include "options.h" #include "decoder.h" #include "exceptions.h" #include "scaler.h" @@ -151,12 +150,12 @@ main (int argc, char* argv[]) server = new ServerDescription (server_host, 1); shared_ptr film (new Film (film_dir, true)); - DecodeOptions opt; - opt.decode_audio = false; - opt.decode_subtitles = true; - opt.video_sync = true; + /* XXX */ +// opt.decode_audio = false; +// opt.decode_subtitles = true; +// opt.video_sync = true; - Decoders decoders = decoder_factory (film, opt); + Decoders decoders = decoder_factory (film); try { decoders.video->Video.connect (boost::bind (process_video, _1, _2, _3)); bool done = false; diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index ce1c1abe8..f9a91f8fa 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -347,6 +347,7 @@ FilmEditor::make_content_panel () s->Add (_content, 1, wxEXPAND | wxTOP | wxBOTTOM, 6); _content->InsertColumn (0, ""); + _content->SetColumnWidth (0, 512); wxBoxSizer* b = new wxBoxSizer (wxVERTICAL); _content_add = new wxButton (_content_panel, wxID_ANY, _("Add...")); diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 1e2a74be9..42af4b3c0 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -28,13 +28,13 @@ #include "lib/format.h" #include "lib/util.h" #include "lib/job_manager.h" -#include "lib/options.h" #include "lib/subtitle.h" #include "lib/image.h" #include "lib/scaler.h" #include "lib/exceptions.h" #include "lib/examine_content_job.h" #include "lib/filter.h" +#include "lib/playlist.h" #include "film_viewer.h" #include "wx_util.h" #include "video_decoder.h" @@ -97,24 +97,13 @@ FilmViewer::film_changed (Film::Property p) break; case Film::CONTENT: { - DecodeOptions o; - o.decode_audio = false; - o.decode_subtitles = true; - o.video_sync = false; - - try { - _decoders = decoder_factory (_film, o); - } catch (StringError& e) { - error_dialog (this, wxString::Format (_("Could not open content file (%s)"), std_to_wx(e.what()).data())); - return; - } - - if (_decoders.video == 0) { - break; - } - _decoders.video->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3)); - _decoders.video->OutputChanged.connect (boost::bind (&FilmViewer::decoder_changed, this)); -// _decoders.video->set_subtitle_stream (_film->subtitle_stream()); + _playlist = _film->playlist (); + _playlist->disable_audio (); + _playlist->disable_subtitles (); + _playlist->disable_video_sync (); + + _playlist->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3)); +// _playlist->OutputChanged.connect (boost::bind (&FilmViewer::decoder_changed, this)); calculate_sizes (); get_frame (); _panel->Refresh (); @@ -129,9 +118,9 @@ FilmViewer::film_changed (Film::Property p) update_from_raw (); break; case Film::SUBTITLE_STREAM: - if (_decoders.video) { +// if (_decoders.video) { // _decoders.video->set_subtitle_stream (_film->subtitle_stream ()); - } +// } break; default: break; @@ -164,7 +153,7 @@ FilmViewer::set_film (shared_ptr f) void FilmViewer::decoder_changed () { - if (_decoders.video == 0 || _decoders.video->seek_to_last ()) { + if (!_playlist == 0 || _playlist->seek_to_last ()) { return; } @@ -176,7 +165,7 @@ FilmViewer::decoder_changed () void FilmViewer::timer (wxTimerEvent &) { - if (!_film || !_decoders.video) { + if (!_playlist) { return; } @@ -185,8 +174,8 @@ FilmViewer::timer (wxTimerEvent &) get_frame (); -// if (_film->length()) { -// int const new_slider_position = 4096 * _decoders.video->last_source_time() / (_film->length().get() / _film->source_frame_rate()); +// if (_playlist->video_length()) { +// int const new_slider_position = 4096 * _playlist->last_source_time() / (_film->length().get() / _film->source_frame_rate()); // if (new_slider_position != _slider->GetValue()) { // _slider->SetValue (new_slider_position); // } @@ -231,13 +220,13 @@ FilmViewer::paint_panel (wxPaintEvent &) void FilmViewer::slider_moved (wxScrollEvent &) { -// if (!_film || !_film->length() || !_decoders.video) { -// return; -// } + if (!_film || !_playlist) { + return; + } -// if (_decoders.video->seek (_slider->GetValue() * _film->length().get() / (4096 * _film->source_frame_rate()))) { -// return; -// } + if (_playlist->seek (_slider->GetValue() * _playlist->video_length() / (4096 * _playlist->video_frame_rate()))) { + return; + } get_frame (); _panel->Refresh (); @@ -319,7 +308,7 @@ FilmViewer::raw_to_display () void FilmViewer::calculate_sizes () { - if (!_film) { + if (!_film || !_playlist) { return; } @@ -342,9 +331,9 @@ FilmViewer::calculate_sizes () of our _display_frame. */ _display_frame_x = 0; -// if (format) { -// _display_frame_x = static_cast (format->dcp_padding (_film)) * _out_size.width / format->dcp_size().width; -// } + if (format) { + _display_frame_x = static_cast (format->dcp_padding (_playlist)) * _out_size.width / format->dcp_size().width; + } _film_size = _out_size; _film_size.width -= _display_frame_x * 2; @@ -392,7 +381,7 @@ FilmViewer::get_frame () /* Clear our raw frame in case we don't get a new one */ _raw_frame.reset (); - if (_decoders.video == 0) { + if (!_playlist) { _display_frame.reset (); return; } @@ -400,7 +389,7 @@ FilmViewer::get_frame () try { _got_frame = false; while (!_got_frame) { - if (_decoders.video->pass ()) { + if (_playlist->pass ()) { /* We didn't get a frame before the decoder gave up, so clear our display frame. */ diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index 456301eb4..b552a3dbc 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -58,6 +58,7 @@ private: void active_jobs_changed (bool); boost::shared_ptr _film; + boost::shared_ptr _playlist; wxSizer* _v_sizer; wxPanel* _panel; @@ -65,7 +66,6 @@ private: wxToggleButton* _play_button; wxTimer _timer; - Decoders _decoders; boost::shared_ptr _raw_frame; boost::shared_ptr _raw_sub; boost::shared_ptr _display_frame; -- cgit v1.2.3 From fff7a8232b18ce6191e60ba911c29b64b9063d4d Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 2 Apr 2013 00:03:45 +0100 Subject: Various bits. --- src/lib/content.h | 19 ++++++++++ src/lib/decoder.h | 2 - src/lib/encoder.h | 2 +- src/lib/ffmpeg_content.cc | 19 ++++++++++ src/lib/ffmpeg_content.h | 19 ++++++++++ src/lib/ffmpeg_decoder.cc | 1 - src/lib/film.cc | 56 ++++++++++++++++++++++++++++ src/lib/film.h | 7 +++- src/lib/imagemagick_content.cc | 46 ++++++++++++++++++++++- src/lib/imagemagick_content.h | 24 +++++++++++- src/lib/imagemagick_decoder.cc | 14 +++---- src/lib/imagemagick_decoder.h | 11 +----- src/lib/playlist.cc | 23 ++++++++++-- src/lib/playlist.h | 2 +- src/lib/util.cc | 14 +------ src/lib/util.h | 83 +----------------------------------------- src/lib/video_content.cc | 8 +++- src/lib/wscript | 1 + src/wx/film_editor.cc | 35 ++++++++++++++---- src/wx/film_viewer.cc | 16 ++++---- src/wx/film_viewer.h | 2 +- 21 files changed, 261 insertions(+), 143 deletions(-) (limited to 'src/lib/decoder.h') diff --git a/src/lib/content.h b/src/lib/content.h index 3a94d2297..87ef46581 100644 --- a/src/lib/content.h +++ b/src/lib/content.h @@ -1,3 +1,22 @@ +/* + Copyright (C) 2013 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + #ifndef DVDOMATIC_CONTENT_H #define DVDOMATIC_CONTENT_H diff --git a/src/lib/decoder.h b/src/lib/decoder.h index 4ccdc046f..34accf6c7 100644 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@ -58,8 +58,6 @@ public: virtual bool seek (double); virtual bool seek_to_last (); - boost::signals2::signal OutputChanged; - protected: boost::shared_ptr _film; diff --git a/src/lib/encoder.h b/src/lib/encoder.h index 86880bc34..2cbd498e8 100644 --- a/src/lib/encoder.h +++ b/src/lib/encoder.h @@ -106,7 +106,7 @@ private: static int const _history_size; /** Number of video frames received so far */ - SourceFrame _video_frames_in; + ContentVideoFrame _video_frames_in; /** Number of video frames written for the DCP so far */ int _video_frames_out; diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc index 42e04e838..50a69ae7b 100644 --- a/src/lib/ffmpeg_content.cc +++ b/src/lib/ffmpeg_content.cc @@ -1,3 +1,22 @@ +/* + Copyright (C) 2013 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + #include #include "ffmpeg_content.h" #include "ffmpeg_decoder.h" diff --git a/src/lib/ffmpeg_content.h b/src/lib/ffmpeg_content.h index 95e24b7b3..c56dc0a61 100644 --- a/src/lib/ffmpeg_content.h +++ b/src/lib/ffmpeg_content.h @@ -1,3 +1,22 @@ +/* + Copyright (C) 2013 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + #ifndef DVDOMATIC_FFMPEG_CONTENT_H #define DVDOMATIC_FFMPEG_CONTENT_H diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 25ca9bb88..ced9b95e9 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -592,7 +592,6 @@ FFmpegDecoder::film_changed (Film::Property p) boost::mutex::scoped_lock lm (_filter_graphs_mutex); _filter_graphs.clear (); } - OutputChanged (); break; default: diff --git a/src/lib/film.cc b/src/lib/film.cc index fe16a65fa..19e900784 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -1043,6 +1043,62 @@ Film::add_content (shared_ptr c) examine_content (c); } +void +Film::remove_content (shared_ptr c) +{ + { + boost::mutex::scoped_lock lm (_state_mutex); + ContentList::iterator i = find (_content.begin(), _content.end(), c); + if (i != _content.end ()) { + _content.erase (i); + } + } + + signal_changed (CONTENT); +} + +void +Film::move_content_earlier (shared_ptr c) +{ + { + boost::mutex::scoped_lock lm (_state_mutex); + ContentList::iterator i = find (_content.begin(), _content.end(), c); + if (i == _content.begin () || i == _content.end()) { + return; + } + + ContentList::iterator j = i; + --j; + + swap (*i, *j); + } + + signal_changed (CONTENT); +} + +void +Film::move_content_later (shared_ptr c) +{ + { + boost::mutex::scoped_lock lm (_state_mutex); + ContentList::iterator i = find (_content.begin(), _content.end(), c); + if (i == _content.end()) { + return; + } + + ContentList::iterator j = i; + ++j; + if (j == _content.end ()) { + return; + } + + swap (*i, *j); + } + + signal_changed (CONTENT); + +} + ContentAudioFrame Film::audio_length () const { diff --git a/src/lib/film.h b/src/lib/film.h index 6e097d44e..9682a37d7 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -38,6 +38,7 @@ extern "C" { #include "dcp_content_type.h" #include "util.h" #include "dci_metadata.h" +#include "types.h" class Format; class Job; @@ -171,7 +172,7 @@ public: return _trust_content_headers; } - std::list > content () const { + ContentList content () const { boost::mutex::scoped_lock lm (_state_mutex); return _content; } @@ -268,6 +269,9 @@ public: void set_use_dci_name (bool); void set_trust_content_headers (bool); void add_content (boost::shared_ptr); + void remove_content (boost::shared_ptr); + void move_content_earlier (boost::shared_ptr); + void move_content_later (boost::shared_ptr); void set_dcp_content_type (DCPContentType const *); void set_format (Format const *); void set_crop (Crop); @@ -325,7 +329,6 @@ private: std::string _name; /** True if a auto-generated DCI-compliant name should be used for our DCP */ bool _use_dci_name; - typedef std::list > ContentList; ContentList _content; bool _trust_content_headers; /** The type of content that this Film represents (feature, trailer etc.) */ diff --git a/src/lib/imagemagick_content.cc b/src/lib/imagemagick_content.cc index cb712b417..f9572b518 100644 --- a/src/lib/imagemagick_content.cc +++ b/src/lib/imagemagick_content.cc @@ -1,5 +1,25 @@ +/* + Copyright (C) 2013 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + #include #include "imagemagick_content.h" +#include "imagemagick_decoder.h" #include "compose.hpp" #include "i18n.h" @@ -11,8 +31,7 @@ ImageMagickContent::ImageMagickContent (boost::filesystem::path f) : Content (f) , VideoContent (f) { - /* XXX */ - _video_length = 10 * 24; + } ImageMagickContent::ImageMagickContent (shared_ptr node) @@ -35,3 +54,26 @@ ImageMagickContent::valid_file (boost::filesystem::path f) transform (ext.begin(), ext.end(), ext.begin(), ::tolower); return (ext == ".tif" || ext == ".tiff" || ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".bmp"); } + +void +ImageMagickContent::as_xml (xmlpp::Node* node) const +{ + node->add_child("Type")->add_child_text ("ImageMagick"); + Content::as_xml (node); + VideoContent::as_xml (node); +} + +void +ImageMagickContent::examine (shared_ptr film, shared_ptr job, bool quick) +{ + Content::examine (film, job, quick); + shared_ptr decoder (new ImageMagickDecoder (film, shared_from_this())); + + { + boost::mutex::scoped_lock lm (_mutex); + /* XXX */ + _video_length = 10 * 24; + } + + take_from_video_decoder (decoder); +} diff --git a/src/lib/imagemagick_content.h b/src/lib/imagemagick_content.h index 99b614512..5820bd807 100644 --- a/src/lib/imagemagick_content.h +++ b/src/lib/imagemagick_content.h @@ -1,16 +1,38 @@ +/* + Copyright (C) 2013 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include #include "video_content.h" namespace cxml { class Node; } -class ImageMagickContent : public VideoContent +class ImageMagickContent : public VideoContent, public boost::enable_shared_from_this { public: ImageMagickContent (boost::filesystem::path); ImageMagickContent (boost::shared_ptr); + void examine (boost::shared_ptr, boost::shared_ptr, bool); std::string summary () const; + void as_xml (xmlpp::Node *) const; static bool valid_file (boost::filesystem::path); }; diff --git a/src/lib/imagemagick_decoder.cc b/src/lib/imagemagick_decoder.cc index 279c8bf32..508863e3e 100644 --- a/src/lib/imagemagick_decoder.cc +++ b/src/lib/imagemagick_decoder.cc @@ -52,6 +52,12 @@ ImageMagickDecoder::native_size () const return s; } +int +ImageMagickDecoder::video_length () const +{ + return _imagemagick_content->video_length (); +} + bool ImageMagickDecoder::pass () { @@ -120,11 +126,3 @@ ImageMagickDecoder::seek (double t) _position = f; return false; } - -void -ImageMagickDecoder::film_changed (Film::Property p) -{ - if (p == Film::CROP) { - OutputChanged (); - } -} diff --git a/src/lib/imagemagick_decoder.h b/src/lib/imagemagick_decoder.h index 7ad08df03..424cefe08 100644 --- a/src/lib/imagemagick_decoder.h +++ b/src/lib/imagemagick_decoder.h @@ -31,16 +31,11 @@ public: ImageMagickDecoder (boost::shared_ptr, boost::shared_ptr); float frames_per_second () const { - /* We don't know */ - return 0; + return 24; } libdcp::Size native_size () const; - - ContentVideoFrame video_length () const { - /* We don't know */ - return 0; - } + ContentVideoFrame video_length () const; int audio_channels () const { return 0; @@ -80,8 +75,6 @@ protected: } private: - void film_changed (Film::Property); - boost::shared_ptr _imagemagick_content; ContentVideoFrame _position; }; diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc index d9bf8ac36..609d4096c 100644 --- a/src/lib/playlist.cc +++ b/src/lib/playlist.cc @@ -27,6 +27,7 @@ #include "imagemagick_decoder.h" using std::list; +using std::cout; using boost::shared_ptr; using boost::dynamic_pointer_cast; @@ -38,12 +39,12 @@ Playlist::Playlist () } void -Playlist::setup (list > content) +Playlist::setup (ContentList content) { _video_from = VIDEO_NONE; _audio_from = AUDIO_NONE; - for (list >::const_iterator i = content.begin(); i != content.end(); ++i) { + for (ContentList::const_iterator i = content.begin(); i != content.end(); ++i) { shared_ptr fc = dynamic_pointer_cast (*i); if (fc) { assert (!_ffmpeg); @@ -287,11 +288,12 @@ Player::process_audio (shared_ptr b) Audio (b); } +/** @return true on error */ bool Player::seek (double t) { bool r = false; - + switch (_playlist->video_from()) { case Playlist::VIDEO_NONE: break; @@ -301,7 +303,20 @@ Player::seek (double t) } break; case Playlist::VIDEO_IMAGEMAGICK: - if ((*_imagemagick_decoder)->seek (t)) { + /* 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 (this_length < t) { + break; + } + t -= this_length; + ++_imagemagick_decoder; + } + + if (_imagemagick_decoder != _imagemagick_decoders.end()) { + (*_imagemagick_decoder)->seek (t); + } else { r = true; } break; diff --git a/src/lib/playlist.h b/src/lib/playlist.h index 827849049..403fb58d4 100644 --- a/src/lib/playlist.h +++ b/src/lib/playlist.h @@ -40,7 +40,7 @@ class Playlist public: Playlist (); - void setup (std::list >); + void setup (ContentList); ContentAudioFrame audio_length () const; int audio_channels () const; diff --git a/src/lib/util.cc b/src/lib/util.cc index 1c020875a..e0de82c64 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -476,16 +476,6 @@ dcp_audio_sample_rate (int fs) return 96000; } -bool operator== (Crop const & a, Crop const & b) -{ - return (a.left == b.left && a.right == b.right && a.top == b.top && a.bottom == b.bottom); -} - -bool operator!= (Crop const & a, Crop const & b) -{ - return !(a == b); -} - /** @param index Colour LUT index. * @return Human-readable name. */ @@ -867,13 +857,13 @@ ensure_ui_thread () assert (this_thread::get_id() == ui_thread); } -/** @param v Source video frame. +/** @param v Content video frame. * @param audio_sample_rate Source audio sample rate. * @param frames_per_second Number of video frames per second. * @return Equivalent number of audio frames for `v'. */ int64_t -video_frames_to_audio_frames (SourceFrame v, float audio_sample_rate, float frames_per_second) +video_frames_to_audio_frames (ContentVideoFrame v, float audio_sample_rate, float frames_per_second) { return ((int64_t) v * audio_sample_rate / frames_per_second); } diff --git a/src/lib/util.h b/src/lib/util.h index b8c1e3116..23ebd52bc 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -37,6 +37,7 @@ extern "C" { #include } #include "compose.hpp" +#include "types.h" #ifdef DVDOMATIC_DEBUG #define TIMING(...) _film->log()->microsecond_log (String::compose (__VA_ARGS__), Log::TIMING); @@ -65,10 +66,6 @@ extern std::string audio_channel_name (int); extern boost::filesystem::path mo_path (); #endif -typedef int SourceFrame; -typedef int64_t ContentAudioFrame; -typedef int ContentVideoFrame; - struct FrameRateConversion { FrameRateConversion (float, int); @@ -106,82 +103,6 @@ struct FrameRateConversion int best_dcp_frame_rate (float); -/** @struct Crop - * @brief A description of the crop of an image or video. - */ -struct Crop -{ - Crop () : left (0), right (0), top (0), bottom (0) {} - - /** Number of pixels to remove from the left-hand side */ - int left; - /** Number of pixels to remove from the right-hand side */ - int right; - /** Number of pixels to remove from the top */ - int top; - /** Number of pixels to remove from the bottom */ - int bottom; -}; - -extern bool operator== (Crop const & a, Crop const & b); -extern bool operator!= (Crop const & a, Crop const & b); - -/** @struct Position - * @brief A position. - */ -struct Position -{ - Position () - : x (0) - , y (0) - {} - - Position (int x_, int y_) - : x (x_) - , y (y_) - {} - - /** x coordinate */ - int x; - /** y coordinate */ - int y; -}; - -/** @struct Rect - * @brief A rectangle. - */ -struct Rect -{ - Rect () - : x (0) - , y (0) - , width (0) - , height (0) - {} - - Rect (int x_, int y_, int w_, int h_) - : x (x_) - , y (y_) - , width (w_) - , height (h_) - {} - - int x; - int y; - int width; - int height; - - Position position () const { - return Position (x, y); - } - - libdcp::Size size () const { - return libdcp::Size (width, height); - } - - Rect intersection (Rect const & other) const; -}; - extern std::string crop_string (Position, libdcp::Size); extern int dcp_audio_sample_rate (int); extern std::string colour_lut_index_to_name (int index); @@ -286,7 +207,7 @@ private: int _source_channels; }; -extern int64_t video_frames_to_audio_frames (SourceFrame v, float audio_sample_rate, float frames_per_second); +extern int64_t video_frames_to_audio_frames (ContentVideoFrame v, float audio_sample_rate, float frames_per_second); extern std::pair cpu_info (); #endif diff --git a/src/lib/video_content.cc b/src/lib/video_content.cc index 8a4414c18..e697a281d 100644 --- a/src/lib/video_content.cc +++ b/src/lib/video_content.cc @@ -39,10 +39,14 @@ VideoContent::as_xml (xmlpp::Node* node) const void VideoContent::take_from_video_decoder (shared_ptr d) { + /* These decoder calls could call other content methods which take a lock on the mutex */ + libdcp::Size const vs = d->native_size (); + float const vfr = d->frames_per_second (); + { boost::mutex::scoped_lock lm (_mutex); - _video_size = d->native_size (); - _video_frame_rate = d->frames_per_second (); + _video_size = vs; + _video_frame_rate = vfr; } Changed (VideoContentProperty::VIDEO_SIZE); diff --git a/src/lib/wscript b/src/lib/wscript index 303a9951f..f2bb678aa 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -49,6 +49,7 @@ sources = """ timer.cc transcode_job.cc transcoder.cc + types.cc ui_signaller.cc util.cc version.cc diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index 560c4ef27..7930d86ce 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -200,9 +200,9 @@ FilmEditor::connect_to_widgets () _trust_content_headers->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::trust_content_headers_changed), 0, this); _content->Connect (wxID_ANY, wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler (FilmEditor::content_item_selected), 0, this); _content_add->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_add_clicked), 0, this); - _content_remove->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_add_clicked), 0, this); - _content_earlier->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_add_clicked), 0, this); - _content_later->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_add_clicked), 0, this); + _content_remove->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_remove_clicked), 0, this); + _content_earlier->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_earlier_clicked), 0, this); + _content_later->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::content_later_clicked), 0, this); _left_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::left_crop_changed), 0, this); _right_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::right_crop_changed), 0, this); _top_crop->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::top_crop_changed), 0, this); @@ -1135,13 +1135,13 @@ FilmEditor::best_dcp_frame_rate_clicked (wxCommandEvent &) return; } -// _film->set_dcp_frame_rate (best_dcp_frame_rate (_film->source_frame_rate ())); + _film->set_dcp_frame_rate (best_dcp_frame_rate (_film->video_frame_rate ())); } void FilmEditor::setup_show_audio_sensitivity () { -// _show_audio->Enable (_film && _film->has_audio ()); + _show_audio->Enable (_film && _film->has_audio ()); } void @@ -1149,8 +1149,8 @@ FilmEditor::setup_content () { _content->DeleteAllItems (); - list > content = _film->content (); - for (list >::iterator i = content.begin(); i != content.end(); ++i) { + ContentList content = _film->content (); + for (ContentList::iterator i = content.begin(); i != content.end(); ++i) { _content->InsertItem (_content->GetItemCount(), std_to_wx ((*i)->summary ())); } } @@ -1181,19 +1181,40 @@ FilmEditor::content_add_clicked (wxCommandEvent &) void FilmEditor::content_remove_clicked (wxCommandEvent &) { + int const s = _content->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); + if (s == -1) { + return; + } + ContentList c = _film->content (); + assert (s >= 0 && size_t (s) < c.size ()); + _film->remove_content (c[s]); } void FilmEditor::content_earlier_clicked (wxCommandEvent &) { + int const s = _content->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); + if (s == -1) { + return; + } + ContentList c = _film->content (); + assert (s >= 0 && size_t (s) < c.size ()); + _film->move_content_earlier (c[s]); } void FilmEditor::content_later_clicked (wxCommandEvent &) { + int const s = _content->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); + if (s == -1) { + return; + } + ContentList c = _film->content (); + assert (s >= 0 && size_t (s) < c.size ()); + _film->move_content_later (c[s]); } void diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 79b3d982f..e45f79a87 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -103,7 +103,6 @@ FilmViewer::film_changed (Film::Property p) _player->disable_video_sync (); _player->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3)); -// _player->OutputChanged.connect (boost::bind (&FilmViewer::decoder_changed, this)); calculate_sizes (); get_frame (); _panel->Refresh (); @@ -115,12 +114,8 @@ FilmViewer::film_changed (Film::Property p) case Film::SUBTITLE_SCALE: case Film::SCALER: case Film::FILTERS: - update_from_raw (); - break; - case Film::SUBTITLE_STREAM: -// if (_decoders.video) { -// _decoders.video->set_subtitle_stream (_film->subtitle_stream ()); -// } + case Film::CROP: + update_from_decoder (); break; default: break; @@ -151,7 +146,7 @@ FilmViewer::set_film (shared_ptr f) } void -FilmViewer::decoder_changed () +FilmViewer::update_from_decoder () { if (!_player || _player->seek_to_last ()) { return; @@ -223,7 +218,7 @@ FilmViewer::slider_moved (wxScrollEvent &) if (!_film || !_player) { return; } - + if (_player->seek (_slider->GetValue() * _film->video_length() / (4096 * _film->video_frame_rate()))) { return; } @@ -375,6 +370,9 @@ FilmViewer::process_video (shared_ptr image, bool, shared_ptr s _got_frame = true; } +/** Get a new _raw_frame from the decoder and then do + * raw_to_display (). + */ void FilmViewer::get_frame () { diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index 1e75045ac..f557d69b8 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -51,7 +51,7 @@ private: void calculate_sizes (); void check_play_state (); void update_from_raw (); - void decoder_changed (); + void update_from_decoder (); void raw_to_display (); void get_frame (); void active_jobs_changed (bool); -- cgit v1.2.3 From b66010a281acd3e3e58ef7202bce55023fc29d7f Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 9 Apr 2013 23:43:00 +0100 Subject: Merge ImageMagick and FFmpeg content into VideoContent list; remove seek_to_last hacks. --- run/dvdomatic | 4 +- src/lib/decoder.cc | 11 +-- src/lib/decoder.h | 1 - src/lib/ffmpeg_decoder.cc | 16 +--- src/lib/ffmpeg_decoder.h | 2 - src/lib/film.cc | 3 +- src/lib/imagemagick_content.cc | 2 +- src/lib/imagemagick_decoder.cc | 10 -- src/lib/imagemagick_decoder.h | 1 - src/lib/player.cc | 205 ++++++++++++++--------------------------- src/lib/player.h | 10 +- src/lib/playlist.cc | 178 ++++++++++++++++++----------------- src/lib/playlist.h | 24 +---- src/lib/video_decoder.cc | 4 +- src/lib/video_decoder.h | 6 +- src/tools/dvdomatic.cc | 21 ++++- src/wx/film_viewer.cc | 2 +- 17 files changed, 196 insertions(+), 304 deletions(-) (limited to 'src/lib/decoder.h') diff --git a/run/dvdomatic b/run/dvdomatic index 147c001cd..dbc63d44a 100755 --- a/run/dvdomatic +++ b/run/dvdomatic @@ -3,7 +3,7 @@ export LD_LIBRARY_PATH=build/src/lib:build/src/wx:build/src/asdcplib/src:$LD_LIBRARY_PATH if [ "$1" == "--debug" ]; then shift - gdb --args build/src/tools/dvdomatic "$*" + gdb --args build/src/tools/dvdomatic $* elif [ "$1" == "--valgrind" ]; then shift valgrind --tool="memcheck" build/src/tools/dvdomatic $* @@ -11,5 +11,5 @@ elif [ "$1" == "--i18n" ]; then shift LANGUAGE=fr_FR.UTF8 LANG=fr_FR.UTF8 build/src/tools/dvdomatic "$*" else - build/src/tools/dvdomatic "$*" + build/src/tools/dvdomatic $* fi 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 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 _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 c) --j; swap (*i, *j); - _playlist->setup (_content); } signal_changed (CONTENT); @@ -1107,7 +1107,6 @@ Film::move_content_later (shared_ptr 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 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 @@ -105,16 +105,6 @@ ImageMagickDecoder::pixel_format () const return PIX_FMT_RGB24; } -bool -ImageMagickDecoder::seek_to_last () -{ - if (_position > 0) { - --_position; - } - - return false; -} - bool ImageMagickDecoder::seek (double t) { 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 f, shared_ptr 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) { /* 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 >::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 >::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 > vc = _playlist->video (); + for (list >::iterator i = vc.begin(); i != vc.end(); ++i) { + + shared_ptr d; + + /* XXX: into content? */ + + shared_ptr fc = dynamic_pointer_cast (*i); + if (fc) { + shared_ptr 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 ic = dynamic_pointer_cast (*i); + if (ic) { + d.reset (new ImageMagickDecoder (_film, ic)); + } - if (_video && _playlist->video_from() == Playlist::VIDEO_IMAGEMAGICK) { - list > ic = _playlist->imagemagick (); - for (list >::iterator i = ic.begin(); i != ic.end(); ++i) { - shared_ptr 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 >::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 >::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 w, int p) if (p == VideoContentProperty::VIDEO_LENGTH) { if (dynamic_pointer_cast (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); 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 _ffmpeg_decoder; - bool _ffmpeg_decoder_done; - std::list > _imagemagick_decoders; - std::list >::iterator _imagemagick_decoder; + std::list > _video_decoders; + std::list >::iterator _video_decoder; std::list > _sndfile_decoders; boost::shared_ptr _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::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 fc = dynamic_pointer_cast (*i); - if (fc) { - assert (!_ffmpeg); - _ffmpeg = fc; - _video_from = VIDEO_FFMPEG; - if (_audio_from == AUDIO_NONE) { - _audio_from = AUDIO_FFMPEG; - } + shared_ptr vc = dynamic_pointer_cast (*i); + if (vc) { + _video.push_back (vc); } - shared_ptr ic = dynamic_pointer_cast (*i); - if (ic) { - _imagemagick.push_back (ic); - if (_video_from == VIDEO_NONE) { - _video_from = VIDEO_IMAGEMAGICK; - } - } - shared_ptr sc = dynamic_pointer_cast (*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 >::const_iterator i = _video.begin(); i != _video.end(); ++i) { + shared_ptr fc = dynamic_pointer_cast (*i); + if (fc) { + len += fc->audio_length (); + } + } + break; case AUDIO_SNDFILE: - { - ContentAudioFrame l = 0; for (list >::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 >::const_iterator i = _video.begin(); i != _video.end(); ++i) { + shared_ptr fc = dynamic_pointer_cast (*i); + if (fc) { + channels = max (channels, fc->audio_channels ()); + } + } + break; case AUDIO_SNDFILE: - { - int c = 0; for (list >::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 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 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 >::const_iterator i = _imagemagick.begin(); i != _imagemagick.end(); ++i) { - l += (*i)->video_length (); - } - return l; + ContentVideoFrame len = 0; + for (list >::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 c, int p) ContentChanged (c, p); } +shared_ptr +Playlist::first_ffmpeg () const +{ + for (list >::const_iterator i = _video.begin(); i != _video.end(); ++i) { + shared_ptr fc = dynamic_pointer_cast (*i); + if (fc) { + return fc; + } + } + + return shared_ptr (); +} + + 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 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 >::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 ffmpeg () const { - return _ffmpeg; - } - - std::list > imagemagick () const { - return _imagemagick; + std::list > video () const { + return _video; } std::list > sndfile () const { @@ -93,12 +78,11 @@ public: private: void content_changed (boost::weak_ptr, int); + boost::shared_ptr first_ffmpeg () const; - VideoFrom _video_from; AudioFrom _audio_from; - boost::shared_ptr _ffmpeg; - std::list > _imagemagick; + std::list > _video; std::list > _sndfile; std::list _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 f) : Decoder (f) , _video_frame (0) - , _last_source_time (0) + , _last_content_time (0) { } @@ -88,7 +88,7 @@ VideoDecoder::signal_video (shared_ptr image, bool same, shared_ptr, bool, boost::shared_ptr, double); int _video_frame; - double _last_source_time; + double _last_content_time; boost::shared_ptr _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; 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 f) void FilmViewer::update_from_decoder () { - if (!_player || _player->seek_to_last ()) { + if (!_player || _player->seek (_player->last_video_time ())) { return; } -- cgit v1.2.3 From 7ee21d16c01b90c22192cd10f118419881fe504e Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 13 Apr 2013 12:53:40 +0100 Subject: DVD-o-matic -> DCP-o-matic. --- Doxyfile | 2 +- README | 13 +- TODO | 137 ------ builds/control-12.04-32 | 8 +- builds/control-12.04-64 | 8 +- builds/control-12.10-32 | 8 +- builds/control-12.10-64 | 8 +- cscript | 14 +- cscript.py | 8 - debian/changelog | 136 +++--- debian/copyright | 4 +- debian/files | 2 +- debian/rules | 2 +- doc/mainpage.txt | 20 +- doc/manual/Makefile | 22 +- doc/manual/dvdomatic-html.xsl | 12 - doc/manual/dvdomatic-pdf.xsl | 17 - doc/manual/dvdomatic.css | 19 - doc/manual/dvdomatic.sty | 68 --- doc/manual/dvdomatic.xml | 932 ------------------------------------- dvdomatic.desktop.in | 10 - hacks/python-playback/config.py | 2 - hacks/python-playback/dvdomatic | 209 --------- hacks/python-playback/film.py | 188 -------- hacks/python-playback/film_view.py | 212 --------- hacks/python-playback/player.py | 112 ----- hacks/python-playback/ratio.py | 56 --- hacks/python-playback/screens | 62 --- hacks/python-playback/screens.py | 85 ---- hacks/python-playback/thumbs.py | 76 --- hacks/python-playback/util.py | 7 - hacks/python-playback/xrandr-notes | 17 - icons/128x128/dvdomatic.png | Bin 18365 -> 0 bytes icons/16x16/dvdomatic.png | Bin 211 -> 0 bytes icons/22x22/dvdomatic.png | Bin 994 -> 0 bytes icons/32x32/dvdomatic.png | Bin 1747 -> 0 bytes icons/48x48/dvdomatic.png | Bin 3407 -> 0 bytes icons/64x64/dvdomatic.png | Bin 5421 -> 0 bytes run/dvdomatic | 15 - src/lib/audio_analysis.h | 4 +- src/lib/audio_content.h | 4 +- src/lib/audio_decoder.h | 4 +- src/lib/audio_mapping.h | 4 +- src/lib/audio_sink.h | 4 +- src/lib/audio_source.h | 4 +- src/lib/config.cc | 4 +- src/lib/config.h | 4 +- src/lib/content.h | 4 +- src/lib/cross.cc | 10 +- src/lib/cross.h | 4 +- src/lib/dci_metadata.h | 4 +- src/lib/dcp_content_type.h | 4 +- src/lib/dcp_video_frame.cc | 2 +- src/lib/decoder.h | 4 +- src/lib/encoder.cc | 2 +- src/lib/encoder.h | 4 +- src/lib/exceptions.h | 4 +- src/lib/ffmpeg_content.h | 4 +- src/lib/film.cc | 10 +- src/lib/film.h | 6 +- src/lib/filter.h | 4 +- src/lib/filter_graph.h | 4 +- src/lib/i18n.h | 2 +- src/lib/image.h | 4 +- src/lib/job.cc | 4 +- src/lib/job.h | 4 +- src/lib/job_manager.cc | 2 +- src/lib/log.h | 4 +- src/lib/player.h | 4 +- src/lib/po/es_ES.po | 6 +- src/lib/po/fr_FR.po | 8 +- src/lib/po/it_IT.po | 4 +- src/lib/po/sv_SE.po | 6 +- src/lib/processor.h | 4 +- src/lib/scaler.h | 4 +- src/lib/sound_processor.h | 4 +- src/lib/timer.h | 4 +- src/lib/types.h | 4 +- src/lib/ui_signaller.h | 4 +- src/lib/util.cc | 28 +- src/lib/util.h | 14 +- src/lib/version.h | 4 +- src/lib/video_content.h | 4 +- src/lib/video_decoder.h | 4 +- src/lib/video_sink.h | 4 +- src/lib/video_source.h | 4 +- src/lib/wscript | 10 +- src/tools/dvdomatic.cc | 578 ----------------------- src/tools/makedcp.cc | 12 +- src/tools/po/es_ES.po | 58 +-- src/tools/po/fr_FR.po | 58 +-- src/tools/po/it_IT.po | 56 +-- src/tools/po/sv_SE.po | 58 +-- src/tools/servomatic_cli.cc | 4 +- src/tools/servomatic_gui.cc | 6 +- src/tools/servomatictest.cc | 2 +- src/tools/wscript | 14 +- src/wx/audio_dialog.cc | 2 +- src/wx/config_dialog.cc | 6 +- src/wx/config_dialog.h | 4 +- src/wx/po/es_ES.po | 16 +- src/wx/po/fr_FR.po | 16 +- src/wx/po/it_IT.po | 16 +- src/wx/po/sv_SE.po | 18 +- src/wx/wscript | 12 +- src/wx/wx_util.cc | 2 +- test/test.cc | 14 +- test/wscript | 2 +- windows/dvdomatic.bmp | Bin 343254 -> 0 bytes windows/dvdomatic.ico | Bin 9662 -> 0 bytes windows/dvdomatic.rc | 3 - windows/dvdomatic_taskbar.ico | Bin 1150 -> 0 bytes windows/installer.nsi.32.in | 70 +-- windows/installer.nsi.64.in | 72 +-- wscript | 24 +- 115 files changed, 515 insertions(+), 3345 deletions(-) delete mode 100644 TODO delete mode 100644 cscript.py delete mode 100644 doc/manual/dvdomatic-html.xsl delete mode 100644 doc/manual/dvdomatic-pdf.xsl delete mode 100644 doc/manual/dvdomatic.css delete mode 100644 doc/manual/dvdomatic.sty delete mode 100644 doc/manual/dvdomatic.xml delete mode 100644 dvdomatic.desktop.in delete mode 100644 hacks/python-playback/config.py delete mode 100755 hacks/python-playback/dvdomatic delete mode 100644 hacks/python-playback/film.py delete mode 100644 hacks/python-playback/film_view.py delete mode 100644 hacks/python-playback/player.py delete mode 100644 hacks/python-playback/ratio.py delete mode 100644 hacks/python-playback/screens delete mode 100644 hacks/python-playback/screens.py delete mode 100644 hacks/python-playback/thumbs.py delete mode 100644 hacks/python-playback/util.py delete mode 100644 hacks/python-playback/xrandr-notes delete mode 100644 icons/128x128/dvdomatic.png delete mode 100644 icons/16x16/dvdomatic.png delete mode 100644 icons/22x22/dvdomatic.png delete mode 100644 icons/32x32/dvdomatic.png delete mode 100644 icons/48x48/dvdomatic.png delete mode 100644 icons/64x64/dvdomatic.png delete mode 100755 run/dvdomatic delete mode 100644 src/tools/dvdomatic.cc delete mode 100644 windows/dvdomatic.bmp delete mode 100644 windows/dvdomatic.ico delete mode 100644 windows/dvdomatic.rc delete mode 100644 windows/dvdomatic_taskbar.ico (limited to 'src/lib/decoder.h') diff --git a/Doxyfile b/Doxyfile index 56f7e1d3c..4ed65e4f1 100644 --- a/Doxyfile +++ b/Doxyfile @@ -26,7 +26,7 @@ DOXYFILE_ENCODING = UTF-8 # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. -PROJECT_NAME = DVD-o-matic +PROJECT_NAME = DCP-o-matic # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or diff --git a/README b/README index fd3983c29..c218ed1a5 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -dvd-o-matic +DCP-o-matic ----------- Hello! @@ -33,27 +33,22 @@ You will need these libraries: libsndfile libssh -and also the command line tool: - - vobcopy (if you want to rip DVDs straight into DVD-o-matic) - Documentation ------------- -There is a manual available at http://carlh.net/software/dvdomatic +There is a manual available at http://carlh.net/software/dcpomatic The DocBook source for this is in doc/manual. In a nutshell ------------- -The `dvdomatic' program is a GTK front-end which is probably easiest +The `dcpomatic' program is a GTK front-end which is probably easiest to use. It will create a directory for a particular project, and write its data to that directory. The basic approach is: "File->New"; specify a directory. -Choose "Jobs->Copy from DVD" to read a DVD from your drive, if you have one. Fill in the fields in the window (most importantly the `content' field: specify your video, and the `Name' field: give your project [and hence DCP] a name.) @@ -76,7 +71,7 @@ Server/client ------------- Running the `servomatic' program on a remote machine will make it -listen on port 6192 (by default) and process requests from a dvdomatic +listen on port 6192 (by default) and process requests from a dcpomatic instance. This has been written with no thought to security, so don't do it over the public internet! The connection will probably need to be 1 Gb/s to make it worthwhile. diff --git a/TODO b/TODO deleted file mode 100644 index 17f02e429..000000000 --- a/TODO +++ /dev/null @@ -1,137 +0,0 @@ -Make a DCP with subs using subtitle edit. - -Look at http://liblqr.wikidot.com/en:manual - -EC2 - -Small instance $0.085 ph -Sintel Trailer 1080p @ 200000 Mbps -1247 frames @ 24fps ie 51.96s -Took 1h20 to encode - -High-CPU medium $0.186 ph -Sintel Trailer 1080p @ 200000 Mbps -1247 frames @ 24fps ie 51.96s -Took 23m to encode - -High-CPU extra-large $0.744 ph -Sintel Trailer 1080p @ 200000 Mbps -1247 frames @ 24fps ie 51.96s - - -Transfer in free -Transfer out $0.120 per GB - - -Port DVD rip - -Write still j2ks straight to a MXF. -md5_data to use openssl -Write all j2ks straight to a MXF? Possible? - -Standardise j2c/j2k -Format name in ~/.dvdomatic screws up with spaces; use ID or something -Thumbnails are poorly named -x-thread signaller -Restartable jobs somehow -More logging -Nice error when trying to thumbnail with no content. -Destroy _buffer_src_context / _buffer_sink_context -Don't start later jobs when one breaks. -Compute time remaining based on more recent information. -Use lexical_cast more -Do deps better - -options summary - -1: L -2: R -3: C -4: Lfe -5: Ls -6: Rs - -City Screen - -Screen 1: "1.37" masking preset, projector only has DCI 133 preset. - -With 1480x1080 alignment in DCI 133: bottom you see purple, yellow; top purple; left and right no lines -With 1480x1080 alignment in DCI Flat: outside masks, but you see bottom purple, yellow; left/right all; top purple - - -Screen 2: no real masking preset, projector has DCI 133 and DCI 137 - -1480x1080, DCI 133 -L yellow purple -R none -B purple -T none -1480x1080, DCI 137 -L all -R all but blue -T purple -B purple - - -Screen 3: projector has DCI 1.38 - -1480x1080 -L, R, T none -B purple + yellow - - -films-0.6: Dolby Countdown looks as though it's 3D. THX Terminator 2 fucked -(these on default settings) -fq/gradfun --- no obvious effect -hqdn3d --- pretty good denoising -ow --- no obvious effect -tn --- interesting; much noise reduction, bad artefacts on movement, colour tint even in black -unsharp --- worse - -Benchmark SWS options: lanczos ? -hqdn3d=0:0:6 ? (turn off chroma/luma blurring) - -Lanczos; no visible effect on Ghostbusters. - - -THX_Monster with master Intel Core 2 Duo E4600 (2.4GHz), slave Intel Core i3 M350 (2.27GHz) -1920 x 1080 original -> DCI Flat -240 frames - -[Gbit: gigabit ethernet rather than 100Mbit] -[im-mod: after modification to memcpy RGB data then to RGB -> XYZ in the encode thread -[hack1]: after modification to pass YUV and to swscale in the encode thread (includes im-mod) -[hack2]: modified hack1 - Time Seconds FPS Speedup relative to 1 local -1 local: 20m57 1257 0.19 x 1 -2 local: 11m24 684 0.35 x 1.84 -2 local [im-mod]: 13m13 -2 local + 1 slave: 6m34 394 0.61 x 3.19 -2 local + 2 slave: 5m13 313 0.77 x 4.02 -2 local + 4 slave: 5m05 303 0.79 x 4.15 -2 local + 4 slave [Gbit]: 2m50 170 1.41 x 7.39 -2 local + 4 slave [Gbit,im-mod]:2m33 -2 local + 4 slave [Gbit,hack1]: 3m20 -2 local + 4 slave [Gbit,hack2]: 2m22 -1 local + 8 slave [Gbit]: 2m28 148 1.62 x 8.49 -2 local + 8 slave [Gbit]: 2m41 161 1.49 x 7.81 -2 local + 8 slave [Gbit,im-mod]:2m35 - - - -Just encode 52s -Encode + Image create 1m27 -Encode + Image create (memcpy, not convert) 53s. - -THX_Monster with master Intel Core i3 M350 (2.27GHz), slave Intel Core 2 Duo E4600 (2.4GHz) -1920 x 1080 original -> DCI Flat -240 frames - - -4 local: 2m45 -4 local [im-mod]: 2m53 -4 local + 2 slave [Gbit]: 2m22 -4 local + 4 slave [Gbit]: 2m21 -4 local + 4 slave [Gbit,in-mod]:2m21 - - diff --git a/builds/control-12.04-32 b/builds/control-12.04-32 index 8cb5aceb3..d31a5e384 100644 --- a/builds/control-12.04-32 +++ b/builds/control-12.04-32 @@ -1,15 +1,15 @@ -Source: dvdomatic +Source: dcpomatic Section: video Priority: extra Maintainer: Carl Hetherington Build-Depends: debhelper (>= 8.0.0), python (>= 2.7.3), g++ (>= 4:4.6.3), pkg-config (>= 0.26), libwxgtk2.8-dev (>= 2.8.12.1), libssh-dev (>= 0.5.2), libboost-filesystem-dev (>= 1.46.0), libboost-thread-dev (>= 1.46.0), libsndfile1-dev (>= 1.0.25), libmagick++-dev (>= 8:6.6.9.7) Standards-Version: 3.9.3 -Homepage: http://carlh.net/software/dvdomatic +Homepage: http://carlh.net/software/dcpomatic -Package: dvdomatic +Package: dcpomatic Architecture: i386 Depends: libc6 (>= 2.15), libwxgtk2.8-0 (>= 2.8.12.1), libssh-4 (>= 0.5.2), libboost-filesystem1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libsndfile1 (>= 1.0.25), libmagick++4 (>= 8:6.6.9.7), libxml++2.6-2 (>= 2.34.1) Description: Generator of Digital Cinema Packages (DCPs) - DVD-o-matic generates Digital Cinema Packages (DCPs) from video and audio + DCP-o-matic generates Digital Cinema Packages (DCPs) from video and audio files (such as those from DVDs or Blu-Rays) for presentation on DCI-compliant digital projectors. diff --git a/builds/control-12.04-64 b/builds/control-12.04-64 index cdb15a87b..5d41558b6 100644 --- a/builds/control-12.04-64 +++ b/builds/control-12.04-64 @@ -1,15 +1,15 @@ -Source: dvdomatic +Source: dcpomatic Section: video Priority: extra Maintainer: Carl Hetherington Build-Depends: debhelper (>= 8.0.0), python (>= 2.7.3), g++ (>= 4:4.6.3), pkg-config (>= 0.26), libwxgtk2.8-dev (>= 2.8.12.1), libssh-dev (>= 0.5.2), libboost-filesystem-dev (>= 1.46.0), libboost-thread-dev (>= 1.46.0), libsndfile1-dev (>= 1.0.25), libmagick++-dev (>= 8:6.6.9.7) Standards-Version: 3.9.3 -Homepage: http://carlh.net/software/dvdomatic +Homepage: http://carlh.net/software/dcpomatic -Package: dvdomatic +Package: dcpomatic Architecture: amd64 Depends: libc6 (>= 2.15), libwxgtk2.8-0 (>= 2.8.12.1), libssh-4 (>= 0.5.2), libboost-filesystem1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libsndfile1 (>= 1.0.25), libmagick++4 (>= 8:6.6.9.7), libxml++2.6-2 (>= 2.34.1) Description: Generator of Digital Cinema Packages (DCPs) - DVD-o-matic generates Digital Cinema Packages (DCPs) from video and audio + DCP-o-matic generates Digital Cinema Packages (DCPs) from video and audio files (such as those from DVDs or Blu-Rays) for presentation on DCI-compliant digital projectors. diff --git a/builds/control-12.10-32 b/builds/control-12.10-32 index 1dc91b701..67933f2ed 100644 --- a/builds/control-12.10-32 +++ b/builds/control-12.10-32 @@ -1,15 +1,15 @@ -Source: dvdomatic +Source: dcpomatic Section: video Priority: extra Maintainer: Carl Hetherington Build-Depends: debhelper (>= 8.0.0), python (>= 2.7.3), g++ (>= 4:4.6.3), pkg-config (>= 0.26), libwxgtk2.8-dev (>= 2.8.12.1), libssh-dev (>= 0.5.2), libboost-filesystem-dev (>= 1.46.0), libboost-thread-dev (>= 1.46.0), libsndfile1-dev (>= 1.0.25), libmagick++-dev (>= 8:6.6.9.7) Standards-Version: 3.9.3 -Homepage: http://carlh.net/software/dvdomatic +Homepage: http://carlh.net/software/dcpomatic -Package: dvdomatic +Package: dcpomatic Architecture: i386 Depends: libc6 (>= 2.15), libwxgtk2.8-0 (>= 2.8.12.1), libssh-4 (>= 0.5.2), libboost-filesystem1.49.0 (>= 1.49.0), libboost-thread1.49.0 (>= 1.49.0), libsndfile1 (>= 1.0.25), libmagick++5 (>= 8:6.7.7.10), libxml++2.6-2 (>= 2.34.2) Description: Generator of Digital Cinema Packages (DCPs) - DVD-o-matic generates Digital Cinema Packages (DCPs) from video and audio + DCP-o-matic generates Digital Cinema Packages (DCPs) from video and audio files (such as those from DVDs or Blu-Rays) for presentation on DCI-compliant digital projectors. diff --git a/builds/control-12.10-64 b/builds/control-12.10-64 index ed0b36b2e..cddf80007 100644 --- a/builds/control-12.10-64 +++ b/builds/control-12.10-64 @@ -1,15 +1,15 @@ -Source: dvdomatic +Source: dcpomatic Section: video Priority: extra Maintainer: Carl Hetherington Build-Depends: debhelper (>= 8.0.0), python (>= 2.7.3), g++ (>= 4:4.6.3), pkg-config (>= 0.26), libwxgtk2.8-dev (>= 2.8.12.1), libssh-dev (>= 0.5.2), libboost-filesystem-dev (>= 1.46.0), libboost-thread-dev (>= 1.46.0), libsndfile1-dev (>= 1.0.25), libmagick++-dev (>= 8:6.6.9.7) Standards-Version: 3.9.3 -Homepage: http://carlh.net/software/dvdomatic +Homepage: http://carlh.net/software/dcpomatic -Package: dvdomatic +Package: dcpomatic Architecture: amd64 Depends: libc6 (>= 2.15), libwxgtk2.8-0 (>= 2.8.12.1), libssh-4 (>= 0.5.2), libboost-filesystem1.49.0 (>= 1.49.0), libboost-thread1.49.0 (>= 1.49.0), libsndfile1 (>= 1.0.25), libmagick++5 (>= 8:6.7.7.10), libxml++2.6-2 (>= 2.34.2) Description: Generator of Digital Cinema Packages (DCPs) - DVD-o-matic generates Digital Cinema Packages (DCPs) from video and audio + DCP-o-matic generates Digital Cinema Packages (DCPs) from video and audio files (such as those from DVDs or Blu-Rays) for presentation on DCI-compliant digital projectors. diff --git a/cscript b/cscript index 4873df654..07840c109 100644 --- a/cscript +++ b/cscript @@ -25,13 +25,13 @@ def build(environment, variant, version): shutil.copyfile(os.path.join('builds', 'control-%s' % variant), os.path.join('debian', 'control')) command('./waf dist') f = open(os.path.join('debian', 'files'), 'w') - print >>f,'dvdomatic_%s-1_%s.deb video extra' % (version, cpu) + print >>f,'dcpomatic_%s-1_%s.deb video extra' % (version, cpu) shutil.rmtree('build/deb', ignore_errors=True) os.makedirs('build/deb') os.chdir('build/deb') - shutil.move('../../dvdomatic-%s.tar.bz2' % version, 'dvdomatic_%s.orig.tar.bz2' % version) - command('tar xjf dvdomatic_%s.orig.tar.bz2' % version) - os.chdir('dvdomatic-%s' % version) + shutil.move('../../dcpomatic-%s.tar.bz2' % version, 'dcpomatic_%s.orig.tar.bz2' % version) + command('tar xjf dcpomatic_%s.orig.tar.bz2' % version) + os.chdir('dcpomatic-%s' % version) command('dch -b -v %s-1 "New upstream release."' % version) command('dpkg-source -b .') command('dpkg-buildpackage') @@ -39,9 +39,9 @@ def build(environment, variant, version): def make_pot(): command('./waf pot') - return [os.path.abspath('build/src/lib/libdvdomatic.pot'), - os.path.abspath('build/src/wx/libdvdomatic-wx.pot'), - os.path.abspath('build/src/tools/dvdomatic.pot')] + return [os.path.abspath('build/src/lib/libdcpomatic.pot'), + os.path.abspath('build/src/wx/libdcpomatic-wx.pot'), + os.path.abspath('build/src/tools/dcpomatic.pot')] def make_manual(): os.chdir('doc/manual') diff --git a/cscript.py b/cscript.py deleted file mode 100644 index 9b8fa46c0..000000000 --- a/cscript.py +++ /dev/null @@ -1,8 +0,0 @@ -import cdist - -def builds(): - return ['source'] - -def build_source(): - cdist.build_source_waf() - diff --git a/debian/changelog b/debian/changelog index d1cea437d..0a53eff15 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,298 +1,298 @@ -dvdomatic (0.83-1) UNRELEASED; urgency=low +dcpomatic (0.83-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Wed, 10 Apr 2013 12:48:25 +0100 -dvdomatic (0.82-1) UNRELEASED; urgency=low +dcpomatic (0.82-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Tue, 09 Apr 2013 23:43:35 +0100 -dvdomatic (0.82beta1-1) UNRELEASED; urgency=low +dcpomatic (0.82beta1-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Tue, 09 Apr 2013 21:48:56 +0100 -dvdomatic (0.81-1) UNRELEASED; urgency=low +dcpomatic (0.81-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Tue, 09 Apr 2013 19:48:04 +0100 -dvdomatic (0.81beta1-1) UNRELEASED; urgency=low +dcpomatic (0.81beta1-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Tue, 09 Apr 2013 15:37:32 +0100 -dvdomatic (0.80-1) UNRELEASED; urgency=low +dcpomatic (0.80-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Sun, 07 Apr 2013 23:48:12 +0100 -dvdomatic (0.80beta4-1) UNRELEASED; urgency=low +dcpomatic (0.80beta4-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Sun, 07 Apr 2013 23:08:49 +0100 -dvdomatic (0.80beta3-1) UNRELEASED; urgency=low +dcpomatic (0.80beta3-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Sun, 07 Apr 2013 22:44:29 +0100 -dvdomatic (0.80beta2-1) UNRELEASED; urgency=low +dcpomatic (0.80beta2-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Sun, 07 Apr 2013 22:19:34 +0100 -dvdomatic (0.80beta1-1) UNRELEASED; urgency=low +dcpomatic (0.80beta1-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Sun, 07 Apr 2013 18:21:33 +0100 -dvdomatic (0.79-1) UNRELEASED; urgency=low +dcpomatic (0.79-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Mon, 01 Apr 2013 22:37:03 +0100 -dvdomatic (0.78-1) UNRELEASED; urgency=low +dcpomatic (0.78-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Sun, 31 Mar 2013 02:43:03 +0100 -dvdomatic (0.78beta16-1) UNRELEASED; urgency=low +dcpomatic (0.78beta16-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Thu, 28 Mar 2013 16:28:05 +0000 -dvdomatic (0.78beta15-1) UNRELEASED; urgency=low +dcpomatic (0.78beta15-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Thu, 28 Mar 2013 14:25:56 +0000 -dvdomatic (0.78beta14-1) UNRELEASED; urgency=low +dcpomatic (0.78beta14-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Thu, 28 Mar 2013 10:38:07 +0000 -dvdomatic (0.78beta13-1) UNRELEASED; urgency=low +dcpomatic (0.78beta13-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Wed, 27 Mar 2013 12:26:55 +0000 -dvdomatic (0.78beta12-1) UNRELEASED; urgency=low +dcpomatic (0.78beta12-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Tue, 26 Mar 2013 21:13:54 +0000 -dvdomatic (0.78beta11-1) UNRELEASED; urgency=low +dcpomatic (0.78beta11-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Tue, 26 Mar 2013 17:34:49 +0000 -dvdomatic (0.78beta10-1) UNRELEASED; urgency=low +dcpomatic (0.78beta10-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Tue, 26 Mar 2013 11:35:15 +0000 -dvdomatic (0.78beta9-1) UNRELEASED; urgency=low +dcpomatic (0.78beta9-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Tue, 26 Mar 2013 10:36:05 +0000 -dvdomatic (0.78beta8-1) UNRELEASED; urgency=low +dcpomatic (0.78beta8-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Tue, 26 Mar 2013 00:59:36 +0000 -dvdomatic (0.78beta7-1) UNRELEASED; urgency=low +dcpomatic (0.78beta7-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Tue, 26 Mar 2013 00:19:21 +0000 -dvdomatic (0.78beta6-1) UNRELEASED; urgency=low +dcpomatic (0.78beta6-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Mon, 25 Mar 2013 00:08:10 +0000 -dvdomatic (0.78beta5-1) UNRELEASED; urgency=low +dcpomatic (0.78beta5-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Thu, 21 Mar 2013 16:32:21 +0000 -dvdomatic (0.78beta4-1) UNRELEASED; urgency=low +dcpomatic (0.78beta4-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Wed, 20 Mar 2013 15:01:10 +0000 -dvdomatic (0.78beta3-1) UNRELEASED; urgency=low +dcpomatic (0.78beta3-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Wed, 20 Mar 2013 10:49:17 +0000 -dvdomatic (0.78beta2-1) UNRELEASED; urgency=low +dcpomatic (0.78beta2-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Tue, 19 Mar 2013 21:35:50 +0000 -dvdomatic (0.78beta1-1) UNRELEASED; urgency=low +dcpomatic (0.78beta1-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Tue, 19 Mar 2013 20:50:54 +0000 -dvdomatic (0.77-1) UNRELEASED; urgency=low +dcpomatic (0.77-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Thu, 14 Mar 2013 17:12:03 +0000 -dvdomatic (0.77beta2-1) UNRELEASED; urgency=low +dcpomatic (0.77beta2-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Thu, 14 Mar 2013 15:50:43 +0000 -dvdomatic (0.77beta1-1) UNRELEASED; urgency=low +dcpomatic (0.77beta1-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Thu, 14 Mar 2013 15:14:01 +0000 -dvdomatic (0.76-1) UNRELEASED; urgency=low +dcpomatic (0.76-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Tue, 05 Mar 2013 13:30:28 +0000 -dvdomatic (0.76beta3-1) UNRELEASED; urgency=low +dcpomatic (0.76beta3-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Tue, 05 Mar 2013 12:47:20 +0000 -dvdomatic (0.76beta2-1) UNRELEASED; urgency=low +dcpomatic (0.76beta2-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Fri, 01 Mar 2013 18:32:16 +0000 -dvdomatic (0.76beta1-1) UNRELEASED; urgency=low +dcpomatic (0.76beta1-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Fri, 01 Mar 2013 17:36:55 +0000 -dvdomatic (0.75-1) UNRELEASED; urgency=low +dcpomatic (0.75-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Wed, 27 Feb 2013 11:03:07 +0000 -dvdomatic (0.75beta1-1) UNRELEASED; urgency=low +dcpomatic (0.75beta1-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Wed, 27 Feb 2013 08:20:42 +0000 -dvdomatic (0.74-1) UNRELEASED; urgency=low +dcpomatic (0.74-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Sat, 23 Feb 2013 22:57:20 +0000 -dvdomatic (0.74beta1-1) UNRELEASED; urgency=low +dcpomatic (0.74beta1-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Sat, 23 Feb 2013 21:44:22 +0000 -dvdomatic (0.73-1) UNRELEASED; urgency=low +dcpomatic (0.73-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Thu, 21 Feb 2013 00:43:40 +0000 -dvdomatic (0.73beta9-1) UNRELEASED; urgency=low +dcpomatic (0.73beta9-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Wed, 20 Feb 2013 23:40:24 +0000 -dvdomatic (0.73beta8-1) UNRELEASED; urgency=low +dcpomatic (0.73beta8-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Mon, 18 Feb 2013 22:35:51 +0000 -dvdomatic (0.73beta7-1) UNRELEASED; urgency=low +dcpomatic (0.73beta7-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Mon, 18 Feb 2013 20:38:51 +0000 -dvdomatic (0.73beta6-1) UNRELEASED; urgency=low +dcpomatic (0.73beta6-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Sun, 17 Feb 2013 23:05:56 +0000 -dvdomatic (0.73beta3-1) UNRELEASED; urgency=low +dcpomatic (0.73beta3-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Sun, 17 Feb 2013 23:05:05 +0000 -dvdomatic (0.73beta2-1) UNRELEASED; urgency=low +dcpomatic (0.73beta2-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Sat, 16 Feb 2013 22:42:32 +0000 -dvdomatic (0.73beta1-1) UNRELEASED; urgency=low +dcpomatic (0.73beta1-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Sat, 16 Feb 2013 21:19:24 +0000 -dvdomatic (0.72-1) UNRELEASED; urgency=low +dcpomatic (0.72-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Thu, 24 Jan 2013 15:31:57 +0000 -dvdomatic (0.71-1) UNRELEASED; urgency=low +dcpomatic (0.71-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Thu, 24 Jan 2013 11:36:04 +0000 -dvdomatic (0.70-1) UNRELEASED; urgency=low +dcpomatic (0.70-1) UNRELEASED; urgency=low * New upstream release. * New upstream release. @@ -300,7 +300,7 @@ dvdomatic (0.70-1) UNRELEASED; urgency=low -- Carl Hetherington Sat, 12 Jan 2013 23:07:15 +0000 -dvdomatic (0.70beta3-1) UNRELEASED; urgency=low +dcpomatic (0.70beta3-1) UNRELEASED; urgency=low * New upstream release. * New upstream release. @@ -309,13 +309,13 @@ dvdomatic (0.70beta3-1) UNRELEASED; urgency=low -- Carl Hetherington Sun, 06 Jan 2013 23:44:24 +0000 -dvdomatic (0.68-1) UNRELEASED; urgency=low +dcpomatic (0.68-1) UNRELEASED; urgency=low * New upstream release. -- Carl Hetherington Sun, 23 Dec 2012 01:43:44 +0000 -dvdomatic (0.68beta10-1) UNRELEASED; urgency=low +dcpomatic (0.68beta10-1) UNRELEASED; urgency=low * New upstream release. * New upstream release. @@ -325,91 +325,91 @@ dvdomatic (0.68beta10-1) UNRELEASED; urgency=low -- Carl Hetherington Sat, 22 Dec 2012 13:27:27 +0000 -dvdomatic (0.68beta5-1) unstable; urgency=low +dcpomatic (0.68beta5-1) unstable; urgency=low * New upstream release. -- Carl Hetherington Thu, 20 Dec 2012 07:53:46 +0000 -dvdomatic (0.68beta4-1) unstable; urgency=low +dcpomatic (0.68beta4-1) unstable; urgency=low * New upstream release. -- Carl Hetherington Thu, 20 Dec 2012 07:48:45 +0000 -dvdomatic (0.68beta3-1) unstable; urgency=low +dcpomatic (0.68beta3-1) unstable; urgency=low * New upstream release. -- Carl Hetherington Thu, 20 Dec 2012 00:35:45 +0000 -dvdomatic (0.68beta2-1) unstable; urgency=low +dcpomatic (0.68beta2-1) unstable; urgency=low * New upstream release. -- Carl Hetherington Wed, 19 Dec 2012 11:22:58 +0000 -dvdomatic (0.68beta1-1) unstable; urgency=low +dcpomatic (0.68beta1-1) unstable; urgency=low * New upstream release. -- Carl Hetherington Wed, 19 Dec 2012 10:11:13 +0000 -dvdomatic (0.67-1) unstable; urgency=low +dcpomatic (0.67-1) unstable; urgency=low * New upstream release. -- Carl Hetherington Tue, 18 Dec 2012 23:49:27 +0000 -dvdomatic (0.66-1) unstable; urgency=low +dcpomatic (0.66-1) unstable; urgency=low * New upstream release. -- Carl Hetherington Tue, 18 Dec 2012 11:29:04 +0000 -dvdomatic (0.65-1) unstable; urgency=low +dcpomatic (0.65-1) unstable; urgency=low * New upstream release. -- Carl Hetherington Tue, 18 Dec 2012 09:24:56 +0000 -dvdomatic (0.64-1) unstable; urgency=low +dcpomatic (0.64-1) unstable; urgency=low * New upstream release. -- Carl Hetherington Thu, 13 Dec 2012 21:52:09 +0000 -dvdomatic (0.63pre-1) unstable; urgency=low +dcpomatic (0.63pre-1) unstable; urgency=low * New upstream release. -- Carl Hetherington Tue, 11 Dec 2012 23:15:52 +0000 -dvdomatic (0.60-1) unstable; urgency=low +dcpomatic (0.60-1) unstable; urgency=low * New upstream release. -- Carl Hetherington Tue, 11 Dec 2012 22:46:04 +0000 -dvdomatic (0.59-1) unstable; urgency=low +dcpomatic (0.59-1) unstable; urgency=low * New upstream release. -- Carl Hetherington Mon, 10 Dec 2012 20:58:19 +0000 -dvdomatic (0.59beta5-1) unstable; urgency=low +dcpomatic (0.59beta5-1) unstable; urgency=low * New upstream release. -- Carl Hetherington Sun, 09 Dec 2012 23:51:55 +0000 -dvdomatic (0.59beta4-1) unstable; urgency=low +dcpomatic (0.59beta4-1) unstable; urgency=low * New upstream release. -- Carl Hetherington Sun, 09 Dec 2012 21:38:00 +0000 -dvdomatic (0.59beta1-1) unstable; urgency=low +dcpomatic (0.59beta1-1) unstable; urgency=low * Initial release. diff --git a/debian/copyright b/debian/copyright index 2579947e4..0cf23aacd 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,6 +1,6 @@ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: dvdomatic -Source: +Upstream-Name: dcpomatic +Source: Files: * Copyright: 2012 Carl Hetherington diff --git a/debian/files b/debian/files index 7639f05ac..ca46cf438 100644 --- a/debian/files +++ b/debian/files @@ -1 +1 @@ -dvdomatic_0.59beta1-1_i386.deb video extra +dcpomatic_0.59beta1-1_i386.deb video extra diff --git a/debian/rules b/debian/rules index 3320087a5..ba42e5291 100755 --- a/debian/rules +++ b/debian/rules @@ -19,5 +19,5 @@ override_dh_auto_build: ./waf --nocache build override_dh_auto_install: - ./waf --nocache install --destdir=debian/dvdomatic + ./waf --nocache install --destdir=debian/dcpomatic diff --git a/doc/mainpage.txt b/doc/mainpage.txt index 59c578899..649c9c609 100644 --- a/doc/mainpage.txt +++ b/doc/mainpage.txt @@ -1,37 +1,37 @@ -/** @mainpage DVD-o-matic +/** @mainpage DCP-o-matic * - * DVD-o-matic is a tool to create digital cinema packages (DCPs) from + * DCP-o-matic is a tool to create digital cinema packages (DCPs) from * video files, or from sets of TIFF image files. It is written in C++ * and distributed under the GPL. * * Video files are decoded using FFmpeg (http://ffmpeg.org), so any video - * supported by FFmpeg should be usable with DVD-o-matic. DVD-o-matic's output has been + * supported by FFmpeg should be usable with DCP-o-matic. DCP-o-matic's output has been * tested on numerous digital projectors. * - * DVD-o-matic allows you to crop black borders from movies, scale them to the correct + * DCP-o-matic allows you to crop black borders from movies, scale them to the correct * aspect ratio and apply FFmpeg filters. The time-consuming encoding of JPEG2000 files * can be parallelised amongst any number of processors on the local host and any number * of servers over a network. * - * DVD-o-matic can also make DCPs from still images, for advertisements and such-like. + * DCP-o-matic can also make DCPs from still images, for advertisements and such-like. * - * Parts of DVD-o-matic are based on OpenDCP (http://code.google.com/p/opendcp), + * Parts of DCP-o-matic are based on OpenDCP (http://code.google.com/p/opendcp), * written by Terrence Meiczinger. * - * DVD-o-matic uses libopenjpeg (http://code.google.com/p/openjpeg/) for JPEG2000 encoding + * DCP-o-matic uses libopenjpeg (http://code.google.com/p/openjpeg/) for JPEG2000 encoding * and libsndfile (http://www.mega-nerd.com/libsndfile/) for WAV file manipulation. It * also makes heavy use of the boost libraries (http://www.boost.org/). ImageMagick * (http://www.imagemagick.org/) is used for still-image encoding and decoding, and the GUI is * built using wxWidgets (http://wxwidgets.org/). It also uses libmhash (http://mhash.sourceforge.net/) * for debugging purposes. * - * Thanks are due to the authors and communities of all DVD-o-matic's dependencies. + * Thanks are due to the authors and communities of all DCP-o-matic's dependencies. * - * DVD-o-matic is distributed in the hope that there are still cinemas with projectionists + * DCP-o-matic is distributed in the hope that there are still cinemas with projectionists * who might want to use it. As Mark Kermode says, "if it doesn't have a projectionist * it's not a cinema - it's a sweetshop with a video-screen." * * Email correspondance is welcome to cth@carlh.net * - * More details can be found at http://carlh.net/software/dvdomatic + * More details can be found at http://carlh.net/software/dcpomatic */ diff --git a/doc/manual/Makefile b/doc/manual/Makefile index 94abc8516..115d7c3c8 100644 --- a/doc/manual/Makefile +++ b/doc/manual/Makefile @@ -1,4 +1,4 @@ -# DVD-o-matic manual makefile +# DCP-o-matic manual makefile all: html pdf @@ -8,7 +8,7 @@ SCREENSHOTS := file-new.png video-new-film.png still-new-film.png click-content- still-select-content-file.png examine-thumbs.png \ calculate-audio-gain.png prefs.png making-dcp.png filters.png film-tab.png video-tab.png audio-tab.png subtitles-tab.png -XML := dvdomatic.xml +XML := dcpomatic.xml GRAPHICS := @@ -70,7 +70,7 @@ diagrams/%.pdf: diagrams/%.svg # HTML # -html: $(XML) dvdomatic-html.xsl extensions-html.ent dvdomatic.css \ +html: $(XML) dcpomatic-html.xsl extensions-html.ent dcpomatic.css \ $(addprefix html/screenshots/,$(SCREENSHOTS)) \ $(subst .svg,.png,$(addprefix diagrams/,$(DIAGRAMS))) \ $(subst .svg,.png,$(addprefix graphics/,$(GRAPHICS))) \ @@ -80,19 +80,19 @@ html: $(XML) dvdomatic-html.xsl extensions-html.ent dvdomatic.css \ cp extensions-html.ent extensions.ent # DocBoox -> html - xmlto html -m dvdomatic-html.xsl dvdomatic.xml --skip-validation -o html + xmlto html -m dcpomatic-html.xsl dcpomatic.xml --skip-validation -o html # Copy graphics and CSS in # mkdir -p html/diagrams html/graphics # cp diagrams/*.png html/diagrams # cp graphics/*.png html/graphics - cp dvdomatic.css html + cp dcpomatic.css html # # PDF # -pdf: $(XML) dvdomatic-pdf.xsl extensions-pdf.ent screenshots/*.png $(subst .svg,.pdf,$(addprefix diagrams/,$(DIAGRAMS))) +pdf: $(XML) dcpomatic-pdf.xsl extensions-pdf.ent screenshots/*.png $(subst .svg,.pdf,$(addprefix diagrams/,$(DIAGRAMS))) # The DocBook needs to know what file extensions to look for # for screenshots and diagrams; use the correct file to tell it. @@ -100,14 +100,14 @@ pdf: $(XML) dvdomatic-pdf.xsl extensions-pdf.ent screenshots/*.png $(subst .svg, mkdir -p pdf - dblatex -p dvdomatic-pdf.xsl -s dvdomatic.sty -r pptex.py -T native dvdomatic.xml -t pdf -o pdf/dvdomatic.pdf + dblatex -p dcpomatic-pdf.xsl -s dcpomatic.sty -r pptex.py -T native dcpomatic.xml -t pdf -o pdf/dcpomatic.pdf # # LaTeX (handy for debugging) # -tex: $(XML) dvdomatic-pdf.xsl extensions-pdf.ent +tex: $(XML) dcpomatic-pdf.xsl extensions-pdf.ent # The DocBook needs to know what file extensions to look for # for screenshots and diagrams; use the correct file to tell it. @@ -116,8 +116,8 @@ tex: $(XML) dvdomatic-pdf.xsl extensions-pdf.ent mkdir -p tex # -P removes the revhistory table - dblatex -P doc.collab.show=0 -P latex.output.revhistory=0 -p dvdomatic-pdf.xsl -s dvdomatic.sty -r pptex.py -T native dvdomatic.xml -t tex -o tex/dvdomatic.tex + dblatex -P doc.collab.show=0 -P latex.output.revhistory=0 -p dcpomatic-pdf.xsl -s dcpomatic.sty -r pptex.py -T native dcpomatic.xml -t tex -o tex/dcpomatic.tex -clean:; rm -rf html pdf diagrams/*.pdf diagrams/*.png graphics/*.png *.aux dvdomatic.cb dvdomatic.cb2 dvdomatic.glo dvdomatic.idx dvdomatic.ilg - rm -rf dvdomatic.ind dvdomatic.lof dvdomatic.log dvdomatic.tex dvdomatic.toc extensions.ent dvdomatic.out +clean:; rm -rf html pdf diagrams/*.pdf diagrams/*.png graphics/*.png *.aux dcpomatic.cb dcpomatic.cb2 dcpomatic.glo dcpomatic.idx dcpomatic.ilg + rm -rf dcpomatic.ind dcpomatic.lof dcpomatic.log dcpomatic.tex dcpomatic.toc extensions.ent dcpomatic.out diff --git a/doc/manual/dvdomatic-html.xsl b/doc/manual/dvdomatic-html.xsl deleted file mode 100644 index 059d7ead7..000000000 --- a/doc/manual/dvdomatic-html.xsl +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - diff --git a/doc/manual/dvdomatic-pdf.xsl b/doc/manual/dvdomatic-pdf.xsl deleted file mode 100644 index 414fb64b8..000000000 --- a/doc/manual/dvdomatic-pdf.xsl +++ /dev/null @@ -1,17 +0,0 @@ - - - - -colorlinks,linkcolor=black,urlcolor=black - - -0 -0 - - -scale=0.6 - - -3 - - diff --git a/doc/manual/dvdomatic.css b/doc/manual/dvdomatic.css deleted file mode 100644 index 0e4982f20..000000000 --- a/doc/manual/dvdomatic.css +++ /dev/null @@ -1,19 +0,0 @@ -body { - font-family: luxi sans, sans-serif; - margin-left: 4em; - margin-right: 4em; - margin-top: 1em; - margin-bottom: 1em; - background-color: #E2E8EE; -} - -div.sidebar { - margin-left: 1em; - margin-right: 1em; - padding-left: 1em; - padding-right: 1em; - border-color: #000000; - border-width: 2px; - border-style: solid; - background-color: #E2E8EE; -} diff --git a/doc/manual/dvdomatic.sty b/doc/manual/dvdomatic.sty deleted file mode 100644 index 834e581fc..000000000 --- a/doc/manual/dvdomatic.sty +++ /dev/null @@ -1,68 +0,0 @@ -%% -%% This style is derivated from the docbook one -%% -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{ardour}[2007/04/04 My DocBook Style] - -%% Just use the original package and pass the options -\RequirePackageWithOptions{docbook} - -% Use a nice font -\usepackage{lmodern} - -% Define \dbend as the dangerous bend sign -\font\manual=manfnt -\def\dbend{{\manual\char127}} - -% Redefine sidebar environment to use the dangerous bend style -% Danger, Will Robinson! -\def\sidebar{\begin{trivlist}\item[]\noindent% -\begingroup\hangindent=2pc\hangafter=-2%\clubpenalty=10000% -\def\par{\endgraf\endgroup}% -\hbox to0pt{\hskip-\hangindent\dbend\hfill}\ignorespaces} -\def\endsidebar{\par\end{trivlist}} - - -% Futz with the title page; basically a copy of -% /usr/share/texmf/tex/latex/dblatex/style/dbk_title.sty -% with authors added. - -\def\DBKcover{ -\ifthenelse{\equal{\DBKedition}{}}{\def\edhead{}}{\def\edhead{Ed. \DBKedition}} - -\pagestyle{empty} - -% interligne double -\setlength{\oldbaselineskip}{\baselineskip} -\setlength{\baselineskip}{2\oldbaselineskip} -\textsf{ -\vfill -\vspace{2.5cm} -\begin{center} - \huge{\textbf{\DBKtitle}}\\ % - \ \\ % - \ \\ % - \Large{\DBKauthor}\\ % - \ifx\DBKsubtitle\relax\else% - \underline{\ \ \ \ \ \ \ \ \ \ \ }\\ % - \ \\ % - \huge{\textbf{\DBKsubtitle}}\\ % - \fi -\end{center} -\vfill -\setlength{\baselineskip}{\oldbaselineskip} -\hspace{1cm} -\vspace{1cm} -\begin{center} -\begin{tabular}{p{7cm} p{7cm}} -\Large{\DBKreference{} \edhead} & \\ -\end{tabular} -\end{center} -} - -% Format for the other pages -\newpage -\setlength{\baselineskip}{\oldbaselineskip} -%\chead[]{\DBKcheadfront} -\lfoot[]{} -} diff --git a/doc/manual/dvdomatic.xml b/doc/manual/dvdomatic.xml deleted file mode 100644 index 58315eca6..000000000 --- a/doc/manual/dvdomatic.xml +++ /dev/null @@ -1,932 +0,0 @@ - - - - -%dbcent; - -%extensions; -]> - - - -DVD-o-matic -CarlHetherington - - - -Introduction - - -Hello, and welcome to DVD-o-matic! - - -
-What is DVD-o-matic? - - -DVD-o-matic is a program to generate Digital -Cinema Packages (DCPs) from DVDs, Blu-Rays, video files such as MP4 -and AVI, or still images. The resulting DCPs will play on modern digital -cinema projectors. - - - -You might find it useful to make DVDs easier to present, to encode -independently-shot feature films, or to generate local advertising for -your cinema. - - -
- -
-Licence - - -DVD-o-matic is licensed under the GNU GPL. - - -
- -
- - -Installation - -
-Windows - - -To install DVD-o-matic on Windows, simply download the installer from -http://carlh.net -and double-click it. Click through the installer wizard, and -DVD-o-matic will be installed onto your machine. - - - -If you are using a 32-bit version of Windows, you will need the 32-bit -installer. For 64-bit Windows, either installer will work, but I -suggest you used the 64-bit version as it will allow DVD-o-matic to -use more memory. You may find that DVD-o-matic crashes if you run -many parallel encoding threads (more than 4) on the 32-bit -version. - - -
- -
-Ubuntu Linux - - -You can install DVD-o-matic on Ubuntu 12.04 (‘Precise -Pangolin’) or 12.10 (‘Quantal Quetzal’) using -.deb packages: download the appropriate package from -http://carlh.net and -double-click it. Ubuntu will install the necessary bits and pieces -and set DVD-o-matic up for you. - - -
- -
-Other Linux distributions - - -Installation on non-Ubuntu Linux is currently a little involved, as -there are no packages available (yet); you will have to compile it -from source. If you are using a non-Ubuntu distribution, do let me -know via the mailing -list and I will see about building some packages. - - - -The following dependencies are required: - -FFmpeg -libsndfile -OpenSSL -libopenjpeg -ImageMagick -Boost -libssh -GTK -wxWidgets -libdcp - - - - -Once you have installed the development packages for the dependencies, -download the source code from http://carlh.net, -unpack it and run the following commands from inside the source -directory: - - - -./waf configure -./waf build -sudo ./waf install - - - -With any luck, this will build and install DVD-o-matic on your system. To run it, enter: - - - -dvdomatic - - - -in a shell. - - -
-
- - -Creating a video DCP - - -In this chapter we will see how to create a video DCP using -DVD-o-matic. We will gloss over some of the finer details, which are -explained in later chapters. - - -
-Creating a new film - - -Let's make a very simple DCP to see how DVD-o-matic works. First, we -need some content. Download the low-resolution trailer for the open -movie Sintel from their -website. Generally, of course, one would want to use the -highest-resolution material available, but for this test we will use -the low-resolution version to save everyone's bandwidth bills. - - - -Now, start DVD-o-matic and its window will open. First, we will -create a new ‘film’. A ‘film’ is how DVD-o-matic refers to -a piece of content, along with some settings, which we will make into -a DCP. DVD-o-matic stores its data in a folder on your disk while it -creates the DCP. You can create a new film by selecting -New from the File menu, as -shown in . - - -
- Creating a new film - - - - - -
- - -This will open a dialogue box for the new film, as shown in . - - -
- Dialogue box for creating a new film - - - - - -
- - -In this dialogue box you can choose a name for the film. This will be -used to name the folder to store its data in, and also as the initial -name for the DCP itself. You can also choose whereabouts you want to create -the film. In the example from the figure, DVD-o-matic will create a -folder called ‘DCP Test’ inside my home folder (carl) into which it -will write its working files. - - - -If you always create your DCPs in a particular folder, you can use -DVD-o-matic's Preferences to make life a little -easier by setting the default folder that DVD-o-matic will offer in this dialogue. -See . - - -
- -
-Selecting content - - -The next step is to set the content that you want to use. Click the -content selector, as shown in , and a file chooser will -open for you to select the content file to use, as shown in . - - -
- Opening the content selector - - - - - -
- -
- Selecting a video content file - - - - - -
- - -Select your content file and click Open. In this -case we are using the Sintel trailer that we downloaded earlier. - - - -When you do this, DVD-o-matic will take a look at your file. After a -short while (when the progress bar at the bottom right of the window -has finished), you can look through your content using the slider to -the right of the window, as shown in . - - -
- Examining the content - - - - - -
- - -Dragging the slider will move through your video. You can also click -the Play button to play the content back. Note -that there will be no sound, and playback might not be entirely -accurate (it may be slightly slower or faster than it should be, for -example). This player is really only intended for brief inspection of -content; if you need to check it more thoroughly, use another player -such as Totem, mplayer or VLC. - - -
- -
-Setting up - - -Now there are a few things to set up to describe how the DCP should be -created. The settings are divided into four tabs: film, video, audio and subtitles. - - -
-Film tab - - -The ‘film’ tab contains settings that pertain to the whole film, as shown in . - - -
- Film settings tab - - - - - -
- - -The first thing here is the name. This is generally set to the title -of the film that is being encoded. If Use DCI -name is not ticked, the name that you specify will be used -as-is for the name of the DCP. If Use DCI name -is ticked, the name that you enter will be used as part of a -DCI-compliant name. - - - -Underneath the name field is a preview of the name that the DCP will -get. To use a DCI-compliant name, tick the Use DCI -name checkbox. The DCI name will be composed using details -of your content's soundtrack, the current date and other things that -can be specified in the DCI name details dialogue box, which you can -open by clicking on the Details button. - - - -If the DCP name is long, it may not all be visible. You can see the -full name by hovering the mouse pointer over the partial name. - - - -The Trust content's header button starts off -checked, and this means that DVD-o-matic will use the content's header -information to determine its length. If, for some reason, this header -length is wrong, uncheck the Trust content's -header button and DVD-o-matic will run through the content -to find its exact length. This may take a while for large pieces of content. - - - -Next up is the content type. This can be -‘feature’, ‘trailer’ or whatever; select the -required type from the drop-down list. - - - -The trim frames settings allow you to trim frames -from the beginning and end of the content; any trimmed frames will not -be included in the DCP. - - -
- -
-Video tab - - -This tab contains settings related to the picture in your DCP, as shown in . - - -
- Video settings tab - - - - - -
- - -The first option on this tab is the format. This will govern the -shape that DVD-o-matic will make your image into. Select the aspect -ratio that your content should be presented in. The ‘4:3 within -Flat’ and ‘16:9 within Flat’ settings will put the -image at the specified ratio within a Flat (1.85:1) frame, so that you -can project the DCP using your projector's Flat preset. - - - -The remaining options can often be left alone, but may sometimes be -useful. The ‘crop’ settings can be used to crop your -content, which can be used to remove black borders from round the -edges of DVD images, for example. The specified number of pixels will -be trimmed from each edge, and the content image in the right of the -window will be updated to show the effect of the crop. - - - -The ‘filters’ settings allow you to apply various video -filters to the image. These may be useful to try to improve -poor-quality sources like DVDs. We will discuss filtering later in the manual. - - - - -The ‘scaler’ is the method that will be used to scale up -your content to the required size for the DCP, if required. We will -discuss the options in more detail later; Bicubic is a fine choice in -most situations. - - - - -The ‘colour look-up table’ specifies the colour space that -your input content will be expected to be in. If in doubt, leave it -set to ‘sRGB’. - - - -Finally, the ‘JPEG2000 bandwidth’ setting changes how big the final -image files used within the DCP will be. Larger numbers will give -better quality, but correspondingly larger DCPs. The bandwidth can be -between 50 and 250 megabits per second (MBps). - - -
- -
-Audio tab - - -This tab contains settings related to the sound in your DCP, as shown in . - - -
- Audio settings tab - - - - - -
- - - -‘Audio Gain’ is used to alter the volume of the -soundtrack. The specified gain (in dB) will be applied to each sound -channel before it is written to the DCP. - - - -If you use a sound processor that DVD-o-matic knows about, it can help -you calculate changes in gain that you should apply. Say, for -example, that you make a test DCP and find that you have to run it at -volume 5 instead of volume 7 to get a good sound level in the screen. -If this is the case, click the Calculate... -button next to the audio gain entry, and the dialogue box in will open. - - -
- Calculating audio gain - - - - - -
- - -For our example, put 5 in the first box and 7 in the second and click -OK. DVD-o-matic will calculate the audio gain -that it should apply to make this happen. Then you can re-make the -DCP (this will be reasonably fast, as the video data will already have -been done) and it should play back at the correct volume with 7 on -your sound-rack fader. - - - -Current versions of DVD-o-matic only know about the Dolby CP750. If -you use a different sound processor, and know the gain curve of its -volume control, get in -touch. - - - -‘Audio Delay’ is used to adjust the synchronisation -between audio and video. A positive delay will move the audio later -with respect to the video, and a negative delay will move it earlier. - - - -By default the Use content‘s audio button -will be selected. This means that the DCP will use one of the -soundtracks from your content file; you can select the soundtrack that -you wish to use from the drop-down box. - - - -Note that if your content's audio is mono, DVD-o-matic will place it -in the centre channel in the DCP. - - - -Alternatively, you can supply different sound files by clicking the -Use external audio button and choosing a WAV file -for any channels that you want to appear in the DCP. These files can -be any bit depth and sampling rate, and will be re-sampled and -bit-depth converted if required. - - -
-
-Subtitles tab - - -This tab contains settings related to subtitles in your DCP, as shown in . - - -
- Subtitle settings tab - - - - - -
- - -DVD-o-matic will extract subtitles from the content, if present, and -they can be ‘burnt into’ the DCP (that is, they are -included in the image and not overlaid by the projector). Note that -DVD and Blu-Ray subtitles are stored as bitmaps, so it is not possible -(automatically) to use non-burnt-in subtitles with these sources. -Select the With Subtitles checkbox to enable -subtitles. The offset control moves the -subtitles up and down the image, and the scale -control changes their size. - - - -Future versions of DVD-o-matic will hopefully include the option to -use text subtitles (as is the norm with most professionally-mastered -DCPs). - - -
-
- -
-Making the DCP - - -Now that we have set everything up, choose Make -DCP from the Jobs menu. DVD-o-matic -will encode your DCP. This may take some time (many hours in some -cases). While the job is in progress, DVD-o-matic will update you on -how it is getting on with the progress bar in the bottom of its window, as shown in . - - -
- Making the DCP - - - - - -
- - -When it has finished, the DCP will end up on your disk inside the -film's directory. You can then copy this to a projector via a USB -stick, hard-drive or network connection. - - - -Alternatively, if you have a projector or TMS that is accessible via -SCP across your network, you can upload the content directly from -DVD-o-matic. See . - - -
-
- - - -Creating a still-image DCP - - -DVD-o-matic can also be used to create DCPs of a still image, perhaps -for an advertisement or an on-screen announcement. This chapter shows you -how to do it. - - - -As with video DCPs, the first step is to create a new -‘Film’; select New from the -File menu and the new film dialogue will open as -shown in . - - -
- Dialogue box for creating a new film - - - - - -
- - -Enter a name and click OK. Then we set up the -content; click the content selector as before, and this time we will -choose an image file, as shown in . - - -
- Selecting a still content file - - - - - -
- - -Setting up for a still image DCP is somewhat simpler than for a video; -the tabs are all the same, but many options are removed and a few are added. - - - -As with video, you can select a content type and the format (ratio) -that your image should be presented in. It will be scaled and padded -to fit the selected ratio, but in such a way that the pixel aspect -ratio is preserved. In other words, the image will not be stretched, -merely scaled; if you want to stretch your image, you will need to do -so in a separate program before importing it into DVD-o-matic. You -can also crop your image, if you so choose, and then set a duration -(in seconds) that the image should appear on screen. - - - -Still-image DCPs can include sound; this can be added from the -Audio tab. If your specified duration is shorter -than the audio, the audio will be cut off at the duration; if it is -longer, silence will be added after your audio. - - - -Finally, as with video, you can choose Make DCP -from the Jobs menu to create your DCP. This will -be much quicker than creating a video DCP, as DVD-o-matic only needs -to encode a single frame which it can then repeat. - - -
- - - -Preferences - - -DVD-o-matic provides a few preferences which can be used to modify its -behaviour. This chapter explains those options. - - -
-The preferences dialogue - - -The preferences dialogue is opened by choosing -Preferences... from the Edit -menu. The dialogue is shown in . - - -
- Preferences - - - - - -
- -
-TMS setup - - -The first part of the dialogue gives some options for specifying -details about your TMS. If you do this, and your TMS accepts SSH -connections, you can upload DCPs directly from DVD-o-matic to the TMS. -This is discussed in . - - - -TMS IP address should be set to the IP address of -your TMS, TMS target path to the place that DCPs -should be uploaded to (which will be relative to the home directory of -the SSH user). Finally, the user name and password are the -credentials required to log into the TMS via SSH. - -
- -
-Threads - - -When DVD-o-matic is encoding DCPs it can use multiple parallel threads -to speed things up. Set this value to the number of threads -DVD-o-matic should use. This would typically be set to the number of -processors (or processor cores) in your machine. - - -
- -
-Default directory for new films - - -This is the directory which DVD-o-matic will suggest initially as a place to put new films. - - -
- -
-A/B options - - -These options are for DVD-o-matic's special mode of making A/B -comparison DCPs for checking the performance of video filters. Their -use is described in . - - -
- -
-Encoding servers - - -If you have spare machines sitting around on your network not doing -much, they can be pressed into service to speed up DCP encodes. This -is done by running a small server program on the machine, which will -encode video sent to it by the ‘master’ DVD-o-matic. This -option is described in more detail in . -Use these preferences to specify the encoding servers that should be -used. - - -
- -
-
- - -Advanced topics - -This chapter describes some parts of DVD-o-matic that are -probably not essential, but which you might find useful in some -circumstances. - - -
-Filtering - - -DVD-o-matic offers a variety of filters that can be applied to your -video content. You can set up the filters by clicking the -Edit button next to the filters entry in the -setup area of the DVD-o-matic window; this opens the filters selector -as shown in . - - -
- Filters selector - - - - - -
- - -After changing the filters setup, you will need to regenerate the DCP -to see the effect on the cinema screen. The preview in DVD-o-matic -will update itself whenever filters are changed, though of course this -image is much smaller and of lower resolution than a projected image! - - -
- -
-Scaling - - -If your source material is not of the DCI-specified size, or if it -uses non-square pixels, DVD-o-matic will need to scale it. The -algorithm used to scale is set up by the Scaler -entry in the film setup area. We think ‘Bicubic’ is the -best all-round option, but tests are ongoing. - - -
- -
-TMS upload - - -If you have configured details of a TMS in the preferences dialogue -() you can upload a completed DCP -straight to your TMS buy choosing Send DCP to TMS -from the Jobs menu. - - -
- - -
-A/B comparison - - -When evaluating the effects of different filters or scalers on the -image quality, A/B mode might be useful. In this mode, DVD-o-matic -will generate a DCP where the left half of the image uses some -‘reference’ filtering and scaling, and the right half of -the image uses a different set of filters and a different scaler. -This DCP can then be played back on a projector and the image quality -evaluated. - - - -To enable A/B mode, click the A/B checkbox in the setup area of the -DVD-o-matic window. When you generate your DCP, the left half of the -screen will use the filters and scaler specified in the preferences dialogue, and the right -half will use the filters and scaler specified in the film setup. - - -
- -
-Encoding servers - - -One way to increase the speed of DCP encoding is to use more -than one machine at the same time. An instance of DVD-o-matic can -offload some of the time-consuming JPEG2000 encoding to any number of -other machines on a network. To do this, one ‘master’ -machine runs DVD-o-matic, and the ‘server’ machines run -a small program called ‘servomatic’. - - -
-Running the servers - - -There are two options for the encoding server; -servomatic_cli, which runs on the command line, and -servomatic_gui, which has a simple GUI. The command line -version is well-suited to headless servers, especially on Linux, and -the GUI version works best on Windows where it will put an icon in the -system tray. - - - -To run the command line version, simply enter: - - - -servomatic_cli - - - -at a command prompt. If you are running the program on a machine with -a multi-core processor, you can run multiple parallel encoding threads -by doing something like: - - - -servomatic_cli -t 4 - - - -to run 4 threads in parallel. - - - -To run the GUI version on windows, run the ‘DVD-o-matic encode -server’ from the start menu. An icon will appear in the system -tray; right-click it to open a menu from whence you can quit the -server or open a window to show its status. - - -
-
-Setting up DVD-o-matic - - -Once your servers are running, you need to tell your master -DVD-o-matic instance about them. Start DVD-o-matic and open the -Preferences dialog from the -Edit menu. At the bottom of this dialog is a -section where you can add, edit and remove encoding servers. For each -encoding server you need only specify its IP address and the number of -threads that it is running, so that DVD-o-matic knows how many -parallel encode jobs to send to the server. - - - -Once this is done, any encodes that you start will split the workload -up between the master machine and the servers. - - -
-
-Some notes about encode servers - - -DVD-o-matic does not mind if servers come and go; if a server -disappears, DVD-o-matic will stop sending work to it, and will check -it every minute or so in case it has come back online. - - - -You will probably find that using a 1Gb/s or faster network will -provide a significant speed-up compared to a 100Mb/s network. - - - -Making changes to the server configuration in the master DVD-o-matic -will have no effect while an encode is running; the changes will only -be noticed when a new encode is started. - - -
-
- -
- - -
diff --git a/dvdomatic.desktop.in b/dvdomatic.desktop.in deleted file mode 100644 index 65067eb3b..000000000 --- a/dvdomatic.desktop.in +++ /dev/null @@ -1,10 +0,0 @@ -[Desktop Entry] -Encoding=UTF-8 -Version=1.0 -Type=Application -Terminal=false -Exec=@PREFIX@/bin/dvdomatic -Name=DVD-o-matic -Icon=dvdomatic -Comment=DCP generator -Categories=AudioVideo;Video diff --git a/hacks/python-playback/config.py b/hacks/python-playback/config.py deleted file mode 100644 index fecf261f5..000000000 --- a/hacks/python-playback/config.py +++ /dev/null @@ -1,2 +0,0 @@ - -LEFT_SCREEN_WIDTH = 1366 diff --git a/hacks/python-playback/dvdomatic b/hacks/python-playback/dvdomatic deleted file mode 100755 index ce405f37e..000000000 --- a/hacks/python-playback/dvdomatic +++ /dev/null @@ -1,209 +0,0 @@ -#!/usr/bin/python - -import os -import operator -import traceback -import pygtk -pygtk.require('2.0') -import gtk -import glib -import gobject -import film -import film_view -import player -import screens -import thumbs -import ratio -import util - -FILM_DIRECTORY = '/home/carl/DVD' - -current_player = None -films = [] -inhibit_selection_update = False - -def find_films(): - global films - films = [] - for root, dirs, files in os.walk(FILM_DIRECTORY): - for name in files: - if os.path.basename(name) == 'info': - films.append(film.Film(os.path.join(root, os.path.dirname(name)))) - - films.sort(key = operator.attrgetter('name')) - -def update_film_store(): - global film_store - global films - global inhibit_selection_update - inhibit_selection_update = True - film_store.clear() - for f in films: - film_store.append([f.name]) - inhibit_selection_update = False - -def update_screen_store(screen_store, screens): - screen_store.clear() - for s in screens.screens: - screen_store.append([s.name]) - -def create_film_tree_view(film_store): - view = gtk.TreeView(film_store) - column = gtk.TreeViewColumn() - view.append_column(column) - cell = gtk.CellRendererText() - column.pack_start(cell) - column.add_attribute(cell, 'text', 0) - view.get_selection().set_mode(gtk.SELECTION_SINGLE) - return view - -def create_screen_view(screen_store): - view = gtk.TreeView(screen_store) - column = gtk.TreeViewColumn() - view.append_column(column) - cell = gtk.CellRendererText() - column.pack_start(cell) - column.add_attribute(cell, 'text', 0) - view.get_selection().set_mode(gtk.SELECTION_SINGLE) - return view - -def get_selected_film(): - (model, iter) = film_tree_view.get_selection().get_selected() - - for f in films: - if f.name == model.get(iter, 0)[0]: - return f - - return None - -# @return Selected screen name -def get_selected_screen(): - (model, iter) = screen_view.get_selection().get_selected() - return model.get(iter, 0)[0] - -def film_selected(selection): - if inhibit_selection_update: - return - - film_view.set(get_selected_film()) - check_for_playability() - -def screen_selected(selection): - check_for_playability() - -def check_for_playability(): - f = get_selected_film() - if screens.get_format(get_selected_screen(), f.ratio) is not None: - play_button.set_label("Play") - play_button.set_sensitive(True) - else: - play_button.set_label("Cannot play: no setting for %s on screen %s" % (ratio.find(f.ratio).name(), get_selected_screen())) - play_button.set_sensitive(False) - -def update_status(s): - global current_player - if current_player is None: - s.set_text("Not playing") - return True - - position = current_player.time_pos - if position is None: - return True - position_hms = util.s_to_hms(position) - - length = current_player.length - if length is None: - return True - - remaining = length - position - remaining_hms = util.s_to_hms(remaining) - s.set_text("Playing: %d:%02d:%02d, %d:%02d:%02d remaining" % (position_hms[0], position_hms[1], position_hms[2], remaining_hms[0], remaining_hms[1], remaining_hms[2])) - return True - -def play_clicked(b): - global current_player - f = get_selected_film() - current_player = player.get_player(f, screens.get_format(get_selected_screen(), f.ratio)) - print current_player.args - -def stop_clicked(b): - global current_player - if current_player is not None: - current_player.stop() - current_player = None - -def add_film_clicked(b): - global films - c = gtk.FileChooserDialog("New Film", main_window, gtk.FILE_CHOOSER_ACTION_CREATE_FOLDER, (("Add", gtk.RESPONSE_OK))) - c.set_current_folder(FILM_DIRECTORY) - if c.run() == gtk.RESPONSE_OK: - f = film.Film() - f.data = c.get_filename() - f.name = os.path.basename(c.get_filename()) - f.write() - find_films() - update_film_store() - c.hide() - - for i in range(0, len(films)): - if films[i].name == f.name: - film_tree_view.get_selection().select_path((i, )) - -main_window = gtk.Window(gtk.WINDOW_TOPLEVEL) -main_window.set_title("DVD-o-matic") -main_window.maximize() - -main_hbox = gtk.HBox() -main_hbox.set_spacing(12) -main_hbox.set_border_width(12) -main_window.add(main_hbox) - -find_films() -film_view = film_view.FilmView(main_window) -screens = screens.Screens("screens") - -left_vbox = gtk.VBox() -left_vbox.set_spacing(12) -main_hbox.pack_start(left_vbox, False, False) -right_vbox = gtk.VBox() -right_vbox.set_spacing(12) -main_hbox.pack_start(right_vbox) - -film_store = gtk.ListStore(gobject.TYPE_STRING) -update_film_store() - -film_tree_view = create_film_tree_view(film_store) -left_vbox.pack_start(film_tree_view, True, True) -film_tree_view.get_selection().select_path((0, )) -film_tree_view.get_selection().connect("changed", film_selected) - -add_film_button = gtk.Button(stock = gtk.STOCK_ADD) -left_vbox.pack_start(add_film_button, False, False) -add_film_button.connect("clicked", add_film_clicked) - -screen_store = gtk.ListStore(gobject.TYPE_STRING) -update_screen_store(screen_store, screens) - -screen_view = create_screen_view(screen_store) -left_vbox.pack_start(screen_view, False, False) -screen_view.get_selection().select_path((0, )) -screen_view.get_selection().connect("changed", screen_selected) - -right_vbox.pack_start(film_view, False, False) -film_view.set(films[0]) - -play_button = gtk.Button("Play") -right_vbox.pack_start(play_button) -play_button.connect("clicked", play_clicked) - -stop_button = gtk.Button("Stop") -right_vbox.pack_start(stop_button) -stop_button.connect("clicked", stop_clicked) - -status = gtk.Label() -right_vbox.pack_start(status, False, False) -glib.timeout_add_seconds(1, update_status, status) - -check_for_playability() -main_window.show_all() -gtk.main() diff --git a/hacks/python-playback/film.py b/hacks/python-playback/film.py deleted file mode 100644 index 3ad128027..000000000 --- a/hacks/python-playback/film.py +++ /dev/null @@ -1,188 +0,0 @@ -import os -import subprocess -import shlex -import shutil -import player - -class Film: - def __init__(self, data = None): - # File or directory containing content - self.content = None - # True if content is in DVD format - self.dvd = False - # DVD title number - self.dvd_title = 1 - # Directory containing metadata - self.data = None - # Film name - self.name = None - # Number of pixels by which to crop the content from each edge - self.left_crop = 0 - self.top_crop = 0 - self.right_crop = 0 - self.bottom_crop = 0 - # Use deinterlacing filter - self.deinterlace = False - # Target ratio - self.ratio = 1.85 - # Audio stream ID to play - self.aid = None - - self.width = None - self.height = None - self.fps = None - self.length = None - - if data is not None: - self.data = data - f = open(os.path.join(self.data, 'info'), 'r') - while 1: - l = f.readline() - if l == '': - break - - d = l.strip() - - s = d.find(' ') - if s != -1: - key = d[:s] - value = d[s+1:] - - if key == 'name': - self.name = value - elif key == 'content': - self.content = value - elif key == 'dvd': - self.dvd = int(value) == 1 - elif key == 'dvd_title': - self.dvd_title = int(value) - elif key == 'left_crop': - self.left_crop = int(value) - elif key == 'top_crop': - self.top_crop = int(value) - elif key == 'right_crop': - self.right_crop = int(value) - elif key == 'bottom_crop': - self.bottom_crop = int(value) - elif key == 'deinterlace': - self.deinterlace = int(value) == 1 - elif key == 'ratio': - self.ratio = float(value) - elif key == 'aid': - self.aid = int(value) - elif key == 'width': - self.width = int(value) - elif key == 'height': - self.height = int(value) - elif key == 'fps': - self.fps = float(value) - elif key == 'length': - self.length = float(value) - - if self.width is None or self.height is None or self.fps is None or self.length is None: - self.update_content_metadata() - - def write(self): - try: - os.mkdir(self.data) - except OSError: - pass - - f = open(os.path.join(self.data, 'info'), 'w') - self.write_datum(f, 'name', self.name) - self.write_datum(f, 'content', self.content) - self.write_datum(f, 'dvd', int(self.dvd)) - self.write_datum(f, 'dvd_title', self.dvd_title) - self.write_datum(f, 'left_crop', self.left_crop) - self.write_datum(f, 'top_crop', self.top_crop) - self.write_datum(f, 'right_crop', self.right_crop) - self.write_datum(f, 'bottom_crop', self.bottom_crop) - self.write_datum(f, 'deinterlace', int(self.deinterlace)) - self.write_datum(f, 'ratio', self.ratio) - self.write_datum(f, 'aid', self.aid) - self.write_datum(f, 'width', self.width) - self.write_datum(f, 'height', self.height) - self.write_datum(f, 'fps', self.fps) - self.write_datum(f, 'length', self.length) - - def write_datum(self, f, key, value): - if value is not None: - print >>f,'%s %s' % (key, str(value)) - - def thumbs_dir(self): - t = os.path.join(self.data, 'thumbs') - - try: - os.mkdir(t) - except OSError: - pass - - return t - - def thumb(self, n): - return os.path.join(self.thumbs_dir(), str('%08d.png' % (n + 1))) - - def thumbs(self): - return len(os.listdir(self.thumbs_dir())) - - def remove_thumbs(self): - shutil.rmtree(self.thumbs_dir()) - - def make_thumbs(self): - num_thumbs = 128 - cl = self.player_command_line() - if self.length is not None: - sstep = self.length / num_thumbs - else: - sstep = 100 - cl.extra = '-vo png -frames %d -sstep %d -nosound' % (num_thumbs, sstep) - os.chdir(self.thumbs_dir()) - os.system(cl.get(True)) - - def set_dvd(self, d): - self.dvd = d - self.remove_thumbs() - - def set_dvd_title(self, t): - self.dvd_title = t - self.remove_thumbs() - - def set_content(self, c): - if c == self.content: - return - - self.content = c - self.update_content_metadata() - - def player_command_line(self): - cl = player.CommandLine() - cl.dvd = self.dvd - cl.dvd_title = self.dvd_title - cl.content = self.content - return cl - - def update_content_metadata(self): - if self.content is None: - return - - self.width = None - self.height = None - self.fps = None - self.length = None - - cl = self.player_command_line() - cl.extra = '-identify -vo null -ao null -frames 0' - text = subprocess.check_output(shlex.split(cl.get(True))).decode('utf-8') - lines = text.split('\n') - for l in lines: - s = l.strip() - b = s.split('=') - if len(b) == 2: - if b[0] == 'ID_VIDEO_WIDTH': - self.width = int(b[1]) - elif b[0] == 'ID_VIDEO_HEIGHT': - self.height = int(b[1]) - elif b[0] == 'ID_VIDEO_FPS': - self.fps = float(b[1]) - elif b[0] == 'ID_LENGTH': - self.length = float(b[1]) diff --git a/hacks/python-playback/film_view.py b/hacks/python-playback/film_view.py deleted file mode 100644 index c11b2e657..000000000 --- a/hacks/python-playback/film_view.py +++ /dev/null @@ -1,212 +0,0 @@ -import os -import pygtk -pygtk.require('2.0') -import gtk -import ratio -import util -import thumbs - -class FilmView(gtk.HBox): - def __init__(self, parent): - gtk.HBox.__init__(self) - - self.parent_window = parent - - self.inhibit_save = True - - self.table = gtk.Table() - self.pack_start(self.table, True, True) - - self.table.set_row_spacings(4) - self.table.set_col_spacings(12) - self.film_name = gtk.Entry() - self.ratio = gtk.combo_box_new_text() - for r in ratio.ratios: - self.ratio.append_text(r.name()) - self.content_file_radio = gtk.RadioButton() - self.content_file_radio.set_label("File") - self.content_file_chooser = gtk.FileChooserDialog("Content", self.parent_window, gtk.FILE_CHOOSER_ACTION_OPEN, (("Select", gtk.RESPONSE_OK))) - self.content_file_button = gtk.FileChooserButton(self.content_file_chooser) - self.content_folder_radio = gtk.RadioButton() - self.content_folder_radio.set_label("Folder") - self.content_folder_radio.set_group(self.content_file_radio) - self.content_folder_chooser = gtk.FileChooserDialog("Content", self.parent_window, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, (("Select", gtk.RESPONSE_OK))) - self.content_folder_button = gtk.FileChooserButton(self.content_folder_chooser) - self.dvd = gtk.CheckButton("DVD") - self.dvd_title = gtk.SpinButton() - self.dvd_title.set_range(0, 32) - self.dvd_title.set_increments(1, 4) - self.deinterlace = gtk.CheckButton("Deinterlace") - self.left_crop = self.crop_spinbutton() - self.right_crop = self.crop_spinbutton() - self.top_crop = self.crop_spinbutton() - self.bottom_crop = self.crop_spinbutton() - - # Information about the content (immutable) - self.source_size = self.label() - self.fps = self.label() - self.length = self.label() - - # Buttons - self.thumbs_button = gtk.Button("Show Thumbnails") - - self.film_name.connect("changed", self.changed, self) - self.ratio.connect("changed", self.changed, self) - self.deinterlace.connect("toggled", self.changed, self) - self.thumbs_button.connect("clicked", self.thumbs_clicked, self) - self.content_file_radio.connect("toggled", self.content_radio_toggled, self) - self.content_folder_radio.connect("toggled", self.content_radio_toggled, self) - self.content_file_button.connect("file-set", self.content_file_chooser_file_set, self) - self.content_folder_button.connect("file-set", self.content_folder_chooser_file_set, self) - self.dvd.connect("toggled", self.changed, self) - self.dvd_title.connect("value-changed", self.changed, self) - - n = 0 - self.table.attach(self.label("Film"), 0, 1, n, n + 1) - self.table.attach(self.film_name, 1, 2, n, n + 1) - n += 1 - self.table.attach(self.label("Ratio"), 0, 1, n, n + 1) - self.table.attach(self.ratio, 1, 2, n, n + 1) - n += 1 - self.table.attach(self.label("Content"), 0, 1, n, n + 1) - b = gtk.HBox() - b.set_spacing(4) - b.pack_start(self.content_file_radio, False, False) - b.pack_start(self.content_file_button, True, True) - b.pack_start(self.content_folder_radio, False, False) - b.pack_start(self.content_folder_button, True, True) - self.table.attach(b, 1, 2, n, n + 1) - n += 1 - self.table.attach(self.dvd, 0, 2, n, n + 1) - n += 1 - self.table.attach(self.label("DVD title"), 0, 1, n, n + 1) - self.table.attach(self.dvd_title, 1, 2, n, n + 1) - n += 1 - self.table.attach(self.deinterlace, 0, 2, n, n + 1) - n += 1 - self.table.attach(self.label("Left Crop"), 0, 1, n, n + 1) - self.table.attach(self.left_crop, 1, 2, n, n + 1) - n += 1 - self.table.attach(self.label("Right Crop"), 0, 1, n, n + 1) - self.table.attach(self.right_crop, 1, 2, n, n + 1) - n += 1 - self.table.attach(self.label("Top Crop"), 0, 1, n, n + 1) - self.table.attach(self.top_crop, 1, 2, n, n + 1) - n += 1 - self.table.attach(self.label("Bottom Crop"), 0, 1, n, n + 1) - self.table.attach(self.bottom_crop, 1, 2, n, n + 1) - n += 1 - self.table.attach(self.label("Source size"), 0, 1, n, n + 1) - self.table.attach(self.source_size, 1, 2, n, n + 1) - n += 1 - self.table.attach(self.label("Frames per second"), 0, 1, n, n + 1) - self.table.attach(self.fps, 1, 2, n, n + 1) - n += 1 - self.table.attach(self.label("Length"), 0, 1, n, n + 1) - self.table.attach(self.length, 1, 2, n, n + 1) - - self.right_vbox = gtk.VBox() - self.pack_start(self.right_vbox, False, False) - - self.right_vbox.pack_start(self.thumbs_button, False, False) - - self.inhibit_save = False - - def set(self, film): - self.inhibit_save = True - - self.film = film - self.film_name.set_text(film.name) - self.ratio.set_active(ratio.ratio_to_index(film.ratio)) - if film.content is not None: - if os.path.isfile(film.content): - self.set_content_is_file(True) - self.content_file_button.set_filename(film.content) - else: - self.set_content_is_file(False) - self.content_folder_button.set_filename(film.content) - self.dvd.set_active(film.dvd) - self.dvd_title.set_value(film.dvd_title) - self.dvd_title.set_sensitive(film.dvd) - self.deinterlace.set_active(film.deinterlace) - self.left_crop.set_value(film.left_crop) - self.right_crop.set_value(film.right_crop) - self.top_crop.set_value(film.top_crop) - self.bottom_crop.set_value(film.bottom_crop) - - # Content information - if film.width is not None and film.height is not None: - self.source_size.set_text("%dx%d" % (film.width, film.height)) - else: - self.source_size.set_text("Unknown") - if film.fps is not None: - self.fps.set_text(str(film.fps)) - if film.length is not None: - self.length.set_text("%d:%02d:%02d" % util.s_to_hms(film.length)) - - self.inhibit_save = False - - def set_content_is_file(self, f): - self.content_file_button.set_sensitive(f) - self.content_folder_button.set_sensitive(not f) - self.content_file_radio.set_active(f) - self.content_folder_radio.set_active(not f) - - def label(self, text = ""): - l = gtk.Label(text) - l.set_alignment(0, 0.5) - return l - - def changed(self, a, b): - self.dvd_title.set_sensitive(self.dvd.get_active()) - self.save_film() - - def crop_spinbutton(self): - s = gtk.SpinButton() - s.set_range(0, 1024) - s.set_increments(1, 16) - s.connect("value-changed", self.changed, self) - return s - - def save_film(self): - if self.inhibit_save: - return - - self.film.name = self.film_name.get_text() - self.film.ratio = ratio.index_to_ratio(self.ratio.get_active()).ratio - - if self.content_file_radio.get_active(): - self.film.set_content(self.content_file_button.get_filename()) - else: - self.film.set_content(self.content_folder_button.get_filename()) - self.film.set_dvd(self.dvd.get_active()) - self.film.set_dvd_title(self.dvd_title.get_value_as_int()) - self.film.deinterlace = self.deinterlace.get_active() - self.film.left_crop = self.left_crop.get_value_as_int() - self.film.right_crop = self.right_crop.get_value_as_int() - self.film.top_crop = self.top_crop.get_value_as_int() - self.film.bottom_crop = self.bottom_crop.get_value_as_int() - self.film.write() - - def thumbs_clicked(self, a, b): - if self.film.thumbs() == 0: - self.film.make_thumbs() - - t = thumbs.Thumbs(self.film) - t.run() - t.hide() - self.left_crop.set_value(t.left_crop()) - self.right_crop.set_value(t.right_crop()) - self.top_crop.set_value(t.top_crop()) - self.bottom_crop.set_value(t.bottom_crop()) - - def content_file_chooser_file_set(self, a, b): - self.changed(a, b) - - def content_folder_chooser_file_set(self, a, b): - self.changed(a, b) - - def content_radio_toggled(self, a, b): - self.set_content_is_file(self.content_file_radio.get_active()) - self.changed(a, b) - diff --git a/hacks/python-playback/player.py b/hacks/python-playback/player.py deleted file mode 100644 index 5cc8da711..000000000 --- a/hacks/python-playback/player.py +++ /dev/null @@ -1,112 +0,0 @@ -import os -import threading -import subprocess -import shlex -import select -import film -import config -import mplayer - -class CommandLine: - def __init__(self): - self.position_x = 0 - self.position_y = 0 - self.output_width = None - self.output_height = None - self.mov = False - self.delay = None - self.dvd = False - self.dvd_title = 1 - self.content = None - self.extra = '' - self.crop_x = None - self.crop_y = None - self.crop_w = None - self.crop_h = None - self.deinterlace = False - self.aid = None - - def get(self, with_binary): - # hqdn3d? - # nr, unsharp? - # -vo x11 appears to be necessary to prevent unwanted hardware scaling - # -noaspect stops mplayer rescaling to the movie's specified aspect ratio - args = '-vo x11 -noaspect -ao pulse -noborder -noautosub -nosub -sws 10 ' - args += '-geometry %d:%d ' % (self.position_x, self.position_y) - - # Video filters (passed to -vf) - - filters = [] - - if self.crop_x is not None or self.crop_y is not None or self.crop_w is not None or self.crop_h is not None: - crop = 'crop=' - if self.crop_w is not None and self.crop_h is not None: - crop += '%d:%d' % (self.crop_w, self.crop_h) - if self.crop_x is not None and self.crop_x is not None: - crop += ':%d:%d' % (self.crop_x, self.crop_y) - filters.append(crop) - - if self.output_width is not None or self.output_height is not None: - filters.append('scale=%d:%d' % (self.output_width, self.output_height)) - - # Post processing - pp = [] - if self.deinterlace: - pp.append('lb') - - # Deringing filter - pp.append('dr') - - if len(pp) > 0: - pp_string = 'pp=' - for i in range(0, len(pp)): - pp_string += pp[i] - if i < len(pp) - 1: - pp += ',' - - filters.append(pp_string) - - if len(filters) > 0: - args += '-vf ' - for i in range(0, len(filters)): - args += filters[i] - if i < len(filters) - 1: - args += ',' - args += ' ' - - if self.mov: - args += '-demuxer mov ' - if self.delay is not None: - args += '-delay %f ' % float(args.delay) - if self.aid is not None: - args += '-aid %s ' % self.aid - - args += self.extra - - if self.dvd: - data_specifier = 'dvd://%d -dvd-device \"%s\"' % (self.dvd_title, self.content) - else: - data_specifier = '\"%s\"' % self.content - - if with_binary: - return 'mplayer %s %s' % (args, data_specifier) - - return '%s %s' % (args, data_specifier) - -def get_player(film, format): - cl = CommandLine() - cl.dvd = film.dvd - cl.dvd_title = film.dvd_title - cl.content = film.content - cl.crop_w = film.width - film.left_crop - film.right_crop - cl.crop_h = film.height - film.top_crop - film.bottom_crop - cl.position_x = format.x - if format.external: - cl.position_x = format.x + config.LEFT_SCREEN_WIDTH - cl.position_y = format.y - cl.output_width = format.width - cl.output_height = format.height - cl.deinterlace = film.deinterlace - cl.aid = film.aid - return mplayer.Player(cl.get(False)) - diff --git a/hacks/python-playback/ratio.py b/hacks/python-playback/ratio.py deleted file mode 100644 index 62320dc8a..000000000 --- a/hacks/python-playback/ratio.py +++ /dev/null @@ -1,56 +0,0 @@ -# Class to describe a Ratio, and a collection of common -# (and not-so-common) film ratios collected from Wikipedia. - -class Ratio: - def __init__(self, ratio, nickname = None): - self.nickname = nickname - self.ratio = ratio - - # @return presentation name of this ratio - def name(self): - if self.nickname is not None: - return "%.2f (%s)" % (self.ratio, self.nickname) - - return "%.2f" % self.ratio - -ratios = [] -ratios.append(Ratio(1.33, '4:3')) -ratios.append(Ratio(1.37, 'Academy')) -ratios.append(Ratio(1.78, '16:9')) -ratios.append(Ratio(1.85, 'Flat / widescreen')) -ratios.append(Ratio(2.39, 'CinemaScope / Panavision')) -ratios.append(Ratio(1.15, 'Movietone')) -ratios.append(Ratio(1.43, 'IMAX')) -ratios.append(Ratio(1.5)) -ratios.append(Ratio(1.56, '14:9')) -ratios.append(Ratio(1.6, '16:10')) -ratios.append(Ratio(1.67)) -ratios.append(Ratio(2, 'SuperScope')) -ratios.append(Ratio(2.2, 'Todd-AO')) -ratios.append(Ratio(2.35, 'Early CinemaScope / Panavision')) -ratios.append(Ratio(2.37, '21:9')) -ratios.append(Ratio(2.55, 'CinemaScope 55')) -ratios.append(Ratio(2.59, 'Cinerama')) -ratios.append(Ratio(2.76, 'Ultra Panavision')) -ratios.append(Ratio(2.93, 'MGM Camera 65')) -ratios.append(Ratio(4, 'Polyvision')) - -# Find a Ratio object from a fractional ratio -def find(ratio): - for r in ratios: - if r.ratio == ratio: - return r - - return None - -# @return the ith ratio -def index_to_ratio(i): - return ratios[i] - -# @return the index within the ratios list of a given fractional ratio -def ratio_to_index(r): - for i in range(0, len(ratios)): - if ratios[i].ratio == r: - return i - - return None diff --git a/hacks/python-playback/screens b/hacks/python-playback/screens deleted file mode 100644 index f389cb1c4..000000000 --- a/hacks/python-playback/screens +++ /dev/null @@ -1,62 +0,0 @@ -# Screen 1 (untested) -screen 1 -ratio 1.85 -x 175 -y 100 -width 1550 -height 950 -external 1 -ratio 2.39 -x 0 -y 200 -width 2000 -height 860 -external 1 - -# Screen 2 -screen 2 -ratio 1.85 -x 175 -y 100 -width 1550 -height 950 -external 1 -ratio 2.39 -x 0 -y 200 -width 2000 -height 860 -external 1 - -# Screen 3 (untested) -screen 3 -ratio 1.85 -x 175 -y 100 -width 1550 -height 950 -external 1 -ratio 2.39 -x 0 -y 200 -width 2000 -height 860 -external 1 - -# Carl's Laptop -screen laptop -ratio 1.85 -x 0 -y 0 -width 1366 -height 738 -ratio 2.39 -x 0 -y 0 -width 1366 -height 572 -ratio 1.78 -x 0 -y 0 -width 1366 -height 767 diff --git a/hacks/python-playback/screens.py b/hacks/python-playback/screens.py deleted file mode 100644 index 4230a4cf8..000000000 --- a/hacks/python-playback/screens.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/python - -class Screen: - def __init__(self): - self.name = None - self.formats = [] - -class Format: - def __init__(self): - self.ratio = None - self.x = None - self.y = None - self.width = None - self.height = None - self.external = False - -class Screens: - def __init__(self, file): - - self.screens = [] - - f = open(file, 'r') - current_screen = None - current_format = None - while 1: - l = f.readline() - if l == '': - break - if len(l) > 0 and l[0] == '#': - continue - - s = l.strip() - - if len(s) == 0: - continue - - b = s.split() - - if len(b) != 2: - print "WARNING: ignored line `%s' in screens file" % (s) - continue - - if b[0] == 'screen': - if current_format is not None: - current_screen.formats.append(current_format) - current_format = None - - if current_screen is not None: - self.screens.append(current_screen) - current_screen = None - - current_screen = Screen() - current_screen.name = b[1] - elif b[0] == 'ratio': - if current_format is not None: - current_screen.formats.append(current_format) - current_format = None - - current_format = Format() - current_format.ratio = float(b[1]) - elif b[0] == 'x': - current_format.x = int(b[1]) - elif b[0] == 'y': - current_format.y = int(b[1]) - elif b[0] == 'width': - current_format.width = int(b[1]) - elif b[0] == 'height': - current_format.height = int(b[1]) - elif b[0] == 'external': - current_format.external = int(b[1]) == 1 - - if current_format is not None: - current_screen.formats.append(current_format) - - if current_screen is not None: - self.screens.append(current_screen) - - def get_format(self, screen, ratio): - for s in self.screens: - if s.name == screen: - for f in s.formats: - if f.ratio == ratio: - return f - - return None diff --git a/hacks/python-playback/thumbs.py b/hacks/python-playback/thumbs.py deleted file mode 100644 index 921f82f5d..000000000 --- a/hacks/python-playback/thumbs.py +++ /dev/null @@ -1,76 +0,0 @@ -# GUI to display thumbnails and allow cropping -# to be set up - -import os -import sys -import pygtk -pygtk.require('2.0') -import gtk -import film -import player - -class Thumbs(gtk.Dialog): - def __init__(self, film): - gtk.Dialog.__init__(self) - self.film = film - self.controls = gtk.Table() - self.controls.set_col_spacings(4) - self.thumb_adj = gtk.Adjustment(0, 0, self.film.thumbs() - 1, 1, 10) - self.add_control("Thumbnail", self.thumb_adj, 0) - self.left_crop_adj = gtk.Adjustment(self.film.left_crop, 0, 1024, 1, 128) - self.add_control("Left crop", self.left_crop_adj, 1) - self.right_crop_adj = gtk.Adjustment(self.film.right_crop, 0, 1024, 1, 128) - self.add_control("Right crop", self.right_crop_adj, 2) - self.top_crop_adj = gtk.Adjustment(self.film.top_crop, 0, 1024, 1, 128) - self.add_control("Top crop", self.top_crop_adj, 3) - self.bottom_crop_adj = gtk.Adjustment(self.film.bottom_crop, 0, 1024, 1, 128) - self.add_control("Bottom crop", self.bottom_crop_adj, 4) - self.display_image = gtk.Image() - self.update_display() - window_box = gtk.HBox() - window_box.set_spacing(12) - - controls_vbox = gtk.VBox() - controls_vbox.set_spacing(4) - controls_vbox.pack_start(self.controls, False, False) - - window_box.pack_start(controls_vbox, True, True) - window_box.pack_start(self.display_image) - - self.set_title("%s Thumbnails" % film.name) - self.get_content_area().add(window_box) - self.add_button("Close", gtk.RESPONSE_ACCEPT) - self.show_all() - - for a in [self.thumb_adj, self.left_crop_adj, self.right_crop_adj, self.top_crop_adj, self.bottom_crop_adj]: - a.connect('value-changed', self.update_display, self) - - def add_control(self, name, adj, n): - l = gtk.Label(name) - l.set_alignment(1, 0.5) - self.controls.attach(l, 0, 1, n, n + 1) - s = gtk.SpinButton(adj) - self.controls.attach(s, 1, 2, n, n + 1) - - def update_display(self, a = None, b = None): - thumb_pixbuf = gtk.gdk.pixbuf_new_from_file(self.film.thumb(self.thumb_adj.get_value())) - self.width = thumb_pixbuf.get_width() - self.height = thumb_pixbuf.get_height() - left = self.left_crop() - right = self.right_crop() - top = self.top_crop() - bottom = self.bottom_crop() - pixbuf = thumb_pixbuf.subpixbuf(left, top, self.width - left - right, self.height - top - bottom) - self.display_image.set_from_pixbuf(pixbuf) - - def top_crop(self): - return int(self.top_crop_adj.get_value()) - - def bottom_crop(self): - return int(self.bottom_crop_adj.get_value()) - - def left_crop(self): - return int(self.left_crop_adj.get_value()) - - def right_crop(self): - return int(self.right_crop_adj.get_value()) diff --git a/hacks/python-playback/util.py b/hacks/python-playback/util.py deleted file mode 100644 index d78abdd00..000000000 --- a/hacks/python-playback/util.py +++ /dev/null @@ -1,7 +0,0 @@ - -def s_to_hms(s): - m = int(s / 60) - s -= (m * 60) - h = int(m / 60) - m -= (h * 60) - return (h, m, s) diff --git a/hacks/python-playback/xrandr-notes b/hacks/python-playback/xrandr-notes deleted file mode 100644 index eeabf1423..000000000 --- a/hacks/python-playback/xrandr-notes +++ /dev/null @@ -1,17 +0,0 @@ -Recommended 1680 x 1050, 60 fps -xrandr --output HDMI1 --mode 0xbc - -List modes -xrandr --verbose -q - -2048 x 1024, 24 fps -xrandr --output HDMI1 --mode 0xd1 - -cvt -to give modeline, then -xrandr --newmode modeline -then add -xrandr --verbose --addmode HDMI1 modename -then activate -xrandr --output HDMI1 --mode foo - diff --git a/icons/128x128/dvdomatic.png b/icons/128x128/dvdomatic.png deleted file mode 100644 index 9936b39af..000000000 Binary files a/icons/128x128/dvdomatic.png and /dev/null differ diff --git a/icons/16x16/dvdomatic.png b/icons/16x16/dvdomatic.png deleted file mode 100644 index 3c5a10f2d..000000000 Binary files a/icons/16x16/dvdomatic.png and /dev/null differ diff --git a/icons/22x22/dvdomatic.png b/icons/22x22/dvdomatic.png deleted file mode 100644 index dddb86298..000000000 Binary files a/icons/22x22/dvdomatic.png and /dev/null differ diff --git a/icons/32x32/dvdomatic.png b/icons/32x32/dvdomatic.png deleted file mode 100644 index 8cecf08f8..000000000 Binary files a/icons/32x32/dvdomatic.png and /dev/null differ diff --git a/icons/48x48/dvdomatic.png b/icons/48x48/dvdomatic.png deleted file mode 100644 index 07bf2d10b..000000000 Binary files a/icons/48x48/dvdomatic.png and /dev/null differ diff --git a/icons/64x64/dvdomatic.png b/icons/64x64/dvdomatic.png deleted file mode 100644 index 35564a8a2..000000000 Binary files a/icons/64x64/dvdomatic.png and /dev/null differ diff --git a/run/dvdomatic b/run/dvdomatic deleted file mode 100755 index dbc63d44a..000000000 --- a/run/dvdomatic +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -export LD_LIBRARY_PATH=build/src/lib:build/src/wx:build/src/asdcplib/src:$LD_LIBRARY_PATH -if [ "$1" == "--debug" ]; then - shift - gdb --args build/src/tools/dvdomatic $* -elif [ "$1" == "--valgrind" ]; then - shift - valgrind --tool="memcheck" build/src/tools/dvdomatic $* -elif [ "$1" == "--i18n" ]; then - shift - LANGUAGE=fr_FR.UTF8 LANG=fr_FR.UTF8 build/src/tools/dvdomatic "$*" -else - build/src/tools/dvdomatic $* -fi diff --git a/src/lib/audio_analysis.h b/src/lib/audio_analysis.h index 6e0e2b78a..ec6905105 100644 --- a/src/lib/audio_analysis.h +++ b/src/lib/audio_analysis.h @@ -17,8 +17,8 @@ */ -#ifndef DVDOMATIC_AUDIO_ANALYSIS_H -#define DVDOMATIC_AUDIO_ANALYSIS_H +#ifndef DCPOMATIC_AUDIO_ANALYSIS_H +#define DCPOMATIC_AUDIO_ANALYSIS_H #include #include diff --git a/src/lib/audio_content.h b/src/lib/audio_content.h index dbd55943d..2362786d9 100644 --- a/src/lib/audio_content.h +++ b/src/lib/audio_content.h @@ -17,8 +17,8 @@ */ -#ifndef DVDOMATIC_AUDIO_CONTENT_H -#define DVDOMATIC_AUDIO_CONTENT_H +#ifndef DCPOMATIC_AUDIO_CONTENT_H +#define DCPOMATIC_AUDIO_CONTENT_H #include "content.h" #include "util.h" diff --git a/src/lib/audio_decoder.h b/src/lib/audio_decoder.h index 24e2796ae..418fc6da2 100644 --- a/src/lib/audio_decoder.h +++ b/src/lib/audio_decoder.h @@ -21,8 +21,8 @@ * @brief Parent class for audio decoders. */ -#ifndef DVDOMATIC_AUDIO_DECODER_H -#define DVDOMATIC_AUDIO_DECODER_H +#ifndef DCPOMATIC_AUDIO_DECODER_H +#define DCPOMATIC_AUDIO_DECODER_H #include "audio_source.h" #include "decoder.h" diff --git a/src/lib/audio_mapping.h b/src/lib/audio_mapping.h index 4f2cdb7f8..248d2570e 100644 --- a/src/lib/audio_mapping.h +++ b/src/lib/audio_mapping.h @@ -17,8 +17,8 @@ */ -#ifndef DVDOMATIC_AUDIO_MAPPING_H -#define DVDOMATIC_AUDIO_MAPPING_H +#ifndef DCPOMATIC_AUDIO_MAPPING_H +#define DCPOMATIC_AUDIO_MAPPING_H #include #include diff --git a/src/lib/audio_sink.h b/src/lib/audio_sink.h index 11d578a60..085491657 100644 --- a/src/lib/audio_sink.h +++ b/src/lib/audio_sink.h @@ -17,8 +17,8 @@ */ -#ifndef DVDOMATIC_AUDIO_SINK_H -#define DVDOMATIC_AUDIO_SINK_H +#ifndef DCPOMATIC_AUDIO_SINK_H +#define DCPOMATIC_AUDIO_SINK_H class AudioSink { diff --git a/src/lib/audio_source.h b/src/lib/audio_source.h index 5a1510d3c..ee5c606dc 100644 --- a/src/lib/audio_source.h +++ b/src/lib/audio_source.h @@ -21,8 +21,8 @@ * @brief Parent class for classes which emit audio data. */ -#ifndef DVDOMATIC_AUDIO_SOURCE_H -#define DVDOMATIC_AUDIO_SOURCE_H +#ifndef DCPOMATIC_AUDIO_SOURCE_H +#define DCPOMATIC_AUDIO_SOURCE_H #include diff --git a/src/lib/config.cc b/src/lib/config.cc index 2defa0539..354940b1c 100644 --- a/src/lib/config.cc +++ b/src/lib/config.cc @@ -155,9 +155,9 @@ Config::file (bool old) const boost::filesystem::path p; p /= g_get_user_config_dir (); if (old) { - p /= ".dvdomatic"; + p /= ".dcpomatic"; } else { - p /= ".dvdomatic.xml"; + p /= ".dcpomatic.xml"; } return p.string (); } diff --git a/src/lib/config.h b/src/lib/config.h index 13d36d236..57f4fb8a9 100644 --- a/src/lib/config.h +++ b/src/lib/config.h @@ -21,8 +21,8 @@ * @brief Class holding configuration. */ -#ifndef DVDOMATIC_CONFIG_H -#define DVDOMATIC_CONFIG_H +#ifndef DCPOMATIC_CONFIG_H +#define DCPOMATIC_CONFIG_H #include #include diff --git a/src/lib/content.h b/src/lib/content.h index c8aa6b0e0..d39fc9e1a 100644 --- a/src/lib/content.h +++ b/src/lib/content.h @@ -17,8 +17,8 @@ */ -#ifndef DVDOMATIC_CONTENT_H -#define DVDOMATIC_CONTENT_H +#ifndef DCPOMATIC_CONTENT_H +#define DCPOMATIC_CONTENT_H #include #include diff --git a/src/lib/cross.cc b/src/lib/cross.cc index 2c66ab53a..f232f1779 100644 --- a/src/lib/cross.cc +++ b/src/lib/cross.cc @@ -18,20 +18,20 @@ */ #include "cross.h" -#ifdef DVDOMATIC_POSIX +#ifdef DCPOMATIC_POSIX #include #endif -#ifdef DVDOMATIC_WINDOWS +#ifdef DCPOMATIC_WINDOWS #include "windows.h" #endif void -dvdomatic_sleep (int s) +dcpomatic_sleep (int s) { -#ifdef DVDOMATIC_POSIX +#ifdef DCPOMATIC_POSIX sleep (s); #endif -#ifdef DVDOMATIC_WINDOWS +#ifdef DCPOMATIC_WINDOWS Sleep (s * 1000); #endif } diff --git a/src/lib/cross.h b/src/lib/cross.h index 110660b16..00457c968 100644 --- a/src/lib/cross.h +++ b/src/lib/cross.h @@ -17,8 +17,8 @@ */ -#ifdef DVDOMATIC_WINDOWS +#ifdef DCPOMATIC_WINDOWS #define WEXITSTATUS(w) (w) #endif -void dvdomatic_sleep (int); +void dcpomatic_sleep (int); diff --git a/src/lib/dci_metadata.h b/src/lib/dci_metadata.h index f61dae5a8..b87609ed0 100644 --- a/src/lib/dci_metadata.h +++ b/src/lib/dci_metadata.h @@ -17,8 +17,8 @@ */ -#ifndef DVDOMATIC_DCI_METADATA_H -#define DVDOMATIC_DCI_METADATA_H +#ifndef DCPOMATIC_DCI_METADATA_H +#define DCPOMATIC_DCI_METADATA_H #include #include diff --git a/src/lib/dcp_content_type.h b/src/lib/dcp_content_type.h index 960bb0129..14204bd72 100644 --- a/src/lib/dcp_content_type.h +++ b/src/lib/dcp_content_type.h @@ -17,8 +17,8 @@ */ -#ifndef DVDOMATIC_DCP_CONTENT_TYPE_H -#define DVDOMATIC_DCP_CONTENT_TYPE_H +#ifndef DCPOMATIC_DCP_CONTENT_TYPE_H +#define DCPOMATIC_DCP_CONTENT_TYPE_H /** @file src/content_type.h * @brief A description of the type of content for a DCP (e.g. feature, trailer etc.) diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc index e9499871a..da51665d1 100644 --- a/src/lib/dcp_video_frame.cc +++ b/src/lib/dcp_video_frame.cc @@ -266,7 +266,7 @@ DCPVideoFrame::encode_locally () _parameters->tcp_numlayers++; _parameters->cp_disto_alloc = 1; _parameters->cp_rsiz = CINEMA2K; - _parameters->cp_comment = strdup (N_("DVD-o-matic")); + _parameters->cp_comment = strdup (N_("DCP-o-matic")); _parameters->cp_cinema = CINEMA2K_24; /* 3 components, so use MCT */ diff --git a/src/lib/decoder.h b/src/lib/decoder.h index 0fffef257..72b866ffe 100644 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@ -21,8 +21,8 @@ * @brief Parent class for decoders of content. */ -#ifndef DVDOMATIC_DECODER_H -#define DVDOMATIC_DECODER_H +#ifndef DCPOMATIC_DECODER_H +#define DCPOMATIC_DECODER_H #include #include diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc index b897c8a31..a8e3547a1 100644 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@ -423,7 +423,7 @@ Encoder::encoder_thread (ServerDescription* server) } if (remote_backoff > 0) { - dvdomatic_sleep (remote_backoff); + dcpomatic_sleep (remote_backoff); } lock.lock (); diff --git a/src/lib/encoder.h b/src/lib/encoder.h index 70e6eea9a..56007fd48 100644 --- a/src/lib/encoder.h +++ b/src/lib/encoder.h @@ -17,8 +17,8 @@ */ -#ifndef DVDOMATIC_ENCODER_H -#define DVDOMATIC_ENCODER_H +#ifndef DCPOMATIC_ENCODER_H +#define DCPOMATIC_ENCODER_H /** @file src/encoder.h * @brief Encoder to J2K and WAV for DCP. diff --git a/src/lib/exceptions.h b/src/lib/exceptions.h index 6920556e5..6bad7c924 100644 --- a/src/lib/exceptions.h +++ b/src/lib/exceptions.h @@ -17,8 +17,8 @@ */ -#ifndef DVDOMATIC_EXCEPTIONS_H -#define DVDOMATIC_EXCEPTIONS_H +#ifndef DCPOMATIC_EXCEPTIONS_H +#define DCPOMATIC_EXCEPTIONS_H /** @file src/exceptions.h * @brief Our exceptions. diff --git a/src/lib/ffmpeg_content.h b/src/lib/ffmpeg_content.h index b49e5790e..8bf4d42a5 100644 --- a/src/lib/ffmpeg_content.h +++ b/src/lib/ffmpeg_content.h @@ -17,8 +17,8 @@ */ -#ifndef DVDOMATIC_FFMPEG_CONTENT_H -#define DVDOMATIC_FFMPEG_CONTENT_H +#ifndef DCPOMATIC_FFMPEG_CONTENT_H +#define DCPOMATIC_FFMPEG_CONTENT_H #include #include "video_content.h" diff --git a/src/lib/film.cc b/src/lib/film.cc index 6ab6551da..67605ffca 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -254,7 +254,7 @@ Film::make_dcp () throw BadSettingError (_("name"), _("cannot contain slashes")); } - log()->log (String::compose ("DVD-o-matic %1 git %2 using %3", dvdomatic_version, dvdomatic_git_commit, dependency_version_summary())); + log()->log (String::compose ("DCP-o-matic %1 git %2 using %3", dcpomatic_version, dcpomatic_git_commit, dependency_version_summary())); { char buffer[128]; @@ -270,10 +270,10 @@ Film::make_dcp () // log()->log (String::compose ("Content at %1 fps, DCP at %2 fps", source_frame_rate(), dcp_frame_rate())); log()->log (String::compose ("%1 threads", Config::instance()->num_local_encoding_threads())); log()->log (String::compose ("J2K bandwidth %1", j2k_bandwidth())); -#ifdef DVDOMATIC_DEBUG - log()->log ("DVD-o-matic built in debug mode."); +#ifdef DCPOMATIC_DEBUG + log()->log ("DCP-o-matic built in debug mode."); #else - log()->log ("DVD-o-matic built in optimised mode."); + log()->log ("DCP-o-matic built in optimised mode."); #endif #ifdef LIBDCP_DEBUG log()->log ("libdcp built in debug mode."); @@ -432,7 +432,7 @@ Film::read_metadata () boost::mutex::scoped_lock lm (_state_mutex); if (boost::filesystem::exists (file ("metadata")) && !boost::filesystem::exists (file ("metadata.xml"))) { - throw StringError (_("This film was created with an older version of DVD-o-matic, and unfortunately it cannot be loaded into this version. You will need to create a new Film, re-add your content and set it up again. Sorry!")); + throw StringError (_("This film was created with an older version of DCP-o-matic, and unfortunately it cannot be loaded into this version. You will need to create a new Film, re-add your content and set it up again. Sorry!")); } cxml::File f (file ("metadata.xml"), "Metadata"); diff --git a/src/lib/film.h b/src/lib/film.h index 4d994996e..ffa5d0690 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -22,8 +22,8 @@ * how they should be presented in a DCP. */ -#ifndef DVDOMATIC_FILM_H -#define DVDOMATIC_FILM_H +#ifndef DCPOMATIC_FILM_H +#define DCPOMATIC_FILM_H #include #include @@ -336,7 +336,7 @@ private: /** Mutex for _directory */ mutable boost::mutex _directory_mutex; - /** Name for DVD-o-matic */ + /** Name for DCP-o-matic */ std::string _name; /** True if a auto-generated DCI-compliant name should be used for our DCP */ bool _use_dci_name; diff --git a/src/lib/filter.h b/src/lib/filter.h index 205d92482..7587312c2 100644 --- a/src/lib/filter.h +++ b/src/lib/filter.h @@ -21,8 +21,8 @@ * @brief A class to describe one of FFmpeg's video or post-processing filters. */ -#ifndef DVDOMATIC_FILTER_H -#define DVDOMATIC_FILTER_H +#ifndef DCPOMATIC_FILTER_H +#define DCPOMATIC_FILTER_H #include #include diff --git a/src/lib/filter_graph.h b/src/lib/filter_graph.h index db86a677d..1ff5527ab 100644 --- a/src/lib/filter_graph.h +++ b/src/lib/filter_graph.h @@ -21,8 +21,8 @@ * @brief A graph of FFmpeg filters. */ -#ifndef DVDOMATIC_FILTER_GRAPH_H -#define DVDOMATIC_FILTER_GRAPH_H +#ifndef DCPOMATIC_FILTER_GRAPH_H +#define DCPOMATIC_FILTER_GRAPH_H #include "util.h" #include "ffmpeg_compatibility.h" diff --git a/src/lib/i18n.h b/src/lib/i18n.h index 46bb1d565..890313bc6 100644 --- a/src/lib/i18n.h +++ b/src/lib/i18n.h @@ -19,5 +19,5 @@ #include -#define _(x) dgettext ("libdvdomatic", x) +#define _(x) dgettext ("libdcpomatic", x) #define N_(x) x diff --git a/src/lib/image.h b/src/lib/image.h index 6b9ade99e..1d7d75dfc 100644 --- a/src/lib/image.h +++ b/src/lib/image.h @@ -21,8 +21,8 @@ * @brief A set of classes to describe video images. */ -#ifndef DVDOMATIC_IMAGE_H -#define DVDOMATIC_IMAGE_H +#ifndef DCPOMATIC_IMAGE_H +#define DCPOMATIC_IMAGE_H #include #include diff --git a/src/lib/job.cc b/src/lib/job.cc index ff0332d6d..2a4986f0d 100644 --- a/src/lib/job.cc +++ b/src/lib/job.cc @@ -87,7 +87,7 @@ Job::run_wrapper () set_state (FINISHED_ERROR); set_error ( e.what (), - _("It is not known what caused this error. The best idea is to report the problem to the DVD-o-matic mailing list (dvdomatic@carlh.net)") + _("It is not known what caused this error. The best idea is to report the problem to the DCP-o-matic mailing list (dcpomatic@carlh.net)") ); } catch (...) { @@ -96,7 +96,7 @@ Job::run_wrapper () set_state (FINISHED_ERROR); set_error ( _("Unknown error"), - _("It is not known what caused this error. The best idea is to report the problem to the DVD-o-matic mailing list (dvdomatic@carlh.net)") + _("It is not known what caused this error. The best idea is to report the problem to the DCP-o-matic mailing list (dcpomatic@carlh.net)") ); } diff --git a/src/lib/job.h b/src/lib/job.h index f5175c525..2119db2f3 100644 --- a/src/lib/job.h +++ b/src/lib/job.h @@ -21,8 +21,8 @@ * @brief A parent class to represent long-running tasks which are run in their own thread. */ -#ifndef DVDOMATIC_JOB_H -#define DVDOMATIC_JOB_H +#ifndef DCPOMATIC_JOB_H +#define DCPOMATIC_JOB_H #include #include diff --git a/src/lib/job_manager.cc b/src/lib/job_manager.cc index 910597628..f96275467 100644 --- a/src/lib/job_manager.cc +++ b/src/lib/job_manager.cc @@ -126,7 +126,7 @@ JobManager::scheduler () } } - dvdomatic_sleep (1); + dcpomatic_sleep (1); } } diff --git a/src/lib/log.h b/src/lib/log.h index 3a2cfcbfd..3ad6516c1 100644 --- a/src/lib/log.h +++ b/src/lib/log.h @@ -17,8 +17,8 @@ */ -#ifndef DVDOMATIC_LOG_H -#define DVDOMATIC_LOG_H +#ifndef DCPOMATIC_LOG_H +#define DCPOMATIC_LOG_H /** @file src/log.h * @brief A very simple logging class. diff --git a/src/lib/player.h b/src/lib/player.h index 8a82ab298..dbfde09a6 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -17,8 +17,8 @@ */ -#ifndef DVDOMATIC_PLAYER_H -#define DVDOMATIC_PLAYER_H +#ifndef DCPOMATIC_PLAYER_H +#define DCPOMATIC_PLAYER_H #include #include diff --git a/src/lib/po/es_ES.po b/src/lib/po/es_ES.po index 17051bd98..5c8d642e3 100644 --- a/src/lib/po/es_ES.po +++ b/src/lib/po/es_ES.po @@ -5,7 +5,7 @@ # msgid "" msgstr "" -"Project-Id-Version: LIBDVDOMATIC\n" +"Project-Id-Version: LIBDCPOMATIC\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-04-09 11:14+0100\n" "PO-Revision-Date: 2013-04-02 19:10-0500\n" @@ -250,10 +250,10 @@ msgstr "Horizontal deblocking filter A" #: src/lib/job.cc:92 src/lib/job.cc:101 msgid "" "It is not known what caused this error. The best idea is to report the " -"problem to the DVD-o-matic mailing list (dvdomatic@carlh.net)" +"problem to the DCP-o-matic mailing list (dcpomatic@carlh.net)" msgstr "" "Error desconocido. La mejor idea es informar del problema a la lista de " -"correo de DVD-O-matic (dvdomatic@carlh.net)" +"correo de DCP-o-matic (dcpomatic@carlh.net)" #: src/lib/filter.cc:82 msgid "Kernel deinterlacer" diff --git a/src/lib/po/fr_FR.po b/src/lib/po/fr_FR.po index d9d945b52..af6890d97 100644 --- a/src/lib/po/fr_FR.po +++ b/src/lib/po/fr_FR.po @@ -5,7 +5,7 @@ # msgid "" msgstr "" -"Project-Id-Version: DVD-o-matic FRENCH\n" +"Project-Id-Version: DCP-o-matic FRENCH\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-04-09 11:14+0100\n" "PO-Revision-Date: 2013-03-20 00:39+0100\n" @@ -248,10 +248,10 @@ msgstr "Filtre dé-bloc horizontal" #: src/lib/job.cc:92 src/lib/job.cc:101 msgid "" "It is not known what caused this error. The best idea is to report the " -"problem to the DVD-o-matic mailing list (dvdomatic@carlh.net)" +"problem to the DCP-o-matic mailing list (dcpomatic@carlh.net)" msgstr "" -"Erreur indéterminée. Merci de rapporter le problème à la liste DVD-o-matic " -"(dvdomatic@carlh.net)" +"Erreur indéterminée. Merci de rapporter le problème à la liste DCP-o-matic " +"(dcpomatic@carlh.net)" #: src/lib/filter.cc:82 msgid "Kernel deinterlacer" diff --git a/src/lib/po/it_IT.po b/src/lib/po/it_IT.po index 992eda107..c1ca26ea3 100644 --- a/src/lib/po/it_IT.po +++ b/src/lib/po/it_IT.po @@ -248,10 +248,10 @@ msgstr "Filtro A sblocco orizzontale" #: src/lib/job.cc:92 src/lib/job.cc:101 msgid "" "It is not known what caused this error. The best idea is to report the " -"problem to the DVD-o-matic mailing list (dvdomatic@carlh.net)" +"problem to the DCP-o-matic mailing list (dcpomatic@carlh.net)" msgstr "" "Non sappiamo cosa ha causato questo errore. La cosa migliore è inviare un " -"report del problema alla mailing list di DVD-o-matic (dvdomatic@carlh.net)" +"report del problema alla mailing list di DCP-o-matic (dcpomatic@carlh.net)" #: src/lib/filter.cc:82 msgid "Kernel deinterlacer" diff --git a/src/lib/po/sv_SE.po b/src/lib/po/sv_SE.po index d574261c8..c8695ce4d 100644 --- a/src/lib/po/sv_SE.po +++ b/src/lib/po/sv_SE.po @@ -5,7 +5,7 @@ # msgid "" msgstr "" -"Project-Id-Version: DVD-o-matic\n" +"Project-Id-Version: DCP-o-matic\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-04-09 11:14+0100\n" "PO-Revision-Date: 2013-04-09 10:13+0100\n" @@ -249,10 +249,10 @@ msgstr "Filter för horisontal kantighetsutjämning A" #: src/lib/job.cc:92 src/lib/job.cc:101 msgid "" "It is not known what caused this error. The best idea is to report the " -"problem to the DVD-o-matic mailing list (dvdomatic@carlh.net)" +"problem to the DCP-o-matic mailing list (dcpomatic@carlh.net)" msgstr "" "Det är inte känt vad som orsakade detta fel. Bästa sättet att rapportera " -"problemet är till DVD-o-matics mejl-lista (dvdomatic@carlh.net)" +"problemet är till DCP-o-matics mejl-lista (dcpomatic@carlh.net)" #: src/lib/filter.cc:82 msgid "Kernel deinterlacer" diff --git a/src/lib/processor.h b/src/lib/processor.h index 1ba396f2f..5dbafab7f 100644 --- a/src/lib/processor.h +++ b/src/lib/processor.h @@ -21,8 +21,8 @@ * @brief Parent class for classes which accept and then emit video or audio data. */ -#ifndef DVDOMATIC_PROCESSOR_H -#define DVDOMATIC_PROCESSOR_H +#ifndef DCPOMATIC_PROCESSOR_H +#define DCPOMATIC_PROCESSOR_H #include "video_source.h" #include "video_sink.h" diff --git a/src/lib/scaler.h b/src/lib/scaler.h index c80f4b7db..a736e92de 100644 --- a/src/lib/scaler.h +++ b/src/lib/scaler.h @@ -21,8 +21,8 @@ * @brief A class to describe one of FFmpeg's software scalers. */ -#ifndef DVDOMATIC_SCALER_H -#define DVDOMATIC_SCALER_H +#ifndef DCPOMATIC_SCALER_H +#define DCPOMATIC_SCALER_H #include #include diff --git a/src/lib/sound_processor.h b/src/lib/sound_processor.h index 2edf38840..bdbe72ba2 100644 --- a/src/lib/sound_processor.h +++ b/src/lib/sound_processor.h @@ -21,8 +21,8 @@ * @brief A class to describe a sound processor. */ -#ifndef DVDOMATIC_SOUND_PROCESSOR_H -#define DVDOMATIC_SOUND_PROCESSOR_H +#ifndef DCPOMATIC_SOUND_PROCESSOR_H +#define DCPOMATIC_SOUND_PROCESSOR_H #include #include diff --git a/src/lib/timer.h b/src/lib/timer.h index f509a7492..173d0d961 100644 --- a/src/lib/timer.h +++ b/src/lib/timer.h @@ -22,8 +22,8 @@ * @brief Some timing classes for debugging and profiling. */ -#ifndef DVDOMATIC_TIMER_H -#define DVDOMATIC_TIMER_H +#ifndef DCPOMATIC_TIMER_H +#define DCPOMATIC_TIMER_H #include #include diff --git a/src/lib/types.h b/src/lib/types.h index f821a74ac..c2bb9d853 100644 --- a/src/lib/types.h +++ b/src/lib/types.h @@ -17,8 +17,8 @@ */ -#ifndef DVDOMATIC_TYPES_H -#define DVDOMATIC_TYPES_H +#ifndef DCPOMATIC_TYPES_H +#define DCPOMATIC_TYPES_H #include #include diff --git a/src/lib/ui_signaller.h b/src/lib/ui_signaller.h index 221bcbe95..428ab698f 100644 --- a/src/lib/ui_signaller.h +++ b/src/lib/ui_signaller.h @@ -17,8 +17,8 @@ */ -#ifndef DVDOMATIC_UI_SIGNALLER_H -#define DVDOMATIC_UI_SIGNALLER_H +#ifndef DCPOMATIC_UI_SIGNALLER_H +#define DCPOMATIC_UI_SIGNALLER_H #include #include diff --git a/src/lib/util.cc b/src/lib/util.cc index 06da94294..ad08c6ab4 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -27,7 +27,7 @@ #include #include #include -#ifdef DVDOMATIC_POSIX +#ifdef DCPOMATIC_POSIX #include #include #endif @@ -148,7 +148,7 @@ seconds_to_approximate_hms (int s) return ap.str (); } -#ifdef DVDOMATIC_POSIX +#ifdef DCPOMATIC_POSIX /** @param l Mangled C++ identifier. * @return Demangled version. */ @@ -247,11 +247,11 @@ seconds (struct timeval t) return t.tv_sec + (double (t.tv_usec) / 1e6); } -/** Call the required functions to set up DVD-o-matic's static arrays, etc. +/** Call the required functions to set up DCP-o-matic's static arrays, etc. * Must be called from the UI thread, if there is one. */ void -dvdomatic_setup () +dcpomatic_setup () { avfilter_register_all (); @@ -264,7 +264,7 @@ dvdomatic_setup () ui_thread = boost::this_thread::get_id (); } -#ifdef DVDOMATIC_WINDOWS +#ifdef DCPOMATIC_WINDOWS boost::filesystem::path mo_path () { @@ -279,9 +279,9 @@ mo_path () #endif void -dvdomatic_setup_i18n (string lang) +dcpomatic_setup_i18n (string lang) { -#ifdef DVDOMATIC_POSIX +#ifdef DCPOMATIC_POSIX lang += ".UTF8"; #endif @@ -297,15 +297,15 @@ dvdomatic_setup_i18n (string lang) } setlocale (LC_ALL, ""); - textdomain ("libdvdomatic"); + textdomain ("libdcpomatic"); -#ifdef DVDOMATIC_WINDOWS - bindtextdomain ("libdvdomatic", mo_path().string().c_str()); - bind_textdomain_codeset ("libdvdomatic", "UTF8"); +#ifdef DCPOMATIC_WINDOWS + bindtextdomain ("libdcpomatic", mo_path().string().c_str()); + bind_textdomain_codeset ("libdcpomatic", "UTF8"); #endif -#ifdef DVDOMATIC_POSIX - bindtextdomain ("libdvdomatic", POSIX_LOCALE_PREFIX); +#ifdef DCPOMATIC_POSIX + bindtextdomain ("libdcpomatic", POSIX_LOCALE_PREFIX); #endif } @@ -909,7 +909,7 @@ cpu_info () pair info; info.second = 0; -#ifdef DVDOMATIC_POSIX +#ifdef DCPOMATIC_POSIX ifstream f (N_("/proc/cpuinfo")); while (f.good ()) { string l; diff --git a/src/lib/util.h b/src/lib/util.h index f4af7c22b..065801a88 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -22,8 +22,8 @@ * @brief Some utility functions and classes. */ -#ifndef DVDOMATIC_UTIL_H -#define DVDOMATIC_UTIL_H +#ifndef DCPOMATIC_UTIL_H +#define DCPOMATIC_UTIL_H #include #include @@ -39,7 +39,7 @@ extern "C" { #include "compose.hpp" #include "types.h" -#ifdef DVDOMATIC_DEBUG +#ifdef DCPOMATIC_DEBUG #define TIMING(...) _film->log()->microsecond_log (String::compose (__VA_ARGS__), Log::TIMING); #else #define TIMING(...) @@ -55,14 +55,14 @@ extern std::string seconds_to_approximate_hms (int); extern void stacktrace (std::ostream &, int); extern std::string dependency_version_summary (); extern double seconds (struct timeval); -extern void dvdomatic_setup (); -extern void dvdomatic_setup_i18n (std::string); +extern void dcpomatic_setup (); +extern void dcpomatic_setup_i18n (std::string); extern std::vector split_at_spaces_considering_quotes (std::string); extern std::string md5_digest (boost::filesystem::path); extern std::string md5_digest (void const *, int); extern void ensure_ui_thread (); extern std::string audio_channel_name (int); -#ifdef DVDOMATIC_WINDOWS +#ifdef DCPOMATIC_WINDOWS extern boost::filesystem::path mo_path (); #endif @@ -117,7 +117,7 @@ extern std::string get_optional_string (std::multimap /** @class Socket * @brief A class to wrap a boost::asio::ip::tcp::socket with some things - * that are useful for DVD-o-matic. + * that are useful for DCP-o-matic. * * This class wraps some things that I could not work out how to do with boost; * most notably, sync read/write calls with timeouts. diff --git a/src/lib/version.h b/src/lib/version.h index 71639e3bc..518862fc4 100644 --- a/src/lib/version.h +++ b/src/lib/version.h @@ -1,3 +1,3 @@ -extern char const * dvdomatic_version; -extern char const * dvdomatic_git_commit; +extern char const * dcpomatic_version; +extern char const * dcpomatic_git_commit; diff --git a/src/lib/video_content.h b/src/lib/video_content.h index 3d2c4cab2..75e507d4d 100644 --- a/src/lib/video_content.h +++ b/src/lib/video_content.h @@ -17,8 +17,8 @@ */ -#ifndef DVDOMATIC_VIDEO_CONTENT_H -#define DVDOMATIC_VIDEO_CONTENT_H +#ifndef DCPOMATIC_VIDEO_CONTENT_H +#define DCPOMATIC_VIDEO_CONTENT_H #include "content.h" #include "util.h" diff --git a/src/lib/video_decoder.h b/src/lib/video_decoder.h index 05cf99a96..23817c055 100644 --- a/src/lib/video_decoder.h +++ b/src/lib/video_decoder.h @@ -17,8 +17,8 @@ */ -#ifndef DVDOMATIC_VIDEO_DECODER_H -#define DVDOMATIC_VIDEO_DECODER_H +#ifndef DCPOMATIC_VIDEO_DECODER_H +#define DCPOMATIC_VIDEO_DECODER_H #include "video_source.h" #include "decoder.h" diff --git a/src/lib/video_sink.h b/src/lib/video_sink.h index 7c128cf73..c68651005 100644 --- a/src/lib/video_sink.h +++ b/src/lib/video_sink.h @@ -17,8 +17,8 @@ */ -#ifndef DVDOMATIC_VIDEO_SINK_H -#define DVDOMATIC_VIDEO_SINK_H +#ifndef DCPOMATIC_VIDEO_SINK_H +#define DCPOMATIC_VIDEO_SINK_H #include #include "util.h" diff --git a/src/lib/video_source.h b/src/lib/video_source.h index e60e7dfd0..e7c9805ef 100644 --- a/src/lib/video_source.h +++ b/src/lib/video_source.h @@ -21,8 +21,8 @@ * @brief Parent class for classes which emit video data. */ -#ifndef DVDOMATIC_VIDEO_SOURCE_H -#define DVDOMATIC_VIDEO_SOURCE_H +#ifndef DCPOMATIC_VIDEO_SOURCE_H +#define DCPOMATIC_VIDEO_SOURCE_H #include #include diff --git a/src/lib/wscript b/src/lib/wscript index 2a26c2bfe..fddebe8e6 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -66,7 +66,7 @@ def build(bld): else: obj = bld(features = 'cxx cxxshlib') - obj.name = 'libdvdomatic' + obj.name = 'libdcpomatic' obj.export_includes = ['.'] obj.uselib = """ AVCODEC AVUTIL AVFORMAT AVFILTER SWSCALE SWRESAMPLE @@ -78,12 +78,12 @@ def build(bld): if bld.env.STATIC: obj.uselib += ' XML++' obj.source = sources + " version.cc" - obj.target = 'dvdomatic' + obj.target = 'dcpomatic' - i18n.po_to_mo(os.path.join('src', 'lib'), 'libdvdomatic', bld) + i18n.po_to_mo(os.path.join('src', 'lib'), 'libdcpomatic', bld) def pot(bld): - i18n.pot(os.path.join('src', 'lib'), sources, 'libdvdomatic') + i18n.pot(os.path.join('src', 'lib'), sources, 'libdcpomatic') def pot_merge(bld): - i18n.pot_merge(os.path.join('src', 'lib'), 'libdvdomatic') + i18n.pot_merge(os.path.join('src', 'lib'), 'libdcpomatic') diff --git a/src/tools/dvdomatic.cc b/src/tools/dvdomatic.cc deleted file mode 100644 index 768819abc..000000000 --- a/src/tools/dvdomatic.cc +++ /dev/null @@ -1,578 +0,0 @@ -/* - Copyright (C) 2012 Carl Hetherington - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#ifdef __WXMSW__ -#include -#endif -#include -#include -#include -#include "wx/film_viewer.h" -#include "wx/film_editor.h" -#include "wx/job_manager_view.h" -#include "wx/config_dialog.h" -#include "wx/job_wrapper.h" -#include "wx/wx_util.h" -#include "wx/new_film_dialog.h" -#include "wx/properties_dialog.h" -#include "wx/wx_ui_signaller.h" -#include "lib/film.h" -#include "lib/format.h" -#include "lib/config.h" -#include "lib/filter.h" -#include "lib/util.h" -#include "lib/scaler.h" -#include "lib/exceptions.h" -#include "lib/version.h" -#include "lib/ui_signaller.h" -#include "lib/log.h" - -using std::cout; -using std::string; -using std::wstring; -using std::stringstream; -using std::map; -using std::make_pair; -using std::exception; -using boost::shared_ptr; - -static FilmEditor* film_editor = 0; -static FilmViewer* film_viewer = 0; -static shared_ptr 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; - -static void set_menu_sensitivity (); - -class FilmChangedDialog -{ -public: - FilmChangedDialog () - { - _dialog = new wxMessageDialog ( - 0, - wxString::Format (_("Save changes to film \"%s\" before closing?"), std_to_wx (film->name ()).data()), - _("Film changed"), - wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION - ); - } - - ~FilmChangedDialog () - { - _dialog->Destroy (); - } - - int run () - { - return _dialog->ShowModal (); - } - -private: - wxMessageDialog* _dialog; -}; - - -void -maybe_save_then_delete_film () -{ - if (!film) { - return; - } - - if (film->dirty ()) { - FilmChangedDialog d; - switch (d.run ()) { - case wxID_NO: - break; - case wxID_YES: - film->write_metadata (); - break; - } - } - - film.reset (); -} - -enum Sensitivity { - ALWAYS, - NEEDS_FILM -}; - -map menu_items; - -void -add_item (wxMenu* menu, wxString text, int id, Sensitivity sens) -{ - wxMenuItem* item = menu->Append (id, text); - menu_items.insert (make_pair (item, sens)); -} - -void -set_menu_sensitivity () -{ - for (map::iterator i = menu_items.begin(); i != menu_items.end(); ++i) { - if (i->second == NEEDS_FILM) { - i->first->Enable (film != 0); - } else { - i->first->Enable (true); - } - } -} - -enum { - ID_file_new = 1, - ID_file_open, - ID_file_save, - ID_file_properties, - ID_file_quit, - ID_edit_preferences, - ID_jobs_make_dcp, - ID_jobs_send_dcp_to_tms, - ID_jobs_show_dcp, - ID_jobs_analyse_audio, - ID_help_about -}; - -void -setup_menu (wxMenuBar* m) -{ - wxMenu* file = new wxMenu; - add_item (file, _("New..."), ID_file_new, ALWAYS); - add_item (file, _("&Open..."), ID_file_open, ALWAYS); - file->AppendSeparator (); - add_item (file, _("&Save"), ID_file_save, NEEDS_FILM); - file->AppendSeparator (); - add_item (file, _("&Properties..."), ID_file_properties, NEEDS_FILM); - file->AppendSeparator (); - add_item (file, _("&Quit"), ID_file_quit, ALWAYS); - - wxMenu* edit = new wxMenu; - add_item (edit, _("&Preferences..."), ID_edit_preferences, ALWAYS); - - jobs_menu = new wxMenu; - add_item (jobs_menu, _("&Make DCP"), ID_jobs_make_dcp, NEEDS_FILM); - add_item (jobs_menu, _("&Send DCP to TMS"), ID_jobs_send_dcp_to_tms, NEEDS_FILM); - add_item (jobs_menu, _("S&how DCP"), ID_jobs_show_dcp, NEEDS_FILM); - jobs_menu->AppendSeparator (); - add_item (jobs_menu, _("&Analyse audio"), ID_jobs_analyse_audio, NEEDS_FILM); - - wxMenu* help = new wxMenu; - add_item (help, _("About"), ID_help_about, ALWAYS); - - m->Append (file, _("&File")); - m->Append (edit, _("&Edit")); - m->Append (jobs_menu, _("&Jobs")); - m->Append (help, _("&Help")); -} - -bool -window_closed (wxCommandEvent &) -{ - maybe_save_then_delete_film (); - return false; -} - -class Frame : public wxFrame -{ -public: - Frame (wxString const & title) - : wxFrame (NULL, -1, title) - { - wxMenuBar* bar = new wxMenuBar; - setup_menu (bar); - SetMenuBar (bar); - - Connect (ID_file_new, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_new)); - Connect (ID_file_open, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_open)); - Connect (ID_file_save, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_save)); - Connect (ID_file_properties, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_properties)); - Connect (ID_file_quit, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::file_quit)); - Connect (ID_edit_preferences, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::edit_preferences)); - Connect (ID_jobs_make_dcp, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_make_dcp)); - Connect (ID_jobs_send_dcp_to_tms, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_send_dcp_to_tms)); - Connect (ID_jobs_show_dcp, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_show_dcp)); - Connect (ID_jobs_analyse_audio, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_analyse_audio)); - Connect (ID_help_about, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::help_about)); - - Connect (wxID_ANY, wxEVT_MENU_OPEN, wxMenuEventHandler (Frame::menu_opened)); - - wxPanel* panel = new wxPanel (this); - wxSizer* s = new wxBoxSizer (wxHORIZONTAL); - s->Add (panel, 1, wxEXPAND); - SetSizer (s); - - film_editor = new FilmEditor (film, panel); - film_viewer = new FilmViewer (film, panel); - JobManagerView* job_manager_view = new JobManagerView (panel); - - _top_sizer = new wxBoxSizer (wxHORIZONTAL); - _top_sizer->Add (film_editor, 0, wxALL, 6); - _top_sizer->Add (film_viewer, 1, wxEXPAND | wxALL, 6); - - wxBoxSizer* main_sizer = new wxBoxSizer (wxVERTICAL); - main_sizer->Add (_top_sizer, 2, wxEXPAND | wxALL, 6); - main_sizer->Add (job_manager_view, 1, wxEXPAND | wxALL, 6); - panel->SetSizer (main_sizer); - - set_menu_sensitivity (); - - film_editor->FileChanged.connect (bind (&Frame::file_changed, this, _1)); - if (film) { - file_changed (film->directory ()); - } else { - file_changed (""); - } - - set_film (); - - film_editor->Connect (wxID_ANY, wxEVT_SIZE, wxSizeEventHandler (Frame::film_editor_sized), 0, this); - } - -private: - - void film_editor_sized (wxSizeEvent &) - { - static bool in_layout = false; - if (!in_layout) { - in_layout = true; - _top_sizer->Layout (); - in_layout = false; - } - } - - void menu_opened (wxMenuEvent& ev) - { - if (ev.GetMenu() != jobs_menu) { - return; - } - - bool const have_dcp = film && film->have_dcp(); - jobs_menu->Enable (ID_jobs_send_dcp_to_tms, have_dcp); - jobs_menu->Enable (ID_jobs_show_dcp, have_dcp); - } - - void set_film () - { - film_viewer->set_film (film); - film_editor->set_film (film); - set_menu_sensitivity (); - } - - void file_changed (string f) - { - stringstream s; - s << wx_to_std (_("DVD-o-matic")); - if (!f.empty ()) { - s << " - " << f; - } - - SetTitle (std_to_wx (s.str())); - } - - void file_new (wxCommandEvent &) - { - NewFilmDialog* d = new NewFilmDialog (this); - int const r = d->ShowModal (); - - if (r == wxID_OK) { - - if (boost::filesystem::exists (d->get_path())) { - error_dialog (this, std_to_wx (String::compose (wx_to_std (_("The directory %1 already exists.")), d->get_path().c_str()))); - return; - } - - maybe_save_then_delete_film (); - film.reset (new Film (d->get_path (), false)); - film->log()->set_level (log_level); - film->set_name (boost::filesystem::path (d->get_path()).filename().generic_string()); - set_film (); - } - - d->Destroy (); - } - - void file_open (wxCommandEvent &) - { - wxDirDialog* c = new wxDirDialog (this, _("Select film to open"), wxStandardPaths::Get().GetDocumentsDir(), wxDEFAULT_DIALOG_STYLE | wxDD_DIR_MUST_EXIST); - int r; - while (1) { - r = c->ShowModal (); - if (r == wxID_OK && c->GetPath() == wxStandardPaths::Get().GetDocumentsDir()) { - error_dialog (this, _("You did not select a folder. Make sure that you select a folder before clicking Open.")); - } else { - break; - } - } - - if (r == wxID_OK) { - maybe_save_then_delete_film (); - try { - film.reset (new Film (wx_to_std (c->GetPath ()))); - film->log()->set_level (log_level); - set_film (); - } catch (std::exception& e) { - wxString p = c->GetPath (); - wxCharBuffer b = p.ToUTF8 (); - error_dialog (this, wxString::Format (_("Could not open film at %s (%s)"), p.data(), std_to_wx (e.what()).data())); - } - } - - c->Destroy (); - } - - void file_save (wxCommandEvent &) - { - film->write_metadata (); - } - - void file_properties (wxCommandEvent &) - { - PropertiesDialog* d = new PropertiesDialog (this, film); - d->ShowModal (); - d->Destroy (); - } - - void file_quit (wxCommandEvent &) - { - maybe_save_then_delete_film (); - Close (true); - } - - void edit_preferences (wxCommandEvent &) - { - ConfigDialog* d = new ConfigDialog (this); - d->ShowModal (); - d->Destroy (); - Config::instance()->write (); - } - - void jobs_make_dcp (wxCommandEvent &) - { - JobWrapper::make_dcp (this, film); - } - - void jobs_send_dcp_to_tms (wxCommandEvent &) - { - film->send_dcp_to_tms (); - } - - void jobs_show_dcp (wxCommandEvent &) - { -#ifdef __WXMSW__ - string d = film->directory(); - wstring w; - w.assign (d.begin(), d.end()); - ShellExecute (0, L"open", w.c_str(), 0, 0, SW_SHOWDEFAULT); -#else - int r = system ("which nautilus"); - if (WEXITSTATUS (r) == 0) { - system (string ("nautilus " + film->directory()).c_str ()); - } else { - int r = system ("which konqueror"); - if (WEXITSTATUS (r) == 0) { - system (string ("konqueror " + film->directory()).c_str ()); - } - } -#endif - } - - void jobs_analyse_audio (wxCommandEvent &) - { - film->analyse_audio (); - } - - void help_about (wxCommandEvent &) - { - wxAboutDialogInfo info; - info.SetName (_("DVD-o-matic")); - if (strcmp (dvdomatic_git_commit, "release") == 0) { - info.SetVersion (std_to_wx (String::compose ("version %1", dvdomatic_version))); - } else { - info.SetVersion (std_to_wx (String::compose ("version %1 git %2", dvdomatic_version, dvdomatic_git_commit))); - } - info.SetDescription (_("Free, open-source DCP generation from almost anything.")); - info.SetCopyright (_("(C) 2012-2013 Carl Hetherington, Terrence Meiczinger, Paul Davis, Ole Laursen")); - - wxArrayString authors; - authors.Add (wxT ("Carl Hetherington")); - authors.Add (wxT ("Terrence Meiczinger")); - authors.Add (wxT ("Paul Davis")); - authors.Add (wxT ("Ole Laursen")); - info.SetDevelopers (authors); - - wxArrayString translators; - translators.Add (wxT ("Olivier Perriere")); - translators.Add (wxT ("Lilian Lefranc")); - translators.Add (wxT ("Thierry Journet")); - translators.Add (wxT ("Massimiliano Broggi")); - translators.Add (wxT ("Manuel AC")); - translators.Add (wxT ("Adam Klotblixt")); - info.SetTranslators (translators); - - info.SetWebSite (wxT ("http://carlh.net/software/dvdomatic")); - wxAboutBox (info); - } - - wxSizer* _top_sizer; -}; - -#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_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_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 - -void -setup_i18n () -{ - int language = wxLANGUAGE_DEFAULT; - - if (Config::instance()->language()) { - wxLanguageInfo const * li = wxLocale::FindLanguageInfo (std_to_wx (Config::instance()->language().get())); - if (li) { - language = li->Language; - } - } - - if (wxLocale::IsAvailable (language)) { - locale = new wxLocale (language, wxLOCALE_LOAD_DEFAULT); - -#ifdef DVDOMATIC_WINDOWS - locale->AddCatalogLookupPathPrefix (std_to_wx (mo_path().string())); -#endif - - locale->AddCatalog (wxT ("libdvdomatic-wx")); - locale->AddCatalog (wxT ("dvdomatic")); - - if (!locale->IsOk()) { - delete locale; - locale = new wxLocale (wxLANGUAGE_ENGLISH); - language = wxLANGUAGE_ENGLISH; - } - } - - if (locale) { - dvdomatic_setup_i18n (wx_to_std (locale->GetCanonicalName ())); - } -} - -class App : public wxApp -{ - bool OnInit () - { - if (!wxApp::OnInit()) { - return false; - } - -#ifdef DVDOMATIC_POSIX - unsetenv ("UBUNTU_MENUPROXY"); -#endif - - wxInitAllImageHandlers (); - - /* Enable i18n; this will create a Config object - to look for a force-configured language. This Config - object will be wrong, however, because dvdomatic_setup - hasn't yet been called and there aren't any scalers, filters etc. - set up yet. - */ - setup_i18n (); - - /* Set things up, including scalers / filters etc. - which will now be internationalised correctly. - */ - dvdomatic_setup (); - - /* Force the configuration to be re-loaded correctly next - time it is needed. - */ - Config::drop (); - - if (!film_to_load.empty() && boost::filesystem::is_directory (film_to_load)) { - try { - film.reset (new Film (film_to_load)); - film->log()->set_level (log_level); - } catch (exception& e) { - error_dialog (0, std_to_wx (String::compose (wx_to_std (_("Could not load film %1 (%2)")), film_to_load, e.what()))); - } - } - - 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 (); - f->Show (); - - ui_signaller = new wxUISignaller (this); - this->Connect (-1, wxEVT_IDLE, wxIdleEventHandler (App::idle)); - - return true; - } - - void OnInitCmdLine (wxCmdLineParser& parser) - { - parser.SetDesc (command_line_description); - parser.SetSwitchChars (wxT ("-")); - } - - bool OnCmdLineParsed (wxCmdLineParser& parser) - { - if (parser.GetParamCount() > 0) { - if (parser.Found (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)) { - log_level = wx_to_std (log); - } - - return true; - } - - void idle (wxIdleEvent &) - { - ui_signaller->ui_idle (); - } -}; - -IMPLEMENT_APP (App) diff --git a/src/tools/makedcp.cc b/src/tools/makedcp.cc index 85134b3c5..e2e1874c4 100644 --- a/src/tools/makedcp.cc +++ b/src/tools/makedcp.cc @@ -47,9 +47,9 @@ static void help (string n) { cerr << "Syntax: " << n << " [OPTION] \n" - << " -v, --version show DVD-o-matic version\n" + << " -v, --version show DCP-o-matic version\n" << " -h, --help show this help\n" - << " -d, --deps list DVD-o-matic dependency details and quit\n" + << " -d, --deps list DCP-o-matic dependency details and quit\n" << " -t, --test run in test mode (repeatable UUID generation, timestamps etc.)\n" << " -n, --no-progress do not print progress to stdout\n" << " -r, --no-remote do not use any remote servers\n" @@ -87,7 +87,7 @@ main (int argc, char* argv[]) switch (c) { case 'v': - cout << "dvdomatic version " << dvdomatic_version << " " << dvdomatic_git_commit << "\n"; + cout << "dcpomatic version " << dcpomatic_version << " " << dcpomatic_git_commit << "\n"; exit (EXIT_SUCCESS); case 'h': help (argv[0]); @@ -117,13 +117,13 @@ main (int argc, char* argv[]) film_dir = argv[optind]; - dvdomatic_setup (); + dcpomatic_setup (); if (no_remote) { Config::instance()->set_servers (vector ()); } - cout << "DVD-o-matic " << dvdomatic_version << " git " << dvdomatic_git_commit; + cout << "DCP-o-matic " << dcpomatic_version << " git " << dcpomatic_git_commit; char buf[256]; if (gethostname (buf, 256) == 0) { cout << " on " << buf; @@ -162,7 +162,7 @@ main (int argc, char* argv[]) bool error = false; while (!should_stop) { - dvdomatic_sleep (5); + dcpomatic_sleep (5); list > jobs = JobManager::instance()->get (); diff --git a/src/tools/po/es_ES.po b/src/tools/po/es_ES.po index abfbfef6d..d35f104c6 100644 --- a/src/tools/po/es_ES.po +++ b/src/tools/po/es_ES.po @@ -5,7 +5,7 @@ # msgid "" msgstr "" -"Project-Id-Version: DVDOMATIC\n" +"Project-Id-Version: DCPOMATIC\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-04-09 11:14+0100\n" "PO-Revision-Date: 2013-03-23 21:08-0500\n" @@ -17,111 +17,111 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.5.5\n" -#: src/tools/dvdomatic.cc:177 +#: src/tools/dcpomatic.cc:177 msgid "&Analyse audio" msgstr "&Analizar audio" -#: src/tools/dvdomatic.cc:183 +#: src/tools/dcpomatic.cc:183 msgid "&Edit" msgstr "&Editar" -#: src/tools/dvdomatic.cc:182 +#: src/tools/dcpomatic.cc:182 msgid "&File" msgstr "&Archivo" -#: src/tools/dvdomatic.cc:185 +#: src/tools/dcpomatic.cc:185 msgid "&Help" msgstr "&Ayuda" -#: src/tools/dvdomatic.cc:184 +#: src/tools/dcpomatic.cc:184 msgid "&Jobs" msgstr "&Tareas" -#: src/tools/dvdomatic.cc:173 +#: src/tools/dcpomatic.cc:173 msgid "&Make DCP" msgstr "&Crear DCP" -#: src/tools/dvdomatic.cc:161 +#: src/tools/dcpomatic.cc:161 msgid "&Open..." msgstr "&Abrir..." -#: src/tools/dvdomatic.cc:170 +#: src/tools/dcpomatic.cc:170 msgid "&Preferences..." msgstr "&Preferencias..." -#: src/tools/dvdomatic.cc:165 +#: src/tools/dcpomatic.cc:165 msgid "&Properties..." msgstr "&Propiedades..." -#: src/tools/dvdomatic.cc:167 +#: src/tools/dcpomatic.cc:167 msgid "&Quit" msgstr "&Salir" -#: src/tools/dvdomatic.cc:163 +#: src/tools/dcpomatic.cc:163 msgid "&Save" msgstr "&Guardar" -#: src/tools/dvdomatic.cc:174 +#: src/tools/dcpomatic.cc:174 msgid "&Send DCP to TMS" msgstr "&Enviar DCP al TMS" -#: src/tools/dvdomatic.cc:417 +#: src/tools/dcpomatic.cc:417 msgid "" "(C) 2012-2013 Carl Hetherington, Terrence Meiczinger, Paul Davis, Ole Laursen" msgstr "" "(C) 2012-2013 Carl Hetherington, Terrence Meiczinger, Paul Davis, Ole Laursen" -#: src/tools/dvdomatic.cc:180 +#: src/tools/dcpomatic.cc:180 msgid "About" msgstr "Acerca de" -#: src/tools/dvdomatic.cc:527 +#: src/tools/dcpomatic.cc:527 #, fuzzy msgid "Could not load film %1 (%2)" msgstr "No se pudo cargar la película %s (%s)" -#: src/tools/dvdomatic.cc:339 +#: src/tools/dcpomatic.cc:339 #, c-format msgid "Could not open film at %s (%s)" msgstr "No se pudo cargar la película en %s (%s)" -#: src/tools/dvdomatic.cc:287 src/tools/dvdomatic.cc:410 -#: src/tools/dvdomatic.cc:531 -msgid "DVD-o-matic" -msgstr "DVD-o-matic" +#: src/tools/dcpomatic.cc:287 src/tools/dcpomatic.cc:410 +#: src/tools/dcpomatic.cc:531 +msgid "DCP-o-matic" +msgstr "DCP-o-matic" -#: src/tools/dvdomatic.cc:75 +#: src/tools/dcpomatic.cc:75 msgid "Film changed" msgstr "Película cambiada" -#: src/tools/dvdomatic.cc:416 +#: src/tools/dcpomatic.cc:416 msgid "Free, open-source DCP generation from almost anything." msgstr "" "Generación de DCP a partir de casi cualquier fuente, libre y de código " "abierto." -#: src/tools/dvdomatic.cc:160 +#: src/tools/dcpomatic.cc:160 msgid "New..." msgstr "Nuevo..." -#: src/tools/dvdomatic.cc:175 +#: src/tools/dcpomatic.cc:175 msgid "S&how DCP" msgstr "&Mostrar DCP" -#: src/tools/dvdomatic.cc:74 +#: src/tools/dcpomatic.cc:74 msgid "Save changes to film \"%s\" before closing?" msgstr "" -#: src/tools/dvdomatic.cc:319 +#: src/tools/dcpomatic.cc:319 msgid "Select film to open" msgstr "Selecciona la película a abrir" -#: src/tools/dvdomatic.cc:303 +#: src/tools/dcpomatic.cc:303 #, fuzzy msgid "The directory %1 already exists." msgstr "La carpeta %s ya existe." -#: src/tools/dvdomatic.cc:324 +#: src/tools/dcpomatic.cc:324 msgid "" "You did not select a folder. Make sure that you select a folder before " "clicking Open." diff --git a/src/tools/po/fr_FR.po b/src/tools/po/fr_FR.po index b40c86877..ef2246992 100644 --- a/src/tools/po/fr_FR.po +++ b/src/tools/po/fr_FR.po @@ -5,7 +5,7 @@ # msgid "" msgstr "" -"Project-Id-Version: DVD-o-matic FRENCH\n" +"Project-Id-Version: DCP-o-matic FRENCH\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-04-09 11:14+0100\n" "PO-Revision-Date: 2013-03-13 22:33+0100\n" @@ -16,109 +16,109 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: src/tools/dvdomatic.cc:177 +#: src/tools/dcpomatic.cc:177 msgid "&Analyse audio" msgstr "&Analyser le son" -#: src/tools/dvdomatic.cc:183 +#: src/tools/dcpomatic.cc:183 msgid "&Edit" msgstr "&Edition" -#: src/tools/dvdomatic.cc:182 +#: src/tools/dcpomatic.cc:182 msgid "&File" msgstr "&Fichier" -#: src/tools/dvdomatic.cc:185 +#: src/tools/dcpomatic.cc:185 msgid "&Help" msgstr "&Aide" -#: src/tools/dvdomatic.cc:184 +#: src/tools/dcpomatic.cc:184 msgid "&Jobs" msgstr "&Travaux" -#: src/tools/dvdomatic.cc:173 +#: src/tools/dcpomatic.cc:173 msgid "&Make DCP" msgstr "&Créer le DCP" -#: src/tools/dvdomatic.cc:161 +#: src/tools/dcpomatic.cc:161 msgid "&Open..." msgstr "&Ouvrir..." -#: src/tools/dvdomatic.cc:170 +#: src/tools/dcpomatic.cc:170 msgid "&Preferences..." msgstr "&Préférences..." -#: src/tools/dvdomatic.cc:165 +#: src/tools/dcpomatic.cc:165 msgid "&Properties..." msgstr "&Propriétés..." -#: src/tools/dvdomatic.cc:167 +#: src/tools/dcpomatic.cc:167 msgid "&Quit" msgstr "&Quitter" -#: src/tools/dvdomatic.cc:163 +#: src/tools/dcpomatic.cc:163 msgid "&Save" msgstr "&Enregistrer" -#: src/tools/dvdomatic.cc:174 +#: src/tools/dcpomatic.cc:174 msgid "&Send DCP to TMS" msgstr "&Envoyer le DCP dans le TMS" -#: src/tools/dvdomatic.cc:417 +#: src/tools/dcpomatic.cc:417 msgid "" "(C) 2012-2013 Carl Hetherington, Terrence Meiczinger, Paul Davis, Ole Laursen" msgstr "" "(C) 2012-2013 Carl Hetherington, Terrence Meiczinger, Paul Davis, Ole Laursen" -#: src/tools/dvdomatic.cc:180 +#: src/tools/dcpomatic.cc:180 msgid "About" msgstr "A Propos" -#: src/tools/dvdomatic.cc:527 +#: src/tools/dcpomatic.cc:527 #, fuzzy msgid "Could not load film %1 (%2)" msgstr "Impossible de charger le film %s (%s)" -#: src/tools/dvdomatic.cc:339 +#: src/tools/dcpomatic.cc:339 #, c-format msgid "Could not open film at %s (%s)" msgstr "Impossible d'ouvrir le film à %s (%s)" -#: src/tools/dvdomatic.cc:287 src/tools/dvdomatic.cc:410 -#: src/tools/dvdomatic.cc:531 -msgid "DVD-o-matic" -msgstr "DVD-o-matic" +#: src/tools/dcpomatic.cc:287 src/tools/dcpomatic.cc:410 +#: src/tools/dcpomatic.cc:531 +msgid "DCP-o-matic" +msgstr "DCP-o-matic" -#: src/tools/dvdomatic.cc:75 +#: src/tools/dcpomatic.cc:75 msgid "Film changed" msgstr "Film changé" -#: src/tools/dvdomatic.cc:416 +#: src/tools/dcpomatic.cc:416 msgid "Free, open-source DCP generation from almost anything." msgstr "Création de DCP libre et open-source à partir de presque tout." -#: src/tools/dvdomatic.cc:160 +#: src/tools/dcpomatic.cc:160 msgid "New..." msgstr "Nouveau..." -#: src/tools/dvdomatic.cc:175 +#: src/tools/dcpomatic.cc:175 msgid "S&how DCP" msgstr "Voir le DCP" -#: src/tools/dvdomatic.cc:74 +#: src/tools/dcpomatic.cc:74 msgid "Save changes to film \"%s\" before closing?" msgstr "" -#: src/tools/dvdomatic.cc:319 +#: src/tools/dcpomatic.cc:319 msgid "Select film to open" msgstr "Sélectionner le film à ouvrir" -#: src/tools/dvdomatic.cc:303 +#: src/tools/dcpomatic.cc:303 #, fuzzy msgid "The directory %1 already exists." msgstr "Le dossier %s existe déjà." -#: src/tools/dvdomatic.cc:324 +#: src/tools/dcpomatic.cc:324 msgid "" "You did not select a folder. Make sure that you select a folder before " "clicking Open." diff --git a/src/tools/po/it_IT.po b/src/tools/po/it_IT.po index 38cbec157..998f70059 100644 --- a/src/tools/po/it_IT.po +++ b/src/tools/po/it_IT.po @@ -17,107 +17,107 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.5.5\n" -#: src/tools/dvdomatic.cc:177 +#: src/tools/dcpomatic.cc:177 msgid "&Analyse audio" msgstr "&Analizza audio" -#: src/tools/dvdomatic.cc:183 +#: src/tools/dcpomatic.cc:183 msgid "&Edit" msgstr "&Modifica" -#: src/tools/dvdomatic.cc:182 +#: src/tools/dcpomatic.cc:182 msgid "&File" msgstr "&File" -#: src/tools/dvdomatic.cc:185 +#: src/tools/dcpomatic.cc:185 msgid "&Help" msgstr "&Aiuto" -#: src/tools/dvdomatic.cc:184 +#: src/tools/dcpomatic.cc:184 msgid "&Jobs" msgstr "&Lavori" -#: src/tools/dvdomatic.cc:173 +#: src/tools/dcpomatic.cc:173 msgid "&Make DCP" msgstr "&Crea DCP" -#: src/tools/dvdomatic.cc:161 +#: src/tools/dcpomatic.cc:161 msgid "&Open..." msgstr "&Apri..." -#: src/tools/dvdomatic.cc:170 +#: src/tools/dcpomatic.cc:170 msgid "&Preferences..." msgstr "&Preferenze..." -#: src/tools/dvdomatic.cc:165 +#: src/tools/dcpomatic.cc:165 msgid "&Properties..." msgstr "&Proprieta'..." -#: src/tools/dvdomatic.cc:167 +#: src/tools/dcpomatic.cc:167 msgid "&Quit" msgstr "&Esci" -#: src/tools/dvdomatic.cc:163 +#: src/tools/dcpomatic.cc:163 msgid "&Save" msgstr "&Salva" -#: src/tools/dvdomatic.cc:174 +#: src/tools/dcpomatic.cc:174 msgid "&Send DCP to TMS" msgstr "&Invia DCP a TMS" -#: src/tools/dvdomatic.cc:417 +#: src/tools/dcpomatic.cc:417 msgid "" "(C) 2012-2013 Carl Hetherington, Terrence Meiczinger, Paul Davis, Ole Laursen" msgstr "" "(C) 2012-2013 Carl Hetherington, Terrence Meiczinger, Paul Davis, Ole Laursen" -#: src/tools/dvdomatic.cc:180 +#: src/tools/dcpomatic.cc:180 msgid "About" msgstr "Informazioni" -#: src/tools/dvdomatic.cc:527 +#: src/tools/dcpomatic.cc:527 msgid "Could not load film %1 (%2)" msgstr "Non posso caricare il film %s (%s)" -#: src/tools/dvdomatic.cc:339 +#: src/tools/dcpomatic.cc:339 #, c-format msgid "Could not open film at %s (%s)" msgstr "Non posso aprire il film in %s (%s)" -#: src/tools/dvdomatic.cc:287 src/tools/dvdomatic.cc:410 -#: src/tools/dvdomatic.cc:531 -msgid "DVD-o-matic" -msgstr "DVD-o-matic" +#: src/tools/dcpomatic.cc:287 src/tools/dcpomatic.cc:410 +#: src/tools/dcpomatic.cc:531 +msgid "DCP-o-matic" +msgstr "DCP-o-matic" -#: src/tools/dvdomatic.cc:75 +#: src/tools/dcpomatic.cc:75 msgid "Film changed" msgstr "Film modificato" -#: src/tools/dvdomatic.cc:416 +#: src/tools/dcpomatic.cc:416 msgid "Free, open-source DCP generation from almost anything." msgstr "Genera DCP da quasi tutto, free e open-source." -#: src/tools/dvdomatic.cc:160 +#: src/tools/dcpomatic.cc:160 msgid "New..." msgstr "Nuovo" -#: src/tools/dvdomatic.cc:175 +#: src/tools/dcpomatic.cc:175 msgid "S&how DCP" msgstr "&Mostra DCP" -#: src/tools/dvdomatic.cc:74 +#: src/tools/dcpomatic.cc:74 msgid "Save changes to film \"%s\" before closing?" msgstr "Salvare i cambiamenti del film \"%s\" prima di chiudere?" -#: src/tools/dvdomatic.cc:319 +#: src/tools/dcpomatic.cc:319 msgid "Select film to open" msgstr "Seleziona il film da aprire" -#: src/tools/dvdomatic.cc:303 +#: src/tools/dcpomatic.cc:303 msgid "The directory %1 already exists." msgstr "La directory %s esiste gia'." -#: src/tools/dvdomatic.cc:324 +#: src/tools/dcpomatic.cc:324 msgid "" "You did not select a folder. Make sure that you select a folder before " "clicking Open." diff --git a/src/tools/po/sv_SE.po b/src/tools/po/sv_SE.po index 57254770c..4765c2d98 100644 --- a/src/tools/po/sv_SE.po +++ b/src/tools/po/sv_SE.po @@ -5,7 +5,7 @@ # msgid "" msgstr "" -"Project-Id-Version: DVD-o-matic\n" +"Project-Id-Version: DCP-o-matic\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-04-09 11:14+0100\n" "PO-Revision-Date: 2013-04-09 10:12+0100\n" @@ -17,108 +17,108 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.5.5\n" -#: src/tools/dvdomatic.cc:177 +#: src/tools/dcpomatic.cc:177 msgid "&Analyse audio" msgstr "&Analysera audio" -#: src/tools/dvdomatic.cc:183 +#: src/tools/dcpomatic.cc:183 msgid "&Edit" msgstr "&Redigera" -#: src/tools/dvdomatic.cc:182 +#: src/tools/dcpomatic.cc:182 msgid "&File" msgstr "&Fil" -#: src/tools/dvdomatic.cc:185 +#: src/tools/dcpomatic.cc:185 msgid "&Help" msgstr "&Hjälp" -#: src/tools/dvdomatic.cc:184 +#: src/tools/dcpomatic.cc:184 msgid "&Jobs" msgstr "&Jobb" -#: src/tools/dvdomatic.cc:173 +#: src/tools/dcpomatic.cc:173 msgid "&Make DCP" msgstr "&Skapa DCP" -#: src/tools/dvdomatic.cc:161 +#: src/tools/dcpomatic.cc:161 msgid "&Open..." msgstr "&Öppna" -#: src/tools/dvdomatic.cc:170 +#: src/tools/dcpomatic.cc:170 msgid "&Preferences..." msgstr "&Inställningar" -#: src/tools/dvdomatic.cc:165 +#: src/tools/dcpomatic.cc:165 msgid "&Properties..." msgstr "&Egenskaper" -#: src/tools/dvdomatic.cc:167 +#: src/tools/dcpomatic.cc:167 msgid "&Quit" msgstr "&Avsluta" -#: src/tools/dvdomatic.cc:163 +#: src/tools/dcpomatic.cc:163 msgid "&Save" msgstr "&Spara" -#: src/tools/dvdomatic.cc:174 +#: src/tools/dcpomatic.cc:174 msgid "&Send DCP to TMS" msgstr "&Skicka DCP till TMS" -#: src/tools/dvdomatic.cc:417 +#: src/tools/dcpomatic.cc:417 msgid "" "(C) 2012-2013 Carl Hetherington, Terrence Meiczinger, Paul Davis, Ole Laursen" msgstr "" "(C) 2012-2013 Carl Hetherington, Terrence Meiczinger, Paul Davis, Ole Laursen" -#: src/tools/dvdomatic.cc:180 +#: src/tools/dcpomatic.cc:180 msgid "About" msgstr "Om" -#: src/tools/dvdomatic.cc:527 +#: src/tools/dcpomatic.cc:527 msgid "Could not load film %1 (%2)" msgstr "Kunde inte öppna filmen %1 (%2)" -#: src/tools/dvdomatic.cc:339 +#: src/tools/dcpomatic.cc:339 #, c-format msgid "Could not open film at %s (%s)" msgstr "Kunde inte öppna filmen vid %s (%s)" -#: src/tools/dvdomatic.cc:287 src/tools/dvdomatic.cc:410 -#: src/tools/dvdomatic.cc:531 -msgid "DVD-o-matic" -msgstr "DVD-o-matic" +#: src/tools/dcpomatic.cc:287 src/tools/dcpomatic.cc:410 +#: src/tools/dcpomatic.cc:531 +msgid "DCP-o-matic" +msgstr "DCP-o-matic" -#: src/tools/dvdomatic.cc:75 +#: src/tools/dcpomatic.cc:75 msgid "Film changed" msgstr "Film ändrad" -#: src/tools/dvdomatic.cc:416 +#: src/tools/dcpomatic.cc:416 msgid "Free, open-source DCP generation from almost anything." msgstr "" "Fri, öppen-källkodsprogramvara för DCP-generering från nästan vad som helst." -#: src/tools/dvdomatic.cc:160 +#: src/tools/dcpomatic.cc:160 msgid "New..." msgstr "Ny..." -#: src/tools/dvdomatic.cc:175 +#: src/tools/dcpomatic.cc:175 msgid "S&how DCP" msgstr "&Visa DCP" -#: src/tools/dvdomatic.cc:74 +#: src/tools/dcpomatic.cc:74 msgid "Save changes to film \"%s\" before closing?" msgstr "Spara ändringarna till filmen \"%s\" före avslut?" -#: src/tools/dvdomatic.cc:319 +#: src/tools/dcpomatic.cc:319 msgid "Select film to open" msgstr "Välj film att öppna" -#: src/tools/dvdomatic.cc:303 +#: src/tools/dcpomatic.cc:303 msgid "The directory %1 already exists." msgstr "Katalogen %1 finns redan." -#: src/tools/dvdomatic.cc:324 +#: src/tools/dcpomatic.cc:324 msgid "" "You did not select a folder. Make sure that you select a folder before " "clicking Open." diff --git a/src/tools/servomatic_cli.cc b/src/tools/servomatic_cli.cc index 6626d45b9..76d085034 100644 --- a/src/tools/servomatic_cli.cc +++ b/src/tools/servomatic_cli.cc @@ -51,7 +51,7 @@ static void help (string n) { cerr << "Syntax: " << n << " [OPTION]\n" - << " -v, --version show DVD-o-matic version\n" + << " -v, --version show DCP-o-matic version\n" << " -h, --help show this help\n" << " -t, --threads number of parallel encoding threads to use\n"; } @@ -78,7 +78,7 @@ main (int argc, char* argv[]) switch (c) { case 'v': - cout << "dvdomatic version " << dvdomatic_version << " " << dvdomatic_git_commit << "\n"; + cout << "dcpomatic version " << dcpomatic_version << " " << dcpomatic_git_commit << "\n"; exit (EXIT_SUCCESS); case 'h': help (argv[0]); diff --git a/src/tools/servomatic_gui.cc b/src/tools/servomatic_gui.cc index 5e36660eb..152e063c1 100644 --- a/src/tools/servomatic_gui.cc +++ b/src/tools/servomatic_gui.cc @@ -61,7 +61,7 @@ class StatusDialog : public wxDialog { public: StatusDialog () - : wxDialog (0, wxID_ANY, _("DVD-o-matic encode server"), wxDefaultPosition, wxSize (600, 80), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) + : wxDialog (0, wxID_ANY, _("DCP-o-matic encode server"), wxDefaultPosition, wxSize (600, 80), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) , _timer (this, ID_timer) { _sizer = new wxFlexGridSizer (1, 6, 6); @@ -103,7 +103,7 @@ public: wxIcon icon; icon.CopyFromBitmap (bitmap); #endif - SetIcon (icon, std_to_wx ("DVD-o-matic encode server")); + SetIcon (icon, std_to_wx ("DCP-o-matic encode server")); Connect (ID_status, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (TaskBarIcon::status)); Connect (ID_quit, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (TaskBarIcon::quit)); @@ -147,7 +147,7 @@ private: return false; } - dvdomatic_setup (); + dcpomatic_setup (); _icon = new TaskBarIcon; _thread = new thread (bind (&App::main_thread, this)); diff --git a/src/tools/servomatictest.cc b/src/tools/servomatictest.cc index d3222faa3..42cc76871 100644 --- a/src/tools/servomatictest.cc +++ b/src/tools/servomatictest.cc @@ -145,7 +145,7 @@ main (int argc, char* argv[]) exit (EXIT_FAILURE); } - dvdomatic_setup (); + dcpomatic_setup (); server = new ServerDescription (server_host, 1); shared_ptr film (new Film (film_dir, true)); diff --git a/src/tools/wscript b/src/tools/wscript index 9cc7e9d1b..f0ffb8e89 100644 --- a/src/tools/wscript +++ b/src/tools/wscript @@ -8,25 +8,25 @@ def build(bld): obj = bld(features = 'cxx cxxprogram') obj.uselib = 'BOOST_THREAD OPENJPEG DCP CXML AVFORMAT AVFILTER AVCODEC AVUTIL SWSCALE POSTPROC' obj.includes = ['..'] - obj.use = ['libdvdomatic'] + obj.use = ['libdcpomatic'] obj.source = '%s.cc' % t obj.target = t if not bld.env.DISABLE_GUI: - for t in ['dvdomatic', 'servomatic_gui']: + for t in ['dcpomatic', 'servomatic_gui']: obj = bld(features = 'cxx cxxprogram') obj.uselib = 'DCP CXML OPENJPEG AVFORMAT AVFILTER AVCODEC AVUTIL SWSCALE POSTPROC' obj.includes = ['..'] - obj.use = ['libdvdomatic', 'libdvdomatic-wx'] + obj.use = ['libdcpomatic', 'libdcpomatic-wx'] obj.source = '%s.cc' % t if bld.env.TARGET_WINDOWS: - obj.source += ' ../../windows/dvdomatic.rc' + obj.source += ' ../../windows/dcpomatic.rc' obj.target = t - i18n.po_to_mo(os.path.join('src', 'tools'), 'dvdomatic', bld) + i18n.po_to_mo(os.path.join('src', 'tools'), 'dcpomatic', bld) def pot(bld): - i18n.pot(os.path.join('src', 'tools'), 'dvdomatic.cc', 'dvdomatic') + i18n.pot(os.path.join('src', 'tools'), 'dcpomatic.cc', 'dcpomatic') def pot_merge(bld): - i18n.pot_merge(os.path.join('src', 'tools'), 'dvdomatic') + i18n.pot_merge(os.path.join('src', 'tools'), 'dcpomatic') diff --git a/src/wx/audio_dialog.cc b/src/wx/audio_dialog.cc index bed7aac6d..15d746839 100644 --- a/src/wx/audio_dialog.cc +++ b/src/wx/audio_dialog.cc @@ -100,7 +100,7 @@ AudioDialog::set_film (shared_ptr f) _film_changed_connection = _film->Changed.connect (bind (&AudioDialog::film_changed, this, _1)); _film_audio_analysis_succeeded_connection = _film->AudioAnalysisSucceeded.connect (bind (&AudioDialog::try_to_load_analysis, this)); - SetTitle (wxString::Format (_("DVD-o-matic audio - %s"), std_to_wx(_film->name()).data())); + SetTitle (wxString::Format (_("DCP-o-matic audio - %s"), std_to_wx(_film->name()).data())); } diff --git a/src/wx/config_dialog.cc b/src/wx/config_dialog.cc index 1d025f3fa..4ae8f1eb4 100644 --- a/src/wx/config_dialog.cc +++ b/src/wx/config_dialog.cc @@ -18,7 +18,7 @@ */ /** @file src/config_dialog.cc - * @brief A dialogue to edit DVD-o-matic configuration. + * @brief A dialogue to edit DCP-o-matic configuration. */ #include @@ -41,7 +41,7 @@ using namespace std; using boost::bind; ConfigDialog::ConfigDialog (wxWindow* parent) - : wxDialog (parent, wxID_ANY, _("DVD-o-matic Preferences"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) + : wxDialog (parent, wxID_ANY, _("DCP-o-matic Preferences"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { wxFlexGridSizer* table = new wxFlexGridSizer (3, 6, 6); table->AddGrowableCol (1, 1); @@ -58,7 +58,7 @@ ConfigDialog::ConfigDialog (wxWindow* parent) table->AddSpacer (0); table->AddSpacer (0); - wxStaticText* restart = add_label_to_sizer (table, this, _("(restart DVD-o-matic to see language changes)")); + wxStaticText* restart = add_label_to_sizer (table, this, _("(restart DCP-o-matic to see language changes)")); wxFont font = restart->GetFont(); font.SetStyle (wxFONTSTYLE_ITALIC); font.SetPointSize (font.GetPointSize() - 1); diff --git a/src/wx/config_dialog.h b/src/wx/config_dialog.h index f6f3b3707..a2fc1f4b1 100644 --- a/src/wx/config_dialog.h +++ b/src/wx/config_dialog.h @@ -18,7 +18,7 @@ */ /** @file src/config_dialog.h - * @brief A dialogue to edit DVD-o-matic configuration. + * @brief A dialogue to edit DCP-o-matic configuration. */ #include @@ -31,7 +31,7 @@ class DirPickerCtrl; class ServerDescription; /** @class ConfigDialog - * @brief A dialogue to edit DVD-o-matic configuration. + * @brief A dialogue to edit DCP-o-matic configuration. */ class ConfigDialog : public wxDialog { diff --git a/src/wx/po/es_ES.po b/src/wx/po/es_ES.po index 207708589..abb6b780f 100644 --- a/src/wx/po/es_ES.po +++ b/src/wx/po/es_ES.po @@ -5,7 +5,7 @@ # msgid "" msgstr "" -"Project-Id-Version: libdvdomatic-wx\n" +"Project-Id-Version: libdcpomatic-wx\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-04-09 11:14+0100\n" "PO-Revision-Date: 2013-04-02 19:08-0500\n" @@ -22,7 +22,7 @@ msgid "%" msgstr "%" #: src/wx/config_dialog.cc:61 -msgid "(restart DVD-o-matic to see language changes)" +msgid "(restart DCP-o-matic to see language changes)" msgstr "" #: src/wx/film_editor.cc:1269 @@ -141,17 +141,17 @@ msgid "DCP Name" msgstr "Nombre DCP" #: src/wx/wx_util.cc:61 -msgid "DVD-o-matic" -msgstr "DVD-o-matic" +msgid "DCP-o-matic" +msgstr "DCP-o-matic" #: src/wx/config_dialog.cc:44 -msgid "DVD-o-matic Preferences" -msgstr "Preferencias DVD-o-matic" +msgid "DCP-o-matic Preferences" +msgstr "Preferencias DCP-o-matic" #: src/wx/audio_dialog.cc:101 #, fuzzy, c-format -msgid "DVD-o-matic audio - %s" -msgstr "Audio DVD-o-matic - %1" +msgid "DCP-o-matic audio - %s" +msgstr "Audio DCP-o-matic - %1" #: src/wx/config_dialog.cc:102 msgid "Default DCI name details" diff --git a/src/wx/po/fr_FR.po b/src/wx/po/fr_FR.po index 80ee5dbfd..2aac7114c 100644 --- a/src/wx/po/fr_FR.po +++ b/src/wx/po/fr_FR.po @@ -5,7 +5,7 @@ # msgid "" msgstr "" -"Project-Id-Version: DVD-o-matic FRENCH\n" +"Project-Id-Version: DCP-o-matic FRENCH\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-04-09 11:14+0100\n" "PO-Revision-Date: 2013-03-20 00:34+0100\n" @@ -21,7 +21,7 @@ msgid "%" msgstr "%" #: src/wx/config_dialog.cc:61 -msgid "(restart DVD-o-matic to see language changes)" +msgid "(restart DCP-o-matic to see language changes)" msgstr "" #: src/wx/film_editor.cc:1269 @@ -140,17 +140,17 @@ msgid "DCP Name" msgstr "Nom du DCP" #: src/wx/wx_util.cc:61 -msgid "DVD-o-matic" -msgstr "DVD-o-matic" +msgid "DCP-o-matic" +msgstr "DCP-o-matic" #: src/wx/config_dialog.cc:44 -msgid "DVD-o-matic Preferences" -msgstr "Préférences DVD-o-matic" +msgid "DCP-o-matic Preferences" +msgstr "Préférences DCP-o-matic" #: src/wx/audio_dialog.cc:101 #, c-format -msgid "DVD-o-matic audio - %s" -msgstr "Son DVD-o-matic - %s" +msgid "DCP-o-matic audio - %s" +msgstr "Son DCP-o-matic - %s" #: src/wx/config_dialog.cc:102 msgid "Default DCI name details" diff --git a/src/wx/po/it_IT.po b/src/wx/po/it_IT.po index 78fd0dee9..7b06495e8 100644 --- a/src/wx/po/it_IT.po +++ b/src/wx/po/it_IT.po @@ -22,8 +22,8 @@ msgid "%" msgstr "%" #: src/wx/config_dialog.cc:61 -msgid "(restart DVD-o-matic to see language changes)" -msgstr "(riavviare DVD-o-matic per vedere i cambiamenti di lingua)" +msgid "(restart DCP-o-matic to see language changes)" +msgstr "(riavviare DCP-o-matic per vedere i cambiamenti di lingua)" #: src/wx/film_editor.cc:1269 msgid "1 channel" @@ -141,17 +141,17 @@ msgid "DCP Name" msgstr "Nome del DCP" #: src/wx/wx_util.cc:61 -msgid "DVD-o-matic" -msgstr "DVD-o-matic" +msgid "DCP-o-matic" +msgstr "DCP-o-matic" #: src/wx/config_dialog.cc:44 -msgid "DVD-o-matic Preferences" -msgstr "Preferenze DVD-o-matic" +msgid "DCP-o-matic Preferences" +msgstr "Preferenze DCP-o-matic" #: src/wx/audio_dialog.cc:101 #, c-format -msgid "DVD-o-matic audio - %s" -msgstr "Audio DVD-o-matic - %s" +msgid "DCP-o-matic audio - %s" +msgstr "Audio DCP-o-matic - %s" #: src/wx/config_dialog.cc:102 msgid "Default DCI name details" diff --git a/src/wx/po/sv_SE.po b/src/wx/po/sv_SE.po index e52589ff0..96fafadeb 100644 --- a/src/wx/po/sv_SE.po +++ b/src/wx/po/sv_SE.po @@ -5,7 +5,7 @@ # msgid "" msgstr "" -"Project-Id-Version: DVD-o-matic\n" +"Project-Id-Version: DCP-o-matic\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-04-09 11:14+0100\n" "PO-Revision-Date: 2013-04-09 10:13+0100\n" @@ -22,8 +22,8 @@ msgid "%" msgstr "%" #: src/wx/config_dialog.cc:61 -msgid "(restart DVD-o-matic to see language changes)" -msgstr "(starta om DVD-o-matic för att se språkändringar)" +msgid "(restart DCP-o-matic to see language changes)" +msgstr "(starta om DCP-o-matic för att se språkändringar)" #: src/wx/film_editor.cc:1269 msgid "1 channel" @@ -141,17 +141,17 @@ msgid "DCP Name" msgstr "DCP Namn" #: src/wx/wx_util.cc:61 -msgid "DVD-o-matic" -msgstr "DVD-o-matic" +msgid "DCP-o-matic" +msgstr "DCP-o-matic" #: src/wx/config_dialog.cc:44 -msgid "DVD-o-matic Preferences" -msgstr "DVD-o-matic Inställningar" +msgid "DCP-o-matic Preferences" +msgstr "DCP-o-matic Inställningar" #: src/wx/audio_dialog.cc:101 #, c-format -msgid "DVD-o-matic audio - %s" -msgstr "DVD-o-matic audio - %s" +msgid "DCP-o-matic audio - %s" +msgstr "DCP-o-matic audio - %s" #: src/wx/config_dialog.cc:102 msgid "Default DCI name details" diff --git a/src/wx/wscript b/src/wx/wscript index 7f9cde9ac..09bf40393 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -34,18 +34,18 @@ def build(bld): else: obj = bld(features = 'cxx cxxshlib') - obj.name = 'libdvdomatic-wx' + obj.name = 'libdcpomatic-wx' obj.includes = [ '..' ] obj.export_includes = ['.'] obj.uselib = 'WXWIDGETS' - obj.use = 'libdvdomatic' + obj.use = 'libdcpomatic' obj.source = sources - obj.target = 'dvdomatic-wx' + obj.target = 'dcpomatic-wx' - i18n.po_to_mo(os.path.join('src', 'wx'), 'libdvdomatic-wx', bld) + i18n.po_to_mo(os.path.join('src', 'wx'), 'libdcpomatic-wx', bld) def pot(bld): - i18n.pot(os.path.join('src', 'wx'), sources, 'libdvdomatic-wx') + i18n.pot(os.path.join('src', 'wx'), sources, 'libdcpomatic-wx') def pot_merge(bld): - i18n.pot_merge(os.path.join('src', 'wx'), 'libdvdomatic-wx') + i18n.pot_merge(os.path.join('src', 'wx'), 'libdcpomatic-wx') diff --git a/src/wx/wx_util.cc b/src/wx/wx_util.cc index 720a058cb..3dad6e7fd 100644 --- a/src/wx/wx_util.cc +++ b/src/wx/wx_util.cc @@ -58,7 +58,7 @@ add_label_to_grid_bag_sizer (wxGridBagSizer* s, wxWindow* p, wxString t, wxGBPos void error_dialog (wxWindow* parent, wxString m) { - wxMessageDialog* d = new wxMessageDialog (parent, m, _("DVD-o-matic"), wxOK); + wxMessageDialog* d = new wxMessageDialog (parent, m, _("DCP-o-matic"), wxOK); d->ShowModal (); d->Destroy (); } diff --git a/test/test.cc b/test/test.cc index 592bad836..39a921d36 100644 --- a/test/test.cc +++ b/test/test.cc @@ -42,7 +42,7 @@ #include "sndfile_decoder.h" #include "dcp_content_type.h" #define BOOST_TEST_DYN_LINK -#define BOOST_TEST_MODULE dvdomatic_test +#define BOOST_TEST_MODULE dcpomatic_test #include using std::string; @@ -90,7 +90,7 @@ new_test_film (string name) BOOST_AUTO_TEST_CASE (make_black_test) { /* This needs to happen in the first test */ - dvdomatic_setup (); + dcpomatic_setup (); libdcp::Size in_size (512, 512); libdcp::Size out_size (1024, 1024); @@ -392,7 +392,7 @@ BOOST_AUTO_TEST_CASE (client_server_test) new thread (boost::bind (&Server::run, server, 2)); /* Let the server get itself ready */ - dvdomatic_sleep (1); + dcpomatic_sleep (1); ServerDescription description ("localhost", 2); @@ -421,7 +421,7 @@ BOOST_AUTO_TEST_CASE (make_dcp_test) film->write_metadata (); while (JobManager::instance()->work_to_do ()) { - dvdomatic_sleep (1); + dcpomatic_sleep (1); } BOOST_CHECK_EQUAL (JobManager::instance()->errors(), false); @@ -452,7 +452,7 @@ BOOST_AUTO_TEST_CASE (make_dcp_with_range_test) film->make_dcp (); while (JobManager::instance()->work_to_do() && !JobManager::instance()->errors()) { - dvdomatic_sleep (1); + dcpomatic_sleep (1); } BOOST_CHECK_EQUAL (JobManager::instance()->errors(), false); @@ -689,10 +689,10 @@ BOOST_AUTO_TEST_CASE (job_manager_test) shared_ptr a (new TestJob (f)); JobManager::instance()->add (a); - dvdomatic_sleep (1); + dcpomatic_sleep (1); BOOST_CHECK_EQUAL (a->running (), true); a->set_finished_ok (); - dvdomatic_sleep (2); + dcpomatic_sleep (2); BOOST_CHECK_EQUAL (a->finished_ok(), true); } diff --git a/test/wscript b/test/wscript index 493270903..61c391663 100644 --- a/test/wscript +++ b/test/wscript @@ -9,7 +9,7 @@ def build(bld): obj = bld(features = 'cxx cxxprogram') obj.name = 'unit-tests' obj.uselib = 'BOOST_TEST CXML DCP OPENJPEG AVFORMAT AVFILTER AVCODEC AVUTIL SWSCALE POSTPROC' - obj.use = 'libdvdomatic' + obj.use = 'libdcpomatic' obj.source = 'test.cc' obj.target = 'unit-tests' obj.install_path = '' diff --git a/windows/dvdomatic.bmp b/windows/dvdomatic.bmp deleted file mode 100644 index 0a196f7a0..000000000 Binary files a/windows/dvdomatic.bmp and /dev/null differ diff --git a/windows/dvdomatic.ico b/windows/dvdomatic.ico deleted file mode 100644 index 225008cfe..000000000 Binary files a/windows/dvdomatic.ico and /dev/null differ diff --git a/windows/dvdomatic.rc b/windows/dvdomatic.rc deleted file mode 100644 index 17790cf0d..000000000 --- a/windows/dvdomatic.rc +++ /dev/null @@ -1,3 +0,0 @@ -id ICON "dvdomatic.ico" -taskbar_icon ICON "dvdomatic_taskbar.ico" -#include "wx-2.9/wx/msw/wx.rc" diff --git a/windows/dvdomatic_taskbar.ico b/windows/dvdomatic_taskbar.ico deleted file mode 100644 index f4489fa14..000000000 Binary files a/windows/dvdomatic_taskbar.ico and /dev/null differ diff --git a/windows/installer.nsi.32.in b/windows/installer.nsi.32.in index 553a94d2b..15a0a1886 100644 --- a/windows/installer.nsi.32.in +++ b/windows/installer.nsi.32.in @@ -1,14 +1,14 @@ !include "MUI2.nsh" -Name "DVD-o-matic" +Name "DCP-o-matic" RequestExecutionLevel admin -outFile "DVD-o-matic @version@ 32-bit Installer.exe" -!define MUI_ICON "%resources%/dvdomatic.ico" -!define MUI_UNICON "%resources%/dvdomatic.ico" -!define MUI_SPECIALBITMAP "%resources%/dvdomatic.bmp" +outFile "DCP-o-matic @version@ 32-bit Installer.exe" +!define MUI_ICON "%resources%/dcpomatic.ico" +!define MUI_UNICON "%resources%/dcpomatic.ico" +!define MUI_SPECIALBITMAP "%resources%/dcpomatic.bmp" -InstallDir "$PROGRAMFILES\DVD-o-matic" +InstallDir "$PROGRAMFILES\DCP-o-matic" !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_LICENSE "../../COPYING" @@ -81,9 +81,9 @@ File "%deps%/bin/libexpat-1.dll" File "%deps%/bin/libbz2.dll" File "%deps%/bin/cxml.dll" -File "%binaries%/src/wx/dvdomatic-wx.dll" -File "%binaries%/src/lib/dvdomatic.dll" -File "%binaries%/src/tools/dvdomatic.exe" +File "%binaries%/src/wx/dcpomatic-wx.dll" +File "%binaries%/src/lib/dcpomatic.dll" +File "%binaries%/src/tools/dcpomatic.exe" File "%binaries%/src/tools/servomatic_cli.exe" File "%binaries%/src/tools/servomatic_gui.exe" @@ -95,32 +95,32 @@ SetOutPath "$PROFILE\.magick" File "%deps%/etc/ImageMagick/delegates.xml" SetOutPath "$INSTDIR\locale\fr\LC_MESSAGES" -File "%binaries%/src/lib/mo/fr_FR/libdvdomatic.mo" -File "%binaries%/src/wx/mo/fr_FR/libdvdomatic-wx.mo" -File "%binaries%/src/tools/mo/fr_FR/dvdomatic.mo" +File "%binaries%/src/lib/mo/fr_FR/libdcpomatic.mo" +File "%binaries%/src/wx/mo/fr_FR/libdcpomatic-wx.mo" +File "%binaries%/src/tools/mo/fr_FR/dcpomatic.mo" SetOutPath "$INSTDIR\locale\it\LC_MESSAGES" -File "%binaries%/src/lib/mo/it_IT/libdvdomatic.mo" -File "%binaries%/src/wx/mo/it_IT/libdvdomatic-wx.mo" -File "%binaries%/src/tools/mo/it_IT/dvdomatic.mo" +File "%binaries%/src/lib/mo/it_IT/libdcpomatic.mo" +File "%binaries%/src/wx/mo/it_IT/libdcpomatic-wx.mo" +File "%binaries%/src/tools/mo/it_IT/dcpomatic.mo" SetOutPath "$INSTDIR\locale\es\LC_MESSAGES" -File "%binaries%/src/lib/mo/es_ES/libdvdomatic.mo" -File "%binaries%/src/wx/mo/es_ES/libdvdomatic-wx.mo" -File "%binaries%/src/tools/mo/es_ES/dvdomatic.mo" +File "%binaries%/src/lib/mo/es_ES/libdcpomatic.mo" +File "%binaries%/src/wx/mo/es_ES/libdcpomatic-wx.mo" +File "%binaries%/src/tools/mo/es_ES/dcpomatic.mo" SetOutPath "$INSTDIR\locale\sv\LC_MESSAGES" -File "%binaries%/src/lib/mo/sv_SE/libdvdomatic.mo" -File "%binaries%/src/wx/mo/sv_SE/libdvdomatic-wx.mo" -File "%binaries%/src/tools/mo/sv_SE/dvdomatic.mo" +File "%binaries%/src/lib/mo/sv_SE/libdcpomatic.mo" +File "%binaries%/src/wx/mo/sv_SE/libdcpomatic-wx.mo" +File "%binaries%/src/tools/mo/sv_SE/dcpomatic.mo" -CreateShortCut "$DESKTOP\DVD-o-matic.lnk" "$INSTDIR\bin\dvdomatic.exe" "" -CreateShortCut "$DESKTOP\DVD-o-matic encode server.lnk" "$INSTDIR\bin\servomatic_gui.exe" "" +CreateShortCut "$DESKTOP\DCP-o-matic.lnk" "$INSTDIR\bin\dcpomatic.exe" "" +CreateShortCut "$DESKTOP\DCP-o-matic encode server.lnk" "$INSTDIR\bin\servomatic_gui.exe" "" -CreateDirectory "$SMPROGRAMS\DVD-o-matic" -CreateShortCut "$SMPROGRAMS\DVD-o-matic\Uninstall DVD-o-matic.lnk" "$INSTDIR\Uninstall.exe" "" "$INSTDIR\Uninstall.exe" 0 -CreateShortCut "$SMPROGRAMS\DVD-o-matic\DVD-o-matic.lnk" "$INSTDIR\bin\dvdomatic.exe" "" "$INSTDIR\bin\dvdomatic.exe" 0 -CreateShortCut "$SMPROGRAMS\DVD-o-matic\DVD-o-matic encode server.lnk" "$INSTDIR\bin\servomatic_gui.exe" "" "$INSTDIR\bin\servomatic_gui.exe" 0 +CreateDirectory "$SMPROGRAMS\DCP-o-matic" +CreateShortCut "$SMPROGRAMS\DCP-o-matic\Uninstall DCP-o-matic.lnk" "$INSTDIR\Uninstall.exe" "" "$INSTDIR\Uninstall.exe" 0 +CreateShortCut "$SMPROGRAMS\DCP-o-matic\DCP-o-matic.lnk" "$INSTDIR\bin\dcpomatic.exe" "" "$INSTDIR\bin\dcpomatic.exe" 0 +CreateShortCut "$SMPROGRAMS\DCP-o-matic\DCP-o-matic encode server.lnk" "$INSTDIR\bin\servomatic_gui.exe" "" "$INSTDIR\bin\servomatic_gui.exe" 0 -WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\DVD-o-matic" "DisplayName" "DVD-o-matic (remove only)" -WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\DVD-o-matic" "UninstallString" "$INSTDIR\Uninstall.exe" +WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\DCP-o-matic" "DisplayName" "DCP-o-matic (remove only)" +WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\DCP-o-matic" "UninstallString" "$INSTDIR\Uninstall.exe" WriteUninstaller "$INSTDIR\Uninstall.exe" @@ -131,11 +131,11 @@ Section "Uninstall" RMDir /r "$INSTDIR\*.*" RMDir "$INSTDIR" -Delete "$DESKTOP\DVD-o-matic.lnk" -Delete "$DESKTOP\DVD-o-matic encode server.lnk" -Delete "$SMPROGRAMS\DVD-o-matic\*.*" -RmDir "$SMPROGRAMS\DVD-o-matic" -DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\DVD-o-matic" -DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\DVD-o-matic" +Delete "$DESKTOP\DCP-o-matic.lnk" +Delete "$DESKTOP\DCP-o-matic encode server.lnk" +Delete "$SMPROGRAMS\DCP-o-matic\*.*" +RmDir "$SMPROGRAMS\DCP-o-matic" +DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\DCP-o-matic" +DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\DCP-o-matic" SectionEnd diff --git a/windows/installer.nsi.64.in b/windows/installer.nsi.64.in index bb5456936..566907e39 100644 --- a/windows/installer.nsi.64.in +++ b/windows/installer.nsi.64.in @@ -1,16 +1,16 @@ !include "MUI2.nsh" !include "x64.nsh" -Name "DVD-o-matic" +Name "DCP-o-matic" RequestExecutionLevel admin -outFile "DVD-o-matic @version@ 64-bit Installer.exe" -!define MUI_ICON "%resources%/dvdomatic.ico" -!define MUI_UNICON "%resources%/dvdomatic.ico" -!define MUI_SPECIALBITMAP "%resources%/dvdomatic.bmp" +outFile "DCP-o-matic @version@ 64-bit Installer.exe" +!define MUI_ICON "%resources%/dcpomatic.ico" +!define MUI_UNICON "%resources%/dcpomatic.ico" +!define MUI_SPECIALBITMAP "%resources%/dcpomatic.bmp" -InstallDir "$PROGRAMFILES\DVD-o-matic" +InstallDir "$PROGRAMFILES\DCP-o-matic" !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_LICENSE "../../COPYING" @@ -32,7 +32,7 @@ ${If} ${RunningX64} ; disable registry redirection (enable access to 64-bit portion of registry) SetRegView 64 ; change install dir - StrCpy $INSTDIR "$PROGRAMFILES64\DVD-o-matic" + StrCpy $INSTDIR "$PROGRAMFILES64\DCP-o-matic" ${EndIf} SetOutPath "$INSTDIR\bin" @@ -91,9 +91,9 @@ File "%deps%/bin/libexpat-1.dll" File "%deps%/bin/libbz2.dll" File "%deps%/bin/cxml.dll" -File "%binaries%/src/wx/dvdomatic-wx.dll" -File "%binaries%/src/lib/dvdomatic.dll" -File "%binaries%/src/tools/dvdomatic.exe" +File "%binaries%/src/wx/dcpomatic-wx.dll" +File "%binaries%/src/lib/dcpomatic.dll" +File "%binaries%/src/tools/dcpomatic.exe" File "%binaries%/src/tools/servomatic_cli.exe" File "%binaries%/src/tools/servomatic_gui.exe" @@ -105,32 +105,32 @@ SetOutPath "$PROFILE\.magick" File "%deps%/etc/ImageMagick/delegates.xml" SetOutPath "$INSTDIR\locale\fr\LC_MESSAGES" -File "%binaries%/src/lib/mo/fr_FR/libdvdomatic.mo" -File "%binaries%/src/wx/mo/fr_FR/libdvdomatic-wx.mo" -File "%binaries%/src/tools/mo/fr_FR/dvdomatic.mo" +File "%binaries%/src/lib/mo/fr_FR/libdcpomatic.mo" +File "%binaries%/src/wx/mo/fr_FR/libdcpomatic-wx.mo" +File "%binaries%/src/tools/mo/fr_FR/dcpomatic.mo" SetOutPath "$INSTDIR\locale\it\LC_MESSAGES" -File "%binaries%/src/lib/mo/it_IT/libdvdomatic.mo" -File "%binaries%/src/wx/mo/it_IT/libdvdomatic-wx.mo" -File "%binaries%/src/tools/mo/it_IT/dvdomatic.mo" +File "%binaries%/src/lib/mo/it_IT/libdcpomatic.mo" +File "%binaries%/src/wx/mo/it_IT/libdcpomatic-wx.mo" +File "%binaries%/src/tools/mo/it_IT/dcpomatic.mo" SetOutPath "$INSTDIR\locale\es\LC_MESSAGES" -File "%binaries%/src/lib/mo/es_ES/libdvdomatic.mo" -File "%binaries%/src/wx/mo/es_ES/libdvdomatic-wx.mo" -File "%binaries%/src/tools/mo/es_ES/dvdomatic.mo" +File "%binaries%/src/lib/mo/es_ES/libdcpomatic.mo" +File "%binaries%/src/wx/mo/es_ES/libdcpomatic-wx.mo" +File "%binaries%/src/tools/mo/es_ES/dcpomatic.mo" SetOutPath "$INSTDIR\locale\sv\LC_MESSAGES" -File "%binaries%/src/lib/mo/sv_SE/libdvdomatic.mo" -File "%binaries%/src/wx/mo/sv_SE/libdvdomatic-wx.mo" -File "%binaries%/src/tools/mo/sv_SE/dvdomatic.mo" +File "%binaries%/src/lib/mo/sv_SE/libdcpomatic.mo" +File "%binaries%/src/wx/mo/sv_SE/libdcpomatic-wx.mo" +File "%binaries%/src/tools/mo/sv_SE/dcpomatic.mo" -CreateShortCut "$DESKTOP\DVD-o-matic.lnk" "$INSTDIR\bin\dvdomatic.exe" "" -CreateShortCut "$DESKTOP\DVD-o-matic encode server.lnk" "$INSTDIR\bin\servomatic_gui.exe" "" +CreateShortCut "$DESKTOP\DCP-o-matic.lnk" "$INSTDIR\bin\dcpomatic.exe" "" +CreateShortCut "$DESKTOP\DCP-o-matic encode server.lnk" "$INSTDIR\bin\servomatic_gui.exe" "" -CreateDirectory "$SMPROGRAMS\DVD-o-matic" -CreateShortCut "$SMPROGRAMS\DVD-o-matic\Uninstall DVD-o-matic.lnk" "$INSTDIR\Uninstall.exe" "" "$INSTDIR\Uninstall.exe" 0 -CreateShortCut "$SMPROGRAMS\DVD-o-matic\DVD-o-matic.lnk" "$INSTDIR\bin\dvdomatic.exe" "" "$INSTDIR\bin\dvdomatic.exe" 0 -CreateShortCut "$SMPROGRAMS\DVD-o-matic\DVD-o-matic encode server.lnk" "$INSTDIR\bin\servomatic_gui.exe" "" "$INSTDIR\bin\servomatic_gui.exe" 0 +CreateDirectory "$SMPROGRAMS\DCP-o-matic" +CreateShortCut "$SMPROGRAMS\DCP-o-matic\Uninstall DCP-o-matic.lnk" "$INSTDIR\Uninstall.exe" "" "$INSTDIR\Uninstall.exe" 0 +CreateShortCut "$SMPROGRAMS\DCP-o-matic\DCP-o-matic.lnk" "$INSTDIR\bin\dcpomatic.exe" "" "$INSTDIR\bin\dcpomatic.exe" 0 +CreateShortCut "$SMPROGRAMS\DCP-o-matic\DCP-o-matic encode server.lnk" "$INSTDIR\bin\servomatic_gui.exe" "" "$INSTDIR\bin\servomatic_gui.exe" 0 -WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\DVD-o-matic" "DisplayName" "DVD-o-matic (remove only)" -WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\DVD-o-matic" "UninstallString" "$INSTDIR\Uninstall.exe" +WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\DCP-o-matic" "DisplayName" "DCP-o-matic (remove only)" +WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\DCP-o-matic" "UninstallString" "$INSTDIR\Uninstall.exe" WriteUninstaller "$INSTDIR\Uninstall.exe" @@ -141,11 +141,11 @@ Section "Uninstall" RMDir /r "$INSTDIR\*.*" RMDir "$INSTDIR" -Delete "$DESKTOP\DVD-o-matic.lnk" -Delete "$DESKTOP\DVD-o-matic encode server.lnk" -Delete "$SMPROGRAMS\DVD-o-matic\*.*" -RmDir "$SMPROGRAMS\DVD-o-matic" -DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\DVD-o-matic" -DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\DVD-o-matic" +Delete "$DESKTOP\DCP-o-matic.lnk" +Delete "$DESKTOP\DCP-o-matic encode server.lnk" +Delete "$SMPROGRAMS\DCP-o-matic\*.*" +RmDir "$SMPROGRAMS\DCP-o-matic" +DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\DCP-o-matic" +DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\DCP-o-matic" SectionEnd diff --git a/wscript b/wscript index 502f27fd1..f784d760d 100644 --- a/wscript +++ b/wscript @@ -2,7 +2,7 @@ import subprocess import os import sys -APPNAME = 'dvdomatic' +APPNAME = 'dcpomatic' VERSION = '0.84pre' def options(opt): @@ -25,7 +25,7 @@ def configure(conf): '-Wall', '-Wno-attributes', '-Wextra']) if conf.options.target_windows: - conf.env.append_value('CXXFLAGS', ['-DDVDOMATIC_WINDOWS', '-DWIN32_LEAN_AND_MEAN', '-DBOOST_USE_WINDOWS_H', '-DUNICODE']) + conf.env.append_value('CXXFLAGS', ['-DDCPOMATIC_WINDOWS', '-DWIN32_LEAN_AND_MEAN', '-DBOOST_USE_WINDOWS_H', '-DUNICODE']) wxrc = os.popen('wx-config --rescomp').read().split()[1:] conf.env.append_value('WINRCFLAGS', wxrc) if conf.options.enable_debug: @@ -35,9 +35,9 @@ def configure(conf): boost_lib_suffix = '-mt' boost_thread = 'boost_thread_win32-mt' else: - conf.env.append_value('CXXFLAGS', '-DDVDOMATIC_POSIX') + conf.env.append_value('CXXFLAGS', '-DDCPOMATIC_POSIX') conf.env.append_value('CXXFLAGS', '-DPOSIX_LOCALE_PREFIX="%s/share/locale"' % conf.env['PREFIX']) - conf.env.append_value('CXXFLAGS', '-DPOSIX_ICON_PREFIX="%s/share/dvdomatic"' % conf.env['PREFIX']) + conf.env.append_value('CXXFLAGS', '-DPOSIX_ICON_PREFIX="%s/share/dcpomatic"' % conf.env['PREFIX']) boost_lib_suffix = '' boost_thread = 'boost_thread' conf.env.append_value('LINKFLAGS', '-pthread') @@ -50,7 +50,7 @@ def configure(conf): conf.env.VERSION = VERSION if conf.options.enable_debug: - conf.env.append_value('CXXFLAGS', ['-g', '-DDVDOMATIC_DEBUG']) + conf.env.append_value('CXXFLAGS', ['-g', '-DDCPOMATIC_DEBUG']) else: conf.env.append_value('CXXFLAGS', '-O2') @@ -228,16 +228,16 @@ def build(bld): d = { 'PREFIX' : '${PREFIX' } obj = bld(features = 'subst') - obj.source = 'dvdomatic.desktop.in' - obj.target = 'dvdomatic.desktop' + obj.source = 'dcpomatic.desktop.in' + obj.target = 'dcpomatic.desktop' obj.dict = d - bld.install_files('${PREFIX}/share/applications', 'dvdomatic.desktop') + bld.install_files('${PREFIX}/share/applications', 'dcpomatic.desktop') for r in ['22x22', '32x32', '48x48', '64x64', '128x128']: - bld.install_files('${PREFIX}/share/icons/hicolor/%s/apps' % r, 'icons/%s/dvdomatic.png' % r) + bld.install_files('${PREFIX}/share/icons/hicolor/%s/apps' % r, 'icons/%s/dcpomatic.png' % r) if not bld.env.TARGET_WINDOWS: - bld.install_files('${PREFIX}/share/dvdomatic', 'icons/taskbar_icon.png') + bld.install_files('${PREFIX}/share/dcpomatic', 'icons/taskbar_icon.png') bld.add_post_fun(post) @@ -259,8 +259,8 @@ def create_version_cc(version): try: text = '#include "version.h"\n' - text += 'char const * dvdomatic_git_commit = \"%s\";\n' % commit - text += 'char const * dvdomatic_version = \"%s\";\n' % version + text += 'char const * dcpomatic_git_commit = \"%s\";\n' % commit + text += 'char const * dcpomatic_version = \"%s\";\n' % version print('Writing version information to src/lib/version.cc') o = open('src/lib/version.cc', 'w') o.write(text) -- cgit v1.2.3 From 98499a61e17e68c438e56fd8854081a4c98b15ad Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 20 Apr 2013 02:26:23 +0100 Subject: Somewhat hacky but seemingly functional frame back/forward (rest of #68). --- src/lib/decoder.h | 2 ++ src/lib/ffmpeg_decoder.cc | 46 +++++++++++++++++++++++++++++++++++++++++----- src/lib/ffmpeg_decoder.h | 4 +++- src/lib/format.cc | 2 +- src/wx/film_viewer.cc | 40 ++++++++++++++++++++++++++++++++++++---- src/wx/film_viewer.h | 6 +++++- 6 files changed, 88 insertions(+), 12 deletions(-) (limited to 'src/lib/decoder.h') diff --git a/src/lib/decoder.h b/src/lib/decoder.h index f2f523516..2bc462c33 100644 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@ -59,6 +59,8 @@ public: virtual bool pass () = 0; virtual bool seek (double); virtual bool seek_to_last (); + virtual void seek_back () {} + virtual void seek_forward () {} boost::signals2::signal OutputChanged; diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 2d7092789..7c88c3c35 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -530,7 +530,7 @@ FFmpegDecoder::filter_and_emit_video () bool FFmpegDecoder::seek (double p) { - return do_seek (p, false); + return do_seek (p, false, false); } bool @@ -540,21 +540,57 @@ FFmpegDecoder::seek_to_last () (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); + return do_seek (last_source_time(), true, false); +} + +void +FFmpegDecoder::seek_back () +{ + do_seek (last_source_time() - 2.5 / frames_per_second (), true, true); +} + +void +FFmpegDecoder::seek_forward () +{ + do_seek (last_source_time() - 0.5 / frames_per_second(), true, true); } bool -FFmpegDecoder::do_seek (double p, bool backwards) +FFmpegDecoder::do_seek (double p, bool backwards, bool accurate) { 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); - + avcodec_flush_buffers (_video_codec_context); if (_subtitle_codec_context) { avcodec_flush_buffers (_subtitle_codec_context); } - + + if (accurate) { + while (1) { + int r = av_read_frame (_format_context, &_packet); + if (r < 0) { + return true; + } + + avcodec_get_frame_defaults (_frame); + + if (_packet.stream_index == _video_stream) { + int finished = 0; + int const r = avcodec_decode_video2 (_video_codec_context, _frame, &finished, &_packet); + if (r >= 0 && finished) { + int64_t const bet = av_frame_get_best_effort_timestamp (_frame); + if (bet > vt) { + break; + } + } + } + + av_free_packet (&_packet); + } + } + return r < 0; } diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index 2a4d40b1d..0c89b973d 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -102,11 +102,13 @@ public: bool seek (double); bool seek_to_last (); + void seek_forward (); + void seek_back (); private: bool pass (); - bool do_seek (double p, bool); + bool do_seek (double p, bool, bool); PixelFormat pixel_format () const; AVSampleFormat audio_sample_format () const; int bytes_per_audio_sample () const; diff --git a/src/lib/format.cc b/src/lib/format.cc index 640eee167..8c3d0d8ad 100644 --- a/src/lib/format.cc +++ b/src/lib/format.cc @@ -50,7 +50,7 @@ FixedFormat::name () const s << _nickname << N_(" ("); } - s << setprecision(3) << (_ratio / 100.0) << N_(":1"); + s << setprecision(3) << _ratio << N_(":1"); if (!_nickname.empty ()) { s << N_(")"); diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 00f895285..5770c5b70 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -51,6 +51,8 @@ FilmViewer::FilmViewer (shared_ptr f, wxWindow* p) : wxPanel (p) , _panel (new wxPanel (this)) , _slider (new wxSlider (this, wxID_ANY, 0, 0, 4096)) + , _back_button (new wxButton (this, wxID_ANY, wxT("<"))) + , _forward_button (new wxButton (this, wxID_ANY, wxT(">"))) , _frame (new wxStaticText (this, wxID_ANY, wxT(""))) , _timecode (new wxStaticText (this, wxID_ANY, wxT(""))) , _play_button (new wxToggleButton (this, wxID_ANY, _("Play"))) @@ -72,14 +74,18 @@ FilmViewer::FilmViewer (shared_ptr f, wxWindow* p) wxBoxSizer* time_sizer = new wxBoxSizer (wxVERTICAL); time_sizer->Add (_frame, 0, wxEXPAND); time_sizer->Add (_timecode, 0, wxEXPAND); - + + h_sizer->Add (_back_button, 0, wxALL, 2); h_sizer->Add (time_sizer, 0, wxEXPAND); + h_sizer->Add (_forward_button, 0, wxALL, 2); h_sizer->Add (_play_button, 0, wxEXPAND); h_sizer->Add (_slider, 1, wxEXPAND); _v_sizer->Add (h_sizer, 0, wxEXPAND | wxALL, 6); _frame->SetMinSize (wxSize (84, -1)); + _back_button->SetMinSize (wxSize (32, -1)); + _forward_button->SetMinSize (wxSize (32, -1)); _panel->Connect (wxID_ANY, wxEVT_PAINT, wxPaintEventHandler (FilmViewer::paint_panel), 0, this); _panel->Connect (wxID_ANY, wxEVT_SIZE, wxSizeEventHandler (FilmViewer::panel_sized), 0, this); @@ -88,6 +94,8 @@ FilmViewer::FilmViewer (shared_ptr f, wxWindow* p) _slider->Connect (wxID_ANY, wxEVT_SCROLL_PAGEDOWN, wxScrollEventHandler (FilmViewer::slider_moved), 0, this); _play_button->Connect (wxID_ANY, wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler (FilmViewer::play_clicked), 0, this); _timer.Connect (wxID_ANY, wxEVT_TIMER, wxTimerEventHandler (FilmViewer::timer), 0, this); + _back_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmViewer::back_clicked), 0, this); + _forward_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmViewer::forward_clicked), 0, this); set_film (f); @@ -121,7 +129,7 @@ FilmViewer::film_changed (Film::Property p) if (_decoders.video == 0) { break; } - _decoders.video->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3)); + _decoders.video->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3, _4)); _decoders.video->OutputChanged.connect (boost::bind (&FilmViewer::decoder_changed, this)); _decoders.video->set_subtitle_stream (_film->subtitle_stream()); calculate_sizes (); @@ -392,7 +400,7 @@ FilmViewer::check_play_state () } void -FilmViewer::process_video (shared_ptr image, bool, shared_ptr sub) +FilmViewer::process_video (shared_ptr image, bool, shared_ptr sub, double t) { _raw_frame = image; _raw_sub = sub; @@ -401,7 +409,6 @@ FilmViewer::process_video (shared_ptr image, bool, shared_ptr s _got_frame = true; - double const t = _decoders.video->last_source_time (); double const fps = _decoders.video->frames_per_second (); _frame->SetLabel (wxString::Format ("%d", int (rint (t * fps)))); @@ -465,3 +472,28 @@ FilmViewer::active_jobs_changed (bool a) _play_button->Enable (!a); } +void +FilmViewer::back_clicked (wxCommandEvent &) +{ + if (!_decoders.video) { + return; + } + + _decoders.video->seek_back (); + get_frame (); + _panel->Refresh (); + _panel->Update (); +} + +void +FilmViewer::forward_clicked (wxCommandEvent &) +{ + if (!_decoders.video) { + return; + } + + _decoders.video->seek_forward (); + get_frame (); + _panel->Refresh (); + _panel->Update (); +} diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index 859bf7ede..a78c772a4 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -48,7 +48,7 @@ private: void slider_moved (wxScrollEvent &); void play_clicked (wxCommandEvent &); void timer (wxTimerEvent &); - void process_video (boost::shared_ptr, bool, boost::shared_ptr); + void process_video (boost::shared_ptr, bool, boost::shared_ptr, double); void calculate_sizes (); void check_play_state (); void update_from_raw (); @@ -56,12 +56,16 @@ private: void raw_to_display (); void get_frame (); void active_jobs_changed (bool); + void back_clicked (wxCommandEvent &); + void forward_clicked (wxCommandEvent &); boost::shared_ptr _film; wxSizer* _v_sizer; wxPanel* _panel; wxSlider* _slider; + wxButton* _back_button; + wxButton* _forward_button; wxStaticText* _frame; wxStaticText* _timecode; wxToggleButton* _play_button; -- cgit v1.2.3 From 23050047454f1c1f7aadad41bf7b05d00d8ffe7f Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Fri, 26 Apr 2013 15:24:57 +0100 Subject: Attempted fixes for some unimplemented timing bits. --- src/lib/decoder.h | 8 +++-- src/lib/ffmpeg_decoder.cc | 16 +++++++--- src/lib/ffmpeg_decoder.h | 4 +-- src/lib/player.cc | 77 ++++++++++++++++++++++++++--------------------- src/lib/player.h | 18 +++++++---- 5 files changed, 75 insertions(+), 48 deletions(-) (limited to 'src/lib/decoder.h') diff --git a/src/lib/decoder.h b/src/lib/decoder.h index 20e32bfbf..02ccaa42b 100644 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@ -56,8 +56,12 @@ public: virtual bool pass () = 0; virtual bool seek (double); - virtual void seek_back () {} - virtual void seek_forward () {} + virtual bool seek_back () { + return true; + } + virtual bool seek_forward () { + return true; + } boost::signals2::signal OutputChanged; diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 82c7cafd1..d5285b73a 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -519,16 +519,24 @@ FFmpegDecoder::seek (double p) return do_seek (p, false, false); } -void +bool FFmpegDecoder::seek_back () { - do_seek (last_content_time() - 2.5 / video_frame_rate(), true, true); + if (last_content_time() < 2.5) { + return true; + } + + return do_seek (last_content_time() - 2.5 / video_frame_rate(), true, true); } -void +bool FFmpegDecoder::seek_forward () { - do_seek (last_content_time() - 0.5 / video_frame_rate(), true, true); + if (last_content_time() >= (video_length() - video_frame_rate())) { + return true; + } + + return do_seek (last_content_time() - 0.5 / video_frame_rate(), true, true); } bool diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index 174cc3995..1e273752a 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -77,8 +77,8 @@ public: } bool seek (double); - void seek_forward (); - void seek_back (); + bool seek_forward (); + bool seek_back (); bool pass (); private: diff --git a/src/lib/player.cc b/src/lib/player.cc index 7a149d734..01bdc5ee0 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -30,6 +30,7 @@ using std::list; using std::cout; +using std::vector; using boost::shared_ptr; using boost::weak_ptr; using boost::dynamic_pointer_cast; @@ -74,27 +75,27 @@ Player::pass () bool done = true; - if (_video_decoder != _video_decoders.end ()) { + if (_video_decoder < _video_decoders.size ()) { /* Run video decoder; this may also produce audio */ - if ((*_video_decoder)->pass ()) { + if (_video_decoders[_video_decoder]->pass ()) { _video_decoder++; } - if (_video_decoder != _video_decoders.end ()) { + if (_video_decoder < _video_decoders.size ()) { done = false; } - } else if (!_video && _playlist->audio_from() == Playlist::AUDIO_FFMPEG && _sequential_audio_decoder != _audio_decoders.end ()) { + } else if (!_video && _playlist->audio_from() == Playlist::AUDIO_FFMPEG && _sequential_audio_decoder < _audio_decoders.size ()) { /* We're not producing video, so we may need to run FFmpeg content to get the audio */ - if ((*_sequential_audio_decoder)->pass ()) { + if (_audio_decoders[_sequential_audio_decoder]->pass ()) { _sequential_audio_decoder++; } - if (_sequential_audio_decoder != _audio_decoders.end ()) { + if (_sequential_audio_decoder < _audio_decoders.size ()) { done = false; } @@ -102,7 +103,7 @@ Player::pass () /* We're getting audio from SndfileContent */ - for (list >::iterator i = _audio_decoders.begin(); i != _audio_decoders.end(); ++i) { + for (vector >::iterator i = _audio_decoders.begin(); i != _audio_decoders.end(); ++i) { if (!(*i)->pass ()) { done = false; } @@ -121,35 +122,30 @@ Player::set_progress (shared_ptr job) { /* Assume progress can be divined from how far through the video we are */ - if (_video_decoder == _video_decoders.end() || !_playlist->video_length()) { + if (_video_decoder >= _video_decoders.size() || !_playlist->video_length()) { return; } - - ContentVideoFrame p = 0; - list >::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 ()); + job->set_progress ((_video_start[_video_decoder] + _video_decoders[_video_decoder]->video_frame()) / _playlist->video_length ()); } void Player::process_video (shared_ptr i, bool same, shared_ptr s, double t) { - /* XXX: this time will need mangling to add on the offset of the start of the content */ - Video (i, same, s, t); + Video (i, same, s, _video_start[_video_decoder] + t); } void Player::process_audio (weak_ptr c, shared_ptr b, double t) { - /* XXX: this time will need mangling to add on the offset of the start of the content */ AudioMapping mapping = _film->audio_mapping (); if (!_audio_buffers) { _audio_buffers.reset (new AudioBuffers (mapping.dcp_channels(), b->frames ())); _audio_buffers->make_silent (); _audio_time = t; + if (_playlist->audio_from() == Playlist::AUDIO_FFMPEG) { + _audio_time = _audio_time.get() + _audio_start[_sequential_audio_decoder]; + } } for (int i = 0; i < b->channels(); ++i) { @@ -177,18 +173,20 @@ Player::seek (double t) } /* Find the decoder that contains this position */ - _video_decoder = _video_decoders.begin (); - while (_video_decoder != _video_decoders.end ()) { - double const this_length = double ((*_video_decoder)->video_length()) / _film->video_frame_rate (); - if (t < this_length) { + _video_decoder = 0; + while (_video_decoder < _video_decoders.size ()) { + if (t < _video_start[_video_decoder]) { + assert (_video_decoder); + --_video_decoder; break; } - t -= this_length; + + t -= _video_start[_video_decoder]; ++_video_decoder; } - if (_video_decoder != _video_decoders.end()) { - (*_video_decoder)->seek (t); + if (_video_decoder < _video_decoders.size()) { + _video_decoders[_video_decoder]->seek (t); } else { return true; } @@ -216,13 +214,21 @@ void Player::setup_decoders () { _video_decoders.clear (); - _video_decoder = _video_decoders.end (); + _video_decoder = 0; _audio_decoders.clear (); + _sequential_audio_decoder = 0; + + _video_start.clear(); + _audio_start.clear(); + + double video_so_far = 0; + double audio_so_far = 0; if (_video) { list > vc = _playlist->video (); for (list >::iterator i = vc.begin(); i != vc.end(); ++i) { + shared_ptr c; shared_ptr d; /* XXX: into content? */ @@ -241,19 +247,23 @@ Player::setup_decoders () fd->Audio.connect (bind (&Player::process_audio, this, fc, _1, _2)); } + c = fc; d = fd; } shared_ptr ic = dynamic_pointer_cast (*i); if (ic) { + c = ic; d.reset (new ImageMagickDecoder (_film, ic)); } d->connect_video (shared_from_this ()); _video_decoders.push_back (d); + _video_start.push_back (video_so_far); + video_so_far += c->video_length() / c->video_frame_rate(); } - _video_decoder = _video_decoders.begin (); + _video_decoder = 0; } if (_playlist->audio_from() == Playlist::AUDIO_FFMPEG && !_video) { @@ -278,9 +288,11 @@ Player::setup_decoders () d->Audio.connect (bind (&Player::process_audio, this, fc, _1, _2)); _audio_decoders.push_back (d); + _audio_start.push_back (audio_so_far); + audio_so_far += fc->audio_length() / fc->audio_frame_rate(); } - _sequential_audio_decoder = _audio_decoders.begin (); + _sequential_audio_decoder = 0; } if (_playlist->audio_from() == Playlist::AUDIO_SNDFILE) { @@ -294,6 +306,8 @@ Player::setup_decoders () shared_ptr d (new SndfileDecoder (_film, sc)); d->Audio.connect (bind (&Player::process_audio, this, sc, _1, _2)); _audio_decoders.push_back (d); + _audio_start.push_back (audio_so_far); + audio_so_far += sc->audio_length () / sc->audio_frame_rate(); } } } @@ -301,12 +315,7 @@ Player::setup_decoders () double Player::last_video_time () const { - double t = 0; - for (list >::const_iterator i = _video_decoders.begin(); i != _video_decoder; ++i) { - t += (*i)->video_length() / (*i)->video_frame_rate (); - } - - return t + (*_video_decoder)->last_content_time (); + return _video_start[_video_decoder] + _video_decoders[_video_decoder]->last_content_time (); } void diff --git a/src/lib/player.h b/src/lib/player.h index 44b7c126d..2069064d7 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -72,12 +72,18 @@ private: /** Our decoders are ready to go; if this is false the decoders must be (re-)created before they are used */ bool _have_valid_decoders; - std::list > _video_decoders; - std::list >::iterator _video_decoder; - std::list > _audio_decoders; - - /** Current audio decoder if we are running them sequentially; otherwise undefined */ - std::list >::iterator _sequential_audio_decoder; + /** Video decoders in order of presentation */ + std::vector > _video_decoders; + /** Start positions of each video decoder in seconds*/ + std::vector _video_start; + /** Index of current video decoder */ + size_t _video_decoder; + /** Audio decoders in order of presentation (if they are from FFmpeg) */ + std::vector > _audio_decoders; + /** Start positions of each audio decoder (if they are from FFmpeg) in seconds */ + std::vector _audio_start; + /** Current audio decoder index if we are running them sequentially; otherwise undefined */ + size_t _sequential_audio_decoder; boost::shared_ptr _audio_buffers; boost::optional _audio_time; -- cgit v1.2.3 From 21ce34c2cd04a2e7e133ff693b84c054182f4f91 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 16 May 2013 08:36:47 +0100 Subject: Compiles; strange hang on adding content to a film. --- src/lib/analyse_audio_job.cc | 4 +- src/lib/audio_buffers.cc | 222 +++++++++++++++++++++ src/lib/audio_buffers.h | 67 +++++++ src/lib/audio_content.cc | 6 - src/lib/audio_content.h | 5 +- src/lib/audio_decoder.cc | 14 +- src/lib/audio_decoder.h | 1 + src/lib/audio_mapping.cc | 51 ++--- src/lib/audio_mapping.h | 28 +-- src/lib/audio_sink.h | 2 + src/lib/combiner.cc | 4 +- src/lib/content.h | 2 +- src/lib/decoder.h | 1 - src/lib/encoder.cc | 17 +- src/lib/encoder.h | 2 - src/lib/ffmpeg_content.cc | 33 +++- src/lib/ffmpeg_content.h | 5 +- src/lib/ffmpeg_decoder.cc | 5 +- src/lib/film.cc | 188 ++++++------------ src/lib/film.h | 48 ++--- src/lib/format.cc | 3 +- src/lib/format.h | 2 +- src/lib/imagemagick_content.cc | 7 + src/lib/imagemagick_content.h | 1 + src/lib/player.cc | 338 +++++++++++++++----------------- src/lib/player.h | 53 ++--- src/lib/playlist.cc | 419 +++++++++++++--------------------------- src/lib/playlist.h | 77 +++----- src/lib/sndfile_content.cc | 14 +- src/lib/sndfile_content.h | 5 +- src/lib/sndfile_decoder.cc | 3 +- src/lib/subtitle.h | 2 +- src/lib/transcode_job.cc | 13 +- src/lib/types.h | 10 +- src/lib/util.cc | 227 +--------------------- src/lib/util.h | 50 +---- src/lib/video_content.cc | 6 - src/lib/video_content.h | 1 - src/lib/video_decoder.cc | 4 +- src/lib/writer.cc | 47 ++--- src/lib/wscript | 1 + src/wx/audio_dialog.cc | 4 - src/wx/audio_mapping_view.cc | 8 +- src/wx/ffmpeg_content_dialog.cc | 2 +- src/wx/film_editor.cc | 149 ++++---------- src/wx/film_editor.h | 6 - src/wx/film_viewer.cc | 18 +- src/wx/properties_dialog.cc | 10 +- src/wx/timeline.cc | 102 ++++------ src/wx/timeline.h | 16 +- src/wx/timeline_dialog.cc | 4 +- src/wx/timeline_dialog.h | 2 +- test/test.cc | 32 +-- wscript | 2 +- 54 files changed, 990 insertions(+), 1353 deletions(-) create mode 100644 src/lib/audio_buffers.cc create mode 100644 src/lib/audio_buffers.h (limited to 'src/lib/decoder.h') diff --git a/src/lib/analyse_audio_job.cc b/src/lib/analyse_audio_job.cc index f3c55b208..0ed33827c 100644 --- a/src/lib/analyse_audio_job.cc +++ b/src/lib/analyse_audio_job.cc @@ -55,13 +55,13 @@ AnalyseAudioJob::run () player->Audio.connect (bind (&AnalyseAudioJob::audio, this, _1)); - _samples_per_point = max (int64_t (1), _film->audio_length() / _num_points); + _samples_per_point = max (int64_t (1), _film->time_to_audio_frames (_film->length()) / _num_points); _current.resize (MAX_AUDIO_CHANNELS); _analysis.reset (new AudioAnalysis (MAX_AUDIO_CHANNELS)); while (!player->pass()) { - set_progress (float (_done) / _film->audio_length ()); + set_progress (float (_done) / _film->time_to_audio_frames (_film->length ())); } _analysis->write (_film->audio_analysis_path ()); diff --git a/src/lib/audio_buffers.cc b/src/lib/audio_buffers.cc new file mode 100644 index 000000000..cd8fcd35b --- /dev/null +++ b/src/lib/audio_buffers.cc @@ -0,0 +1,222 @@ +/* + Copyright (C) 2012-2013 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include +#include "audio_buffers.h" + +using std::bad_alloc; +using boost::shared_ptr; + +/** Construct an AudioBuffers. Audio data is undefined after this constructor. + * @param channels Number of channels. + * @param frames Number of frames to reserve space for. + */ +AudioBuffers::AudioBuffers (int channels, int frames) + : _channels (channels) + , _frames (frames) + , _allocated_frames (frames) +{ + _data = static_cast (malloc (_channels * sizeof (float *))); + if (!_data) { + throw bad_alloc (); + } + + for (int i = 0; i < _channels; ++i) { + _data[i] = static_cast (malloc (frames * sizeof (float))); + if (!_data[i]) { + throw bad_alloc (); + } + } +} + +/** Copy constructor. + * @param other Other AudioBuffers; data is copied. + */ +AudioBuffers::AudioBuffers (AudioBuffers const & other) + : _channels (other._channels) + , _frames (other._frames) + , _allocated_frames (other._frames) +{ + _data = static_cast (malloc (_channels * sizeof (float *))); + if (!_data) { + throw bad_alloc (); + } + + for (int i = 0; i < _channels; ++i) { + _data[i] = static_cast (malloc (_frames * sizeof (float))); + if (!_data[i]) { + throw bad_alloc (); + } + memcpy (_data[i], other._data[i], _frames * sizeof (float)); + } +} + +/* XXX: it's a shame that this is a copy-and-paste of the above; + probably fixable with c++0x. +*/ +AudioBuffers::AudioBuffers (boost::shared_ptr other) + : _channels (other->_channels) + , _frames (other->_frames) + , _allocated_frames (other->_frames) +{ + _data = static_cast (malloc (_channels * sizeof (float *))); + if (!_data) { + throw bad_alloc (); + } + + for (int i = 0; i < _channels; ++i) { + _data[i] = static_cast (malloc (_frames * sizeof (float))); + if (!_data[i]) { + throw bad_alloc (); + } + memcpy (_data[i], other->_data[i], _frames * sizeof (float)); + } +} + +/** AudioBuffers destructor */ +AudioBuffers::~AudioBuffers () +{ + for (int i = 0; i < _channels; ++i) { + free (_data[i]); + } + + free (_data); +} + +/** @param c Channel index. + * @return Buffer for this channel. + */ +float* +AudioBuffers::data (int c) const +{ + assert (c >= 0 && c < _channels); + return _data[c]; +} + +/** Set the number of frames that these AudioBuffers will report themselves + * as having. + * @param f Frames; must be less than or equal to the number of allocated frames. + */ +void +AudioBuffers::set_frames (int f) +{ + assert (f <= _allocated_frames); + _frames = f; +} + +/** Make all samples on all channels silent */ +void +AudioBuffers::make_silent () +{ + for (int i = 0; i < _channels; ++i) { + make_silent (i); + } +} + +/** Make all samples on a given channel silent. + * @param c Channel. + */ +void +AudioBuffers::make_silent (int c) +{ + assert (c >= 0 && c < _channels); + + for (int i = 0; i < _frames; ++i) { + _data[c][i] = 0; + } +} + +/** Copy data from another AudioBuffers to this one. All channels are copied. + * @param from AudioBuffers to copy from; must have the same number of channels as this. + * @param frames_to_copy Number of frames to copy. + * @param read_offset Offset to read from in `from'. + * @param write_offset Offset to write to in `to'. + */ +void +AudioBuffers::copy_from (AudioBuffers const * from, int frames_to_copy, int read_offset, int write_offset) +{ + assert (from->channels() == channels()); + + assert (from); + assert (read_offset >= 0 && (read_offset + frames_to_copy) <= from->_allocated_frames); + assert (write_offset >= 0 && (write_offset + frames_to_copy) <= _allocated_frames); + + for (int i = 0; i < _channels; ++i) { + memcpy (_data[i] + write_offset, from->_data[i] + read_offset, frames_to_copy * sizeof(float)); + } +} + +/** Move audio data around. + * @param from Offset to move from. + * @param to Offset to move to. + * @param frames Number of frames to move. + */ + +void +AudioBuffers::move (int from, int to, int frames) +{ + if (frames == 0) { + return; + } + + assert (from >= 0); + assert (from < _frames); + assert (to >= 0); + assert (to < _frames); + assert (frames > 0); + assert (frames <= _frames); + assert ((from + frames) <= _frames); + assert ((to + frames) <= _frames); + + for (int i = 0; i < _channels; ++i) { + memmove (_data[i] + to, _data[i] + from, frames * sizeof(float)); + } +} + +/** Add data from from `from', `from_channel' to our channel `to_channel' */ +void +AudioBuffers::accumulate (AudioBuffers const * from, int from_channel, int to_channel) +{ + int const N = frames (); + assert (from->frames() == N); + + float* s = from->data (from_channel); + float* d = _data[to_channel]; + + for (int i = 0; i < N; ++i) { + *d++ += *s++; + } +} + +void +AudioBuffers::ensure_size (int frames) +{ + if (_allocated_frames >= frames) { + return; + } + + for (int i = 0; i < _channels; ++i) { + _data[i] = static_cast (realloc (_data[i], _frames * sizeof (float))); + if (!_data[i]) { + throw bad_alloc (); + } + } +} diff --git a/src/lib/audio_buffers.h b/src/lib/audio_buffers.h new file mode 100644 index 000000000..5e7b9fda4 --- /dev/null +++ b/src/lib/audio_buffers.h @@ -0,0 +1,67 @@ +/* + Copyright (C) 2012-2013 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include + +/** @class AudioBuffers + * @brief A class to hold multi-channel audio data in float format. + */ +class AudioBuffers +{ +public: + AudioBuffers (int channels, int frames); + AudioBuffers (AudioBuffers const &); + AudioBuffers (boost::shared_ptr); + ~AudioBuffers (); + + void ensure_size (int); + + float** data () const { + return _data; + } + + float* data (int) const; + + int channels () const { + return _channels; + } + + int frames () const { + return _frames; + } + + void set_frames (int f); + + void make_silent (); + void make_silent (int c); + + void copy_from (AudioBuffers const * from, int frames_to_copy, int read_offset, int write_offset); + void move (int from, int to, int frames); + void accumulate (AudioBuffers const *, int, int); + +private: + /** Number of channels */ + int _channels; + /** Number of frames (where a frame is one sample across all channels) */ + int _frames; + /** Number of frames that _data can hold */ + int _allocated_frames; + /** Audio data (so that, e.g. _data[2][6] is channel 2, sample 6) */ + float** _data; +}; diff --git a/src/lib/audio_content.cc b/src/lib/audio_content.cc index dfa48d97e..9968f4725 100644 --- a/src/lib/audio_content.cc +++ b/src/lib/audio_content.cc @@ -43,9 +43,3 @@ AudioContent::AudioContent (AudioContent const & o) { } - -Time -AudioContent::temporal_length () const -{ - return audio_length() / audio_frame_rate(); -} diff --git a/src/lib/audio_content.h b/src/lib/audio_content.h index 18107843c..87858488c 100644 --- a/src/lib/audio_content.h +++ b/src/lib/audio_content.h @@ -44,9 +44,8 @@ public: virtual int audio_channels () const = 0; virtual ContentAudioFrame audio_length () const = 0; - virtual int audio_frame_rate () const = 0; - - Time temporal_length () const; + virtual int content_audio_frame_rate () const = 0; + virtual int output_audio_frame_rate (boost::shared_ptr) const = 0; }; #endif diff --git a/src/lib/audio_decoder.cc b/src/lib/audio_decoder.cc index 68554daf9..e1c93ac77 100644 --- a/src/lib/audio_decoder.cc +++ b/src/lib/audio_decoder.cc @@ -18,6 +18,7 @@ */ #include "audio_decoder.h" +#include "audio_buffers.h" #include "exceptions.h" #include "log.h" @@ -30,11 +31,12 @@ using boost::shared_ptr; AudioDecoder::AudioDecoder (shared_ptr f, shared_ptr c) : Decoder (f) , _audio_content (c) + , _output_audio_frame_rate (_audio_content->output_audio_frame_rate (f)) { - if (_audio_content->audio_frame_rate() != _film->target_audio_sample_rate()) { + if (_audio_content->content_audio_frame_rate() != _output_audio_frame_rate) { stringstream s; - s << String::compose ("Will resample audio from %1 to %2", _audio_content->audio_frame_rate(), _film->target_audio_sample_rate()); + s << String::compose ("Will resample audio from %1 to %2", _audio_content->content_audio_frame_rate(), _output_audio_frame_rate); _film->log()->log (s.str ()); /* We will be using planar float data when we call the @@ -49,10 +51,10 @@ AudioDecoder::AudioDecoder (shared_ptr f, shared_ptrtarget_audio_sample_rate(), + _output_audio_frame_rate, av_get_default_channel_layout (MAX_AUDIO_CHANNELS), AV_SAMPLE_FMT_FLTP, - _audio_content->audio_frame_rate(), + _audio_content->content_audio_frame_rate(), 0, 0 ); @@ -74,7 +76,7 @@ AudioDecoder::~AudioDecoder () void AudioDecoder::process_end () { - if (_film->has_audio() && _swr_context) { + if (_swr_context) { shared_ptr out (new AudioBuffers (_film->audio_mapping().dcp_channels(), 256)); @@ -106,7 +108,7 @@ AudioDecoder::emit_audio (shared_ptr data, Time time) if (_swr_context) { /* Compute the resampled frames count and add 32 for luck */ - int const max_resampled_frames = ceil ((int64_t) data->frames() * _film->target_audio_sample_rate() / _audio_content->audio_frame_rate()) + 32; + int const max_resampled_frames = ceil ((int64_t) data->frames() * _output_audio_frame_rate / _audio_content->content_audio_frame_rate()) + 32; shared_ptr resampled (new AudioBuffers (MAX_AUDIO_CHANNELS, max_resampled_frames)); diff --git a/src/lib/audio_decoder.h b/src/lib/audio_decoder.h index 1c7287a55..94845ec23 100644 --- a/src/lib/audio_decoder.h +++ b/src/lib/audio_decoder.h @@ -46,6 +46,7 @@ public: private: boost::shared_ptr _audio_content; SwrContext* _swr_context; + int _output_audio_frame_rate; }; #endif diff --git a/src/lib/audio_mapping.cc b/src/lib/audio_mapping.cc index 7e28aa5c4..e1fa0c220 100644 --- a/src/lib/audio_mapping.cc +++ b/src/lib/audio_mapping.cc @@ -31,7 +31,7 @@ using boost::lexical_cast; using boost::dynamic_pointer_cast; void -AudioMapping::add (Channel c, libdcp::Channel d) +AudioMapping::add (int c, libdcp::Channel d) { _content_to_dcp.push_back (make_pair (c, d)); } @@ -40,7 +40,7 @@ AudioMapping::add (Channel c, libdcp::Channel d) int AudioMapping::dcp_channels () const { - for (list >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) { + for (list >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) { if (((int) i->second) >= 2) { return 6; } @@ -49,11 +49,11 @@ AudioMapping::dcp_channels () const return 2; } -list +list AudioMapping::dcp_to_content (libdcp::Channel d) const { - list c; - for (list >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) { + list c; + for (list >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) { if (i->second == d) { c.push_back (i->first); } @@ -62,11 +62,11 @@ AudioMapping::dcp_to_content (libdcp::Channel d) const return c; } -list +list AudioMapping::content_channels () const { - list c; - for (list >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) { + list c; + for (list >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) { if (find (c.begin(), c.end(), i->first) == c.end ()) { c.push_back (i->first); } @@ -76,10 +76,10 @@ AudioMapping::content_channels () const } list -AudioMapping::content_to_dcp (Channel c) const +AudioMapping::content_to_dcp (int c) const { list d; - for (list >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) { + for (list >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) { if (i->first == c) { d.push_back (i->second); } @@ -91,41 +91,18 @@ AudioMapping::content_to_dcp (Channel c) const void AudioMapping::as_xml (xmlpp::Node* node) const { - for (list >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) { + for (list >::const_iterator i = _content_to_dcp.begin(); i != _content_to_dcp.end(); ++i) { xmlpp::Node* t = node->add_child ("Map"); - shared_ptr c = i->first.content.lock (); - t->add_child ("Content")->add_child_text (c->digest ()); - t->add_child ("ContentIndex")->add_child_text (lexical_cast (i->first.index)); + t->add_child ("ContentIndex")->add_child_text (lexical_cast (i->first)); t->add_child ("DCP")->add_child_text (lexical_cast (i->second)); } } void -AudioMapping::set_from_xml (ContentList const & content, shared_ptr node) +AudioMapping::set_from_xml (shared_ptr node) { list > const c = node->node_children ("Map"); for (list >::const_iterator i = c.begin(); i != c.end(); ++i) { - string const c = (*i)->string_child ("Content"); - ContentList::const_iterator j = content.begin (); - while (j != content.end() && (*j)->digest() != c) { - ++j; - } - - if (j == content.end ()) { - continue; - } - - shared_ptr ac = dynamic_pointer_cast (*j); - assert (ac); - - add (AudioMapping::Channel (ac, (*i)->number_child ("ContentIndex")), static_cast ((*i)->number_child ("DCP"))); + add ((*i)->number_child ("ContentIndex"), static_cast ((*i)->number_child ("DCP"))); } } - -bool -operator== (AudioMapping::Channel const & a, AudioMapping::Channel const & b) -{ - shared_ptr sa = a.content.lock (); - shared_ptr sb = b.content.lock (); - return sa == sb && a.index == b.index; -} diff --git a/src/lib/audio_mapping.h b/src/lib/audio_mapping.h index 248d2570e..3c471d3f4 100644 --- a/src/lib/audio_mapping.h +++ b/src/lib/audio_mapping.h @@ -30,33 +30,21 @@ class AudioMapping { public: void as_xml (xmlpp::Node *) const; - void set_from_xml (ContentList const &, boost::shared_ptr); - - struct Channel { - Channel (boost::weak_ptr c, int i) - : content (c) - , index (i) - {} - - boost::weak_ptr content; - int index; - }; - - void add (Channel, libdcp::Channel); + void set_from_xml (boost::shared_ptr); + + void add (int, libdcp::Channel); int dcp_channels () const; - std::list dcp_to_content (libdcp::Channel) const; - std::list > content_to_dcp () const { + std::list dcp_to_content (libdcp::Channel) const; + std::list > content_to_dcp () const { return _content_to_dcp; } - std::list content_channels () const; - std::list content_to_dcp (Channel) const; + std::list content_channels () const; + std::list content_to_dcp (int) const; private: - std::list > _content_to_dcp; + std::list > _content_to_dcp; }; -extern bool operator== (AudioMapping::Channel const &, AudioMapping::Channel const &); - #endif diff --git a/src/lib/audio_sink.h b/src/lib/audio_sink.h index 2e3ead005..1aad5edf9 100644 --- a/src/lib/audio_sink.h +++ b/src/lib/audio_sink.h @@ -20,6 +20,8 @@ #ifndef DCPOMATIC_AUDIO_SINK_H #define DCPOMATIC_AUDIO_SINK_H +class AudioBuffers; + class AudioSink { public: diff --git a/src/lib/combiner.cc b/src/lib/combiner.cc index 9f9461ec2..0afb9807a 100644 --- a/src/lib/combiner.cc +++ b/src/lib/combiner.cc @@ -33,7 +33,7 @@ Combiner::Combiner (shared_ptr log) * @param image Frame image. */ void -Combiner::process_video (shared_ptr image, bool, shared_ptr, double) +Combiner::process_video (shared_ptr image, bool, shared_ptr, Time) { _image.reset (new SimpleImage (image)); } @@ -43,7 +43,7 @@ Combiner::process_video (shared_ptr image, bool, shared_ptr image, bool, shared_ptr sub, double t) +Combiner::process_video_b (shared_ptr image, bool, shared_ptr sub, Time t) { /* Copy the right half of this image into our _image */ /* XXX: this should probably be in the Image class */ diff --git a/src/lib/content.h b/src/lib/content.h index e1cf41df0..9f465570b 100644 --- a/src/lib/content.h +++ b/src/lib/content.h @@ -46,7 +46,7 @@ public: virtual std::string information () const = 0; virtual void as_xml (xmlpp::Node *) const; virtual boost::shared_ptr clone () const = 0; - virtual Time temporal_length () const = 0; + virtual Time length (boost::shared_ptr) const = 0; boost::filesystem::path file () const { boost::mutex::scoped_lock lm (_mutex); diff --git a/src/lib/decoder.h b/src/lib/decoder.h index 02ccaa42b..ae0d0c671 100644 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@ -29,7 +29,6 @@ #include #include #include -#include "util.h" #include "video_source.h" #include "audio_source.h" #include "film.h" diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc index 6cb384e20..95e98ab76 100644 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@ -58,7 +58,6 @@ int const Encoder::_history_size = 25; Encoder::Encoder (shared_ptr f, shared_ptr j) : _film (f) , _job (j) - , _video_frames_in (0) , _video_frames_out (0) , _have_a_real_frame (false) , _terminate (false) @@ -180,13 +179,6 @@ Encoder::frame_done () void Encoder::process_video (shared_ptr image, bool same, shared_ptr sub, Time) { - FrameRateConversion frc (_film->video_frame_rate(), _film->dcp_frame_rate()); - - if (frc.skip && (_video_frames_in % 2)) { - ++_video_frames_in; - return; - } - boost::mutex::scoped_lock lock (_mutex); /* Wait until the queue has gone down a bit */ @@ -220,7 +212,7 @@ Encoder::process_video (shared_ptr image, bool same, shared_ptrformat()->dcp_size(), _film->format()->dcp_padding (_film), _film->subtitle_offset(), _film->subtitle_scale(), - _film->scaler(), _video_frames_out, _film->dcp_frame_rate(), s.second, + _film->scaler(), _video_frames_out, _film->dcp_video_frame_rate(), s.second, _film->colour_lut(), _film->j2k_bandwidth(), _film->log() ) @@ -230,14 +222,7 @@ Encoder::process_video (shared_ptr image, bool same, shared_ptrrepeat (_video_frames_out); - ++_video_frames_out; - frame_done (); - } } void diff --git a/src/lib/encoder.h b/src/lib/encoder.h index b6d3663fd..6815fa6f6 100644 --- a/src/lib/encoder.h +++ b/src/lib/encoder.h @@ -101,8 +101,6 @@ private: /** Number of frames that we should keep history for */ static int const _history_size; - /** Number of video frames received so far */ - ContentVideoFrame _video_frames_in; /** Number of video frames written for the DCP so far */ int _video_frames_out; diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc index a61f777c8..55281ff9b 100644 --- a/src/lib/ffmpeg_content.cc +++ b/src/lib/ffmpeg_content.cc @@ -206,7 +206,7 @@ FFmpegContent::audio_length () const return 0; } - return video_frames_to_audio_frames (_video_length, audio_frame_rate(), video_frame_rate()); + return video_frames_to_audio_frames (_video_length, content_audio_frame_rate(), video_frame_rate()); } int @@ -220,7 +220,7 @@ FFmpegContent::audio_channels () const } int -FFmpegContent::audio_frame_rate () const +FFmpegContent::content_audio_frame_rate () const { if (!_audio_stream) { return 0; @@ -229,6 +229,28 @@ FFmpegContent::audio_frame_rate () const return _audio_stream->frame_rate; } +int +FFmpegContent::output_audio_frame_rate (shared_ptr film) const +{ + /* Resample to a DCI-approved sample rate */ + double t = dcp_audio_frame_rate (content_audio_frame_rate ()); + + FrameRateConversion frc (video_frame_rate(), film->dcp_video_frame_rate()); + + /* Compensate if the DCP is being run at a different frame rate + to the source; that is, if the video is run such that it will + look different in the DCP compared to the source (slower or faster). + skip/repeat doesn't come into effect here. + */ + + if (frc.change_speed) { + t *= video_frame_rate() * frc.factor() / film->dcp_video_frame_rate(); + cout << "-> " << t << "\n"; + } + + return rint (t); +} + bool operator== (FFmpegSubtitleStream const & a, FFmpegSubtitleStream const & b) { @@ -281,8 +303,9 @@ FFmpegContent::clone () const return shared_ptr (new FFmpegContent (*this)); } -double -FFmpegContent::temporal_length () const +Time +FFmpegContent::length (shared_ptr film) const { - return video_length() / video_frame_rate(); + FrameRateConversion frc (video_frame_rate (), film->dcp_video_frame_rate ()); + return video_length() * frc.factor() * TIME_HZ / film->dcp_video_frame_rate (); } diff --git a/src/lib/ffmpeg_content.h b/src/lib/ffmpeg_content.h index 6d7151498..540df041f 100644 --- a/src/lib/ffmpeg_content.h +++ b/src/lib/ffmpeg_content.h @@ -89,12 +89,13 @@ public: std::string information () const; void as_xml (xmlpp::Node *) const; boost::shared_ptr clone () const; - double temporal_length () const; + Time length (boost::shared_ptr) const; /* AudioContent */ int audio_channels () const; ContentAudioFrame audio_length () const; - int audio_frame_rate () const; + int content_audio_frame_rate () const; + int output_audio_frame_rate (boost::shared_ptr) const; std::vector subtitle_streams () const { boost::mutex::scoped_lock lm (_mutex); diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 0e704bb14..d21a93e29 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -48,6 +48,7 @@ extern "C" { #include "ffmpeg_decoder.h" #include "filter_graph.h" #include "subtitle.h" +#include "audio_buffers.h" #include "i18n.h" @@ -219,8 +220,10 @@ FFmpegDecoder::setup_subtitle () bool FFmpegDecoder::pass () { - int r = av_read_frame (_format_context, &_packet); + cout << "FFmpeg::pass\n"; + int r = av_read_frame (_format_context, &_packet); + if (r < 0) { if (r != AVERROR_EOF) { /* Maybe we should fail here, but for now we'll just finish off instead */ diff --git a/src/lib/film.cc b/src/lib/film.cc index b8102d315..646b114da 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -108,7 +108,7 @@ Film::Film (string d, bool must_exist) , _colour_lut (0) , _j2k_bandwidth (200000000) , _dci_metadata (Config::instance()->default_dci_metadata ()) - , _dcp_frame_rate (0) + , _dcp_video_frame_rate (0) , _dirty (false) { set_dci_date_today (); @@ -179,7 +179,7 @@ Film::Film (Film const & o) , _colour_lut (o._colour_lut) , _j2k_bandwidth (o._j2k_bandwidth) , _dci_metadata (o._dci_metadata) - , _dcp_frame_rate (o._dcp_frame_rate) + , _dcp_video_frame_rate (o._dcp_video_frame_rate) , _dci_date (o._dci_date) , _dirty (o._dirty) { @@ -198,7 +198,7 @@ Film::video_state_identifier () const s << format()->id() << "_" << _playlist->video_digest() << "_" << crop().left << "_" << crop().right << "_" << crop().top << "_" << crop().bottom - << "_" << _dcp_frame_rate + << "_" << _dcp_video_frame_rate << "_" << f.first << "_" << f.second << "_" << scaler()->id() << "_" << j2k_bandwidth() @@ -315,8 +315,8 @@ Film::make_dcp () throw MissingSettingError (_("format")); } - if (_playlist->content().empty ()) { - throw MissingSettingError (_("content")); + if (_playlist->regions().empty ()) { + throw StringError (_("You must add some content to the DCP before creating it")); } if (dcp_content_type() == 0) { @@ -450,9 +450,8 @@ Film::write_metadata () const root->add_child("ColourLUT")->add_child_text (boost::lexical_cast (_colour_lut)); root->add_child("J2KBandwidth")->add_child_text (boost::lexical_cast (_j2k_bandwidth)); _dci_metadata.as_xml (root->add_child ("DCIMetadata")); - root->add_child("DCPFrameRate")->add_child_text (boost::lexical_cast (_dcp_frame_rate)); + root->add_child("DCPVideoFrameRate")->add_child_text (boost::lexical_cast (_dcp_video_frame_rate)); root->add_child("DCIDate")->add_child_text (boost::gregorian::to_iso_string (_dci_date)); - _audio_mapping.as_xml (root->add_child("AudioMapping")); _playlist->as_xml (root->add_child ("Playlist")); doc.write_to_file_formatted (file ("metadata.xml")); @@ -524,11 +523,10 @@ Film::read_metadata () _colour_lut = f.number_child ("ColourLUT"); _j2k_bandwidth = f.number_child ("J2KBandwidth"); _dci_metadata = DCIMetadata (f.node_child ("DCIMetadata")); - _dcp_frame_rate = f.number_child ("DCPFrameRate"); + _dcp_video_frame_rate = f.number_child ("DCPVideoFrameRate"); _dci_date = boost::gregorian::from_undelimited_string (f.string_child ("DCIDate")); _playlist->set_from_xml (f.node_child ("Playlist")); - _audio_mapping.set_from_xml (_playlist->content(), f.node_child ("AudioMapping")); _dirty = false; } @@ -577,32 +575,6 @@ Film::file (string f) const return p.string (); } -/** @return The sampling rate that we will resample the audio to */ -int -Film::target_audio_sample_rate () const -{ - if (!has_audio ()) { - return 0; - } - - /* Resample to a DCI-approved sample rate */ - double t = dcp_audio_sample_rate (audio_frame_rate()); - - FrameRateConversion frc (video_frame_rate(), dcp_frame_rate()); - - /* Compensate if the DCP is being run at a different frame rate - to the source; that is, if the video is run such that it will - look different in the DCP compared to the source (slower or faster). - skip/repeat doesn't come into effect here. - */ - - if (frc.change_speed) { - t *= video_frame_rate() * frc.factor() / dcp_frame_rate(); - } - - return rint (t); -} - /** @return a DCI-compliant name for a DCP of this film */ string Film::dci_name (bool if_created_now) const @@ -649,22 +621,7 @@ Film::dci_name (bool if_created_now) const } } - switch (audio_channels ()) { - case 1: - d << "_10"; - break; - case 2: - d << "_20"; - break; - case 6: - d << "_51"; - break; - case 8: - d << "_71"; - break; - } - - d << "_2K"; + d << "_51_2K"; if (!dm.studio.empty ()) { d << "_" << dm.studio; @@ -738,11 +695,11 @@ Film::set_trust_content_headers (bool t) signal_changed (TRUST_CONTENT_HEADERS); - ContentList content = _playlist->content (); - if (!_trust_content_headers && !content.empty()) { + Playlist::RegionList regions = _playlist->regions (); + if (!_trust_content_headers && !regions.empty()) { /* We just said that we don't trust the content's header */ - for (ContentList::iterator i = content.begin(); i != content.end(); ++i) { - examine_content (*i); + for (Playlist::RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { + examine_content (i->content); } } } @@ -976,13 +933,13 @@ Film::set_dci_metadata (DCIMetadata m) void -Film::set_dcp_frame_rate (int f) +Film::set_dcp_video_frame_rate (int f) { { boost::mutex::scoped_lock lm (_state_mutex); - _dcp_frame_rate = f; + _dcp_video_frame_rate = f; } - signal_changed (DCP_FRAME_RATE); + signal_changed (DCP_VIDEO_FRAME_RATE); } void @@ -995,8 +952,7 @@ Film::signal_changed (Property p) switch (p) { case Film::CONTENT: - set_dcp_frame_rate (best_dcp_frame_rate (video_frame_rate ())); - set_audio_mapping (_playlist->default_audio_mapping ()); + set_dcp_video_frame_rate (_playlist->best_dcp_frame_rate ()); break; default: break; @@ -1082,10 +1038,10 @@ Film::playlist () const return _playlist; } -ContentList -Film::content () const +Playlist::RegionList +Film::regions () const { - return _playlist->content (); + return _playlist->regions (); } void @@ -1101,64 +1057,10 @@ Film::remove_content (shared_ptr c) _playlist->remove (c); } -void -Film::move_content_earlier (shared_ptr c) -{ - _playlist->move_earlier (c); -} - -void -Film::move_content_later (shared_ptr c) -{ - _playlist->move_later (c); -} - -ContentAudioFrame -Film::audio_length () const -{ - return _playlist->audio_length (); -} - -int -Film::audio_channels () const -{ - return _playlist->audio_channels (); -} - -int -Film::audio_frame_rate () const -{ - return _playlist->audio_frame_rate (); -} - -bool -Film::has_audio () const -{ - return _playlist->has_audio (); -} - -float -Film::video_frame_rate () const -{ - return _playlist->video_frame_rate (); -} - -libdcp::Size -Film::video_size () const +Time +Film::length () const { - return _playlist->video_size (); -} - -ContentVideoFrame -Film::video_length () const -{ - return _playlist->video_length (); -} - -ContentVideoFrame -Film::content_length () const -{ - return _playlist->content_length (); + return _playlist->length (shared_from_this ()); } bool @@ -1167,24 +1069,17 @@ Film::has_subtitles () const return _playlist->has_subtitles (); } -void -Film::set_audio_mapping (AudioMapping m) +OutputVideoFrame +Film::best_dcp_video_frame_rate () const { - { - boost::mutex::scoped_lock lm (_state_mutex); - _audio_mapping = m; - } - - signal_changed (AUDIO_MAPPING); + return _playlist->best_dcp_frame_rate (); } void Film::playlist_content_changed (boost::weak_ptr c, int p) { if (p == VideoContentProperty::VIDEO_FRAME_RATE) { - set_dcp_frame_rate (best_dcp_frame_rate (video_frame_rate ())); - } else if (p == AudioContentProperty::AUDIO_CHANNELS) { - set_audio_mapping (_playlist->default_audio_mapping ()); + set_dcp_video_frame_rate (_playlist->best_dcp_frame_rate ()); } if (ui_signaller) { @@ -1209,3 +1104,34 @@ Film::set_loop (int c) { _playlist->set_loop (c); } + +OutputAudioFrame +Film::time_to_audio_frames (Time t) const +{ + return t * dcp_audio_frame_rate () / TIME_HZ; +} + +OutputVideoFrame +Film::time_to_video_frames (Time t) const +{ + return t * dcp_video_frame_rate () / TIME_HZ; +} + +Time +Film::audio_frames_to_time (OutputAudioFrame f) const +{ + return f * TIME_HZ / dcp_audio_frame_rate (); +} + +Time +Film::video_frames_to_time (OutputVideoFrame f) const +{ + return f * TIME_HZ / dcp_video_frame_rate (); +} + +OutputAudioFrame +Film::dcp_audio_frame_rate () const +{ + /* XXX */ + return 48000; +} diff --git a/src/lib/film.h b/src/lib/film.h index 18255a15e..cfc55c0ac 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -36,7 +36,7 @@ #include "dci_metadata.h" #include "types.h" #include "ffmpeg_content.h" -#include "audio_mapping.h" +#include "playlist.h" class DCPContentType; class Format; @@ -48,7 +48,6 @@ class AnalyseAudioJob; class ExternalAudioStream; class Content; class Player; -class Playlist; /** @class Film * @brief A representation of some audio and video content, and details of @@ -87,8 +86,6 @@ public: std::string file (std::string f) const; std::string dir (std::string d) const; - int target_audio_sample_rate () const; - void write_metadata () const; libdcp::Size cropped_size (libdcp::Size) const; @@ -105,27 +102,24 @@ public: boost::shared_ptr player () const; boost::shared_ptr playlist () const; - /* Proxies for some Playlist methods */ + OutputAudioFrame dcp_audio_frame_rate () const; - ContentList content () const; + OutputAudioFrame time_to_audio_frames (Time) const; + OutputVideoFrame time_to_video_frames (Time) const; + Time video_frames_to_time (OutputVideoFrame) const; + Time audio_frames_to_time (OutputAudioFrame) const; - ContentAudioFrame audio_length () const; - int audio_channels () const; - int audio_frame_rate () const; - bool has_audio () const; + /* Proxies for some Playlist methods */ - bool has_subtitles () const; - - float video_frame_rate () const; - libdcp::Size video_size () const; - ContentVideoFrame video_length () const; + Playlist::RegionList regions () const; - ContentVideoFrame content_length () const; + Time length () const; + bool has_subtitles () const; + OutputVideoFrame best_dcp_video_frame_rate () const; void set_loop (int); int loop () const; - enum TrimType { CPL, ENCODE @@ -159,7 +153,7 @@ public: COLOUR_LUT, J2K_BANDWIDTH, DCI_METADATA, - DCP_FRAME_RATE, + DCP_VIDEO_FRAME_RATE, AUDIO_MAPPING }; @@ -271,14 +265,10 @@ public: return _dci_metadata; } - int dcp_frame_rate () const { - boost::mutex::scoped_lock lm (_state_mutex); - return _dcp_frame_rate; - } - - AudioMapping audio_mapping () const { + /* XXX: -> "video_frame_rate" */ + int dcp_video_frame_rate () const { boost::mutex::scoped_lock lm (_state_mutex); - return _audio_mapping; + return _dcp_video_frame_rate; } /* SET */ @@ -289,8 +279,6 @@ public: void set_trust_content_headers (bool); void add_content (boost::shared_ptr); void remove_content (boost::shared_ptr); - void move_content_earlier (boost::shared_ptr); - void move_content_later (boost::shared_ptr); void set_dcp_content_type (DCPContentType const *); void set_format (Format const *); void set_crop (Crop); @@ -312,9 +300,8 @@ public: void set_colour_lut (int); void set_j2k_bandwidth (int); void set_dci_metadata (DCIMetadata); - void set_dcp_frame_rate (int); + void set_dcp_video_frame_rate (int); void set_dci_date_today (); - void set_audio_mapping (AudioMapping); /** Emitted when some property has of the Film has changed */ mutable boost::signals2::signal Changed; @@ -398,10 +385,9 @@ private: /** DCI naming stuff */ DCIMetadata _dci_metadata; /** Frames per second to run our DCP at */ - int _dcp_frame_rate; + int _dcp_video_frame_rate; /** The date that we should use in a DCI name */ boost::gregorian::date _dci_date; - AudioMapping _audio_mapping; /** true if our state has changed since we last saved it */ mutable bool _dirty; diff --git a/src/lib/format.cc b/src/lib/format.cc index f5026c0da..688b22f16 100644 --- a/src/lib/format.cc +++ b/src/lib/format.cc @@ -208,7 +208,8 @@ VariableFormat::VariableFormat (libdcp::Size dcp, string id, string n, string d) float VariableFormat::ratio (shared_ptr f) const { - libdcp::Size const c = f->cropped_size (f->video_size ()); + /* XXX */ + libdcp::Size const c;// = f->cropped_size (f->video_size ()); return float (c.width) / c.height; } diff --git a/src/lib/format.h b/src/lib/format.h index d45a3a10a..29347a3fd 100644 --- a/src/lib/format.h +++ b/src/lib/format.h @@ -24,7 +24,7 @@ #include #include -#include "util.h" +#include class Film; diff --git a/src/lib/imagemagick_content.cc b/src/lib/imagemagick_content.cc index 9e5f00ba0..2e42e25f3 100644 --- a/src/lib/imagemagick_content.cc +++ b/src/lib/imagemagick_content.cc @@ -98,3 +98,10 @@ ImageMagickContent::set_video_length (ContentVideoFrame len) signal_changed (VideoContentProperty::VIDEO_LENGTH); } + +Time +ImageMagickContent::length (shared_ptr film) const +{ + FrameRateConversion frc (24, film->dcp_video_frame_rate ()); + return video_length() * frc.factor() * TIME_HZ / film->dcp_video_frame_rate (); +} diff --git a/src/lib/imagemagick_content.h b/src/lib/imagemagick_content.h index b1e7f9495..366049002 100644 --- a/src/lib/imagemagick_content.h +++ b/src/lib/imagemagick_content.h @@ -38,6 +38,7 @@ public: std::string summary () const; void as_xml (xmlpp::Node *) const; boost::shared_ptr clone () const; + Time length (boost::shared_ptr) const; void set_video_length (ContentVideoFrame); diff --git a/src/lib/player.cc b/src/lib/player.cc index 95036cfe0..9cc166204 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -27,9 +27,11 @@ #include "sndfile_content.h" #include "playlist.h" #include "job.h" +#include "image.h" using std::list; using std::cout; +using std::min; using std::vector; using boost::shared_ptr; using boost::weak_ptr; @@ -42,6 +44,11 @@ Player::Player (shared_ptr f, shared_ptr p) , _audio (true) , _subtitles (true) , _have_valid_decoders (false) + , _position (0) + , _audio_buffers (MAX_AUDIO_CHANNELS, 0) + , _last_video (0) + , _last_was_black (false) + , _last_audio (0) { _playlist->Changed.connect (bind (&Player::playlist_changed, this)); _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2)); @@ -72,118 +79,118 @@ Player::pass () setup_decoders (); _have_valid_decoders = true; } - - bool done = true; - - if (_video && _video_decoder < _video_decoders.size ()) { - - /* Run video decoder; this may also produce audio */ - - if (_video_decoders[_video_decoder]->pass ()) { - _video_decoder++; - } - - if (_video_decoder < _video_decoders.size ()) { - done = false; - } - - } - - if (!_video && _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG && _sequential_audio_decoder < _audio_decoders.size ()) { - - /* We're not producing video, so we may need to run FFmpeg content to get the audio */ - - if (_audio_decoders[_sequential_audio_decoder]->pass ()) { - _sequential_audio_decoder++; - } - - if (_sequential_audio_decoder < _audio_decoders.size ()) { - done = false; - } - - } - - if (_audio && _playlist->audio_from() == Playlist::AUDIO_SNDFILE) { - - /* We're getting audio from SndfileContent */ - - for (vector >::iterator i = _audio_decoders.begin(); i != _audio_decoders.end(); ++i) { - if (!(*i)->pass ()) { - done = false; - } - } - Audio (_audio_buffers, _audio_time.get()); - _audio_buffers.reset (); - _audio_time = boost::none; - } - - return done; + cout << "-> Player::pass\n"; + + /* Here we are just finding the active decoder with the earliest last emission time, then + calling pass on it. If there is no decoder, we skip our position on until there is. + Hence this method will cause video and audio to be emitted, and it is up to the + process_{video,audio} methods to tidy it up. + */ + + Time earliest_pos = TIME_MAX; + shared_ptr earliest; + Time next_wait = TIME_MAX; + + for (list >::iterator i = _decoders.begin(); i != _decoders.end(); ++i) { + Time const ts = (*i)->region.time; + Time const te = (*i)->region.time + (*i)->region.content->length (_film); + if (ts <= _position && te > _position) { + Time const pos = ts + (*i)->last; + if (pos < earliest_pos) { + earliest_pos = pos; + earliest = *i; + } + } + + if (ts > _position) { + next_wait = min (next_wait, ts - _position); + } + } + + if (earliest) { + earliest->decoder->pass (); + _position = earliest->last; + } else if (next_wait < TIME_MAX) { + _position += next_wait; + } else { + cout << "<- Player::pass\n"; + return true; + } + + cout << "<- Player::pass\n"; + return false; } void -Player::process_video (shared_ptr i, bool same, shared_ptr s, double t) +Player::process_video (shared_ptr rd, shared_ptr image, bool same, shared_ptr sub, Time time) { - Video (i, same, s, _video_start[_video_decoder] + t); + shared_ptr vd = dynamic_pointer_cast (rd->decoder); + + Time const global_time = rd->region.time + time; + while ((global_time - _last_video) > 1) { + /* Fill in with black */ + emit_black_frame (); + } + + Video (image, same, sub, global_time); + rd->last = time; + _last_video = global_time; + _last_was_black = false; } void -Player::process_audio (weak_ptr c, shared_ptr b, double t) +Player::process_audio (shared_ptr rd, shared_ptr audio, Time time) { - AudioMapping mapping = _film->audio_mapping (); - if (!_audio_buffers) { - _audio_buffers.reset (new AudioBuffers (mapping.dcp_channels(), b->frames ())); - _audio_buffers->make_silent (); - _audio_time = t; - if (_playlist->audio_from() == Playlist::AUDIO_FFMPEG) { - _audio_time = _audio_time.get() + _audio_start[_sequential_audio_decoder]; - } - } - - for (int i = 0; i < b->channels(); ++i) { - list dcp = mapping.content_to_dcp (AudioMapping::Channel (c, i)); - for (list::iterator j = dcp.begin(); j != dcp.end(); ++j) { - _audio_buffers->accumulate (b, i, static_cast (*j)); - } - } - - if (_playlist->audio_from() == Playlist::AUDIO_FFMPEG) { - /* We can just emit this audio now as it will all be here */ - Audio (_audio_buffers, t); - _audio_buffers.reset (); - _audio_time = boost::none; - } + /* XXX: mapping */ + + /* The time of this audio may indicate that some of our buffered audio is not going to + be added to any more, so it can be emitted. + */ + + if (time > _last_audio) { + /* We can emit some audio from our buffers */ + OutputAudioFrame const N = min (_film->time_to_audio_frames (time - _last_audio), static_cast (_audio_buffers.frames())); + shared_ptr emit (new AudioBuffers (_audio_buffers.channels(), N)); + emit->copy_from (&_audio_buffers, N, 0, 0); + Audio (emit, _last_audio); + _last_audio += _film->audio_frames_to_time (N); + + /* And remove it from our buffers */ + if (_audio_buffers.frames() > N) { + _audio_buffers.move (N, 0, _audio_buffers.frames() - N); + } + _audio_buffers.set_frames (_audio_buffers.frames() - N); + } + + /* Now accumulate the new audio into our buffers */ + + if (_audio_buffers.frames() == 0) { + /* We have no remaining data. Emit silence up to the start of this new data */ + if ((time - _last_audio) > 0) { + emit_silence (time - _last_audio); + } + } + + _audio_buffers.ensure_size (time - _last_audio + audio->frames()); + _audio_buffers.accumulate (audio.get(), 0, _film->time_to_audio_frames (time - _last_audio)); + rd->last = time + _film->audio_frames_to_time (audio->frames ()); } /** @return true on error */ bool -Player::seek (double t) +Player::seek (Time t) { if (!_have_valid_decoders) { setup_decoders (); _have_valid_decoders = true; } - if (_video_decoders.empty ()) { + if (_decoders.empty ()) { return true; } - /* Find the decoder that contains this position */ - _video_decoder = 0; - while (1) { - ++_video_decoder; - if (_video_decoder >= _video_decoders.size () || t < _video_start[_video_decoder]) { - --_video_decoder; - t -= _video_start[_video_decoder]; - break; - } - } - - if (_video_decoder < _video_decoders.size()) { - _video_decoders[_video_decoder]->seek (t); - } else { - return true; - } + /* XXX */ /* XXX: don't seek audio because we don't need to... */ @@ -207,106 +214,60 @@ Player::seek_forward () void Player::setup_decoders () { - vector > old_video_decoders = _video_decoders; + list > old_decoders = _decoders; - _video_decoders.clear (); - _video_decoder = 0; - _audio_decoders.clear (); - _sequential_audio_decoder = 0; + _decoders.clear (); - _video_start.clear(); - _audio_start.clear(); + Playlist::RegionList regions = _playlist->regions (); + for (Playlist::RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { - double video_so_far = 0; - double audio_so_far = 0; + shared_ptr rd (new RegionDecoder); + rd->region = *i; + + /* XXX: into content? */ - for (int l = 0; l < _playlist->loop(); ++l) { - list > vc = _playlist->video (); - for (list >::iterator i = vc.begin(); i != vc.end(); ++i) { - - shared_ptr video_content; - shared_ptr audio_content; - shared_ptr video_decoder; - shared_ptr audio_decoder; - - /* XXX: into content? */ + shared_ptr fc = dynamic_pointer_cast (i->content); + if (fc) { + shared_ptr fd (new FFmpegDecoder (_film, fc, _video, _audio, _subtitles)); - shared_ptr fc = dynamic_pointer_cast (*i); - if (fc) { - shared_ptr fd ( - new FFmpegDecoder ( - _film, fc, _video, - _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG, - _subtitles - ) - ); - - video_content = fc; - audio_content = fc; - video_decoder = fd; - audio_decoder = fd; - - video_decoder->connect_video (shared_from_this ()); - } - - shared_ptr ic = dynamic_pointer_cast (*i); - if (ic) { - video_content = ic; - - /* See if we can re-use an old ImageMagickDecoder */ - for (vector >::const_iterator i = old_video_decoders.begin(); i != old_video_decoders.end(); ++i) { - shared_ptr imd = dynamic_pointer_cast (*i); - if (imd && imd->content() == ic) { - video_decoder = *i; - } - } + fd->Video.connect (bind (&Player::process_video, this, rd, _1, _2, _3, _4)); + fd->Audio.connect (bind (&Player::process_audio, this, rd, _1, _2)); - if (!video_decoder) { - video_decoder.reset (new ImageMagickDecoder (_film, ic)); - video_decoder->connect_video (shared_from_this ()); - } - } - - _video_decoders.push_back (video_decoder); - _video_start.push_back (video_so_far); - video_so_far += video_content->video_length() / video_content->video_frame_rate(); - - if (audio_decoder && _playlist->audio_from() == Playlist::AUDIO_FFMPEG) { - audio_decoder->Audio.connect (bind (&Player::process_audio, this, audio_content, _1, _2)); - _audio_decoders.push_back (audio_decoder); - _audio_start.push_back (audio_so_far); - audio_so_far += double(audio_content->audio_length()) / audio_content->audio_frame_rate(); - } + rd->decoder = fd; } - _video_decoder = 0; - _sequential_audio_decoder = 0; - - if (_playlist->audio_from() == Playlist::AUDIO_SNDFILE) { + shared_ptr ic = dynamic_pointer_cast (i->content); + if (ic) { + shared_ptr id; - list > ac = _playlist->audio (); - for (list >::iterator i = ac.begin(); i != ac.end(); ++i) { - - shared_ptr sc = dynamic_pointer_cast (*i); - assert (sc); - - shared_ptr d (new SndfileDecoder (_film, sc)); - d->Audio.connect (bind (&Player::process_audio, this, sc, _1, _2)); - _audio_decoders.push_back (d); - _audio_start.push_back (audio_so_far); + /* See if we can re-use an old ImageMagickDecoder */ + for (list >::const_iterator i = old_decoders.begin(); i != old_decoders.end(); ++i) { + shared_ptr imd = dynamic_pointer_cast ((*i)->decoder); + if (imd && imd->content() == ic) { + id = imd; + } + } + + if (!id) { + id.reset (new ImageMagickDecoder (_film, ic)); + id->Video.connect (bind (&Player::process_video, this, rd, _1, _2, _3, _4)); } + + rd->decoder = id; } - } -} -double -Player::last_video_time () const -{ - if (_video_decoder >= _video_decoders.size ()) { - return 0; + shared_ptr sc = dynamic_pointer_cast (i->content); + if (sc) { + shared_ptr sd (new SndfileDecoder (_film, sc)); + sd->Audio.connect (bind (&Player::process_audio, this, rd, _1, _2)); + + rd->decoder = sd; + } + + _decoders.push_back (rd); } - - return _video_start[_video_decoder] + _video_decoders[_video_decoder]->last_content_time (); + + _position = 0; } void @@ -327,3 +288,26 @@ Player::playlist_changed () { _have_valid_decoders = false; } + +void +Player::emit_black_frame () +{ + shared_ptr image (new SimpleImage (AV_PIX_FMT_RGB24, libdcp::Size (128, 128), true)); + Video (image, _last_was_black, shared_ptr (), _last_video); + _last_video += _film->video_frames_to_time (1); +} + +void +Player::emit_silence (Time t) +{ + OutputAudioFrame frames = _film->time_to_audio_frames (t); + while (frames) { + /* Do this in half-second chunks so we don't overwhelm anybody */ + OutputAudioFrame this_time = min (_film->dcp_audio_frame_rate() / 2, frames); + shared_ptr silence (new AudioBuffers (MAX_AUDIO_CHANNELS, this_time)); + silence->make_silent (); + Audio (silence, _last_audio); + _last_audio += _film->audio_frames_to_time (this_time); + frames -= this_time; + } +} diff --git a/src/lib/player.h b/src/lib/player.h index b1be2f456..c9bf2a00b 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -27,19 +27,20 @@ #include "audio_source.h" #include "video_sink.h" #include "audio_sink.h" +#include "playlist.h" +#include "audio_buffers.h" -class VideoDecoder; -class AudioDecoder; class Job; class Film; class Playlist; class AudioContent; +class Decoder; /** @class Player * @brief A class which can `play' a Playlist; emitting its audio and video. */ -class Player : public VideoSource, public AudioSource, public VideoSink, public boost::enable_shared_from_this +class Player : public VideoSource, public AudioSource, public boost::enable_shared_from_this { public: Player (boost::shared_ptr, boost::shared_ptr); @@ -49,18 +50,34 @@ public: void disable_subtitles (); bool pass (); - bool seek (double); + bool seek (Time); void seek_back (); void seek_forward (); - double last_video_time () const; + Time last_video () const { + return _last_video; + } private: - void process_video (boost::shared_ptr i, bool same, boost::shared_ptr s, double); - void process_audio (boost::weak_ptr, boost::shared_ptr, double); + + struct RegionDecoder + { + RegionDecoder () + : last (0) + {} + + Playlist::Region region; + boost::shared_ptr decoder; + Time last; + }; + + void process_video (boost::shared_ptr, boost::shared_ptr, bool, boost::shared_ptr, Time); + void process_audio (boost::shared_ptr, boost::shared_ptr, Time); void setup_decoders (); void playlist_changed (); void content_changed (boost::weak_ptr, int); + void emit_black_frame (); + void emit_silence (Time); boost::shared_ptr _film; boost::shared_ptr _playlist; @@ -71,21 +88,13 @@ private: /** Our decoders are ready to go; if this is false the decoders must be (re-)created before they are used */ bool _have_valid_decoders; - /** Video decoders in order of presentation */ - std::vector > _video_decoders; - /** Start positions of each video decoder in seconds*/ - std::vector _video_start; - /** Index of current video decoder */ - size_t _video_decoder; - /** Audio decoders in order of presentation (if they are from FFmpeg) */ - std::vector > _audio_decoders; - /** Start positions of each audio decoder (if they are from FFmpeg) in seconds */ - std::vector _audio_start; - /** Current audio decoder index if we are running them sequentially; otherwise undefined */ - size_t _sequential_audio_decoder; - - boost::shared_ptr _audio_buffers; - boost::optional _audio_time; + std::list > _decoders; + + Time _position; + AudioBuffers _audio_buffers; + Time _last_video; + bool _last_was_black; + Time _last_audio; }; #endif diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc index f1dd881b3..8f4a35ac2 100644 --- a/src/lib/playlist.cc +++ b/src/lib/playlist.cc @@ -29,6 +29,8 @@ #include "imagemagick_decoder.h" #include "imagemagick_content.h" #include "job.h" +#include "config.h" +#include "util.h" #include "i18n.h" @@ -39,171 +41,24 @@ using std::min; using std::max; using std::string; using std::stringstream; +using boost::optional; using boost::shared_ptr; using boost::weak_ptr; using boost::dynamic_pointer_cast; using boost::lexical_cast; Playlist::Playlist () - : _audio_from (AUDIO_FFMPEG) - , _loop (1) + : _loop (1) { } Playlist::Playlist (shared_ptr other) - : _audio_from (other->_audio_from) - , _loop (other->_loop) + : _loop (other->_loop) { - for (ContentList::const_iterator i = other->_content.begin(); i != other->_content.end(); ++i) { - _content.push_back ((*i)->clone ()); + for (RegionList::const_iterator i = other->_regions.begin(); i != other->_regions.end(); ++i) { + _regions.push_back (Region (i->content->clone(), i->time, this)); } - - setup (); -} - -void -Playlist::setup () -{ - _audio_from = AUDIO_FFMPEG; - - _video.clear (); - _audio.clear (); - - for (list::iterator i = _content_connections.begin(); i != _content_connections.end(); ++i) { - i->disconnect (); - } - - _content_connections.clear (); - - for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) { - - /* Video is video */ - shared_ptr vc = dynamic_pointer_cast (*i); - if (vc) { - _video.push_back (vc); - } - - /* FFmpegContent is audio if we are doing AUDIO_FFMPEG */ - shared_ptr fc = dynamic_pointer_cast (*i); - if (fc && _audio_from == AUDIO_FFMPEG) { - _audio.push_back (fc); - } - - /* SndfileContent trumps FFmpegContent for audio */ - shared_ptr sc = dynamic_pointer_cast (*i); - if (sc) { - if (_audio_from == AUDIO_FFMPEG) { - /* This is our fist SndfileContent; clear any FFmpegContent and - say that we are using Sndfile. - */ - _audio.clear (); - _audio_from = AUDIO_SNDFILE; - } - - _audio.push_back (sc); - } - - _content_connections.push_back ((*i)->Changed.connect (bind (&Playlist::content_changed, this, _1, _2))); - } -} - -/** @return Length of our audio */ -ContentAudioFrame -Playlist::audio_length () const -{ - ContentAudioFrame len = 0; - - switch (_audio_from) { - case AUDIO_FFMPEG: - /* FFmpeg content is sequential */ - for (list >::const_iterator i = _audio.begin(); i != _audio.end(); ++i) { - len += (*i)->audio_length (); - } - break; - case AUDIO_SNDFILE: - /* Sndfile content is simultaneous */ - for (list >::const_iterator i = _audio.begin(); i != _audio.end(); ++i) { - len = max (len, (*i)->audio_length ()); - } - break; - } - - return len * _loop; -} - -/** @return number of audio channels */ -int -Playlist::audio_channels () const -{ - int channels = 0; - - switch (_audio_from) { - case AUDIO_FFMPEG: - /* FFmpeg audio is sequential, so use the maximum channel count */ - for (list >::const_iterator i = _audio.begin(); i != _audio.end(); ++i) { - channels = max (channels, (*i)->audio_channels ()); - } - break; - case AUDIO_SNDFILE: - /* Sndfile audio is simultaneous, so it's the sum of the channel counts */ - for (list >::const_iterator i = _audio.begin(); i != _audio.end(); ++i) { - channels += (*i)->audio_channels (); - } - break; - } - - return channels; -} - -int -Playlist::audio_frame_rate () const -{ - if (_audio.empty ()) { - return 0; - } - - /* XXX: assuming that all content has the same rate */ - return _audio.front()->audio_frame_rate (); -} - -float -Playlist::video_frame_rate () const -{ - if (_video.empty ()) { - return 0; - } - - /* XXX: assuming all the same */ - return _video.front()->video_frame_rate (); -} - -libdcp::Size -Playlist::video_size () const -{ - if (_video.empty ()) { - return libdcp::Size (); - } - - /* XXX: assuming all the same */ - return _video.front()->video_size (); -} - -ContentVideoFrame -Playlist::video_length () const -{ - ContentVideoFrame len = 0; - for (list >::const_iterator i = _video.begin(); i != _video.end(); ++i) { - len += (*i)->video_length (); - } - - return len * _loop; -} - -bool -Playlist::has_audio () const -{ - return !_audio.empty (); } void @@ -212,62 +67,19 @@ Playlist::content_changed (weak_ptr c, int p) ContentChanged (c, p); } -AudioMapping -Playlist::default_audio_mapping () const -{ - AudioMapping m; - if (_audio.empty ()) { - return m; - } - - switch (_audio_from) { - case AUDIO_FFMPEG: - { - /* XXX: assumes all the same */ - if (_audio.front()->audio_channels() == 1) { - /* Map mono sources to centre */ - m.add (AudioMapping::Channel (_audio.front(), 0), libdcp::CENTRE); - } else { - int const N = min (_audio.front()->audio_channels (), MAX_AUDIO_CHANNELS); - /* Otherwise just start with a 1:1 mapping */ - for (int i = 0; i < N; ++i) { - m.add (AudioMapping::Channel (_audio.front(), i), (libdcp::Channel) i); - } - } - break; - } - - case AUDIO_SNDFILE: - { - int n = 0; - for (list >::const_iterator i = _audio.begin(); i != _audio.end(); ++i) { - for (int j = 0; j < (*i)->audio_channels(); ++j) { - m.add (AudioMapping::Channel (*i, j), (libdcp::Channel) n); - ++n; - if (n >= MAX_AUDIO_CHANNELS) { - break; - } - } - if (n >= MAX_AUDIO_CHANNELS) { - break; - } - } - break; - } - } - - return m; -} - string Playlist::audio_digest () const { string t; - for (list >::const_iterator i = _audio.begin(); i != _audio.end(); ++i) { - t += (*i)->digest (); + for (RegionList::const_iterator i = _regions.begin(); i != _regions.end(); ++i) { + if (!dynamic_pointer_cast (i->content)) { + continue; + } + + t += i->content->digest (); - shared_ptr fc = dynamic_pointer_cast (*i); + shared_ptr fc = dynamic_pointer_cast (i->content); if (fc) { t += lexical_cast (fc->audio_stream()->id); } @@ -283,9 +95,13 @@ Playlist::video_digest () const { string t; - for (list >::const_iterator i = _video.begin(); i != _video.end(); ++i) { - t += (*i)->digest (); - shared_ptr fc = dynamic_pointer_cast (*i); + for (RegionList::const_iterator i = _regions.begin(); i != _regions.end(); ++i) { + if (!dynamic_pointer_cast (i->content)) { + continue; + } + + t += i->content->digest (); + shared_ptr fc = dynamic_pointer_cast (i->content); if (fc && fc->subtitle_stream()) { t += fc->subtitle_stream()->id; } @@ -296,48 +112,22 @@ Playlist::video_digest () const return md5_digest (t.c_str(), t.length()); } -ContentVideoFrame -Playlist::content_length () const -{ - float const vfr = video_frame_rate() > 0 ? video_frame_rate() : 24; - int const afr = audio_frame_rate() > 0 ? audio_frame_rate() : 48000; - - return max ( - video_length(), - ContentVideoFrame (audio_length() * vfr / afr) - ); -} - void Playlist::set_from_xml (shared_ptr node) { - list > c = node->node_children ("Content"); + list > c = node->node_children ("Region"); for (list >::iterator i = c.begin(); i != c.end(); ++i) { - - string const type = (*i)->string_child ("Type"); - boost::shared_ptr c; - - if (type == "FFmpeg") { - c.reset (new FFmpegContent (*i)); - } else if (type == "ImageMagick") { - c.reset (new ImageMagickContent (*i)); - } else if (type == "Sndfile") { - c.reset (new SndfileContent (*i)); - } - - _content.push_back (c); + _regions.push_back (Region (*i, this)); } _loop = node->number_child ("Loop"); - - setup (); } void Playlist::as_xml (xmlpp::Node* node) { - for (ContentList::iterator i = _content.begin(); i != _content.end(); ++i) { - (*i)->as_xml (node->add_child ("Content")); + for (RegionList::iterator i = _regions.begin(); i != _regions.end(); ++i) { + i->as_xml (node->add_child ("Region")); } node->add_child("Loop")->add_child_text(lexical_cast (_loop)); @@ -346,87 +136,146 @@ Playlist::as_xml (xmlpp::Node* node) void Playlist::add (shared_ptr c) { - _content.push_back (c); - setup (); + _regions.push_back (Region (c, 0, this)); Changed (); } void Playlist::remove (shared_ptr c) { - ContentList::iterator i = find (_content.begin(), _content.end(), c); - if (i != _content.end ()) { - _content.erase (i); + RegionList::iterator i = _regions.begin (); + while (i != _regions.end() && i->content != c) { + ++i; } + + if (i != _regions.end ()) { + _regions.erase (i); + Changed (); + } +} - setup (); +void +Playlist::set_loop (int l) +{ + _loop = l; Changed (); } -void -Playlist::move_earlier (shared_ptr c) +bool +Playlist::has_subtitles () const { - ContentList::iterator i = find (_content.begin(), _content.end(), c); - if (i == _content.begin () || i == _content.end()) { - return; + for (RegionList::const_iterator i = _regions.begin(); i != _regions.end(); ++i) { + shared_ptr fc = dynamic_pointer_cast (i->content); + if (fc && !fc->subtitle_streams().empty()) { + return true; + } } - ContentList::iterator j = i; - --j; - - swap (*i, *j); - - setup (); - Changed (); + return false; } -void -Playlist::move_later (shared_ptr c) +Playlist::Region::Region (shared_ptr c, Time t, Playlist* p) + : content (c) + , time (t) { - ContentList::iterator i = find (_content.begin(), _content.end(), c); - if (i == _content.end()) { - return; - } + connection = c->Changed.connect (bind (&Playlist::content_changed, p, _1, _2)); +} - ContentList::iterator j = i; - ++j; - if (j == _content.end ()) { - return; +Playlist::Region::Region (shared_ptr node, Playlist* p) +{ + shared_ptr content_node = node->node_child ("Content"); + string const type = content_node->string_child ("Type"); + + if (type == "FFmpeg") { + content.reset (new FFmpegContent (content_node)); + } else if (type == "ImageMagick") { + content.reset (new ImageMagickContent (content_node)); + } else if (type == "Sndfile") { + content.reset (new SndfileContent (content_node)); } - swap (*i, *j); - - setup (); - Changed (); + time = node->number_child