X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fvideo_decoder.cc;fp=src%2Flib%2Fvideo_decoder.cc;h=19a99419753f402413652248a82e0df80a6905ee;hb=98342fb53eae4d32440fc69c279f2ca0fef785b5;hp=7a3a3e19b08b16220e1fd39c3deeefab47a575f4;hpb=0e8a1ab7c41756115f44229053e1e7024530fb32;p=dcpomatic.git 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 c) * and so on. */ void -VideoDecoder::emit (shared_ptr film, shared_ptr image, Frame frame) +VideoDecoder::emit (shared_ptr film, shared_ptr 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 film, shared_ptr 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 film, shared_ptr im DCPOMATIC_ASSERT (false); } - _position = ContentTime::from_frames (frame, _content->active_video_frame_rate(film)); + _position = ContentTime::from_frames (frame, afr); } void