X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fvideo_decoder.cc;h=5dd078553659b21d3c09bcf8a030ea77e73ad783;hb=2cf3da72a017eebf741dfb9a5ec158df94a4e7b7;hp=1b6da8a91133a387b62813054cfd8bb2baf506eb;hpb=2f61270d2726445f562efc0e4b33fa19ba235183;p=dcpomatic.git diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc index 1b6da8a91..5dd078553 100644 --- a/src/lib/video_decoder.cc +++ b/src/lib/video_decoder.cc @@ -35,6 +35,7 @@ VideoDecoder::VideoDecoder (shared_ptr c) #else : _video_content (c) #endif + , _same (false) { } @@ -61,8 +62,12 @@ VideoDecoder::decoded_video (VideoFrame frame) list VideoDecoder::get_video (VideoFrame frame, bool accurate) { - if (_decoded_video.empty() || (frame < _decoded_video.front().frame || frame > (_decoded_video.back().frame + 1))) { - /* Either we have no decoded data, or what we do have is a long way from what we want: seek */ + /* At this stage, if we have get_video()ed before, _decoded_video will contain the last frame that this + method returned (and possibly a few more). If the requested frame is not in _decoded_video and it is not the next + one after the end of _decoded_video we need to seek. + */ + + if (_decoded_video.empty() || frame < _decoded_video.front().frame || frame > (_decoded_video.back().frame + 1)) { seek (ContentTime::from_frames (frame, _video_content->video_frame_rate()), accurate); } @@ -70,7 +75,8 @@ VideoDecoder::get_video (VideoFrame frame, bool accurate) /* Now enough pass() calls should either: * (a) give us what we want, or - * (b) hit the end of the decoder. + * (b) give us something after what we want, indicating that we will never get what we want, or + * (c) hit the end of the decoder. */ if (accurate) { /* We are being accurate, so we want the right frame. @@ -105,8 +111,8 @@ VideoDecoder::get_video (VideoFrame frame, bool accurate) } } - /* Clean up decoded_video */ - while (!_decoded_video.empty() && _decoded_video.front().frame < (frame - 1)) { + /* Clean up _decoded_video; keep the frame we are returning, but nothing before that */ + while (!_decoded_video.empty() && _decoded_video.front().frame < dec.front().frame) { _decoded_video.pop_front (); } @@ -116,10 +122,12 @@ VideoDecoder::get_video (VideoFrame frame, bool accurate) /** Called by subclasses when they have a video frame ready */ void -VideoDecoder::video (shared_ptr image, VideoFrame frame) +VideoDecoder::video (shared_ptr image, VideoFrame frame) { - /* We should not receive the same thing twice */ - assert (_decoded_video.empty() || frame != _decoded_video.back().frame); + /* We may receive the same frame index twice for 3D, and we need to know + when that happens. + */ + _same = (!_decoded_video.empty() && frame == _decoded_video.back().frame); /* Fill in gaps */ /* XXX: 3D */ @@ -132,6 +140,7 @@ VideoDecoder::video (shared_ptr image, VideoFrame frame) ContentVideo ( _decoded_video.back().image, _decoded_video.back().eyes, + _decoded_video.back().part, _decoded_video.back().frame + 1 ) ); @@ -139,30 +148,24 @@ VideoDecoder::video (shared_ptr image, VideoFrame frame) switch (_video_content->video_frame_type ()) { case VIDEO_FRAME_TYPE_2D: - _decoded_video.push_back (ContentVideo (image, EYES_BOTH, frame)); + _decoded_video.push_back (ContentVideo (image, EYES_BOTH, PART_WHOLE, frame)); break; case VIDEO_FRAME_TYPE_3D_ALTERNATE: - _decoded_video.push_back (ContentVideo (image, (frame % 2) ? EYES_RIGHT : EYES_LEFT, frame)); + _decoded_video.push_back (ContentVideo (image, _same ? EYES_RIGHT : EYES_LEFT, PART_WHOLE, frame)); break; case VIDEO_FRAME_TYPE_3D_LEFT_RIGHT: - { - int const half = image->size().width / 2; - _decoded_video.push_back (ContentVideo (image->crop (Crop (0, half, 0, 0), true), EYES_LEFT, frame)); - _decoded_video.push_back (ContentVideo (image->crop (Crop (half, 0, 0, 0), true), EYES_RIGHT, frame)); + _decoded_video.push_back (ContentVideo (image, EYES_LEFT, PART_LEFT_HALF, frame)); + _decoded_video.push_back (ContentVideo (image, EYES_RIGHT, PART_RIGHT_HALF, frame)); break; - } case VIDEO_FRAME_TYPE_3D_TOP_BOTTOM: - { - int const half = image->size().height / 2; - _decoded_video.push_back (ContentVideo (image->crop (Crop (0, 0, 0, half), true), EYES_LEFT, frame)); - _decoded_video.push_back (ContentVideo (image->crop (Crop (0, 0, half, 0), true), EYES_RIGHT, frame)); + _decoded_video.push_back (ContentVideo (image, EYES_LEFT, PART_TOP_HALF, frame)); + _decoded_video.push_back (ContentVideo (image, EYES_RIGHT, PART_BOTTOM_HALF, frame)); break; - } case VIDEO_FRAME_TYPE_3D_LEFT: - _decoded_video.push_back (ContentVideo (image, EYES_LEFT, frame)); + _decoded_video.push_back (ContentVideo (image, EYES_LEFT, PART_WHOLE, frame)); break; case VIDEO_FRAME_TYPE_3D_RIGHT: - _decoded_video.push_back (ContentVideo (image, EYES_RIGHT, frame)); + _decoded_video.push_back (ContentVideo (image, EYES_RIGHT, PART_WHOLE, frame)); break; default: assert (false);