]> git.sesse.net Git - ffmpeg/commitdiff
ffmpeg: restructure sending EOF to filters
authorAnton Khirnov <anton@khirnov.net>
Mon, 27 Jun 2016 17:03:42 +0000 (19:03 +0200)
committerwm4 <nfxjfg@googlemail.com>
Fri, 3 Mar 2017 07:45:43 +0000 (08:45 +0100)
Be more careful when an input stream encounters EOF when its filtergraph
has not been configured yet. The current code would immediately mark the
corresponding output streams as finished, while there may still be
buffered frames waiting for frames to appear on other filtergraph
inputs.

This should fix the random FATE failures for complex filtergraph tests
after a3a0230a9870b9018dc7415ae5872784d524cfe5

This merges Libav commit 94ebf55. It was previously skipped.

This is the last filter init related Libav commit that was skipped, so
this also removes the commits from doc/libav-merge.txt.

Signed-off-by: wm4 <nfxjfg@googlemail.com>
doc/libav-merge.txt
ffmpeg.c
ffmpeg.h
ffmpeg_filter.c

index 23b48d1e2bb1ee62e7c2691936e6f511a4551df5..39d846f8fccbf0e2887f7f23cdadd9439e8a05f3 100644 (file)
@@ -95,7 +95,6 @@ Stuff that didn't reach the codebase:
   - 0cef06df0 checkasm: add HEVC MC tests
   - e7078e842 hevcdsp: add x86 SIMD for MC
 - QSV scaling filter (62c58c5)
-- ffmpeg.c filter init decoupling (3e265ca,a3a0230,d2e56cf,94ebf55)
 
 Collateral damage that needs work locally:
 ------------------------------------------
index f52d3e2f0ffdf8abc92409ee6ce9c43747b9ae32..275894dbf574838ae43f137a1ce7d7814f746877 100644 (file)
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -2197,6 +2197,34 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame)
     return 0;
 }
 
+static int ifilter_send_eof(InputFilter *ifilter)
+{
+    int i, j, ret;
+
+    ifilter->eof = 1;
+
+    if (ifilter->filter) {
+        ret = av_buffersrc_add_frame_flags(ifilter->filter, NULL, AV_BUFFERSRC_FLAG_PUSH);
+        if (ret < 0)
+            return ret;
+    } else {
+        // the filtergraph was never configured
+        FilterGraph *fg = ifilter->graph;
+        for (i = 0; i < fg->nb_inputs; i++)
+            if (!fg->inputs[i]->eof)
+                break;
+        if (i == fg->nb_inputs) {
+            // All the input streams have finished without the filtergraph
+            // ever being configured.
+            // Mark the output streams as finished.
+            for (j = 0; j < fg->nb_outputs; j++)
+                finish_output_stream(fg->outputs[j]->ost);
+        }
+    }
+
+    return 0;
+}
+
 // This does not quite work like avcodec_decode_audio4/avcodec_decode_video2.
 // There is the following difference: if you got a frame, you must call
 // it again with pkt=NULL. pkt==NULL is treated differently from pkt.size==0
@@ -2498,18 +2526,11 @@ out:
 
 static int send_filter_eof(InputStream *ist)
 {
-    int i, j, ret;
+    int i, ret;
     for (i = 0; i < ist->nb_filters; i++) {
-        if (ist->filters[i]->filter) {
-            ret = av_buffersrc_add_frame(ist->filters[i]->filter, NULL);
-            if (ret < 0)
-                return ret;
-        } else {
-            // the filtergraph was never configured
-            FilterGraph *fg = ist->filters[i]->graph;
-            for (j = 0; j < fg->nb_outputs; j++)
-                finish_output_stream(fg->outputs[j]->ost);
-        }
+        ret = ifilter_send_eof(ist->filters[i]);
+        if (ret < 0)
+            return ret;
     }
     return 0;
 }
index 56e35ebb9cf1c4ff32828824966eb8763ea1f987..5d20d453eb805c360479fd5a4aa5e16debfb4a3b 100644 (file)
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -248,6 +248,8 @@ typedef struct InputFilter {
     uint64_t channel_layout;
 
     AVBufferRef *hw_frames_ctx;
+
+    int eof;
 } InputFilter;
 
 typedef struct OutputFilter {
index 4d9a4e2eb814ff9a1d7f690a921117b153bd406b..816c906c7e71264b723db84a5da0b48f77655f1c 100644 (file)
@@ -1128,6 +1128,15 @@ int configure_filtergraph(FilterGraph *fg)
         }
     }
 
+    /* send the EOFs for the finished inputs */
+    for (i = 0; i < fg->nb_inputs; i++) {
+        if (fg->inputs[i]->eof) {
+            ret = av_buffersrc_add_frame(fg->inputs[i]->filter, NULL);
+            if (ret < 0)
+                return ret;
+        }
+    }
+
     return 0;
 }