From 9922c1f2eaea674ba2ff6cce5f5853655fd8ad7a Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 13 May 2015 10:15:26 +0100 Subject: [PATCH] Don't bother decoding video frames when we're seeking around trying to find subtitles. --- src/lib/audio_decoder.cc | 4 ++-- src/lib/dcp_decoder.cc | 2 +- src/lib/dcp_decoder.h | 3 ++- src/lib/dcp_subtitle_decoder.cc | 2 +- src/lib/dcp_subtitle_decoder.h | 2 +- src/lib/decoder.h | 12 ++++++++++-- src/lib/ffmpeg_decoder.cc | 9 +++++---- src/lib/ffmpeg_decoder.h | 2 +- src/lib/image_decoder.cc | 2 +- src/lib/image_decoder.h | 5 ++--- src/lib/sndfile_decoder.cc | 2 +- src/lib/sndfile_decoder.h | 5 ++--- src/lib/subrip_decoder.cc | 2 +- src/lib/subrip_decoder.h | 2 +- src/lib/subtitle_decoder.cc | 4 +++- src/lib/video_decoder.cc | 6 +++--- test/audio_decoder_test.cc | 2 +- 17 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/lib/audio_decoder.cc b/src/lib/audio_decoder.cc index 22376e3e3..f6133947a 100644 --- a/src/lib/audio_decoder.cc +++ b/src/lib/audio_decoder.cc @@ -80,10 +80,10 @@ AudioDecoder::get_audio (AudioFrame frame, AudioFrame length, bool accurate) */ if (accurate) { /* Keep stuffing data into _decoded_audio until we have enough data, or the subclass does not want to give us any more */ - while ((_decoded_audio.frame > frame || (_decoded_audio.frame + _decoded_audio.audio->frames()) < end) && !pass ()) {} + while ((_decoded_audio.frame > frame || (_decoded_audio.frame + _decoded_audio.audio->frames()) < end) && !pass (PASS_REASON_AUDIO)) {} decoded_offset = frame - _decoded_audio.frame; } else { - while (_decoded_audio.audio->frames() < length && !pass ()) {} + while (_decoded_audio.audio->frames() < length && !pass (PASS_REASON_AUDIO)) {} /* Use decoded_offset of 0, as we don't really care what frames we return */ } diff --git a/src/lib/dcp_decoder.cc b/src/lib/dcp_decoder.cc index ab0df8a86..3bfbd7720 100644 --- a/src/lib/dcp_decoder.cc +++ b/src/lib/dcp_decoder.cc @@ -55,7 +55,7 @@ DCPDecoder::DCPDecoder (shared_ptr c) } bool -DCPDecoder::pass () +DCPDecoder::pass (PassReason) { if (_reel == _reels.end () || !_dcp_content->can_be_played ()) { return true; diff --git a/src/lib/dcp_decoder.h b/src/lib/dcp_decoder.h index 20ca2bb67..3a05325c7 100644 --- a/src/lib/dcp_decoder.h +++ b/src/lib/dcp_decoder.h @@ -38,8 +38,9 @@ public: DCPDecoder (boost::shared_ptr); private: + bool pass (PassReason); void seek (ContentTime t, bool accurate); - bool pass (); + std::list image_subtitles_during (ContentTimePeriod, bool starting) const; std::list text_subtitles_during (ContentTimePeriod, bool starting) const; diff --git a/src/lib/dcp_subtitle_decoder.cc b/src/lib/dcp_subtitle_decoder.cc index 236e99996..93a122590 100644 --- a/src/lib/dcp_subtitle_decoder.cc +++ b/src/lib/dcp_subtitle_decoder.cc @@ -46,7 +46,7 @@ DCPSubtitleDecoder::seek (ContentTime time, bool accurate) } bool -DCPSubtitleDecoder::pass () +DCPSubtitleDecoder::pass (PassReason) { if (_next == _subtitles.end ()) { return true; diff --git a/src/lib/dcp_subtitle_decoder.h b/src/lib/dcp_subtitle_decoder.h index 9a16fb7c8..52e400416 100644 --- a/src/lib/dcp_subtitle_decoder.h +++ b/src/lib/dcp_subtitle_decoder.h @@ -28,8 +28,8 @@ public: DCPSubtitleDecoder (boost::shared_ptr); protected: + bool pass (PassReason); void seek (ContentTime time, bool accurate); - bool pass (); private: std::list image_subtitles_during (ContentTimePeriod, bool starting) const; diff --git a/src/lib/decoder.h b/src/lib/decoder.h index c1b859865..0703a5426 100644 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2013 Carl Hetherington + Copyright (C) 2012-2015 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 @@ -41,6 +41,7 @@ public: virtual ~Decoder () {} protected: + /** Seek so that the next pass() will yield the next thing * (video/sound frame, subtitle etc.) at or after the requested * time. Pass accurate = true to try harder to ensure that, at worst, @@ -50,7 +51,14 @@ protected: * it may seek to just the right spot. */ 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 reason) = 0; }; #endif diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index a3d647cde..6122a547e 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -132,7 +132,7 @@ FFmpegDecoder::flush () } bool -FFmpegDecoder::pass () +FFmpegDecoder::pass (PassReason reason) { int r = av_read_frame (_format_context, &_packet); @@ -153,12 +153,13 @@ FFmpegDecoder::pass () } int const si = _packet.stream_index; + shared_ptr fc = _ffmpeg_content; - if (si == _video_stream && !_ignore_video) { + if (si == _video_stream && !_ignore_video && reason != PASS_REASON_SUBTITLE) { decode_video_packet (); - } else if (_ffmpeg_content->audio_stream() && _ffmpeg_content->audio_stream()->uses_index (_format_context, si)) { + } else if (fc->audio_stream() && fc->audio_stream()->uses_index (_format_context, si) && reason != PASS_REASON_SUBTITLE) { decode_audio_packet (); - } else if (_ffmpeg_content->subtitle_stream() && _ffmpeg_content->subtitle_stream()->uses_index (_format_context, si)) { + } else if (fc->subtitle_stream() && fc->subtitle_stream()->uses_index (_format_context, si)) { decode_subtitle_packet (); } diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index 0a0eea18a..616fa88dd 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -53,8 +53,8 @@ public: private: friend struct ::ffmpeg_pts_offset_test; + bool pass (PassReason reason); void seek (ContentTime time, bool); - bool pass (); void flush (); AVSampleFormat audio_sample_format () const; diff --git a/src/lib/image_decoder.cc b/src/lib/image_decoder.cc index 78201fc23..250c8f845 100644 --- a/src/lib/image_decoder.cc +++ b/src/lib/image_decoder.cc @@ -43,7 +43,7 @@ ImageDecoder::ImageDecoder (shared_ptr c) } bool -ImageDecoder::pass () +ImageDecoder::pass (PassReason) { if (_video_position >= _image_content->video_length().frames (_image_content->video_frame_rate ())) { return true; diff --git a/src/lib/image_decoder.h b/src/lib/image_decoder.h index 242f69477..ec90051da 100644 --- a/src/lib/image_decoder.h +++ b/src/lib/image_decoder.h @@ -34,10 +34,9 @@ public: return _image_content; } - void seek (ContentTime, bool); - private: - bool pass (); + bool pass (PassReason); + void seek (ContentTime, bool); boost::shared_ptr _image_content; boost::shared_ptr _image; diff --git a/src/lib/sndfile_decoder.cc b/src/lib/sndfile_decoder.cc index 602014d58..09059a8b0 100644 --- a/src/lib/sndfile_decoder.cc +++ b/src/lib/sndfile_decoder.cc @@ -65,7 +65,7 @@ SndfileDecoder::~SndfileDecoder () } bool -SndfileDecoder::pass () +SndfileDecoder::pass (PassReason) { if (_remaining == 0) { return true; diff --git a/src/lib/sndfile_decoder.h b/src/lib/sndfile_decoder.h index 5ebe1da7b..68c8633a0 100644 --- a/src/lib/sndfile_decoder.h +++ b/src/lib/sndfile_decoder.h @@ -30,14 +30,13 @@ public: SndfileDecoder (boost::shared_ptr c); ~SndfileDecoder (); - void seek (ContentTime, bool); - int audio_channels () const; ContentTime audio_length () const; int audio_frame_rate () const; private: - bool pass (); + bool pass (PassReason); + void seek (ContentTime, bool); boost::shared_ptr _sndfile_content; SNDFILE* _sndfile; diff --git a/src/lib/subrip_decoder.cc b/src/lib/subrip_decoder.cc index bef48ba78..6ed2e5254 100644 --- a/src/lib/subrip_decoder.cc +++ b/src/lib/subrip_decoder.cc @@ -48,7 +48,7 @@ SubRipDecoder::seek (ContentTime time, bool accurate) } bool -SubRipDecoder::pass () +SubRipDecoder::pass (PassReason) { if (_next >= _subtitles.size ()) { return true; diff --git a/src/lib/subrip_decoder.h b/src/lib/subrip_decoder.h index 876f763d3..264ca8899 100644 --- a/src/lib/subrip_decoder.h +++ b/src/lib/subrip_decoder.h @@ -32,7 +32,7 @@ public: protected: void seek (ContentTime time, bool accurate); - bool pass (); + bool pass (PassReason); private: std::list image_subtitles_during (ContentTimePeriod, bool starting) const; diff --git a/src/lib/subtitle_decoder.cc b/src/lib/subtitle_decoder.cc index ac9a67e33..edb291ab8 100644 --- a/src/lib/subtitle_decoder.cc +++ b/src/lib/subtitle_decoder.cc @@ -70,7 +70,7 @@ SubtitleDecoder::get (list const & subs, list 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 */ @@ -82,6 +82,8 @@ SubtitleDecoder::get (list const & subs, list const & sp, } } + /* XXX: should clear out _decoded_* at some point */ + return out; } diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc index b7cf1641b..31dc3cdc2 100644 --- a/src/lib/video_decoder.cc +++ b/src/lib/video_decoder.cc @@ -96,7 +96,7 @@ VideoDecoder::get_video (VideoFrame frame, bool accurate) break; } - if (pass ()) { + if (pass (PASS_REASON_VIDEO)) { /* The decoder has nothing more for us */ break; } @@ -113,7 +113,7 @@ VideoDecoder::get_video (VideoFrame 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 ()); } @@ -237,7 +237,7 @@ VideoDecoder::video (shared_ptr image, VideoFrame frame) if (_ignore_video) { return; } - + /* We may receive the same frame index twice for 3D, and we need to know when that happens. */ diff --git a/test/audio_decoder_test.cc b/test/audio_decoder_test.cc index a14e2f9be..b1f672356 100644 --- a/test/audio_decoder_test.cc +++ b/test/audio_decoder_test.cc @@ -40,7 +40,7 @@ public: , _position (0) {} - bool pass () + bool pass (PassReason) { AudioFrame const N = min ( AudioFrame (2000), -- 2.30.2