Move trimming into the encoder; seems to be cleaner.
authorCarl Hetherington <cth@carlh.net>
Mon, 5 Nov 2012 10:36:55 +0000 (10:36 +0000)
committerCarl Hetherington <cth@carlh.net>
Mon, 5 Nov 2012 10:36:55 +0000 (10:36 +0000)
27 files changed:
src/lib/ab_transcoder.cc
src/lib/decoder.cc
src/lib/decoder.h
src/lib/decoder_factory.cc
src/lib/decoder_factory.h
src/lib/encoder.cc
src/lib/encoder.h
src/lib/examine_content_job.cc
src/lib/ffmpeg_decoder.cc
src/lib/ffmpeg_decoder.h
src/lib/film.cc
src/lib/film.h
src/lib/imagemagick_decoder.cc
src/lib/imagemagick_decoder.h
src/lib/imagemagick_encoder.cc
src/lib/imagemagick_encoder.h
src/lib/j2k_still_encoder.cc
src/lib/j2k_still_encoder.h
src/lib/j2k_wav_encoder.cc
src/lib/j2k_wav_encoder.h
src/lib/options.h
src/lib/tiff_decoder.cc
src/lib/tiff_decoder.h
src/lib/transcoder.cc
src/lib/util.cc
src/lib/util.h
src/wx/film_editor.cc

index 0579aa4ff228fe7422f0401cd9eafb4179d817dc..c40c0916e6f1ee474ca3b3ea2b35152fee827d7a 100644 (file)
@@ -57,7 +57,7 @@ ABTranscoder::ABTranscoder (
 
        _da->Video.connect (bind (&ABTranscoder::process_video, this, _1, _2, _3, 0));
        _db->Video.connect (bind (&ABTranscoder::process_video, this, _1, _2, _3, 1));
-       _da->Audio.connect (bind (&Encoder::process_audio, e, _1));
+       _da->Audio.connect (bind (&Encoder::process_audio, e, _1, _2));
 }
 
 ABTranscoder::~ABTranscoder ()
index 617d57ff6762b3a02e32e49fde586396ac0729dd..347c5dbbb909521f1349f346dce7922c73cc5622 100644 (file)
@@ -50,15 +50,12 @@ using boost::shared_ptr;
  *  @param minimal true to do the bare minimum of work; just run through the content.  Useful for acquiring
  *  accurate frame counts as quickly as possible.  This generates no video or audio output.
  */
-Decoder::Decoder (boost::shared_ptr<Film> f, boost::shared_ptr<const Options> o, Job* j, bool minimal)
+Decoder::Decoder (boost::shared_ptr<Film> f, boost::shared_ptr<const Options> o, Job* j)
        : _film (f)
        , _opt (o)
        , _job (j)
-       , _minimal (minimal)
-       , _video_frames_in (0)
-       , _video_frames_out (0)
-       , _audio_frames_in (0)
-       , _audio_frames_out (0)
+       , _video_frame (0)
+       , _audio_frame (0)
        , _delay_line (0)
        , _delay_in_frames (0)
 {
@@ -94,13 +91,15 @@ Decoder::process_end ()
 
                /* Ensure that our video and audio emissions are the same length */
 
-               int64_t audio_short_by_frames = video_frames_to_audio_frames (_video_frames_out) - _audio_frames_out;
+               int64_t audio_short_by_frames = video_frames_to_audio_frames (_video_frame, audio_sample_rate(), frames_per_second()) - _audio_frame;
 
                _film->log()->log (
-                       String::compose ("Decoder has emitted %1 video frames (which equals %2 audio frames) and %3 audio frames",
-                                        _video_frames_out,
-                                        video_frames_to_audio_frames (_video_frames_out),
-                                        _audio_frames_out)
+                       String::compose (
+                               "Decoder has emitted %1 video frames (which equals %2 audio frames) and %3 audio frames",
+                               _video_frame,
+                               video_frames_to_audio_frames (_video_frame, audio_sample_rate(), frames_per_second()),
+                               _audio_frame
+                               )
                        );
 
                if (audio_short_by_frames < 0) {
@@ -116,15 +115,10 @@ Decoder::process_end ()
                        black->make_black ();
                        for (int i = 0; i < black_video_frames; ++i) {
                                emit_video (black, shared_ptr<Subtitle> ());
-
-                               /* This is a bit of a hack, but you can sort-of justify it if you squint at it right.
-                                  It's important because the encoder will probably use this to name its output frame.
-                               */
-                               ++_video_frames_in;
                        }
 
                        /* Now recompute our check value */
-                       audio_short_by_frames = video_frames_to_audio_frames (_video_frames_out) - _audio_frames_out;
+                       audio_short_by_frames = video_frames_to_audio_frames (_video_frame, audio_sample_rate(), frames_per_second()) - _audio_frame;
                }
        
                if (audio_short_by_frames > 0) {
@@ -147,8 +141,8 @@ Decoder::go ()
        }
 
        while (pass () == false) {
-               if (_job && _film->dcp_length()) {
-                       _job->set_progress (float (_video_frames_out) / _film->dcp_length().get());
+               if (_job) {
+                       _job->set_progress (float (_video_frame) / _film->length().get());
                }
        }
 
@@ -162,6 +156,7 @@ Decoder::go ()
 void
 Decoder::process_audio (uint8_t* data, int size)
 {
+       /* XXX: could this be removed? */
        if (size == 0) {
                return;
        }
@@ -236,48 +231,7 @@ Decoder::process_audio (uint8_t* data, int size)
        }
 
        _delay_line->feed (audio);
-
-       int const in_frames = audio->frames ();
-
-       if (_opt->decode_range) {
-               /* Decode range in audio frames */
-               pair<int64_t, int64_t> required_range (
-                       video_frames_to_audio_frames (_opt->decode_range.get().first),
-                       video_frames_to_audio_frames (_opt->decode_range.get().second)
-                       );
-               
-               /* Range of this block of data */
-               pair<int64_t, int64_t> this_range (
-                       _audio_frames_in,
-                       _audio_frames_in + audio->frames()
-                       );
-
-               if (this_range.second < required_range.first || required_range.second < this_range.first) {
-                       /* No part of this audio is within the required range */
-                       audio->set_frames (0);
-               } else if (required_range.first >= this_range.first && required_range.first < this_range.second) {
-                       /* Trim start */
-                       int64_t const shift = required_range.first - this_range.first;
-                       audio->move (shift, 0, audio->frames() - shift);
-                       audio->set_frames (audio->frames() - shift);
-               } else if (required_range.second >= this_range.first && required_range.second < this_range.second) {
-                       /* Trim end */
-                       audio->set_frames (required_range.second - this_range.first);
-               }
-       }
-               
-       if (audio->frames()) {
-               emit_audio (audio);
-       }
-
-       _audio_frames_in += in_frames;
-}
-
-void
-Decoder::emit_audio (shared_ptr<AudioBuffers> audio)
-{
-       Audio (audio);
-       _audio_frames_out += audio->frames ();
+       emit_audio (audio);
 }
 
 /** Called by subclasses to tell the world that some video data is ready.
@@ -287,24 +241,6 @@ Decoder::emit_audio (shared_ptr<AudioBuffers> audio)
 void
 Decoder::process_video (AVFrame* frame)
 {
-       if (_minimal) {
-               ++_video_frames_in;
-               return;
-       }
-
-       if (_opt->decode_video_skip != 0 && (_video_frames_in % _opt->decode_video_skip) != 0) {
-               ++_video_frames_in;
-               return;
-       }
-
-       if (_opt->decode_range) {
-               pair<SourceFrame, SourceFrame> r = _opt->decode_range.get();
-               if (_video_frames_in < r.first || _video_frames_in >= r.second) {
-                       ++_video_frames_in;
-                       return;
-               }
-       }
-
        shared_ptr<FilterGraph> graph;
 
        list<shared_ptr<FilterGraph> >::iterator i = _filter_graphs.begin();
@@ -324,12 +260,11 @@ Decoder::process_video (AVFrame* frame)
 
        for (list<shared_ptr<Image> >::iterator i = images.begin(); i != images.end(); ++i) {
                shared_ptr<Subtitle> sub;
-               if (_timed_subtitle && _timed_subtitle->displayed_at (double (video_frames_in()) / _film->frames_per_second())) {
+               if (_timed_subtitle && _timed_subtitle->displayed_at (double (video_frame()) / _film->frames_per_second())) {
                        sub = _timed_subtitle->subtitle ();
                }
 
                emit_video (*i, sub);
-               ++_video_frames_in;
        }
 }
 
@@ -342,19 +277,26 @@ Decoder::repeat_last_video ()
        }
 
        emit_video (_last_image, _last_subtitle);
-       ++_video_frames_in;
 }
 
 void
 Decoder::emit_video (shared_ptr<Image> image, shared_ptr<Subtitle> sub)
 {
-       TIMING ("Decoder emits %1", _video_frames_out);
-       Video (image, _video_frames_in, sub);
-       ++_video_frames_out;
+       TIMING ("Decoder emits %1", _video_frame);
+       Video (image, _video_frame, sub);
+       ++_video_frame;
+
        _last_image = image;
        _last_subtitle = sub;
 }
 
+void
+Decoder::emit_audio (shared_ptr<AudioBuffers> audio)
+{
+       Audio (audio, _audio_frame);
+       _audio_frame += audio->frames ();
+}
+
 void
 Decoder::process_subtitle (shared_ptr<TimedSubtitle> s)
 {
@@ -366,15 +308,8 @@ Decoder::process_subtitle (shared_ptr<TimedSubtitle> s)
        }
 }
 
-
 int
 Decoder::bytes_per_audio_sample () const
 {
        return av_get_bytes_per_sample (audio_sample_format ());
 }
-
-int64_t
-Decoder::video_frames_to_audio_frames (SourceFrame v) const
-{
-       return ((int64_t) v * audio_sample_rate() / frames_per_second());
-}
index 2154da8bf6183102c9963ead832b0a9077b1a406..9f47bf42562a7255d3071edf9f8144cb438356e6 100644 (file)
@@ -52,7 +52,7 @@ class FilterGraph;
 class Decoder
 {
 public:
-       Decoder (boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *, bool);
+       Decoder (boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *);
        virtual ~Decoder ();
 
        /* Methods to query our input video */
@@ -80,9 +80,8 @@ public:
        void process_end ();
        void go ();
 
-       /** @return the number of video frames we got from the source in the last run */
-       SourceFrame video_frames_in () const {
-               return _video_frames_in;
+       SourceFrame video_frame () const {
+               return _video_frame;
        }
 
        virtual std::vector<AudioStream> audio_streams () const {
@@ -101,7 +100,7 @@ public:
        boost::signals2::signal<void (boost::shared_ptr<Image>, SourceFrame, boost::shared_ptr<Subtitle>)> Video;
 
        /** Emitted when some audio data is ready */
-       boost::signals2::signal<void (boost::shared_ptr<AudioBuffers>)> Audio;
+       boost::signals2::signal<void (boost::shared_ptr<AudioBuffers>, int64_t)> Audio;
 
 protected:
        
@@ -121,21 +120,12 @@ protected:
        /** associated Job, or 0 */
        Job* _job;
 
-       /** true to do the bare minimum of work; just run through the content.  Useful for acquiring
-        *  accurate frame counts as quickly as possible.  This generates no video or audio output.
-        */
-       bool _minimal;
-
 private:
        void emit_video (boost::shared_ptr<Image>, boost::shared_ptr<Subtitle>);
        void emit_audio (boost::shared_ptr<AudioBuffers>);
 
-       int64_t video_frames_to_audio_frames (SourceFrame v) const;
-       
-       SourceFrame _video_frames_in;
-       SourceFrame _video_frames_out;
-       int64_t _audio_frames_in;
-       int64_t _audio_frames_out;
+       SourceFrame _video_frame;
+       int64_t _audio_frame;
        
        std::list<boost::shared_ptr<FilterGraph> > _filter_graphs;
 
index 287bba0da9b1759a638e9317be188c14d2ff764f..d4a91d8d97d312954247f4287e018013fdaa370b 100644 (file)
@@ -32,17 +32,17 @@ using boost::shared_ptr;
 
 shared_ptr<Decoder>
 decoder_factory (
-       shared_ptr<Film> f, shared_ptr<const Options> o, Job* j, bool minimal = false
+       shared_ptr<Film> f, shared_ptr<const Options> o, Job* j
        )
 {
        if (boost::filesystem::is_directory (f->content_path ())) {
                /* Assume a directory contains TIFFs */
-               return shared_ptr<Decoder> (new TIFFDecoder (f, o, j, minimal));
+               return shared_ptr<Decoder> (new TIFFDecoder (f, o, j));
        }
 
        if (f->content_type() == STILL) {
-               return shared_ptr<Decoder> (new ImageMagickDecoder (f, o, j, minimal));
+               return shared_ptr<Decoder> (new ImageMagickDecoder (f, o, j));
        }
        
-       return shared_ptr<Decoder> (new FFmpegDecoder (f, o, j, minimal));
+       return shared_ptr<Decoder> (new FFmpegDecoder (f, o, j));
 }
index b86c60c70f224b1f9b5a7825efb8541388aa2aae..765b38816d83beca0f8aae311fd7c7c29f7de106 100644 (file)
@@ -28,5 +28,5 @@ class Job;
 class Log;
 
 extern boost::shared_ptr<Decoder> decoder_factory (
-       boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *, bool minimal = false
+       boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *
        );
index bb23c9e5922b34a6d82a96d4b449b280a1112a81..b322be04c9a564e5008f4127b0ba11bc522ca56e 100644 (file)
@@ -23,7 +23,9 @@
 
 #include "encoder.h"
 #include "util.h"
+#include "options.h"
 
+using std::pair;
 using namespace boost;
 
 int const Encoder::_history_size = 25;
@@ -101,3 +103,51 @@ Encoder::frame_skipped ()
        boost::mutex::scoped_lock lock (_history_mutex);
        _just_skipped = true;
 }
+
+void
+Encoder::process_video (shared_ptr<const Image> i, SourceFrame f, boost::shared_ptr<Subtitle> s)
+{
+       if (_opt->decode_video_skip != 0 && (f % _opt->decode_video_skip) != 0) {
+               return;
+       }
+
+       if (_opt->video_decode_range) {
+               pair<SourceFrame, SourceFrame> const r = _opt->video_decode_range.get();
+               if (f < r.first || f >= r.second) {
+                       return;
+               }
+       }
+
+       do_process_video (i, f, s);
+}
+
+void
+Encoder::process_audio (shared_ptr<const AudioBuffers> data, int64_t f)
+{
+       if (_opt->audio_decode_range) {
+
+               shared_ptr<AudioBuffers> trimmed (new AudioBuffers (*data.get ()));
+               
+               /* Range that we are encoding */
+               pair<int64_t, int64_t> required_range = _opt->audio_decode_range.get();
+               /* Range of this block of data */
+               pair<int64_t, int64_t> this_range (f, f + trimmed->frames());
+
+               if (this_range.second < required_range.first || required_range.second < this_range.first) {
+                       /* No part of this audio is within the required range */
+                       return;
+               } else if (required_range.first >= this_range.first && required_range.first < this_range.second) {
+                       /* Trim start */
+                       int64_t const shift = required_range.first - this_range.first;
+                       trimmed->move (shift, 0, trimmed->frames() - shift);
+                       trimmed->set_frames (trimmed->frames() - shift);
+               } else if (required_range.second >= this_range.first && required_range.second < this_range.second) {
+                       /* Trim end */
+                       trimmed->set_frames (required_range.second - this_range.first);
+               }
+
+               data = trimmed;
+       }
+
+       do_process_audio (data);
+}
index 704b55e46f5777798d12eeeea16121872eaa13ad..2d9780b52e07cc61ec57bcb95ea73f4265fa9da9 100644 (file)
@@ -57,18 +57,15 @@ public:
        /** Called to indicate that a processing run is about to begin */
        virtual void process_begin (int64_t audio_channel_layout) = 0;
 
-       /** Called with a frame of video.
+       /** Call with a frame of video.
         *  @param i Video frame image.
         *  @param f Frame number within the film's source.
         *  @param s A subtitle that should be on this frame, or 0.
         */
-       virtual void process_video (boost::shared_ptr<const Image> i, SourceFrame f, boost::shared_ptr<Subtitle> s) = 0;
+       void process_video (boost::shared_ptr<const Image> i, SourceFrame f, boost::shared_ptr<Subtitle> s);
 
-       /** Called with some audio data.
-        *  @param d Array of pointers to floating point sample data for each channel.
-        *  @param s Number of frames (ie number of samples in each channel)
-        */
-       virtual void process_audio (boost::shared_ptr<const AudioBuffers>) = 0;
+       /** Call with some audio data */
+       void process_audio (boost::shared_ptr<const AudioBuffers>, int64_t);
 
        /** Called when a processing run has finished */
        virtual void process_end () = 0;
@@ -78,6 +75,17 @@ public:
        SourceFrame last_frame () const;
 
 protected:
+
+       /** Called with a frame of video.
+        *  @param i Video frame image.
+        *  @param f Frame number within the film's source.
+        *  @param s A subtitle that should be on this frame, or 0.
+        */
+       virtual void do_process_video (boost::shared_ptr<const Image> i, SourceFrame f, boost::shared_ptr<Subtitle> s) = 0;
+       
+       /** Called with some audio data */
+       virtual void do_process_audio (boost::shared_ptr<const AudioBuffers>) = 0;
+       
        void frame_done (SourceFrame n);
        void frame_skipped ();
        
index d325102a3ac63b0535ff6af43f0594b745f1a7e3..4646fe8fcdece4092fec59897d0112cef72243c3 100644 (file)
@@ -66,10 +66,10 @@ ExamineContentJob::run ()
 
        descend (0.5);
 
-       _decoder = decoder_factory (_film, o, this, true);
+       _decoder = decoder_factory (_film, o, this);
        _decoder->go ();
 
-       _film->set_length (_decoder->video_frames_in());
+       _film->set_length (_decoder->video_frame());
 
        _film->log()->log (String::compose ("Video length is %1 frames", _film->length()));
 
index fa6500b9e98440689774b192a5aabc69a3d2e55e..a2ca739e28b21b4dd80d7faccc9f0e98e6667eae 100644 (file)
@@ -55,8 +55,8 @@ using std::vector;
 using std::stringstream;
 using boost::shared_ptr;
 
-FFmpegDecoder::FFmpegDecoder (shared_ptr<Film> f, shared_ptr<const Options> o, Job* j, bool minimal)
-       : Decoder (f, o, j, minimal)
+FFmpegDecoder::FFmpegDecoder (shared_ptr<Film> f, shared_ptr<const Options> o, Job* j)
+       : Decoder (f, o, j)
        , _format_context (0)
        , _video_stream (-1)
        , _audio_stream (-1)
@@ -270,7 +270,7 @@ FFmpegDecoder::pass ()
                        }
 
                        /* Where we are in the output, in seconds */
-                       double const out_pts_seconds = video_frames_in() / frames_per_second();
+                       double const out_pts_seconds = video_frame() / frames_per_second();
 
                        /* Where we are in the source, in seconds */
                        double const source_pts_seconds = av_q2d (_format_context->streams[_packet.stream_index]->time_base)
@@ -292,7 +292,7 @@ FFmpegDecoder::pass ()
                                        _film->log()->log (
                                                String::compose (
                                                        "Extra frame inserted at %1s; source frame %2, source PTS %3",
-                                                       out_pts_seconds, video_frames_in(), source_pts_seconds
+                                                       out_pts_seconds, video_frame(), source_pts_seconds
                                                        )
                                                );
                                }
index fbd9e5255b57342b7cc3ef3a9c66985b59a75b54..0265f747804154d3d7ec43715eb7de710a710888 100644 (file)
@@ -52,7 +52,7 @@ class Log;
 class FFmpegDecoder : public Decoder
 {
 public:
-       FFmpegDecoder (boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *, bool);
+       FFmpegDecoder (boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *);
        ~FFmpegDecoder ();
 
        /* Methods to query our input video */
index 26edc80b07a00bbd38d3d83af825cb56a88ebf38..b335f8cc3e75223da839344ed9ffc32793efc556 100644 (file)
@@ -259,7 +259,12 @@ Film::make_dcp (bool transcode)
        o->padding = format()->dcp_padding (shared_from_this ());
        o->ratio = format()->ratio_as_float (shared_from_this ());
        if (dcp_length ()) {
-               o->decode_range = make_pair (dcp_trim_start(), dcp_trim_start() + dcp_length().get());
+               o->video_decode_range = make_pair (dcp_trim_start(), dcp_trim_start() + dcp_length().get());
+               o->audio_decode_range = make_pair (
+                       video_frames_to_audio_frames (o->video_decode_range.get().first, audio_sample_rate(), frames_per_second()),
+                       video_frames_to_audio_frames (o->video_decode_range.get().second, audio_sample_rate(), frames_per_second())
+                       );
+                       
        }
        o->decode_subtitles = with_subtitles ();
        o->decode_video_skip = dcp_frame_rate (frames_per_second()).skip;
@@ -881,7 +886,7 @@ Film::set_content (string c)
                shared_ptr<Options> o (new Options ("", "", ""));
                o->out_size = Size (1024, 1024);
                
-               shared_ptr<Decoder> d = decoder_factory (shared_from_this(), o, 0, 0);
+               shared_ptr<Decoder> d = decoder_factory (shared_from_this(), o, 0);
                
                set_size (d->native_size ());
                set_frames_per_second (d->frames_per_second ());
@@ -1328,3 +1333,4 @@ Film::set_dci_date_today ()
 {
        _dci_date = boost::gregorian::day_clock::local_day ();
 }
+
index 06ebba3ce7545a6cac8939e8b547dd0c2b9bd69c..ee640f33b33e166c505f2afc934a882abc3fc6e2 100644 (file)
@@ -396,7 +396,7 @@ private:
        std::string thumb_base_for_frame (SourceFrame) const;
        void signal_changed (Property);
        void examine_content_finished ();
-       
+
        /** Complete path to directory containing the film metadata;
         *  must not be relative.
         */
index 81349beca72e3ceb8a4ff37cd136698b78439140..cc2fd9d231fa0bd718b785be655cec4c40f740b7 100644 (file)
@@ -27,8 +27,8 @@ using namespace std;
 using namespace boost;
 
 ImageMagickDecoder::ImageMagickDecoder (
-       boost::shared_ptr<Film> f, boost::shared_ptr<const Options> o, Job* j, bool minimal)
-       : Decoder (f, o, j, minimal)
+       boost::shared_ptr<Film> f, boost::shared_ptr<const Options> o, Job* j)
+       : Decoder (f, o, j)
        , _done (false)
 {
        _magick_image = new Magick::Image (_film->content_path ());
index 85bcf4c5bc29811ee9acd36e0507315f10739dc4..b7ab9af18119cf0c1677d3c6a0993f2b48335463 100644 (file)
@@ -26,7 +26,7 @@ namespace Magick {
 class ImageMagickDecoder : public Decoder
 {
 public:
-       ImageMagickDecoder (boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *, bool);
+       ImageMagickDecoder (boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *);
 
        float frames_per_second () const {
                return static_frames_per_second ();
index e0e2d1cdcdbce1f4d8e86b1bc84a8ac61f7a6858..6c70e37496529faf2e066f155afb37714dec5563 100644 (file)
@@ -50,7 +50,7 @@ ImageMagickEncoder::ImageMagickEncoder (shared_ptr<const Film> f, shared_ptr<con
 }
 
 void
-ImageMagickEncoder::process_video (shared_ptr<const Image> image, SourceFrame frame, shared_ptr<Subtitle> sub)
+ImageMagickEncoder::do_process_video (shared_ptr<const Image> image, SourceFrame frame, shared_ptr<Subtitle> sub)
 {
        shared_ptr<Image> scaled = image->scale_and_convert_to_rgb (_opt->out_size, _opt->padding, _film->scaler());
        shared_ptr<Image> compact (new CompactImage (scaled));
index 3d8edd25ed82c80ec60720438a0df7cc815bec08..9adfbf56bf8965e0fc0ec3a3a431ac8b63ae6735 100644 (file)
@@ -37,7 +37,9 @@ public:
        ImageMagickEncoder (boost::shared_ptr<const Film> f, boost::shared_ptr<const Options> o);
 
        void process_begin (int64_t audio_channel_layout) {}
-       void process_video (boost::shared_ptr<const Image>, SourceFrame, boost::shared_ptr<Subtitle>);
-       void process_audio (boost::shared_ptr<const AudioBuffers>) {}
        void process_end () {}
+
+private:       
+       void do_process_video (boost::shared_ptr<const Image>, SourceFrame, boost::shared_ptr<Subtitle>);
+       void do_process_audio (boost::shared_ptr<const AudioBuffers>) {}
 };
index aab686417ba6de0fb14920afa8e43a1deea51d92..2d6c457fccefb472bf17faea0ea345dff66a668d 100644 (file)
@@ -49,7 +49,7 @@ J2KStillEncoder::J2KStillEncoder (shared_ptr<const Film> f, shared_ptr<const Opt
 }
 
 void
-J2KStillEncoder::process_video (shared_ptr<const Image> yuv, SourceFrame frame, shared_ptr<Subtitle> sub)
+J2KStillEncoder::do_process_video (shared_ptr<const Image> yuv, SourceFrame frame, shared_ptr<Subtitle> sub)
 {
        pair<string, string> const s = Filter::ffmpeg_strings (_film->filters());
        DCPVideoFrame* f = new DCPVideoFrame (
index 89222ce18f1f696d2032dcfc3227136e828e26cc..bc324e967b0ca7e48dd754ab5521c9194d0e1ea2 100644 (file)
@@ -37,7 +37,9 @@ public:
        J2KStillEncoder (boost::shared_ptr<const Film>, boost::shared_ptr<const Options>);
 
        void process_begin (int64_t audio_channel_layout) {}
-       void process_video (boost::shared_ptr<const Image>, SourceFrame, boost::shared_ptr<Subtitle>);
-       void process_audio (boost::shared_ptr<const AudioBuffers>) {}
        void process_end () {}
+
+private:
+       void do_process_video (boost::shared_ptr<const Image>, SourceFrame, boost::shared_ptr<Subtitle>);
+       void do_process_audio (boost::shared_ptr<const AudioBuffers>) {}
 };
index 09e87757999ad56c094d895317881ba258147555..6d777babb22c2f7aac216b5a1d440ef3c2f02f53 100644 (file)
@@ -106,7 +106,7 @@ J2KWAVEncoder::close_sound_files ()
 }      
 
 void
-J2KWAVEncoder::process_video (shared_ptr<const Image> yuv, SourceFrame frame, shared_ptr<Subtitle> sub)
+J2KWAVEncoder::do_process_video (shared_ptr<const Image> yuv, SourceFrame frame, shared_ptr<Subtitle> sub)
 {
        boost::mutex::scoped_lock lock (_worker_mutex);
 
@@ -351,7 +351,7 @@ J2KWAVEncoder::process_end ()
 }
 
 void
-J2KWAVEncoder::process_audio (shared_ptr<const AudioBuffers> audio)
+J2KWAVEncoder::do_process_audio (shared_ptr<const AudioBuffers> audio)
 {
        shared_ptr<AudioBuffers> resampled;
        
index 2272d7f4967d94337951475e3904495ede58a123..b494be8e58d382430823fa7ff08cd9df95a5e155 100644 (file)
@@ -51,12 +51,13 @@ public:
        ~J2KWAVEncoder ();
 
        void process_begin (int64_t audio_channel_layout);
-       void process_video (boost::shared_ptr<const Image>, SourceFrame, boost::shared_ptr<Subtitle>);
-       void process_audio (boost::shared_ptr<const AudioBuffers>);
        void process_end ();
 
 private:
 
+       void do_process_video (boost::shared_ptr<const Image>, SourceFrame, boost::shared_ptr<Subtitle>);
+       void do_process_audio (boost::shared_ptr<const AudioBuffers>);
+       
        void write_audio (boost::shared_ptr<const AudioBuffers> audio);
        void encoder_thread (ServerDescription *);
        void close_sound_files ();
index 68786c730cdd4b116f85ceb5f06534506ea5f5bb..29b3b71cd4a91e01bc8d76494608d076d6c4452c 100644 (file)
@@ -24,6 +24,7 @@
 #include <string>
 #include <iomanip>
 #include <sstream>
+#include <boost/optional.hpp>
 #include "util.h"
 
 /** @class Options
@@ -98,8 +99,10 @@ public:
        bool apply_crop;            ///< true to apply cropping
 
        /** Range of video frames to decode */
-       boost::optional<std::pair<SourceFrame, SourceFrame> > decode_range;
-
+       boost::optional<std::pair<SourceFrame, SourceFrame> > video_decode_range;
+       /** Range of audio frames to decode */
+       boost::optional<std::pair<int64_t, int64_t> > audio_decode_range;
+       
        /** Skip frames such that we don't decode any frame where (index % decode_video_skip) != 0; e.g.
         *  1 for every frame, 2 for every other frame, etc.
         */
index 2c050def67e8098e63056640fac2d095b7ad650d..7cca511dda884d0cdceb84178aea0030940f76fb 100644 (file)
@@ -44,11 +44,9 @@ using namespace boost;
 /** @param f Our Film.
  *  @param o Options.
  *  @param j Job that we are associated with, or 0.
- *  @param minimal true to do the bare minimum of work; just run through the content.  Useful for acquiring
- *  accurate frame counts as quickly as possible.  This generates no video or audio output.
  */
-TIFFDecoder::TIFFDecoder (boost::shared_ptr<Film> f, boost::shared_ptr<const Options> o, Job* j, bool minimal)
-       : Decoder (f, o, j, minimal)
+TIFFDecoder::TIFFDecoder (boost::shared_ptr<Film> f, boost::shared_ptr<const Options> o, Job* j)
+       : Decoder (f, o, j)
 {
        string const dir = _film->content_path ();
        
index c02a1d03d72c7373f776b9c71408a0b70b9cb883..1c33443cf17518d5e636fca8f087a4260f61a153 100644 (file)
@@ -42,7 +42,7 @@ class Image;
 class TIFFDecoder : public Decoder
 {
 public:
-       TIFFDecoder (boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *, bool);
+       TIFFDecoder (boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *);
 
        /* Methods to query our input video */
        float frames_per_second () const;
index 9515a43449ba730f6bba81394d92c5f144bb8cc0..66d5606afd30525378e66ae94b5889d84e104316 100644 (file)
@@ -47,7 +47,7 @@ Transcoder::Transcoder (shared_ptr<Film> f, shared_ptr<const Options> o, Job* j,
        assert (_encoder);
        
        _decoder->Video.connect (bind (&Encoder::process_video, e, _1, _2, _3));
-       _decoder->Audio.connect (bind (&Encoder::process_audio, e, _1));
+       _decoder->Audio.connect (bind (&Encoder::process_audio, e, _1, _2));
 }
 
 /** Run the decoder, passing its output to the encoder, until the decoder
index 5dd39c0e837a18e4432594ba33daf688a2d9c966..2194418653b96d4a753e54218bdf3ce3dc1e98e5 100644 (file)
@@ -815,3 +815,9 @@ ensure_ui_thread ()
 {
        assert (this_thread::get_id() == ui_thread);
 }
+
+int64_t
+video_frames_to_audio_frames (SourceFrame v, float audio_sample_rate, float frames_per_second)
+{
+       return ((int64_t) v * audio_sample_rate / frames_per_second);
+}
index bb0a70a053bc453dbacd70dfc63936590d0b274e..7aa9f25e14f01be88c0e4e43bda5b55bc0700b4b 100644 (file)
@@ -251,5 +251,7 @@ private:
        float** _data;
 };
 
+extern int64_t video_frames_to_audio_frames (SourceFrame v, float audio_sample_rate, float frames_per_second);
+
 #endif
 
index 7038a18b0367a18e436cd70aac26114df1e44fe9..36e0f05b0b0ba8b9c863ea933b74a414c92e69c7 100644 (file)
@@ -631,6 +631,7 @@ FilmEditor::set_film (shared_ptr<Film> f)
        film_changed (Film::AUDIO_DELAY);
        film_changed (Film::STILL_DURATION);
        film_changed (Film::WITH_SUBTITLES);
+       film_changed (Film::HAS_SUBTITLES);
        film_changed (Film::SUBTITLE_OFFSET);
        film_changed (Film::SUBTITLE_SCALE);
        film_changed (Film::USE_DCI_NAME);