+ DCPOMATIC_ASSERT (false);
+ }
+
+ /* Now VideoDecoder is required never to have gaps in the frames that it presents
+ via get_video(). Hence we need to fill in any gap between the last thing in _decoded_video
+ and the things we are about to push.
+ */
+
+ boost::optional<Frame> from;
+ boost::optional<Frame> to;
+
+ if (_decoded_video.empty() && _last_seek_time && _last_seek_accurate) {
+ from = _last_seek_time->frames (_video_content->video_frame_rate ());
+ to = to_push.front().frame;
+ } else if (!_decoded_video.empty ()) {
+ from = _decoded_video.back().frame + 1;
+ to = to_push.front().frame;
+ }
+
+ /* If we've pre-rolled on a seek we may now receive out-of-order frames
+ (frames before the last seek time) which we can just ignore.
+ */
+
+ if (from && to && from.get() > to.get()) {
+ return;
+ }
+
+ if (from) {
+ if (_video_content->video_frame_type() == VIDEO_FRAME_TYPE_2D) {
+ fill_2d (from.get(), to.get ());
+ } else {
+ fill_3d (from.get(), to.get(), to_push.front().eyes);
+ }