summaryrefslogtreecommitdiffstats
path: root/audio/filter
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-10-14 18:51:12 +0200
committerwm4 <wm4@nowhere>2015-10-14 18:51:12 +0200
commite0f8d797720ed00a731d8fb8d41995501609c34b (patch)
treed17fc2a31a3ddcec7518caa12739c0b11c1c136e /audio/filter
parentda496ae2fe5575b94eda64f03f23a03075d83477 (diff)
downloadmpv-e0f8d797720ed00a731d8fb8d41995501609c34b.tar.bz2
mpv-e0f8d797720ed00a731d8fb8d41995501609c34b.tar.xz
af_lavrresample: fix unintended audio drift when setting playback speed
Small adjustments to the playback speed use swr_set_compensation() to stretch the audio as it is required. But since large adjustments are now handled by actually reinitializing libswresample, the small adjustments get rounded off completely with typical frame sizes. Compensate for this by accounting for the rounding error and keeping track of fractional samples that should have been output to achieve the correct ratio. This fixes display sync mode behavior, which requires these adjustments to be relatively accurate.
Diffstat (limited to 'audio/filter')
-rw-r--r--audio/filter/af_lavrresample.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/audio/filter/af_lavrresample.c b/audio/filter/af_lavrresample.c
index b73f0d8d0e..11af645910 100644
--- a/audio/filter/af_lavrresample.c
+++ b/audio/filter/af_lavrresample.c
@@ -91,6 +91,8 @@ struct af_resample {
int out_rate;
int out_format;
struct mp_chmap out_channels;
+
+ double missing_samples; // fractional samples not yet output
};
#if HAVE_LIBAVRESAMPLE
@@ -224,6 +226,8 @@ static int configure_lavrr(struct af_instance *af, struct mp_audio *in,
s->out_channels= out->channels;
s->in_channels = in->channels;
+ s->missing_samples = 0;
+
av_opt_set_int(s->avrctx, "filter_size", s->opts.filter_size, 0);
av_opt_set_int(s->avrctx, "phase_shift", s->opts.phase_shift, 0);
av_opt_set_int(s->avrctx, "linear_interp", s->opts.linear, 0);
@@ -519,10 +523,12 @@ static int filter(struct af_instance *af, struct mp_audio *in)
if (!need_reinit && s->avrctx) {
double speed_factor = s->playback_speed * s->in_rate_af / s->in_rate;
int in_samples = in ? in->samples : 0;
- int wanted_samples = lrint(in_samples / speed_factor);
+ double wanted_samples = in_samples / speed_factor + s->missing_samples;
+ int wanted_samples_i = lrint(wanted_samples);
+ s->missing_samples = wanted_samples - wanted_samples_i;
if (avresample_set_compensation(s->avrctx,
- (wanted_samples - in_samples) * s->out_rate / s->in_rate,
- wanted_samples * s->out_rate / s->in_rate) < 0)
+ (wanted_samples_i - in_samples) * s->out_rate / s->in_rate,
+ wanted_samples_i * s->out_rate / s->in_rate) < 0)
need_reinit = true;
}