summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2016-06-27 19:03:42 +0200
committerAnton Khirnov <anton@khirnov.net>2016-06-28 08:30:20 +0200
commit94ebf5565849e4dc036d2ca43979571ed3736457 (patch)
treec05b2f708304279e023b135042816ea9165da36c
parentd2e56cf753a6c462041dee897d9d0c90f349988c (diff)
avconv: restructure sending EOF to filters
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
-rw-r--r--avconv.c43
-rw-r--r--avconv.h2
-rw-r--r--avconv_filter.c9
3 files changed, 43 insertions, 11 deletions
diff --git a/avconv.c b/avconv.c
index 778de654cb..a05894f915 100644
--- a/avconv.c
+++ b/avconv.c
@@ -1242,6 +1242,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(ifilter->filter, NULL);
+ 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
@@ -1415,18 +1443,11 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
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;
}
diff --git a/avconv.h b/avconv.h
index 5d365a00ee..cffe11473f 100644
--- a/avconv.h
+++ b/avconv.h
@@ -212,6 +212,8 @@ typedef struct InputFilter {
uint64_t channel_layout;
AVBufferRef *hw_frames_ctx;
+
+ int eof;
} InputFilter;
typedef struct OutputFilter {
diff --git a/avconv_filter.c b/avconv_filter.c
index 1acbd88166..96277f80eb 100644
--- a/avconv_filter.c
+++ b/avconv_filter.c
@@ -780,6 +780,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;
}