summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-11-18 14:18:37 +0100
committerwm4 <wm4@nowhere>2013-11-18 14:21:01 +0100
commitd5bc4ee79864404423ddf2786d8e8089fc46eeca (patch)
treee884a45b31ef0700af7c9bf85af72a322f4ae77c
parent5594718b6bda3a230e2e2c3cb06d2837c5a02688 (diff)
downloadmpv-d5bc4ee79864404423ddf2786d8e8089fc46eeca.tar.bz2
mpv-d5bc4ee79864404423ddf2786d8e8089fc46eeca.tar.xz
audio: drop buffered filter data when seeking
This could lead to (barely) audible artifacts with --af=scaletempo and modified playback speed.
-rw-r--r--audio/filter/af.c7
-rw-r--r--audio/filter/af.h2
-rw-r--r--audio/filter/af_lavrresample.c11
-rw-r--r--audio/filter/af_scaletempo.c5
-rw-r--r--mpvcore/player/playloop.c2
5 files changed, 27 insertions, 0 deletions
diff --git a/audio/filter/af.c b/audio/filter/af.c
index 6f0241ec2b..2cc6389841 100644
--- a/audio/filter/af.c
+++ b/audio/filter/af.c
@@ -746,3 +746,10 @@ struct af_instance *af_control_any_rev(struct af_stream *s, int cmd, void *arg)
}
return NULL;
}
+
+/* Send control to all filters. Never stop, even if a filter returns AF_OK. */
+void af_control_all(struct af_stream *s, int cmd, void *arg)
+{
+ for (struct af_instance *af = s->first; af; af = af->next)
+ af->control(af, cmd, arg);
+}
diff --git a/audio/filter/af.h b/audio/filter/af.h
index 5c7450721e..7dee490665 100644
--- a/audio/filter/af.h
+++ b/audio/filter/af.h
@@ -99,6 +99,7 @@ struct af_stream {
// Parameters for af_control_*
enum af_control {
AF_CONTROL_REINIT = 1,
+ AF_CONTROL_RESET,
AF_CONTROL_COMMAND_LINE,
AF_CONTROL_SET_RESAMPLE_RATE,
AF_CONTROL_SET_FORMAT,
@@ -125,6 +126,7 @@ void af_uninit(struct af_stream *s);
struct af_instance *af_add(struct af_stream *s, char *name, char **args);
struct mp_audio *af_play(struct af_stream *s, struct mp_audio *data);
struct af_instance *af_control_any_rev(struct af_stream *s, int cmd, void *arg);
+void af_control_all(struct af_stream *s, int cmd, void *arg);
double af_calc_filter_multiplier(struct af_stream *s);
double af_calc_delay(struct af_stream *s);
diff --git a/audio/filter/af_lavrresample.c b/audio/filter/af_lavrresample.c
index f659511f82..95a5547ab5 100644
--- a/audio/filter/af_lavrresample.c
+++ b/audio/filter/af_lavrresample.c
@@ -93,11 +93,19 @@ static int get_delay(struct af_resample *s)
{
return avresample_get_delay(s->avrctx);
}
+static void drop_all_output(struct af_resample *s)
+{
+ while (avresample_read(s->avrctx, NULL, 1000) > 0) {}
+}
#else
static int get_delay(struct af_resample *s)
{
return swr_get_delay(s->avrctx, s->ctx.in_rate);
}
+static void drop_all_output(struct af_resample *s)
+{
+ while (swr_drop_output(s->avrctx, 1000) > 0) {}
+}
#endif
static double af_resample_default_cutoff(int filter_size)
@@ -273,6 +281,9 @@ static int control(struct af_instance *af, int cmd, void *arg)
case AF_CONTROL_SET_RESAMPLE_RATE:
out->rate = *(int *)arg;
return AF_OK;
+ case AF_CONTROL_RESET:
+ drop_all_output(s);
+ return AF_OK;
}
return AF_UNKNOWN;
}
diff --git a/audio/filter/af_scaletempo.c b/audio/filter/af_scaletempo.c
index 9ec7b6b89b..f7e58f0923 100644
--- a/audio/filter/af_scaletempo.c
+++ b/audio/filter/af_scaletempo.c
@@ -428,6 +428,11 @@ static int control(struct af_instance *af, int cmd, void *arg)
}
return AF_OK;
}
+ case AF_CONTROL_RESET:
+ s->bytes_queued = 0;
+ s->bytes_to_slide = 0;
+ s->frames_stride_error = 0;
+ memset(s->buf_overlap, 0, s->bytes_overlap);
}
return AF_UNKNOWN;
}
diff --git a/mpvcore/player/playloop.c b/mpvcore/player/playloop.c
index f7ca8d4598..d611880605 100644
--- a/mpvcore/player/playloop.c
+++ b/mpvcore/player/playloop.c
@@ -184,6 +184,8 @@ static void seek_reset(struct MPContext *mpctx, bool reset_ao)
if (mpctx->sh_audio) {
resync_audio_stream(mpctx->sh_audio);
+ if (mpctx->sh_audio->afilter)
+ af_control_all(mpctx->sh_audio->afilter, AF_CONTROL_RESET, NULL);
if (reset_ao)
clear_audio_output_buffers(mpctx);
clear_audio_decode_buffers(mpctx);