From 814dacdd7d010407a4bea74b3a047079f49c5c39 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 16 Aug 2016 00:03:02 +0200 Subject: af_lavrresample: work around libswresample misbehavior The touched code is for seek resets and such - we simply want to reset the entire resample state. But I noticed after a seek a tiny bit of audio is missing (mpv's audio sync code inserted silence to compensate). It turns out swr_drop_output() either does not reset some internal state as we expect, or it's designed to drop not only buffered samples, but also future samples. On the other hand, libavresample's avresample_read(), does not have this problem. (It is also pretty explicit in what it does - return/skip buffered data, nothing else.) Is the libswresample behavior a bug? Or a feature? Does nobody even know? Who cares - use the hammer to unfuck the situation. Destroy and deallocate the libswresample context and recreate it. On every seek. --- audio/filter/af_lavrresample.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/audio/filter/af_lavrresample.c b/audio/filter/af_lavrresample.c index fdef69a16b..99c080478d 100644 --- a/audio/filter/af_lavrresample.c +++ b/audio/filter/af_lavrresample.c @@ -99,10 +99,6 @@ static double get_delay(struct af_resample *s) return avresample_get_delay(s->avrctx) / (double)s->in_rate + avresample_available(s->avrctx) / (double)s->out_rate; } -static void drop_all_output(struct af_resample *s) -{ - while (avresample_read(s->avrctx, NULL, 1000) > 0) {} -} static int get_out_samples(struct af_resample *s, int in_samples) { return avresample_get_out_samples(s->avrctx, in_samples); @@ -113,10 +109,6 @@ static double get_delay(struct af_resample *s) int64_t base = s->in_rate * (int64_t)s->out_rate; return swr_get_delay(s->avrctx, base) / (double)base; } -static void drop_all_output(struct af_resample *s) -{ - while (swr_drop_output(s->avrctx, 1000) > 0) {} -} static int get_out_samples(struct af_resample *s, int in_samples) { #if LIBSWRESAMPLE_VERSION_MAJOR > 1 || LIBSWRESAMPLE_VERSION_MINOR >= 2 @@ -406,8 +398,16 @@ static int control(struct af_instance *af, int cmd, void *arg) return AF_OK; } case AF_CONTROL_RESET: - if (s->avrctx) - drop_all_output(s); + if (s->avrctx) { +#if HAVE_LIBSWRESAMPLE + // This POS either can't drop state correctly, or doesn't want to. + // It will swallow some minor audio e.g. after a seek. + // Deallocate and recreate the resample state for a full reset. + configure_lavrr(af, &af->fmt_in, &af->fmt_out, false); +#else + while (avresample_read(s->avrctx, NULL, 1000) > 0) {} +#endif + } return AF_OK; } return AF_UNKNOWN; -- cgit v1.2.3