summaryrefslogtreecommitdiffstats
path: root/audio/filter
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-10-07 21:43:05 +0200
committerwm4 <wm4@nowhere>2015-10-07 21:54:45 +0200
commit280251656c4da593d45cc3676facccc7129a8189 (patch)
tree3d0d3d62b0333435855929028ce96ba7d7befea6 /audio/filter
parentaa796c23db097c835aeaa711ab3b2ba1eb8721a8 (diff)
downloadmpv-280251656c4da593d45cc3676facccc7129a8189.tar.bz2
mpv-280251656c4da593d45cc3676facccc7129a8189.tar.xz
af_lavrresample: use libswsresample dynamic rate adjustment feature
swr_set_compensation() changes the apparent sample rate on the fly (who would have guessed). It is thus very well-suited for adjusting audio speed on the fly during playback (like needed by the display-sync mode). It skips the relatively slow resampler reinitialization. If this doesn't work (libswresample soxr backend), then fall back to the old method.
Diffstat (limited to 'audio/filter')
-rw-r--r--audio/filter/af_lavrresample.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/audio/filter/af_lavrresample.c b/audio/filter/af_lavrresample.c
index d651c10f4c..b21b4d84c1 100644
--- a/audio/filter/af_lavrresample.c
+++ b/audio/filter/af_lavrresample.c
@@ -49,6 +49,7 @@
#define avresample_convert(ctx, out, out_planesize, out_samples, in, in_planesize, in_samples) \
swr_convert(ctx, out, out_samples, (const uint8_t**)(in), in_samples)
#define avresample_set_channel_mapping swr_set_channel_mapping
+#define avresample_set_compensation swr_set_compensation
#else
#error "config.h broken or no resampler found"
#endif
@@ -386,14 +387,6 @@ static int control(struct af_instance *af, int cmd, void *arg)
return AF_OK;
case AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE: {
s->playback_speed = *(double *)arg;
- int new_rate = rate_from_speed(s->in_rate_af, s->playback_speed);
- if (new_rate != s->in_rate && s->avrctx && af->fmt_out.format) {
- // Before reconfiguring, drain the audio that is still buffered
- // in the resampler.
- af->filter_frame(af, NULL);
- // Reinitialize resampler.
- configure_lavrr(af, &af->fmt_in, &af->fmt_out, false);
- }
return AF_OK;
}
case AF_CONTROL_RESET:
@@ -455,7 +448,7 @@ static void reorder_planes(struct mp_audio *mpa, int *reorder,
}
}
-static int filter(struct af_instance *af, struct mp_audio *in)
+static int filter_resample(struct af_instance *af, struct mp_audio *in)
{
struct af_resample *s = af->priv;
@@ -516,6 +509,30 @@ error:
return -1;
}
+static int filter(struct af_instance *af, struct mp_audio *in)
+{
+ struct af_resample *s = af->priv;
+
+ int in_samples = in ? in->samples : 0;
+ int wanted_samples = lrint(in_samples / s->playback_speed);
+
+ 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)
+ {
+ int new_rate = rate_from_speed(s->in_rate_af, s->playback_speed);
+ if (new_rate != s->in_rate && s->avrctx && af->fmt_out.format) {
+ // Before reconfiguring, drain the audio that is still buffered
+ // in the resampler.
+ filter_resample(af, NULL);
+ // Reinitialize resampler.
+ configure_lavrr(af, &af->fmt_in, &af->fmt_out, false);
+ }
+ }
+
+ return filter_resample(af, in);
+}
+
static int af_open(struct af_instance *af)
{
struct af_resample *s = af->priv;