summaryrefslogtreecommitdiffstats
path: root/audio/filter/af_lavrresample.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-11-11 19:27:42 +0100
committerwm4 <wm4@nowhere>2015-11-11 19:28:37 +0100
commit9774be0d15e9477db521466cb5f77f07a46cc7c2 (patch)
treeaeda92d268ef6e357284a5a074bd6d4cf1810551 /audio/filter/af_lavrresample.c
parentfee45c01703ace0d6af7b8fe60d151be245a0e3f (diff)
downloadmpv-9774be0d15e9477db521466cb5f77f07a46cc7c2.tar.bz2
mpv-9774be0d15e9477db521466cb5f77f07a46cc7c2.tar.xz
af_lavrresample: simplify set_compensation usage
Just set the ratio directly by working around the intended semantics of the API function. The silly rounding stuff we had isn't needed anymore (and not entirely correct anyway). Note that since the compensation is virtually active forever, we need to reset if it's not needed. So always run this code to be sure to reset it. Also note that libswresample itself had a precision issue, until it was fixed in FFmpeg commit 351e625d.
Diffstat (limited to 'audio/filter/af_lavrresample.c')
-rw-r--r--audio/filter/af_lavrresample.c25
1 files changed, 12 insertions, 13 deletions
diff --git a/audio/filter/af_lavrresample.c b/audio/filter/af_lavrresample.c
index 721bb30165..8f2efec858 100644
--- a/audio/filter/af_lavrresample.c
+++ b/audio/filter/af_lavrresample.c
@@ -91,8 +91,6 @@ 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
@@ -226,8 +224,6 @@ 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);
@@ -521,15 +517,18 @@ static int filter(struct af_instance *af, struct mp_audio *in)
int new_rate = rate_from_speed(s->in_rate_af, s->playback_speed);
bool need_reinit = fabs(new_rate / (double)s->in_rate - 1) > 0.01;
- 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;
- 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_i - in_samples) * s->out_rate / s->in_rate,
- wanted_samples_i * s->out_rate / s->in_rate) < 0)
+ if (s->avrctx) {
+ AVRational r = av_d2q(s->playback_speed * s->in_rate_af / s->in_rate,
+ INT_MAX / 2);
+ // Essentially, swr/avresample_set_compensation() does 2 things:
+ // - adjust output sample rate by sample_delta/compensation_distance
+ // - reset the adjustment after compensation_distance output samples
+ // Increase the compensation_distance to avoid undesired reset
+ // semantics - we want to keep the ratio for the whole frame we're
+ // feeding it, until the next filter() call.
+ int mult = INT_MAX / 2 / MPMAX(MPMAX(abs(r.num), abs(r.den)), 1);
+ r = (AVRational){ r.num * mult, r.den * mult };
+ if (avresample_set_compensation(s->avrctx, r.den - r.num, r.den) < 0)
need_reinit = true;
}