Avoid decoding other packets when looking for subs.
authorCarl Hetherington <cth@carlh.net>
Fri, 16 Oct 2015 13:38:44 +0000 (14:38 +0100)
committerCarl Hetherington <cth@carlh.net>
Fri, 16 Oct 2015 13:38:44 +0000 (14:38 +0100)
The "accumulation" of, for example, video data when we are looking
for audio data is an *optimisation* to reduce the number of seeks.
It should not be necessary for correctness (the output should be right
even if we never kept anything except what we were looking for).

Doing this accumulation is not always an optimisation; sometimes not
doing it is better.  Avoiding it when going back for subtitles is one
of these cases.

17 files changed:
src/lib/audio_decoder_stream.cc
src/lib/dcp_decoder.cc
src/lib/dcp_decoder.h
src/lib/dcp_subtitle_decoder.cc
src/lib/dcp_subtitle_decoder.h
src/lib/decoder.h
src/lib/ffmpeg_decoder.cc
src/lib/ffmpeg_decoder.h
src/lib/image_decoder.cc
src/lib/image_decoder.h
src/lib/sndfile_decoder.cc
src/lib/sndfile_decoder.h
src/lib/subrip_decoder.cc
src/lib/subrip_decoder.h
src/lib/subtitle_decoder.cc
src/lib/video_decoder.cc
test/audio_decoder_test.cc

index 274bf2d547e41ecb29a6d5d7b8abb451fe6da312..4d1a5e4c58837e87d1d5e9fcc1446fc614dbe43b 100644 (file)
@@ -87,7 +87,7 @@ AudioDecoderStream::get (Frame frame, Frame length, bool accurate)
                /* Keep stuffing data into _decoded until we have enough data, or the subclass does not want to give us any more */
                while (
                        (_decoded.frame > frame || (_decoded.frame + _decoded.audio->frames()) < end) &&
-                       !_decoder->pass ()
+                       !_decoder->pass (Decoder::PASS_REASON_AUDIO)
                        )
                {}
 
@@ -95,7 +95,7 @@ AudioDecoderStream::get (Frame frame, Frame length, bool accurate)
        } else {
                while (
                        _decoded.audio->frames() < length &&
-                       !_decoder->pass ()
+                       !_decoder->pass (Decoder::PASS_REASON_AUDIO)
                        )
                {}
 
index 21eb2f7ea48d116f828d9955ff93ca817687636f..ada0d01d1db617dabf66f117f92971e008102776 100644 (file)
@@ -59,7 +59,7 @@ DCPDecoder::DCPDecoder (shared_ptr<const DCPContent> c, bool fast)
 }
 
 bool
-DCPDecoder::pass ()
+DCPDecoder::pass (PassReason reason)
 {
        if (_reel == _reels.end () || !_dcp_content->can_be_played ()) {
                return true;
@@ -68,7 +68,7 @@ DCPDecoder::pass ()
        double const vfr = _dcp_content->video_frame_rate ();
        int64_t const frame = _next.frames_round (vfr);
 
-       if ((*_reel)->main_picture ()) {
+       if ((*_reel)->main_picture () && reason != PASS_REASON_SUBTITLE) {
                shared_ptr<dcp::PictureAsset> asset = (*_reel)->main_picture()->asset ();
                shared_ptr<dcp::MonoPictureAsset> mono = dynamic_pointer_cast<dcp::MonoPictureAsset> (asset);
                shared_ptr<dcp::StereoPictureAsset> stereo = dynamic_pointer_cast<dcp::StereoPictureAsset> (asset);
@@ -88,7 +88,7 @@ DCPDecoder::pass ()
                }
        }
 
-       if ((*_reel)->main_sound ()) {
+       if ((*_reel)->main_sound () && reason != PASS_REASON_SUBTITLE) {
                int64_t const entry_point = (*_reel)->main_sound()->entry_point ();
                shared_ptr<const dcp::SoundFrame> sf = (*_reel)->main_sound()->asset()->get_frame (entry_point + frame);
                uint8_t const * from = sf->data ();
index 6fdbd946af348dcd2f99a7d8306e5c8e6dabeff4..8ec80c2aff5f0651bd8ca41d8b93989e1a18dd4a 100644 (file)
@@ -44,7 +44,7 @@ public:
 private:
        friend struct dcp_subtitle_within_dcp_test;
 
-       bool pass ();
+       bool pass (PassReason);
        void seek (ContentTime t, bool accurate);
 
        std::list<ContentTimePeriod> image_subtitles_during (ContentTimePeriod, bool starting) const;
index 1c6b973d683913722e4b6cecb2570bed205b0f21..0f1cda209dd7d460f8d37cb371f8a1a801e1646b 100644 (file)
@@ -47,7 +47,7 @@ DCPSubtitleDecoder::seek (ContentTime time, bool accurate)
 }
 
 bool
-DCPSubtitleDecoder::pass ()
+DCPSubtitleDecoder::pass (PassReason)
 {
        if (_next == _subtitles.end ()) {
                return true;
index fb2213fa271d2f933d981d042ce268130aaf653f..30bb896e061b3d845d901826c8024a78fb1cdef9 100644 (file)
@@ -28,7 +28,7 @@ public:
        DCPSubtitleDecoder (boost::shared_ptr<const DCPSubtitleContent>);
 
 protected:
-       bool pass ();
+       bool pass (PassReason);
        void seek (ContentTime time, bool accurate);
 
 private:
index 8378373c6e0e29c8c4ed45943a30a6817651ed2e..9e5573662e8acb82f4d71f9c26f22cd99d124044 100644 (file)
@@ -51,7 +51,13 @@ protected:
         */
        virtual void seek (ContentTime time, bool accurate) = 0;
 
-       virtual bool pass () = 0;
+       enum PassReason {
+               PASS_REASON_VIDEO,
+               PASS_REASON_AUDIO,
+               PASS_REASON_SUBTITLE
+       };
+
+       virtual bool pass (PassReason) = 0;
 };
 
 #endif
index 72a3d02b49f6f732827a649ab24d4e4815ce64bf..ee9d9eecbc8258e68615aa47d965dbc48704de23 100644 (file)
@@ -89,7 +89,7 @@ FFmpegDecoder::flush ()
 }
 
 bool
-FFmpegDecoder::pass ()
+FFmpegDecoder::pass (PassReason reason)
 {
        int r = av_read_frame (_format_context, &_packet);
 
@@ -112,11 +112,11 @@ FFmpegDecoder::pass ()
        int const si = _packet.stream_index;
        shared_ptr<const FFmpegContent> fc = _ffmpeg_content;
 
-       if (si == _video_stream && !_ignore_video) {
+       if (si == _video_stream && !_ignore_video && reason != PASS_REASON_SUBTITLE) {
                decode_video_packet ();
        } else if (fc->subtitle_stream() && fc->subtitle_stream()->uses_index (_format_context, si)) {
                decode_subtitle_packet ();
-       } else {
+       } else if (reason != PASS_REASON_SUBTITLE) {
                decode_audio_packet ();
        }
 
index 5475be6122da98b51c4bb8414a837af46d0be087..ce52679364f69844fc9e1d50e92612ba95a6c09d 100644 (file)
@@ -49,7 +49,7 @@ public:
 private:
        friend struct ::ffmpeg_pts_offset_test;
 
-       bool pass ();
+       bool pass (PassReason);
        void seek (ContentTime time, bool);
        void flush ();
 
index db7c5401fa3591c536fdf6083bf0a159e366e255..94c0dfd45709f7f583bbc9a870fef1fcf811d247 100644 (file)
@@ -43,7 +43,7 @@ ImageDecoder::ImageDecoder (shared_ptr<const ImageContent> c)
 }
 
 bool
-ImageDecoder::pass ()
+ImageDecoder::pass (PassReason)
 {
        if (_video_position >= _image_content->video_length()) {
                return true;
index 4d96306a89c63775121f4e243da36ce2aa507372..4ce75a20d043871add2623699877029e45d4f8fe 100644 (file)
@@ -31,7 +31,7 @@ public:
        }
 
 private:
-       bool pass ();
+       bool pass (PassReason);
        void seek (ContentTime, bool);
 
        boost::shared_ptr<const ImageContent> _image_content;
index 49633dd1fad2e503b345bf078fa4c56e454b52c1..7986e3c73da14886de117373d1a296c2860cda6c 100644 (file)
@@ -48,7 +48,7 @@ SndfileDecoder::~SndfileDecoder ()
 }
 
 bool
-SndfileDecoder::pass ()
+SndfileDecoder::pass (PassReason)
 {
        if (_remaining == 0) {
                return true;
index da9016ee09a958c26211df60e4ae68b6a1d9620d..a9d2935b6c36ac75b20e52a644f468f20af8cf48 100644 (file)
@@ -29,7 +29,7 @@ public:
        ~SndfileDecoder ();
 
 private:
-       bool pass ();
+       bool pass (PassReason);
        void seek (ContentTime, bool);
 
        int64_t _done;
index 32d50d86b14e62ad44b0f28015799fea1ce1514b..3c93292a166ef8208cda997893a7e54005f5fc79 100644 (file)
@@ -49,7 +49,7 @@ SubRipDecoder::seek (ContentTime time, bool accurate)
 }
 
 bool
-SubRipDecoder::pass ()
+SubRipDecoder::pass (PassReason)
 {
        if (_next >= _subtitles.size ()) {
                return true;
index db8374c5c86fac05cbac154ca31329618caea02c..b899b5dd8cd53138e735016bcfa06a282d7d64ff 100644 (file)
@@ -32,7 +32,7 @@ public:
 
 protected:
        void seek (ContentTime time, bool accurate);
-       bool pass ();
+       bool pass (PassReason);
 
 private:
        std::list<ContentTimePeriod> image_subtitles_during (ContentTimePeriod, bool starting) const;
index a95964f4773602f0acfe88b4d468909bfce0fc81..30b8661ae640d6ca386e08602e64cb3af8d8ad65 100644 (file)
@@ -79,7 +79,7 @@ SubtitleDecoder::get (list<T> const & subs, list<ContentTimePeriod> const & sp,
         *  (a) give us what we want, or
         *  (b) hit the end of the decoder.
         */
-       while (!pass () && (subs.empty() || (subs.back().period().to < sp.back().to))) {}
+       while (!pass(PASS_REASON_SUBTITLE) && (subs.empty() || (subs.back().period().to < sp.back().to))) {}
 
        /* Now look for what we wanted in the data we have collected */
        /* XXX: inefficient */
index 02f8fa0ac661a6eb946dd9ff498a09fdeb606813..4b9272413b6bca1c1b2995de5042af96a3f08f42 100644 (file)
@@ -98,7 +98,7 @@ VideoDecoder::get_video (Frame frame, bool accurate)
                                break;
                        }
 
-                       if (pass ()) {
+                       if (pass (PASS_REASON_VIDEO)) {
                                /* The decoder has nothing more for us */
                                break;
                        }
@@ -115,7 +115,7 @@ VideoDecoder::get_video (Frame frame, bool accurate)
                dec = decoded_video (frame);
        } else {
                /* Any frame will do: use the first one that comes out of pass() */
-               while (_decoded_video.empty() && !pass ()) {}
+               while (_decoded_video.empty() && !pass (PASS_REASON_VIDEO)) {}
                if (!_decoded_video.empty ()) {
                        dec.push_back (_decoded_video.front ());
                }
index 44d0d60f416e664fa76faf9495b9e8601b4c4f1c..48118c1b7dd85d1308304ab2ff1db64951192af1 100644 (file)
@@ -65,7 +65,7 @@ public:
                , _position (0)
        {}
 
-       bool pass ()
+       bool pass (PassReason)
        {
                Frame const N = min (
                        Frame (2000),