diff --git a/libavfilter/audio.c b/libavfilter/audio.c index 525b471065..e7306b134b 100644 --- a/libavfilter/audio.c +++ b/libavfilter/audio.c @@ -172,6 +172,11 @@ int ff_filter_samples_framed(AVFilterLink *link, AVFilterBufferRef *samplesref) FF_TPRINTF_START(NULL, filter_samples); ff_tlog_link(NULL, link, 1); + if (link->closed) { + avfilter_unref_buffer(samplesref); + return AVERROR_EOF; + } + if (!(filter_samples = dst->filter_samples)) filter_samples = default_filter_samples; diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index b1df5373b3..861a57d400 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -159,6 +159,11 @@ void avfilter_link_free(AVFilterLink **link) av_freep(link); } +void avfilter_link_set_closed(AVFilterLink *link, int closed) +{ + link->closed = closed; +} + int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, unsigned filt_srcpad_idx, unsigned filt_dstpad_idx) { @@ -325,6 +330,8 @@ int ff_request_frame(AVFilterLink *link) int ret = -1; FF_TPRINTF_START(NULL, request_frame); ff_tlog_link(NULL, link, 1); + if (link->closed) + return AVERROR_EOF; if (link->srcpad->request_frame) ret = link->srcpad->request_frame(link); else if (link->src->inputs[0]) @@ -335,6 +342,8 @@ int ff_request_frame(AVFilterLink *link) ff_filter_samples_framed(link, pbuf); return 0; } + if (ret == AVERROR_EOF) + link->closed = 1; return ret; } diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index 9891a72227..c0575ce1d1 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -697,6 +697,18 @@ struct AVFilterLink { * by the filters. */ AVFilterBufferRef *cur_buf_copy; + + /** + * True if the link is closed. + * If set, all attemps of start_frame, filter_samples or request_frame + * will fail with AVERROR_EOF, and if necessary the reference will be + * destroyed. + * If request_frame returns AVERROR_EOF, this flag is set on the + * corresponding link. + * It can be set also be set by either the source or the destination + * filter. + */ + int closed; }; /** @@ -716,6 +728,11 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad, */ void avfilter_link_free(AVFilterLink **link); +/** + * Set the closed field of a link. + */ +void avfilter_link_set_closed(AVFilterLink *link, int closed); + /** * Negotiate the media format, dimensions, etc of all inputs to a filter. * diff --git a/libavfilter/video.c b/libavfilter/video.c index 86332bcfe2..9ab8edb12c 100644 --- a/libavfilter/video.c +++ b/libavfilter/video.c @@ -248,6 +248,11 @@ int ff_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) FF_TPRINTF_START(NULL, start_frame); ff_tlog_link(NULL, link, 0); ff_tlog(NULL, " "); ff_tlog_ref(NULL, picref, 1); + if (link->closed) { + avfilter_unref_buffer(picref); + return AVERROR_EOF; + } + if (!(start_frame = dst->start_frame)) start_frame = default_start_frame;