X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;ds=inline;f=src%2Flib%2Fvideo_decoder.cc;h=64c66ea55caf8bc64adb863aac01966e314820d2;hb=b6c780d3107557d452c6612d715d01e2be52dbda;hp=43b1049ccaf5f89920147f040cf5e96635f66675;hpb=f0edd6ab35c3c2b7800a26ec8206adab75e5f633;p=dcpomatic.git diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc index 43b1049cc..64c66ea55 100644 --- a/src/lib/video_decoder.cc +++ b/src/lib/video_decoder.cc @@ -19,12 +19,14 @@ #include "video_decoder.h" #include "image.h" +#include "image_proxy.h" #include "content_video.h" #include "i18n.h" using std::cout; using std::list; +using std::max; using boost::shared_ptr; using boost::optional; @@ -35,6 +37,7 @@ VideoDecoder::VideoDecoder (shared_ptr c) #else : _video_content (c) #endif + , _same (false) { } @@ -61,8 +64,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 +77,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 +113,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 (); } @@ -118,8 +126,10 @@ VideoDecoder::get_video (VideoFrame frame, bool accurate) void 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 */ @@ -143,7 +153,7 @@ VideoDecoder::video (shared_ptr image, VideoFrame 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, PART_WHOLE, frame)); + _decoded_video.push_back (ContentVideo (image, _same ? EYES_RIGHT : EYES_LEFT, PART_WHOLE, frame)); break; case VIDEO_FRAME_TYPE_3D_LEFT_RIGHT: _decoded_video.push_back (ContentVideo (image, EYES_LEFT, PART_LEFT_HALF, frame));