Move position variables into the video/audio/subtitle decoder classes.
authorCarl Hetherington <cth@carlh.net>
Sat, 19 Nov 2016 20:40:36 +0000 (20:40 +0000)
committerCarl Hetherington <cth@carlh.net>
Sat, 19 Nov 2016 20:40:36 +0000 (20:40 +0000)
20 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 [new file with mode: 0644]
src/lib/decoder_part.h [new file with mode: 0644]
src/lib/ffmpeg_decoder.cc
src/lib/ffmpeg_decoder.h
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
src/lib/wscript

index bc37960583eb52b15edd89435aff901e4c85c1a9..9801a68da90a0c1cb8d9505451742940adf205e6 100644 (file)
@@ -32,10 +32,10 @@ using std::map;
 using boost::shared_ptr;
 
 AudioDecoder::AudioDecoder (Decoder* parent, shared_ptr<const AudioContent> content, shared_ptr<Log> log)
-       : _ignore (false)
+       : DecoderPart (parent)
 {
        BOOST_FOREACH (AudioStreamPtr i, content->streams ()) {
-               _streams[i] = shared_ptr<AudioDecoderStream> (new AudioDecoderStream (content, i, parent, log));
+               _streams[i] = shared_ptr<AudioDecoderStream> (new AudioDecoderStream (content, i, parent, this, log));
        }
 }
 
@@ -48,7 +48,7 @@ AudioDecoder::get (AudioStreamPtr stream, Frame frame, Frame length, bool accura
 void
 AudioDecoder::give (AudioStreamPtr stream, shared_ptr<const AudioBuffers> data, ContentTime time)
 {
-       if (_ignore) {
+       if (ignore ()) {
                return;
        }
 
@@ -94,13 +94,6 @@ AudioDecoder::seek (ContentTime t, bool accurate)
        }
 }
 
-/** Set this decoder never to produce any data */
-void
-AudioDecoder::set_ignore ()
-{
-       _ignore = true;
-}
-
 void
 AudioDecoder::set_fast ()
 {
index 2415bd6ac15f3131cb2da05621cb416b64719994..4b7594f352719a32124684aca0e77b77c7973507 100644 (file)
@@ -28,6 +28,7 @@
 #include "decoder.h"
 #include "content_audio.h"
 #include "audio_stream.h"
+#include "decoder_part.h"
 #include <boost/enable_shared_from_this.hpp>
 
 class AudioBuffers;
@@ -38,7 +39,7 @@ class Log;
 /** @class AudioDecoder.
  *  @brief Parent class for audio decoders.
  */
-class AudioDecoder : public boost::enable_shared_from_this<AudioDecoder>
+class AudioDecoder : public boost::enable_shared_from_this<AudioDecoder>, public DecoderPart
 {
 public:
        AudioDecoder (Decoder* parent, boost::shared_ptr<const AudioContent>, boost::shared_ptr<Log> log);
@@ -51,7 +52,6 @@ public:
         */
        ContentAudio get (AudioStreamPtr stream, Frame time, Frame length, bool accurate);
 
-       void set_ignore ();
        void set_fast ();
 
        void give (AudioStreamPtr stream, boost::shared_ptr<const AudioBuffers>, ContentTime);
@@ -61,7 +61,6 @@ public:
 private:
        /** An AudioDecoderStream object to manage each stream in _audio_content */
        std::map<AudioStreamPtr, boost::shared_ptr<AudioDecoderStream> > _streams;
-       bool _ignore;
 };
 
 #endif
index 7e8e304ef63e83e4d44d9556dfe9ee2f4a0eb969..4f1a2f4ff3f5cdda5105c175edc890ecd299371f 100644 (file)
@@ -40,10 +40,13 @@ using std::max;
 using boost::optional;
 using boost::shared_ptr;
 
-AudioDecoderStream::AudioDecoderStream (shared_ptr<const AudioContent> content, AudioStreamPtr stream, Decoder* decoder, shared_ptr<Log> log)
+AudioDecoderStream::AudioDecoderStream (
+       shared_ptr<const AudioContent> content, AudioStreamPtr stream, Decoder* decoder, AudioDecoder* audio_decoder, shared_ptr<Log> log
+       )
        : _content (content)
        , _stream (stream)
        , _decoder (decoder)
+       , _audio_decoder (audio_decoder)
        , _log (log)
          /* We effectively start having done a seek to zero; this allows silence-padding of the first
             data that comes out of our decoder.
@@ -86,7 +89,7 @@ AudioDecoderStream::get (Frame frame, Frame length, bool accurate)
        }
 
        if (missing) {
-               _decoder->maybe_seek_audio (ContentTime::from_frames (*missing, _content->resampled_frame_rate()), accurate);
+               _audio_decoder->maybe_seek (ContentTime::from_frames (*missing, _content->resampled_frame_rate()), accurate);
        }
 
        /* Offset of the data that we want from the start of _decoded.audio
index a99464b894854071078992f26bd7b8772b9dfc9d..78747bfc5ad713d22faa306281f321ea4fc64af7 100644 (file)
@@ -35,7 +35,7 @@ class Decoder;
 class AudioDecoderStream
 {
 public:
-       AudioDecoderStream (boost::shared_ptr<const AudioContent>, AudioStreamPtr, Decoder* decoder, boost::shared_ptr<Log> log);
+       AudioDecoderStream (boost::shared_ptr<const AudioContent>, AudioStreamPtr, Decoder* decoder, AudioDecoder* audio_decoder, boost::shared_ptr<Log> log);
 
        ContentAudio get (Frame time, Frame length, bool accurate);
        void audio (boost::shared_ptr<const AudioBuffers>, ContentTime);
@@ -51,6 +51,7 @@ private:
        boost::shared_ptr<const AudioContent> _content;
        AudioStreamPtr _stream;
        Decoder* _decoder;
+       AudioDecoder* _audio_decoder;
        boost::shared_ptr<Log> _log;
        boost::shared_ptr<Resampler> _resampler;
        boost::optional<Frame> _position;
index 4f17bdb3b9293b1c6359e39b90a018ae4a677776..1d7c66a5ba52e708c0aed831d63eb806b6ec5679 100644 (file)
@@ -163,7 +163,9 @@ DCPDecoder::pass (PassReason reason, bool)
                }
        }
 
-       _video_position = _audio_position = _subtitle_position = _next;
+       video->set_position (_next);
+       audio->set_position (_next);
+       subtitle->set_position (_next);
        _next += ContentTime::from_frames (1, vfr);
 
        if ((*_reel)->main_picture ()) {
index c67133012df9e3998bb1187ceb17bb0e96839905..fe383226ee7a33f27a474248feba3c9077bd13f3 100644 (file)
@@ -79,7 +79,7 @@ DCPSubtitleDecoder::pass (PassReason, bool)
        }
 
        subtitle->give_text (p, s);
-       _subtitle_position = p.from;
+       subtitle->set_position (p.from);
 
        return false;
 }
index 50356da788e84c018f175e6c611a6d5a6313f52b..988b8fe9b2f9fc73a6261064e673396365f71bdf 100644 (file)
@@ -40,21 +40,3 @@ Decoder::maybe_seek (optional<ContentTime>& position, ContentTime time, bool acc
        position.reset ();
        seek (time, accurate);
 }
-
-void
-Decoder::maybe_seek_video (ContentTime time, bool accurate)
-{
-       maybe_seek (_video_position, time, accurate);
-}
-
-void
-Decoder::maybe_seek_audio (ContentTime time, bool accurate)
-{
-       maybe_seek (_audio_position, time, accurate);
-}
-
-void
-Decoder::maybe_seek_subtitle (ContentTime time, bool accurate)
-{
-       maybe_seek (_subtitle_position, time, accurate);
-}
index d2302d7a20d3057bcfde04fd9df1b11934f45420..bd4bf01c2135bbcb68cab9a850caeb93a3fc8358 100644 (file)
@@ -52,10 +52,6 @@ public:
                PASS_REASON_SUBTITLE
        };
 
-       void maybe_seek_video (ContentTime time, bool accurate);
-       void maybe_seek_audio (ContentTime time, bool accurate);
-       void maybe_seek_subtitle (ContentTime time, bool accurate);
-
        /** @return true if this decoder has already returned all its data and will give no more */
        virtual bool pass (PassReason, bool accurate) = 0;
 
@@ -64,10 +60,7 @@ public:
         */
        virtual void reset () {}
 
-protected:
-       boost::optional<ContentTime> _video_position;
-       boost::optional<ContentTime> _audio_position;
-       boost::optional<ContentTime> _subtitle_position;
+       void maybe_seek (boost::optional<ContentTime>& position, ContentTime time, bool accurate);
 
 private:
        /** Seek so that the next pass() will yield the next thing
@@ -79,7 +72,6 @@ private:
         *  it may seek to just the right spot.
         */
        virtual void seek (ContentTime time, bool accurate) = 0;
-       void maybe_seek (boost::optional<ContentTime>& position, ContentTime time, bool accurate);
 };
 
 #endif
diff --git a/src/lib/decoder_part.cc b/src/lib/decoder_part.cc
new file mode 100644 (file)
index 0000000..9ae9633
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+    Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic 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.
+
+    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "decoder_part.h"
+#include "decoder.h"
+
+DecoderPart::DecoderPart (Decoder* parent)
+       : _parent (parent)
+       , _ignore (false)
+{
+
+}
+
+void
+DecoderPart::maybe_seek (ContentTime time, bool accurate)
+{
+       _parent->maybe_seek (_position, time, accurate);
+}
diff --git a/src/lib/decoder_part.h b/src/lib/decoder_part.h
new file mode 100644 (file)
index 0000000..4b309a6
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+    Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic 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.
+
+    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef DCPOMATIC_DECODER_PART_H
+#define DCPOMATIC_DECODER_PART_H
+
+#include "dcpomatic_time.h"
+#include <boost/optional.hpp>
+
+class Decoder;
+
+class DecoderPart
+{
+public:
+       DecoderPart (Decoder* parent);
+
+       void set_ignore () {
+               _ignore = true;
+       }
+
+       bool ignore () const {
+               return _ignore;
+       }
+
+       void set_position (ContentTime position) {
+               _position = position;
+       }
+
+       boost::optional<ContentTime> position () const {
+               return _position;
+       }
+
+       void maybe_seek (ContentTime time, bool accurate);
+
+protected:
+       Decoder* _parent;
+
+private:
+       bool _ignore;
+       boost::optional<ContentTime> _position;
+};
+
+#endif
index 8f196542a1ea5b10005598c04fcd7290643f0235..ddc563b9855b2b5d5fdd7575d69bfbc9475960e9 100644 (file)
@@ -425,7 +425,7 @@ FFmpegDecoder::decode_audio_packet ()
                                LOG_WARNING ("Crazy timestamp %s", to_string (ct));
                        }
 
-                       update_position (_audio_position, ct);
+                       audio->set_position (ct);
 
                        /* Give this data provided there is some, and its time is sane */
                        if (ct >= ContentTime() && data->frames() > 0) {
@@ -478,7 +478,7 @@ FFmpegDecoder::decode_video_packet ()
                                shared_ptr<ImageProxy> (new RawImageProxy (image)),
                                llrint (pts * _ffmpeg_content->active_video_frame_rate ())
                                );
-                       update_position (_video_position, ContentTime::from_seconds (pts));
+                       video->set_position (ContentTime::from_seconds (pts));
                } else {
                        LOG_WARNING_NC ("Dropping frame without PTS");
                }
@@ -509,7 +509,7 @@ FFmpegDecoder::decode_subtitle_packet ()
        FFmpegSubtitlePeriod sub_period = subtitle_period (sub);
        ContentTimePeriod period;
        period.from = sub_period.from + _pts_offset;
-       update_position (_subtitle_position, period.from);
+       subtitle->set_position (period.from);
        if (sub_period.to) {
                /* We already know the subtitle period `to' time */
                period.to = sub_period.to.get() + _pts_offset;
@@ -644,16 +644,3 @@ FFmpegDecoder::decode_ass_subtitle (string ass, ContentTimePeriod period)
                subtitle->give_text (period, i);
        }
 }
-
-void
-FFmpegDecoder::update_position (optional<ContentTime>& current, ContentTime p)
-{
-       /* current should err on the side of being too big, as then there is less
-          chance that we will erroneously decide not to seek when current > request.
-       */
-       if (!current) {
-               current = p;
-       } else {
-               current = max (*current, p);
-       }
-}
index d6f50cd43511769d2089e79654bcd8d22aa18aa5..76755c1fcc2d6e1a3c75b202d5b2d5dc6c266d1e 100644 (file)
@@ -52,7 +52,6 @@ private:
        bool pass (PassReason, bool accurate);
        void seek (ContentTime time, bool);
        void flush ();
-       void update_position (boost::optional<ContentTime>& current, ContentTime p);
 
        AVSampleFormat audio_sample_format (boost::shared_ptr<FFmpegAudioStream> stream) const;
        int bytes_per_audio_sample (boost::shared_ptr<FFmpegAudioStream> stream) const;
index 7270c97829acf218abd0318b53e9e6f21855d869..28fc9c0a51bd05fe54dea9826f80203320aa3238 100644 (file)
@@ -72,7 +72,7 @@ ImageDecoder::pass (PassReason, bool)
                }
        }
 
-       _video_position = ContentTime::from_frames (_frame_video_position, _image_content->active_video_frame_rate ());
+       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 020a0383c2db81b8c41e6419ed5cfb2ec28f320b..9c6ac969dbd876caf3580b46471e6354c8d3da11 100644 (file)
@@ -41,7 +41,7 @@ SubtitleDecoder::SubtitleDecoder (
        function<list<ContentTimePeriod> (ContentTimePeriod, bool)> image_during,
        function<list<ContentTimePeriod> (ContentTimePeriod, bool)> text_during
        )
-       : _parent (parent)
+       : DecoderPart (parent)
        , _content (c)
        , _image_during (image_during)
        , _text_during (text_during)
@@ -104,7 +104,7 @@ SubtitleDecoder::get (list<T> const & subs, list<ContentTimePeriod> const & sp,
 
        /* Suggest to our parent decoder that it might want to seek if we haven't got what we're being asked for */
        if (missing) {
-               _parent->maybe_seek_subtitle (*missing, true);
+               maybe_seek (*missing, true);
        }
 
        /* Now enough pass() calls will either:
index eba36315e3d6ad0102a9993386878d8a297a89d6..df4946c07848866daeb6a07b8c0c153c4c1b3842 100644 (file)
@@ -25,6 +25,7 @@
 #include "rect.h"
 #include "types.h"
 #include "content_subtitle.h"
+#include "decoder_part.h"
 #include <dcp/subtitle_string.h>
 
 namespace sub {
@@ -33,7 +34,7 @@ namespace sub {
 
 class Image;
 
-class SubtitleDecoder
+class SubtitleDecoder : public DecoderPart
 {
 public:
        /** Second parameter to the _during functions is true if we
@@ -63,7 +64,6 @@ public:
 
 private:
 
-       Decoder* _parent;
        std::list<ContentImageSubtitle> _decoded_image;
        std::list<ContentTextSubtitle> _decoded_text;
        boost::shared_ptr<const SubtitleContent> _content;
index 5f55451088e9b17472b70c0ff304c26c8eb1fd99..1576f50a19ddbe05c49ddb0c1681333ba377f40b 100644 (file)
@@ -68,7 +68,7 @@ TextSubtitleDecoder::pass (PassReason, bool)
 
        ContentTimePeriod const p = content_time_period (_subtitles[_next]);
        subtitle->give_text (p, _subtitles[_next]);
-       _subtitle_position = p.from;
+       subtitle->set_position (p.from);
 
        ++_next;
        return false;
index e3755e44f0b02881577b1eb83c3fe0819ee3b311..bb9004e109397f9342f3bf158900d420c95c53f5 100644 (file)
@@ -37,17 +37,13 @@ using boost::shared_ptr;
 using boost::optional;
 
 VideoDecoder::VideoDecoder (Decoder* parent, shared_ptr<const Content> c, shared_ptr<Log> log)
+       : DecoderPart (parent)
 #ifdef DCPOMATIC_DEBUG
-       : test_gaps (0)
-       , _parent (parent),
-         _content (c)
-#else
-        : _parent (parent)
-       , _content (c)
+       , test_gaps (0)
 #endif
+       , _content (c)
        , _log (log)
        , _last_seek_accurate (true)
-       , _ignore (false)
 {
        _black_image.reset (new Image (AV_PIX_FMT_RGB24, _content->video->size(), true));
        _black_image->make_black ();
@@ -99,7 +95,7 @@ VideoDecoder::get (Frame frame, bool accurate)
                        */
                        seek_frame *= 2;
                }
-               _parent->maybe_seek_video (ContentTime::from_frames (seek_frame, _content->active_video_frame_rate()), accurate);
+               maybe_seek (ContentTime::from_frames (seek_frame, _content->active_video_frame_rate()), accurate);
        }
 
        /* Work out the number of frames that we should return; we
@@ -274,7 +270,7 @@ VideoDecoder::fill_both_eyes (VideoFrame from, VideoFrame to)
 void
 VideoDecoder::give (shared_ptr<const ImageProxy> image, Frame frame)
 {
-       if (_ignore) {
+       if (ignore ()) {
                return;
        }
 
@@ -394,10 +390,3 @@ VideoDecoder::seek (ContentTime s, bool accurate)
        _last_seek_time = s;
        _last_seek_accurate = accurate;
 }
-
-/** Set this decoder never to produce any data */
-void
-VideoDecoder::set_ignore ()
-{
-       _ignore = true;
-}
index 69270244430d1a29fc4778026eab51fa57417580..2442d3173fcb77f66f0c0f955f178ba9b576be30 100644 (file)
@@ -29,6 +29,7 @@
 #include "video_content.h"
 #include "util.h"
 #include "content_video.h"
+#include "decoder_part.h"
 #include <boost/signals2.hpp>
 #include <boost/shared_ptr.hpp>
 
@@ -40,18 +41,13 @@ class Log;
 /** @class VideoDecoder
  *  @brief Parent for classes which decode video.
  */
-class VideoDecoder
+class VideoDecoder : public DecoderPart
 {
 public:
        VideoDecoder (Decoder* parent, boost::shared_ptr<const Content> c, boost::shared_ptr<Log> log);
 
        std::list<ContentVideo> get (Frame frame, bool accurate);
 
-       void set_ignore ();
-       bool ignore () const {
-               return _ignore;
-       }
-
 #ifdef DCPOMATIC_DEBUG
        int test_gaps;
 #endif
@@ -70,15 +66,12 @@ private:
        void fill_one_eye (Frame from, Frame to, Eyes);
        void fill_both_eyes (VideoFrame from, VideoFrame to);
 
-       Decoder* _parent;
        boost::shared_ptr<const Content> _content;
        boost::shared_ptr<Log> _log;
        std::list<ContentVideo> _decoded;
        boost::shared_ptr<Image> _black_image;
        boost::optional<ContentTime> _last_seek_time;
        bool _last_seek_accurate;
-       /** true if this decoder should ignore all video; i.e. never produce any */
-       bool _ignore;
        /** if set, this is a frame for which we got no data because the Decoder said
         *  it has no more to give.
         */
index 321728f58e0e8cd3c2ebfd7649a9e562a0f70069..90a58a16ef45907a803c4def9f1ff7ec57611b40 100644 (file)
@@ -89,7 +89,7 @@ VideoMXFDecoder::pass (PassReason, bool)
                        );
        }
 
-       _video_position = _next;
+       video->set_position (_next);
        _next += ContentTime::from_frames (1, vfr);
        return false;
 }
index 4d63b9be3464a3e9acc4ee890f57ebfc44ed66a9..14e14676ec0da8fdd7c55fb7439e7388f3ca5a34 100644 (file)
@@ -58,6 +58,7 @@ sources = """
           dcpomatic_time.cc
           decoder.cc
           decoder_factory.cc
+          decoder_part.cc
           digester.cc
           dolby_cp750.cc
           emailer.cc