summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-03-17 22:31:05 +0100
committerwm4 <wm4@nowhere>2015-03-17 22:31:05 +0100
commit775a02aab56c8ca01e497517dad8a7526fe0c3ce (patch)
tree04a89ac4009ec8a1b05b994d481742720942ed52
parent8fa036b3a003c24d51e6126f4f03292031e04e21 (diff)
downloadmpv-775a02aab56c8ca01e497517dad8a7526fe0c3ce.tar.bz2
mpv-775a02aab56c8ca01e497517dad8a7526fe0c3ce.tar.xz
af_lavfi: handle seeking
To handle seeking correctly, we need to flush the filter. libavfilter does not support flushing, so we destroy and recreate it. We also need to handle resume-after-EOF, because the mpv audio code sends an EOF before and after seeking (the latter happens because the player drains the filter chain in a generic way, which "causes" EOF).
-rw-r--r--audio/filter/af_lavfi.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/audio/filter/af_lavfi.c b/audio/filter/af_lavfi.c
index 902fe76e3a..249a560fb6 100644
--- a/audio/filter/af_lavfi.c
+++ b/audio/filter/af_lavfi.c
@@ -61,6 +61,8 @@ struct priv {
AVRational timebase_out;
+ bool eof;
+
// options
char *cfg_graph;
char **cfg_avopts;
@@ -71,6 +73,8 @@ static void destroy_graph(struct af_instance *af)
struct priv *p = af->priv;
avfilter_graph_free(&p->graph);
p->in = p->out = NULL;
+ p->samples_in = 0;
+ p->eof = false;
}
static bool recreate_graph(struct af_instance *af, struct mp_audio *config)
@@ -167,6 +171,12 @@ error:
return false;
}
+static void reset(struct af_instance *af)
+{
+ if (!recreate_graph(af, &af->fmt_in))
+ MP_FATAL(af, "Can't recreate libavfilter filter after a seek reset.\n");
+}
+
static int control(struct af_instance *af, int cmd, void *arg)
{
struct priv *p = af->priv;
@@ -203,6 +213,9 @@ static int control(struct af_instance *af, int cmd, void *arg)
return mp_audio_config_equals(in, &orig_in) ? AF_OK : AF_FALSE;
}
+ case AF_CONTROL_RESET:
+ reset(af);
+ return AF_OK;
}
return AF_UNKNOWN;
}
@@ -210,9 +223,16 @@ static int control(struct af_instance *af, int cmd, void *arg)
static int filter_frame(struct af_instance *af, struct mp_audio *data)
{
struct priv *p = af->priv;
+ AVFrame *frame = NULL;
+
+ if (p->eof && data)
+ reset(af);
+
+ if (!p->graph)
+ goto error;
+
AVFilterLink *l_in = p->in->outputs[0];
- AVFrame *frame = NULL;
if (data) {
frame = av_frame_alloc();
if (!frame)
@@ -255,6 +275,9 @@ static int filter_out(struct af_instance *af)
{
struct priv *p = af->priv;
+ if (!p->graph)
+ goto error;
+
AVFrame *frame = av_frame_alloc();
if (!frame)
goto error;
@@ -262,7 +285,10 @@ static int filter_out(struct af_instance *af)
int err = av_buffersink_get_frame(p->out, frame);
if (err == AVERROR(EAGAIN) || err == AVERROR_EOF) {
// Not an error situation - no more output buffers in queue.
+ // AVERROR_EOF means we shouldn't even give the filter more
+ // input, but we don't handle that completely correctly.
av_frame_free(&frame);
+ p->eof |= err == AVERROR_EOF;
return 0;
}