video: always decode 2 frames on playback restart

Unless --video-latency-hacks, always decode 2 frames on playback
restart. This in turn will always compute the correct frame duration
(even for the first frame), which in turn happens to fix that playback
with an image at the beginning breaks display.

If a still image precedes video, and the size/format of the frame is
different from that of the video following it, the incorrect frame
duration caused vo_reconfig2() to be called early, causing the window to
resize, and the renderer to clear the image to black. Specifically, it
hit the default value of 1 second duration (for still images), so the
image was displayed for 1 second, and changed to black until the next
proper video frame was displayed.

Normally this does not happen. Even if a video file displays still
images, it normally repeats the still image at the video's FPS (which is
sane). But you can construct such files, or use EDL to construct
something similarly behaving.

This change may increase seek latency a bit in audio video-sync mode
(the default). It needs to wait until 2 frames are decoded, before it
bothers to display the first frame. This is done even when seeking. In
theory it might be good to introduce a "seek preview" mode, which shows
the target image without all the preparations needed for starting
playback. (For example, it could not decode audio.) But since I'm using
video-sync=display-resample, which already needed to always decode 2
frames, I don't think this is a terribly high priority, nor do I
consider the slightly slower seeking a regression.

Fixes: #6765
This commit is contained in:
wm4 2019-10-06 22:20:10 +02:00
parent 9bc38bd18d
commit 4ad68d9452
1 changed files with 2 additions and 2 deletions

View File

@ -417,12 +417,12 @@ static int get_req_frames(struct MPContext *mpctx, bool eof)
if (mpctx->opts->untimed || mpctx->video_out->driver->untimed)
return 1;
// Normally require at least 2 frames, so we can compute a frame duration.
int min = mpctx->opts->video_latency_hacks ? 1 : 2;
// On the first frame, output a new frame as quickly as possible.
// But display-sync likes to have a correct frame duration always.
if (mpctx->video_pts == MP_NOPTS_VALUE)
return mpctx->opts->video_sync == VS_DEFAULT ? 1 : min;
return min;
int req = vo_get_num_req_frames(mpctx->video_out);
return MPCLAMP(req, min, MP_ARRAY_SIZE(mpctx->next_frames) - 1);