player: don't calculate av delay if there's no audio or video

The point of the mpctx->delay field is for calculating a/v sync and
adjusting the frame timings appropriately. However, the frame_time was
always subtracted from mpctx->delay regardless of the audio status. This
meant that for a video with no audio, every single frame had a
subtraction with nothing ever added to it meaning that you get massive
negative delay times. For weird videos where the audio starts way later,
the massive delay leads to the VO sleeping for basically about as long
as the video was previously playing without audio. This results in
nothing being rendered during that brief period of time and just overall
badness. When using display-sync, it happens to work since the video
doesn't adjust itself based on audio and it renders anyway.

The fix is to simply not touch mpctx->delay in player/video.c unless
there's actually audio playing. This is what the rest of the code
already does aside from setting it to 0 on resets or EOFs. Move the
calculation into adjust_sync after the audio status check. It works
exactly the same as before except that we don't constantly subtract
bogus values when there's no audio playing. The reverse situation in
player/audio.c also has the same issue. For something that is only
audio, mpctx->delay is always added to but nothing will ever subtract
from it. It's not really clear if this particular version could ever
cause a real bug, but logically it needs to be guarded in the same way.
The field here should only be updated if the video is actually playing.

Fixes #12025.
This commit is contained in:
Dudemanguy 2023-10-23 22:57:53 -05:00
parent c62adc3018
commit dac977193c
2 changed files with 3 additions and 2 deletions

View File

@ -723,7 +723,8 @@ static void ao_process(struct mp_filter *f)
mpctx->shown_aframes += samples;
double real_samplerate = mp_aframe_get_rate(af) / mpctx->audio_speed;
mpctx->delay += samples / real_samplerate;
if (mpctx->video_status == STATUS_PLAYING)
mpctx->delay += samples / real_samplerate;
ao_c->last_out_pts = mp_aframe_end_pts(af);
update_throttle(mpctx);

View File

@ -352,6 +352,7 @@ static void adjust_sync(struct MPContext *mpctx, double v_pts, double frame_time
if (mpctx->audio_status != STATUS_PLAYING)
return;
mpctx->delay -= frame_time;
double a_pts = written_audio_pts(mpctx) + opts->audio_delay - mpctx->delay;
double av_delay = a_pts - v_pts;
@ -392,7 +393,6 @@ static void handle_new_frame(struct MPContext *mpctx)
frame_time = 0;
}
}
mpctx->delay -= frame_time;
mpctx->time_frame += frame_time / mpctx->video_speed;
if (mpctx->video_status >= STATUS_PLAYING)
adjust_sync(mpctx, pts, frame_time);