From 9774be0d15e9477db521466cb5f77f07a46cc7c2 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 11 Nov 2015 19:27:42 +0100 Subject: 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. --- audio/filter/af_lavrresample.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'audio/filter/af_lavrresample.c') 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; } -- cgit v1.2.3