From: Carl Hetherington Date: Sat, 19 Nov 2016 00:31:37 +0000 (+0000) Subject: Cope with offsets between video/audio/subtitle data in a muxed file. X-Git-Tag: v2.10.3-test~33 X-Git-Url: https://git.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=24e890682b3f2aa211277ad8b6b3591f2026d4be Cope with offsets between video/audio/subtitle data in a muxed file. --- diff --git a/src/lib/audio_decoder_stream.cc b/src/lib/audio_decoder_stream.cc index c14dc654e..7e8e304ef 100644 --- a/src/lib/audio_decoder_stream.cc +++ b/src/lib/audio_decoder_stream.cc @@ -86,7 +86,7 @@ AudioDecoderStream::get (Frame frame, Frame length, bool accurate) } if (missing) { - _decoder->maybe_seek (ContentTime::from_frames (*missing, _content->resampled_frame_rate()), accurate); + _decoder->maybe_seek_audio (ContentTime::from_frames (*missing, _content->resampled_frame_rate()), accurate); } /* Offset of the data that we want from the start of _decoded.audio diff --git a/src/lib/dcp_decoder.cc b/src/lib/dcp_decoder.cc index 38c2a7ccf..4f17bdb3b 100644 --- a/src/lib/dcp_decoder.cc +++ b/src/lib/dcp_decoder.cc @@ -163,7 +163,7 @@ DCPDecoder::pass (PassReason reason, bool) } } - _position = _next; + _video_position = _audio_position = _subtitle_position = _next; _next += ContentTime::from_frames (1, vfr); if ((*_reel)->main_picture ()) { diff --git a/src/lib/dcp_subtitle_decoder.cc b/src/lib/dcp_subtitle_decoder.cc index d4e1a7fa2..c67133012 100644 --- a/src/lib/dcp_subtitle_decoder.cc +++ b/src/lib/dcp_subtitle_decoder.cc @@ -79,7 +79,7 @@ DCPSubtitleDecoder::pass (PassReason, bool) } subtitle->give_text (p, s); - _position = p.from; + _subtitle_position = p.from; return false; } diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc index cba674d04..50356da78 100644 --- a/src/lib/decoder.cc +++ b/src/lib/decoder.cc @@ -19,20 +19,42 @@ */ #include "decoder.h" +#include + +using std::cout; +using boost::optional; void -Decoder::maybe_seek (ContentTime time, bool accurate) +Decoder::maybe_seek (optional& position, ContentTime time, bool accurate) { - if (!_position) { + if (!position) { /* A seek has just happened */ return; } - if (time >= *_position && time < (*_position + ContentTime::from_seconds(1))) { + if (time >= *position && time < (*position + ContentTime::from_seconds(1))) { /* No need to seek: caller should just pass() */ return; } - _position.reset (); + 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); +} diff --git a/src/lib/decoder.h b/src/lib/decoder.h index 84661ee8c..d2302d7a2 100644 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@ -52,7 +52,9 @@ public: PASS_REASON_SUBTITLE }; - void maybe_seek (ContentTime time, bool accurate); + 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; @@ -63,7 +65,9 @@ public: virtual void reset () {} protected: - boost::optional _position; + boost::optional _video_position; + boost::optional _audio_position; + boost::optional _subtitle_position; private: /** Seek so that the next pass() will yield the next thing @@ -75,6 +79,7 @@ private: * it may seek to just the right spot. */ virtual void seek (ContentTime time, bool accurate) = 0; + void maybe_seek (boost::optional& position, ContentTime time, bool accurate); }; #endif diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 253272e96..8f196542a 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -425,7 +425,7 @@ FFmpegDecoder::decode_audio_packet () LOG_WARNING ("Crazy timestamp %s", to_string (ct)); } - update_position (ct); + update_position (_audio_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 (new RawImageProxy (image)), llrint (pts * _ffmpeg_content->active_video_frame_rate ()) ); - update_position (ContentTime::from_seconds (pts)); + update_position (_video_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 (period.from); + update_position (_subtitle_position, period.from); if (sub_period.to) { /* We already know the subtitle period `to' time */ period.to = sub_period.to.get() + _pts_offset; @@ -646,14 +646,14 @@ FFmpegDecoder::decode_ass_subtitle (string ass, ContentTimePeriod period) } void -FFmpegDecoder::update_position (ContentTime p) +FFmpegDecoder::update_position (optional& current, ContentTime p) { - /* _position should err on the side of being too big, as then there is less - chance that we will erroneously decide not to seek when _position > request. + /* 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 (!_position) { - _position = p; + if (!current) { + current = p; } else { - _position = max (*_position, p); + current = max (*current, p); } } diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index dfe1f2694..d6f50cd43 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -52,7 +52,7 @@ private: bool pass (PassReason, bool accurate); void seek (ContentTime time, bool); void flush (); - void update_position (ContentTime p); + void update_position (boost::optional& current, ContentTime p); AVSampleFormat audio_sample_format (boost::shared_ptr stream) const; int bytes_per_audio_sample (boost::shared_ptr stream) const; diff --git a/src/lib/image_decoder.cc b/src/lib/image_decoder.cc index 41a4949ba..7270c9782 100644 --- a/src/lib/image_decoder.cc +++ b/src/lib/image_decoder.cc @@ -39,7 +39,7 @@ using dcp::Size; ImageDecoder::ImageDecoder (shared_ptr c, shared_ptr log) : _image_content (c) - , _video_position (0) + , _frame_video_position (0) { video.reset (new VideoDecoder (this, c, log)); } @@ -47,13 +47,13 @@ ImageDecoder::ImageDecoder (shared_ptr c, shared_ptr lo bool ImageDecoder::pass (PassReason, bool) { - if (_video_position >= _image_content->video->length()) { + if (_frame_video_position >= _image_content->video->length()) { return true; } if (!_image_content->still() || !_image) { /* Either we need an image or we are using moving images, so load one */ - boost::filesystem::path path = _image_content->path (_image_content->still() ? 0 : _video_position); + boost::filesystem::path path = _image_content->path (_image_content->still() ? 0 : _frame_video_position); if (valid_j2k_file (path)) { AVPixelFormat pf; if (_image_content->video->colour_conversion()) { @@ -72,9 +72,9 @@ ImageDecoder::pass (PassReason, bool) } } - _position = ContentTime::from_frames (_video_position, _image_content->active_video_frame_rate ()); - video->give (_image, _video_position); - ++_video_position; + _video_position = ContentTime::from_frames (_frame_video_position, _image_content->active_video_frame_rate ()); + video->give (_image, _frame_video_position); + ++_frame_video_position; return false; } @@ -82,5 +82,5 @@ void ImageDecoder::seek (ContentTime time, bool accurate) { video->seek (time, accurate); - _video_position = time.frames_round (_image_content->active_video_frame_rate ()); + _frame_video_position = time.frames_round (_image_content->active_video_frame_rate ()); } diff --git a/src/lib/image_decoder.h b/src/lib/image_decoder.h index 9b8cf73bb..d023636bf 100644 --- a/src/lib/image_decoder.h +++ b/src/lib/image_decoder.h @@ -39,5 +39,5 @@ private: boost::shared_ptr _image_content; boost::shared_ptr _image; - Frame _video_position; + Frame _frame_video_position; }; diff --git a/src/lib/subtitle_decoder.cc b/src/lib/subtitle_decoder.cc index 4be5c96b3..020a0383c 100644 --- a/src/lib/subtitle_decoder.cc +++ b/src/lib/subtitle_decoder.cc @@ -104,7 +104,7 @@ SubtitleDecoder::get (list const & subs, list 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 (*missing, true); + _parent->maybe_seek_subtitle (*missing, true); } /* Now enough pass() calls will either: diff --git a/src/lib/text_subtitle_decoder.cc b/src/lib/text_subtitle_decoder.cc index e29bf5809..5f5545108 100644 --- a/src/lib/text_subtitle_decoder.cc +++ b/src/lib/text_subtitle_decoder.cc @@ -68,7 +68,7 @@ TextSubtitleDecoder::pass (PassReason, bool) ContentTimePeriod const p = content_time_period (_subtitles[_next]); subtitle->give_text (p, _subtitles[_next]); - _position = p.from; + _subtitle_position = p.from; ++_next; return false; diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc index f240640d0..e3755e44f 100644 --- a/src/lib/video_decoder.cc +++ b/src/lib/video_decoder.cc @@ -99,7 +99,7 @@ VideoDecoder::get (Frame frame, bool accurate) */ seek_frame *= 2; } - _parent->maybe_seek (ContentTime::from_frames (seek_frame, _content->active_video_frame_rate()), accurate); + _parent->maybe_seek_video (ContentTime::from_frames (seek_frame, _content->active_video_frame_rate()), accurate); } /* Work out the number of frames that we should return; we diff --git a/src/lib/video_mxf_decoder.cc b/src/lib/video_mxf_decoder.cc index 84aec869a..321728f58 100644 --- a/src/lib/video_mxf_decoder.cc +++ b/src/lib/video_mxf_decoder.cc @@ -89,7 +89,7 @@ VideoMXFDecoder::pass (PassReason, bool) ); } - _position = _next; + _video_position = _next; _next += ContentTime::from_frames (1, vfr); return false; }