From fc3f1e7c54074fbbcaa501cb06fd43a36b0e2f15 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 28 Oct 2015 23:50:54 +0100 Subject: [PATCH] player: minor refactor for A/V diff computation Calculate the A/V difference directly in the display sync code, instead of the awkward current way, which reuses the fields for audio sync. We still set time_frame, because it makes falling back to audio sync somewhat smoother. --- player/video.c | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/player/video.c b/player/video.c index dfacbb7c3d..c9213deb2c 100644 --- a/player/video.c +++ b/player/video.c @@ -751,8 +751,8 @@ static void update_avsync_before_frame(struct MPContext *mpctx) } } -// Update the A/V sync difference after a video frame has been shown. -static void update_avsync_after_frame(struct MPContext *mpctx) +// Update the A/V sync difference when a new video frame is being shown. +static void update_av_diff(struct MPContext *mpctx, double offset) { struct MPOpts *opts = mpctx->opts; @@ -763,13 +763,12 @@ static void update_avsync_after_frame(struct MPContext *mpctx) return; double a_pos = playing_audio_pts(mpctx); + if (a_pos != MP_NOPTS_VALUE && mpctx->video_pts != MP_NOPTS_VALUE) { + mpctx->last_av_difference = a_pos - mpctx->video_pts + + opts->audio_delay + offset; + } - mpctx->last_av_difference = a_pos - mpctx->video_pts + opts->audio_delay; - if (mpctx->time_frame > 0) - mpctx->last_av_difference += mpctx->time_frame * mpctx->video_speed; - if (a_pos == MP_NOPTS_VALUE || mpctx->video_pts == MP_NOPTS_VALUE) { - mpctx->last_av_difference = 0; - } else if (fabs(mpctx->last_av_difference) > 0.5 && !mpctx->drop_message_shown) { + if (fabs(mpctx->last_av_difference) > 0.5 && !mpctx->drop_message_shown) { MP_WARN(mpctx, "%s", av_desync_help_text); mpctx->drop_message_shown = true; } @@ -1030,20 +1029,21 @@ static void handle_display_sync_frame(struct MPContext *mpctx, vo_increment_drop_count(vo, 1); // Estimate the video position, so we can calculate a good A/V difference - // value with update_avsync_after_frame() later. This is used to estimate - // A/V drift. - mpctx->time_frame = 0; + // value below. This is used to estimate A/V drift. double time_left = (vo_get_next_frame_start_time(vo) - mp_time_us()) / 1e6; - if (time_left >= 0) - mpctx->time_frame += time_left; + time_left = MPMAX(time_left, 0); // We also know that the timing is (necessarily) off, because we have to // align frame timings on the vsync boundaries. This is unavoidable, and // for the sake of the video sync calculations we pretend it's perfect. - mpctx->time_frame -= mpctx->display_sync_error; + time_left -= mpctx->display_sync_error; // Likewise, we know sync is off, but is going to be compensated. - mpctx->time_frame += drop_repeat * vsync; - mpctx->time_frame /= opts->playback_speed * video_speed_correction; + time_left += drop_repeat * vsync; + mpctx->total_avsync_change = 0; + update_av_diff(mpctx, time_left); + + // A bad guess, only needed when reverting to audio sync. + mpctx->time_frame = time_left; mpctx->speed_factor_v = video_speed_correction; @@ -1065,6 +1065,16 @@ done: MPMAX(0, mpctx->display_sync_disable_counter - 1); } +static void schedule_frame(struct MPContext *mpctx, struct vo_frame *frame) +{ + handle_display_sync_frame(mpctx, frame); + + if (!mpctx->display_sync_active) { + update_av_diff(mpctx, mpctx->time_frame > 0 ? + mpctx->time_frame * mpctx->video_speed : 0); + } +} + // Return the next frame duration as stored in the file. // frame=0 means the current frame, 1 the frame after that etc. // Can return -1, though usually will return a fallback if frame unavailable. @@ -1190,13 +1200,11 @@ void write_video(struct MPContext *mpctx, double endpts) frame->duration = MPCLAMP(diff, 0, 10) * 1e6; } - handle_display_sync_frame(mpctx, frame); - mpctx->video_pts = mpctx->next_frames[0]->pts; mpctx->last_vo_pts = mpctx->video_pts; mpctx->playback_pts = mpctx->video_pts; - update_avsync_after_frame(mpctx); + schedule_frame(mpctx, frame); mpctx->osd_force_update = true; update_osd_msg(mpctx);