1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-23 23:32:26 +00:00

vo: redraw dropped frame if paused between queuing and drawing frame

When frame-stepping with display-sync mode enabled in high framerate
video, the frame was sometimes not redrawn correctly. Only the first OSD
interaction (or something similar) made it visible.

In this case, the core schedules many frames as dropped (because it's
ignorant of pausing/frame-stepping, as in theory the player is _not_
paused during frame-stepping, only at the end of it). There's a race
between the VO rendering the queued frame, and the core calling
vo_set_paused() after it has queued the frame. If the latter happens
first, the existing logic to redraw the previous dropped frame does
things correctly. If the former happens, the frame is not redrawn
automatically, but will be redrawn on the next user input (or if OSD is
enabled, and the pause state change updates it, which leads to an
immediate redraw).

Fix this by never actually dropping a frame in paused mode. The request
by the core to drop it is simply ignored.

Maybe this could be done slightly nicer by updating the pause state with
the VO atomically. Then we wouldn't have the frame drop counter going up
either (it's actually dropped, but then redrawn; but I doubt any user,
or me in a few weeks, would understand this). But I'm not really
interested in polishing this by increasing the complexity of the
frame-step code.
This commit is contained in:
wm4 2019-12-04 23:53:38 +01:00
parent c23b3ac53a
commit 000c045aa8

View File

@ -883,6 +883,9 @@ static bool render_frame(struct vo *vo)
if (in->current_frame->num_vsyncs > 0)
in->current_frame->num_vsyncs -= 1;
// Always render when paused (it's typically the last frame for a while).
in->dropped_frame &= !in->paused;
bool use_vsync = in->current_frame->display_synced && !in->paused;
if (use_vsync && !in->expecting_vsync) // first DS frame in a row
in->prev_vsync = now;