Further fixes and tidying to 'better-seek'.
authorCarl Hetherington <cth@carlh.net>
Thu, 8 Dec 2016 11:23:58 +0000 (11:23 +0000)
committerCarl Hetherington <cth@carlh.net>
Thu, 8 Dec 2016 11:23:58 +0000 (11:23 +0000)
This fixes the failure to keep track of the `position' of
each stream of a multi-stream file.  It also tidies things
up a bit.

18 files changed:
src/lib/audio_decoder.cc
src/lib/audio_decoder.h
src/lib/audio_decoder_stream.cc
src/lib/audio_decoder_stream.h
src/lib/dcp_decoder.cc
src/lib/dcp_subtitle_decoder.cc
src/lib/decoder.cc
src/lib/decoder.h
src/lib/decoder_part.cc
src/lib/decoder_part.h
src/lib/ffmpeg_decoder.cc
src/lib/image_decoder.cc
src/lib/subtitle_decoder.cc
src/lib/subtitle_decoder.h
src/lib/text_subtitle_decoder.cc
src/lib/video_decoder.cc
src/lib/video_decoder.h
src/lib/video_mxf_decoder.cc

index fd0835596924c8d2e19abde7d742396740d9d71b..1b1ae70c0c8195bb27fd95d3e667dc3f03b6e464 100644 (file)
@@ -32,6 +32,7 @@
 using std::cout;
 using std::map;
 using boost::shared_ptr;
+using boost::optional;
 
 AudioDecoder::AudioDecoder (Decoder* parent, shared_ptr<const AudioContent> content, shared_ptr<Log> log)
        : DecoderPart (parent, log)
@@ -83,7 +84,7 @@ AudioDecoder::give (AudioStreamPtr stream, shared_ptr<const AudioBuffers> data,
 void
 AudioDecoder::flush ()
 {
-       for (map<AudioStreamPtr, shared_ptr<AudioDecoderStream> >::const_iterator i = _streams.begin(); i != _streams.end(); ++i) {
+       for (StreamMap::const_iterator i = _streams.begin(); i != _streams.end(); ++i) {
                i->second->flush ();
        }
 }
@@ -92,7 +93,7 @@ void
 AudioDecoder::seek (ContentTime t, bool accurate)
 {
        _log->log (String::compose ("AD seek to %1", to_string(t)), LogEntry::TYPE_DEBUG_DECODE);
-       for (map<AudioStreamPtr, shared_ptr<AudioDecoderStream> >::const_iterator i = _streams.begin(); i != _streams.end(); ++i) {
+       for (StreamMap::const_iterator i = _streams.begin(); i != _streams.end(); ++i) {
                i->second->seek (t, accurate);
        }
 }
@@ -100,7 +101,19 @@ AudioDecoder::seek (ContentTime t, bool accurate)
 void
 AudioDecoder::set_fast ()
 {
-       for (map<AudioStreamPtr, shared_ptr<AudioDecoderStream> >::const_iterator i = _streams.begin(); i != _streams.end(); ++i) {
+       for (StreamMap::const_iterator i = _streams.begin(); i != _streams.end(); ++i) {
                i->second->set_fast ();
        }
 }
+
+optional<ContentTime>
+AudioDecoder::position () const
+{
+       optional<ContentTime> pos;
+       for (StreamMap::const_iterator i = _streams.begin(); i != _streams.end(); ++i) {
+               if (!pos || (i->second->position() && i->second->position().get() < pos.get())) {
+                       pos = i->second->position();
+               }
+       }
+       return pos;
+}
index 4b7594f352719a32124684aca0e77b77c7973507..cdb643ceeabef373aa5ada3f705168beed574766 100644 (file)
@@ -58,9 +58,12 @@ public:
        void flush ();
        void seek (ContentTime t, bool accurate);
 
+       boost::optional<ContentTime> position () const;
+
 private:
        /** An AudioDecoderStream object to manage each stream in _audio_content */
-       std::map<AudioStreamPtr, boost::shared_ptr<AudioDecoderStream> > _streams;
+       typedef std::map<AudioStreamPtr, boost::shared_ptr<AudioDecoderStream> > StreamMap;
+       StreamMap _streams;
 };
 
 #endif
index af46593ab60b20c8948abd977e5d19f05fa98809..a82ebc4cf4b04e8b4d48dec0c20875994078d06c 100644 (file)
@@ -272,3 +272,13 @@ AudioDecoderStream::set_fast ()
                _resampler->set_fast ();
        }
 }
+
+optional<ContentTime>
+AudioDecoderStream::position () const
+{
+       if (!_position) {
+               return optional<ContentTime> ();
+       }
+
+       return ContentTime::from_frames (_position.get(), _content->resampled_frame_rate());
+}
index 78747bfc5ad713d22faa306281f321ea4fc64af7..9ec5c5a096d12284392efeaebd393bbed56eb2e2 100644 (file)
@@ -43,6 +43,8 @@ public:
        void seek (ContentTime time, bool accurate);
        void set_fast ();
 
+       boost::optional<ContentTime> position () const;
+
 private:
 
        void reset_decoded ();
index e384e123045bd32966fb1b06bc584129f22be061..b7397099c3e8c97f34d28a2fd9224cd8db7f279f 100644 (file)
@@ -164,9 +164,6 @@ DCPDecoder::pass (PassReason reason, bool)
                }
        }
 
-       video->set_position (_next);
-       audio->set_position (_next);
-       subtitle->set_position (_next);
        _next += ContentTime::from_frames (1, vfr);
 
        if ((*_reel)->main_picture ()) {
index daafee3e5acfaf687a6d4b5de76f064dfeede0df..824ddba19dad144d8536e99ac5c276c6218b55db 100644 (file)
@@ -80,7 +80,6 @@ DCPSubtitleDecoder::pass (PassReason, bool)
        }
 
        subtitle->give_text (p, s);
-       subtitle->set_position (p.from);
 
        return false;
 }
index b7bd78c1404415e6b61c11940d4ccae67502b8d2..e538a51d4af06a65c718e4eae0a5c8dfee46c993 100644 (file)
 */
 
 #include "decoder.h"
+#include "decoder_part.h"
 #include <iostream>
 
 using std::cout;
 using boost::optional;
 
 void
-Decoder::maybe_seek (optional<ContentTime>& position, ContentTime time, bool accurate)
+Decoder::maybe_seek (opional<ContentTime> position, ContentTime time, bool accurate)
 {
-       if (position && (time >= *position && time < (*position + ContentTime::from_seconds(1)))) {
+       if (position && (time >= position.get() && time < (position.get() + ContentTime::from_seconds(1)))) {
                /* No need to seek: caller should just pass() */
                return;
        }
 
-       position.reset ();
        seek (time, accurate);
 }
index bd4bf01c2135bbcb68cab9a850caeb93a3fc8358..3717d931d63e20be1dd6701ab304cffaf1c13e0b 100644 (file)
@@ -33,6 +33,7 @@ class Decoded;
 class VideoDecoder;
 class AudioDecoder;
 class SubtitleDecoder;
+class DecoderPart;
 
 /** @class Decoder.
  *  @brief Parent class for decoders of content.
@@ -60,7 +61,7 @@ public:
         */
        virtual void reset () {}
 
-       void maybe_seek (boost::optional<ContentTime>& position, ContentTime time, bool accurate);
+       void maybe_seek (boost::optional<ContentTime> position, ContentTime time, bool accurate);
 
 private:
        /** Seek so that the next pass() will yield the next thing
index f210bd7aeb0a48a9bbc44d1ebe6d0bea6a418d29..6d53e4a77c78030ba7d985fadfd192da4c16fade 100644 (file)
@@ -34,5 +34,5 @@ DecoderPart::DecoderPart (Decoder* parent, shared_ptr<Log> log)
 void
 DecoderPart::maybe_seek (ContentTime time, bool accurate)
 {
-       _parent->maybe_seek (_position, time, accurate);
+       _parent->maybe_seek (position(), time, accurate);
 }
index 1a879452703a5dd301ff86a38e253da4360fd757..ed92d43b4258abf95fa03a2049e7b137c69cfe29 100644 (file)
@@ -40,13 +40,7 @@ public:
                return _ignore;
        }
 
-       void set_position (ContentTime position) {
-               _position = position;
-       }
-
-       boost::optional<ContentTime> position () const {
-               return _position;
-       }
+       virtual boost::optional<ContentTime> position () const = 0;
 
        void maybe_seek (ContentTime time, bool accurate);
 
@@ -56,7 +50,6 @@ protected:
 
 private:
        bool _ignore;
-       boost::optional<ContentTime> _position;
 };
 
 #endif
index c732a51730eb15563905ca7b65e47f74afde86fa..b6b6e594d9f41055843220706c960dcb6f5756fd 100644 (file)
@@ -426,8 +426,6 @@ FFmpegDecoder::decode_audio_packet ()
                                LOG_WARNING ("Crazy timestamp %1", to_string (ct));
                        }
 
-                       audio->set_position (ct);
-
                        /* Give this data provided there is some, and its time is sane */
                        if (ct >= ContentTime() && data->frames() > 0) {
                                audio->give (*stream, data, ct);
@@ -479,7 +477,6 @@ FFmpegDecoder::decode_video_packet ()
                                shared_ptr<ImageProxy> (new RawImageProxy (image)),
                                llrint (pts * _ffmpeg_content->active_video_frame_rate ())
                                );
-                       video->set_position (ContentTime::from_seconds (pts));
                } else {
                        LOG_WARNING_NC ("Dropping frame without PTS");
                }
@@ -510,7 +507,6 @@ FFmpegDecoder::decode_subtitle_packet ()
        FFmpegSubtitlePeriod sub_period = subtitle_period (sub);
        ContentTimePeriod period;
        period.from = sub_period.from + _pts_offset;
-       subtitle->set_position (period.from);
        /* We can't trust the `to' time from sub_period as there are some decoders which
           give a sub_period time for `to' which is subsequently overridden by a `stop' subtitle;
           see also FFmpegExaminer.
index 28fc9c0a51bd05fe54dea9826f80203320aa3238..dae73663c7f20104e448d67916aafcfec161d09f 100644 (file)
@@ -72,7 +72,6 @@ ImageDecoder::pass (PassReason, bool)
                }
        }
 
-       video->set_position (ContentTime::from_frames (_frame_video_position, _image_content->active_video_frame_rate ()));
        video->give (_image, _frame_video_position);
        ++_frame_video_position;
        return false;
index 9ec030b383e6f8442afb8c20c98c8a3576b19a7a..c59406c3659c80659d10b3bd11ce39ec6d77aeab 100644 (file)
@@ -63,6 +63,7 @@ void
 SubtitleDecoder::give_image (ContentTimePeriod period, shared_ptr<Image> image, dcpomatic::Rect<double> rect)
 {
        _decoded_image.push_back (ContentImageSubtitle (period, image, rect));
+       _position = period.from;
 }
 
 void
@@ -79,6 +80,7 @@ SubtitleDecoder::give_text (ContentTimePeriod period, list<dcp::SubtitleString>
        }
 
        _decoded_text.push_back (ContentTextSubtitle (period, s));
+       _position = period.from;
 }
 
 /** Get the subtitles that correspond to a given list of periods.
@@ -168,6 +170,7 @@ SubtitleDecoder::seek (ContentTime t, bool)
 {
        _log->log (String::compose ("SD seek to %1", to_string(t)), LogEntry::TYPE_DEBUG_DECODE);
        reset ();
+       _position.reset ();
 }
 
 void
index dfa3d6d909e288c1e5bc4ce612202da9ebda37c1..e5e9316693514e33fead9841e544ffed28e2432c 100644 (file)
@@ -63,6 +63,14 @@ public:
                return _content;
        }
 
+       boost::optional<ContentTime> position () const {
+               return _position;
+       }
+
+       void reset_position () {
+               _position.reset ();
+       }
+
 private:
 
        std::list<ContentImageSubtitle> _decoded_image;
@@ -74,6 +82,8 @@ private:
 
        boost::function<std::list<ContentTimePeriod> (ContentTimePeriod, bool)> _image_during;
        boost::function<std::list<ContentTimePeriod> (ContentTimePeriod, bool)> _text_during;
+
+       boost::optional<ContentTime> _position;
 };
 
 #endif
index ec60bd36b52327a838cf73460c01f0ad74c04b16..dd64cb5d93d97fe44942af1a570eb3b3ebc17304 100644 (file)
@@ -69,7 +69,6 @@ TextSubtitleDecoder::pass (PassReason, bool)
 
        ContentTimePeriod const p = content_time_period (_subtitles[_next]);
        subtitle->give_text (p, _subtitles[_next]);
-       subtitle->set_position (p.from);
 
        ++_next;
        return false;
index 1cde53e8140584b145743c69a26d0c4220fe251d..0e9ee0c1a874d1e9ffe1f7e0531b15369f431d83 100644 (file)
@@ -274,6 +274,7 @@ VideoDecoder::give (shared_ptr<const ImageProxy> image, Frame frame)
        }
 
        _log->log (String::compose ("VD receives %1", frame), LogEntry::TYPE_DEBUG_DECODE);
+       _position = ContentTime::from_frames (frame, _content->active_video_frame_rate());
 
        /* Work out what we are going to push into _decoded next */
        list<ContentVideo> to_push;
@@ -389,4 +390,5 @@ VideoDecoder::seek (ContentTime s, bool accurate)
        _decoded.clear ();
        _last_seek_time = s;
        _last_seek_accurate = accurate;
+       _position.reset ();
 }
index 4f764d203f6406dc2cd979697236abfa7eb86680..156ee42221a0d645a1ac8998934afc6c98ccae78 100644 (file)
@@ -60,6 +60,14 @@ public:
        void seek (ContentTime time, bool accurate);
        void give (boost::shared_ptr<const ImageProxy>, Frame frame);
 
+       boost::optional<ContentTime> position () const {
+               return _position;
+       }
+
+       void reset_position () {
+               _position.reset ();
+       }
+
 private:
 
        std::list<ContentVideo> decoded (Frame frame);
@@ -75,6 +83,7 @@ private:
         *  it has no more to give.
         */
        boost::optional<Frame> _no_data_frame;
+       boost::optional<ContentTime> _position;
 };
 
 #endif
index 90a58a16ef45907a803c4def9f1ff7ec57611b40..dc4f8d60b6882b23b255240cc4e23359bd2dcfbc 100644 (file)
@@ -89,7 +89,6 @@ VideoMXFDecoder::pass (PassReason, bool)
                        );
        }
 
-       video->set_position (_next);
        _next += ContentTime::from_frames (1, vfr);
        return false;
 }