wayland: adjust hidden state detection

The wayland backend needs to keep track of whether or not a window is
hidden for presentation time. There is no presentation feedback when a
window is hidden which means we shouldn't be sending information to the
vo_sync_info structure (i.e. just leave it all at -1). This seemed to
work fine, but recent changes to presentation time in one notable
compositor (Sway; it was probably always broken in Weston actually)
changed the presentation time behavior.

For reasons that aren't clear, there is a greater than 16.666ms delay
between the first presentation time event and the second presentation
time event (compositor latency?) when you switch back to an mpv window
after it is hidden for long enough (a few seconds). When using
presentation time, this causes mpv to feed in some bad values in its
vsync timing mechanism thus causing the A/V desync spike as described in
issue #7223.

This solution is not really ideal. It would be better if the
presentation time events received by the compositors did not have the
aforementioned inconsistency. However since this occurs in both Sway and
Weston and clients can't really fight compositors in wayland-world,
here's a reasonable enough workaround. Basically, just add a slight
delay before we start feeding information into the vo_sync_info again.
We already do this when the window is hidden, so it's not a huge leap.

The delay chosen here is arbitrary, and it basically just recycles the
same parameters used to detect if a window is hidden. If
vo_wayland_wait_frame times out 60 times in a row (or whatever your
monitor's refresh rate is), then we assume the window is hidden. This is
a pretty safe assumption; something has to be terribly wrong for you to
miss 60 vblanks in a row while a window is on the screen.

In this case, we basically just do the reverse of that. If mpv receives
60 frame callbacks in a row (or whatever your monitor's refresh rate
is), then it assumes the window is not hidden. Previously, as soon as it
received 1 frame callback it was declared not hidden. Essentially,
there's just 1 second of delay after reshowing a window before the
presentation time statistics are used again. This should be more than
enough time to skip over the weird inconsistent behavior presentation
time behavior and avoid the A/V desync spike.

Fixes #7223
This commit is contained in:
dudemanguy 2019-12-05 13:03:16 -06:00 committed by Dudemanguy
parent 59b0fec508
commit c68251a3a7
1 changed files with 14 additions and 4 deletions

View File

@ -1613,14 +1613,24 @@ void vo_wayland_wait_frame(struct vo_wayland_state *wl, int frame_offset)
}
if (wl->frame_wait) {
wl->timeout_count += 1;
if (!wl->hidden) {
wl->timeout_count += 1;
} else {
wl->timeout_count = 0;
}
} else {
wl->timeout_count = 0;
wl->hidden = false;
if (wl->hidden) {
wl->timeout_count -= 1;
} else {
wl->timeout_count = 0;
}
}
if (wl->timeout_count > wl->current_output->refresh_rate)
if (wl->timeout_count > wl->current_output->refresh_rate) {
wl->hidden = true;
} else if (wl->timeout_count < -1*wl->current_output->refresh_rate) {
wl->hidden = false;
}
}
void vo_wayland_wait_events(struct vo *vo, int64_t until_time_us)