diff --git a/player/command.c b/player/command.c index d5a315290e..f8fac69ef7 100644 --- a/player/command.c +++ b/player/command.c @@ -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); } diff --git a/player/core.h b/player/core.h index 2fc3c45700..9dc6b8bf90 100644 --- a/player/core.h +++ b/player/core.h @@ -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); diff --git a/player/video.c b/player/video.c index 70ef18958b..6b63cc7b0e 100644 --- a/player/video.c +++ b/player/video.c @@ -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, @@ -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) { @@ -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 && @@ -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; @@ -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;