Basics of DCP import.
[dcpomatic.git] / src / lib / video_decoder.cc
index 43b1049ccaf5f89920147f040cf5e96635f66675..5dd078553659b21d3c09bcf8a030ea77e73ad783 100644 (file)
@@ -35,6 +35,7 @@ VideoDecoder::VideoDecoder (shared_ptr<const VideoContent> c)
 #else
        : _video_content (c)
 #endif
+       , _same (false)
 {
 
 }
@@ -61,8 +62,12 @@ VideoDecoder::decoded_video (VideoFrame frame)
 list<ContentVideo>
 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 ();
        }
 
@@ -118,8 +124,10 @@ VideoDecoder::get_video (VideoFrame frame, bool accurate)
 void
 VideoDecoder::video (shared_ptr<const ImageProxy> 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 +151,7 @@ VideoDecoder::video (shared_ptr<const ImageProxy> 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));