summaryrefslogtreecommitdiffstats
path: root/player/video.c
diff options
context:
space:
mode:
Diffstat (limited to 'player/video.c')
-rw-r--r--player/video.c86
1 files changed, 48 insertions, 38 deletions
diff --git a/player/video.c b/player/video.c
index 281789e2a4..65982d319e 100644
--- a/player/video.c
+++ b/player/video.c
@@ -854,44 +854,47 @@ static bool using_spdif_passthrough(struct MPContext *mpctx)
return false;
}
-static void adjust_audio_speed(struct MPContext *mpctx, double vsync)
+static void adjust_audio_resample_speed(struct MPContext *mpctx, double vsync)
{
struct MPOpts *opts = mpctx->opts;
int mode = opts->video_sync;
- double audio_factor = 1.0;
-
- if (mode == VS_DISP_RESAMPLE && mpctx->audio_status == STATUS_PLAYING) {
- // Try to smooth out audio timing drifts. This can happen if either
- // video isn't playing at expected speed, or audio is not playing at
- // the requested speed. Both are unavoidable.
- // The audio desync is made up of 2 parts: 1. drift due to rounding
- // errors and imperfect information, and 2. an offset, due to
- // unaligned audio/video start, or disruptive events halting audio
- // or video for a small time.
- // Instead of trying to be clever, just apply an awfully dumb drift
- // compensation with a constant factor, which does what we want. In
- // theory we could calculate the exact drift compensation needed,
- // but it likely would be wrong anyway, and we'd run into the same
- // issues again, except with more complex code.
- // 1 means drifts to positive, -1 means drifts to negative
- double max_drift = vsync / 2;
- double av_diff = mpctx->last_av_difference;
- int new = mpctx->display_sync_drift_dir;
- if (av_diff * -mpctx->display_sync_drift_dir >= 0)
- new = 0;
- if (fabs(av_diff) > max_drift)
- new = av_diff >= 0 ? 1 : -1;
- if (mpctx->display_sync_drift_dir != new) {
- MP_VERBOSE(mpctx, "Change display sync audio drift: %d\n", new);
- mpctx->display_sync_drift_dir = new;
- }
- double max_correct = opts->sync_max_audio_change / 100;
- audio_factor = 1 + max_correct * -mpctx->display_sync_drift_dir;
+
+ if (mode != VS_DISP_RESAMPLE || mpctx->audio_status != STATUS_PLAYING) {
+ mpctx->speed_factor_a = mpctx->speed_factor_v;
+ return;
}
- mpctx->speed_factor_a = audio_factor * mpctx->speed_factor_v;
+ // Try to smooth out audio timing drifts. This can happen if either
+ // video isn't playing at expected speed, or audio is not playing at
+ // the requested speed. Both are unavoidable.
+ // The audio desync is made up of 2 parts: 1. drift due to rounding
+ // errors and imperfect information, and 2. an offset, due to
+ // unaligned audio/video start, or disruptive events halting audio
+ // or video for a small time.
+ // Instead of trying to be clever, just apply an awfully dumb drift
+ // compensation with a constant factor, which does what we want. In
+ // theory we could calculate the exact drift compensation needed,
+ // but it likely would be wrong anyway, and we'd run into the same
+ // issues again, except with more complex code.
+ // 1 means drifts to positive, -1 means drifts to negative
+ double max_drift = vsync / 2;
+ double av_diff = mpctx->last_av_difference;
+ int new = mpctx->display_sync_drift_dir;
+ if (av_diff * -mpctx->display_sync_drift_dir >= 0)
+ new = 0;
+ if (fabs(av_diff) > max_drift)
+ new = av_diff >= 0 ? 1 : -1;
+
+ bool change = mpctx->display_sync_drift_dir != new;
+ if (new || change) {
+ if (change)
+ MP_VERBOSE(mpctx, "Change display sync audio drift: %d\n", new);
+ mpctx->display_sync_drift_dir = new;
- MP_STATS(mpctx, "value %f aspeed", mpctx->speed_factor_a - 1);
+ double max_correct = opts->sync_max_audio_change / 100;
+ double audio_factor = 1 + max_correct * -mpctx->display_sync_drift_dir;
+ mpctx->speed_factor_a = audio_factor * mpctx->speed_factor_v;
+ }
}
// Manipulate frame timing for display sync, or do nothing for normal timing.
@@ -908,8 +911,6 @@ static void handle_display_sync_frame(struct MPContext *mpctx,
}
mpctx->display_sync_active = false;
- mpctx->speed_factor_a = 1.0;
- mpctx->speed_factor_v = 1.0;
if (!VS_IS_DISP(mode))
goto done;
@@ -1002,8 +1003,11 @@ static void handle_display_sync_frame(struct MPContext *mpctx,
mpctx->past_frames[0].num_vsyncs = num_vsyncs;
- if (resample)
- adjust_audio_speed(mpctx, vsync);
+ if (resample) {
+ adjust_audio_resample_speed(mpctx, vsync);
+ } else {
+ mpctx->speed_factor_a = 1.0;
+ }
// A bad guess, only needed when reverting to audio sync.
mpctx->time_frame = time_left;
@@ -1012,10 +1016,12 @@ static void handle_display_sync_frame(struct MPContext *mpctx,
frame->display_synced = true;
mpctx->display_sync_active = true;
+ update_playback_speed(mpctx);
-done:
+ MP_STATS(mpctx, "value %f aspeed", mpctx->speed_factor_a - 1);
+ MP_STATS(mpctx, "value %f vspeed", mpctx->speed_factor_v - 1);
- update_playback_speed(mpctx);
+done:
if (mpctx->num_past_frames > 1 &&
((mpctx->past_frames[1].num_vsyncs >= 0) != mpctx->display_sync_active))
@@ -1030,6 +1036,10 @@ static void schedule_frame(struct MPContext *mpctx, struct vo_frame *frame)
handle_display_sync_frame(mpctx, frame);
if (!mpctx->display_sync_active) {
+ mpctx->speed_factor_a = 1.0;
+ mpctx->speed_factor_v = 1.0;
+ update_playback_speed(mpctx);
+
update_av_diff(mpctx, mpctx->time_frame > 0 ?
mpctx->time_frame * mpctx->video_speed : 0);
}