Skip to content

Commit

Permalink
player: reset av state on speed changes
Browse files Browse the repository at this point in the history
Playback speed changes should be treated as a discontinuity just like
seeking. Previously, this was being treated internally as just plain
normal playback, but that can't really work. The frame timings from
before the speed change and after the speed change are completely
different and shouldn't be compared to each other. This lead to frames
being adjusted to weird places and possibly even being skipped (as if
mpv was seeking) on speed changes. What we should do is clear out and
reset all av related fields like what happens when you seek, but it is
not quite as aggressive. No need to do a full video state reset or such.
We also wait an arbitrary amount of frames before adjusting for av sync
again. compute_audio_drift already used a magic number of 10 which
sounds reasonable enough so define that and use it here. Fixes #13513.
  • Loading branch information
Dudemanguy committed Feb 26, 2024
1 parent 7051e94 commit e3af545
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 2 deletions.
1 change: 1 addition & 0 deletions player/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -7228,6 +7228,7 @@ void mp_option_change_callback(void *ctx, struct m_config_option *co, int flags,

if (opt_ptr == &opts->playback_speed) {
update_playback_speed(mpctx);
reset_av_state(mpctx);
mp_wakeup_core(mpctx);
}

Expand Down
1 change: 1 addition & 0 deletions player/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,7 @@ void update_osd_msg(struct MPContext *mpctx);
bool update_subtitles(struct MPContext *mpctx, double video_pts);

// video.c
void reset_av_state(struct MPContext *mpctx);
void reset_video_state(struct MPContext *mpctx);
int init_video_decoder(struct MPContext *mpctx, struct track *track);
void reinit_video_chain(struct MPContext *mpctx);
Expand Down
22 changes: 20 additions & 2 deletions player/video.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
#include "command.h"
#include "screenshot.h"

#define MIN_PAST_FRAMES 10

enum {
// update_video() - code also uses: <0 error, 0 eof, >0 progress
VD_ERROR = -1,
Expand Down Expand Up @@ -95,6 +97,17 @@ static void vo_chain_reset_state(struct vo_chain *vo_c)
vo_c->underrun_signaled = false;
}

void reset_av_state(struct MPContext *mpctx)
{
mpctx->delay = 0;
mpctx->display_sync_drift_dir = 0;
mpctx->display_sync_error = 0;
mpctx->last_av_difference = 0;
mpctx->logged_async_diff = -1;
mpctx->num_past_frames = 0;
mpctx->total_avsync_change = 0;
}

void reset_video_state(struct MPContext *mpctx)
{
if (mpctx->vo_chain) {
Expand Down Expand Up @@ -592,7 +605,9 @@ static void update_avsync_before_frame(struct MPContext *mpctx)

if (mpctx->video_status < STATUS_READY) {
mpctx->time_frame = 0;
} else if (mpctx->display_sync_active || vo->opts->video_sync == VS_NONE) {
} else if (mpctx->display_sync_active || vo->opts->video_sync == VS_NONE ||
mpctx->num_past_frames <= MIN_PAST_FRAMES)
{
// don't touch the timing
} else if (mpctx->audio_status == STATUS_PLAYING &&
mpctx->video_status == STATUS_PLAYING &&
Expand Down Expand Up @@ -726,7 +741,7 @@ static double compute_audio_drift(struct MPContext *mpctx, double vsync)
// audio desync for y. Assume speed didn't change for the frames we're
// looking at for simplicity. This also should actually use the realtime
// (minus paused time) for x, but use vsync scheduling points instead.
if (mpctx->num_past_frames <= 10)
if (mpctx->num_past_frames <= MIN_PAST_FRAMES)
return NAN;
int num = mpctx->num_past_frames - 1;
double sum_x = 0, sum_y = 0, sum_xy = 0, sum_xx = 0;
Expand Down Expand Up @@ -831,6 +846,9 @@ static void handle_display_sync_frame(struct MPContext *mpctx,
if (resample && using_spdif_passthrough(mpctx))
return;

if (mpctx->num_past_frames <= MIN_PAST_FRAMES)
return;

double vsync = vo_get_vsync_interval(vo) / 1e9;
if (vsync <= 0)
return;
Expand Down

0 comments on commit e3af545

Please sign in to comment.