summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-01-02 18:12:51 +0100
committerwm4 <wm4@nowhere>2017-01-02 18:13:08 +0100
commit43386a7c92e14e56abdebfd4ed9335794c795f2b (patch)
treebc0a95618f81b79e4cc99055a2f6d9f64e8acf56
parent8e41f314f19d97849204ff4a7e9ca0fc4e9a8904 (diff)
downloadmpv-43386a7c92e14e56abdebfd4ed9335794c795f2b.tar.bz2
mpv-43386a7c92e14e56abdebfd4ed9335794c795f2b.tar.xz
af_lavfi, vf_lavfi: work around recent libavfilter EOF bug
Looks quite like a bug. If you have a filter chain with only the dynaudnorm filter, and send call av_buffersrc_add_frame(s, NULL), then subsequent av_buffersink_get_frame() calls will return EAGAIN instead of EOF. This was apparently caused by a recent change in FFmpeg. Some other circumstances (which I didn't fully analyze and which is due to the playloop's absurd temporary-EOF behavior on seeks) then led the decoder loop to send data again, but since libavfilter was stuck in the EOF state now, it could never recover. It kept sending new input (due to missing output), until the demuxer refused to return more audio packets. Each time a filter error was printed. Fortunately, it's pretty easy to workaround. We just mark the p->eof flag as we send an EOF frame to libavfilter. The p->eof flag is used only to recover from temporary EOF: it resets the filter if new data is available again. We don't care much about av_buffersink_get_frame() returning a broken EAGAIN state in this situation and essentially ignore it, meaning if we get EAGAIN after sending EOF, we assume effectively that EOF was fully reached.
-rw-r--r--audio/filter/af_lavfi.c6
-rw-r--r--video/filter/vf_lavfi.c6
2 files changed, 12 insertions, 0 deletions
diff --git a/audio/filter/af_lavfi.c b/audio/filter/af_lavfi.c
index bc4a687487..c072fdcb9a 100644
--- a/audio/filter/af_lavfi.c
+++ b/audio/filter/af_lavfi.c
@@ -266,6 +266,12 @@ static int filter_frame(struct af_instance *af, struct mp_audio *data)
if (!p->graph)
goto error;
+ if (!data) {
+ if (p->eof)
+ return 0;
+ p->eof = true;
+ }
+
if (data) {
frame = mp_audio_to_avframe_and_unref(data);
data = NULL;
diff --git a/video/filter/vf_lavfi.c b/video/filter/vf_lavfi.c
index a66bd2a971..6c18f829c4 100644
--- a/video/filter/vf_lavfi.c
+++ b/video/filter/vf_lavfi.c
@@ -298,6 +298,12 @@ static int filter_ext(struct vf_instance *vf, struct mp_image *mpi)
if (!p->graph)
return -1;
+ if (!mpi) {
+ if (p->eof)
+ return 0;
+ p->eof = true;
+ }
+
AVFrame *frame = mp_to_av(vf, mpi);
int r = av_buffersrc_add_frame(p->in, frame) < 0 ? -1 : 0;
av_frame_free(&frame);