summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2019-11-10 22:59:39 +0100
committerCarl Hetherington <cth@carlh.net>2019-11-11 14:15:44 +0100
commit98342fb53eae4d32440fc69c279f2ca0fef785b5 (patch)
tree3af4c35766bd1434ac86b17b482f8a39c98537cd
parent0e8a1ab7c41756115f44229053e1e7024530fb32 (diff)
Don't trust video timestamps from FFmpegDecoder.v2.15.32
-rw-r--r--src/lib/video_decoder.cc44
-rw-r--r--src/lib/video_decoder.h2
2 files changed, 41 insertions, 5 deletions
diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc
index 7a3a3e19b..19a994197 100644
--- a/src/lib/video_decoder.cc
+++ b/src/lib/video_decoder.cc
@@ -54,12 +54,44 @@ VideoDecoder::VideoDecoder (Decoder* parent, shared_ptr<const Content> c)
* and so on.
*/
void
-VideoDecoder::emit (shared_ptr<const Film> film, shared_ptr<const ImageProxy> image, Frame frame)
+VideoDecoder::emit (shared_ptr<const Film> film, shared_ptr<const ImageProxy> image, Frame decoder_frame)
{
if (ignore ()) {
return;
}
+ double const afr = _content->active_video_frame_rate(film);
+
+ Frame frame;
+ if (!_position) {
+ /* This is the first data we have received since initialisation or seek. Set
+ the position based on the frame that was given. After this first time
+ we just cound frames, since (as with audio) it seems that ContentTimes
+ are unreliable from FFmpegDecoder. They are much better than audio times
+ but still we get the occasional one which is duplicated. In this case
+ ffmpeg seems to carry on regardless, processing the video frame as normal.
+ If we drop the frame with the duplicated timestamp we obviously lose sync.
+ */
+ _position = ContentTime::from_frames (decoder_frame, afr);
+ if (_content->video->frame_type() == VIDEO_FRAME_TYPE_3D_ALTERNATE) {
+ frame = decoder_frame / 2;
+ _last_emitted_eyes = EYES_RIGHT;
+ } else {
+ frame = decoder_frame;
+ }
+ } else {
+ if (_content->video->frame_type() == VIDEO_FRAME_TYPE_3D_ALTERNATE) {
+ DCPOMATIC_ASSERT (_last_emitted_eyes);
+ if (_last_emitted_eyes.get() == EYES_RIGHT) {
+ frame = _position->frames_round(afr) + 1;
+ } else {
+ frame = _position->frames_round(afr);
+ }
+ } else {
+ frame = _position->frames_round(afr) + 1;
+ }
+ }
+
switch (_content->video->frame_type ()) {
case VIDEO_FRAME_TYPE_2D:
Data (ContentVideo (image, frame, EYES_BOTH, PART_WHOLE));
@@ -91,9 +123,13 @@ VideoDecoder::emit (shared_ptr<const Film> film, shared_ptr<const ImageProxy> im
break;
}
case VIDEO_FRAME_TYPE_3D_ALTERNATE:
- Data (ContentVideo (image, frame / 2, (frame % 2) ? EYES_RIGHT : EYES_LEFT, PART_WHOLE));
- frame /= 2;
+ {
+ DCPOMATIC_ASSERT (_last_emitted_eyes);
+ Eyes const eyes = _last_emitted_eyes.get() == EYES_LEFT ? EYES_RIGHT : EYES_LEFT;
+ Data (ContentVideo (image, frame, eyes, PART_WHOLE));
+ _last_emitted_eyes = eyes;
break;
+ }
case VIDEO_FRAME_TYPE_3D_LEFT_RIGHT:
Data (ContentVideo (image, frame, EYES_LEFT, PART_LEFT_HALF));
Data (ContentVideo (image, frame, EYES_RIGHT, PART_RIGHT_HALF));
@@ -112,7 +148,7 @@ VideoDecoder::emit (shared_ptr<const Film> film, shared_ptr<const ImageProxy> im
DCPOMATIC_ASSERT (false);
}
- _position = ContentTime::from_frames (frame, _content->active_video_frame_rate(film));
+ _position = ContentTime::from_frames (frame, afr);
}
void
diff --git a/src/lib/video_decoder.h b/src/lib/video_decoder.h
index 34ce8f288..954b8f365 100644
--- a/src/lib/video_decoder.h
+++ b/src/lib/video_decoder.h
@@ -63,7 +63,7 @@ public:
private:
boost::shared_ptr<const Content> _content;
- /** Frame of last thing to be emitted */
+ /** Frame of last thing to be emitted; only used for 3D */
boost::optional<Frame> _last_emitted_frame;
boost::optional<Eyes> _last_emitted_eyes;
boost::optional<dcpomatic::ContentTime> _position;