From 000c045aa873b07cc4ba869dcb82aa4756419637 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 4 Dec 2019 23:53:38 +0100 Subject: 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. --- video/out/vo.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/video/out/vo.c b/video/out/vo.c index 0effc41285..e5f8752f07 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -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; -- cgit v1.2.3