mirror of https://github.com/mpv-player/mpv
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.
This commit is contained in:
parent
466658ee7e
commit
fc3f1e7c54
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue