The branch, release/7.1 has been updated
via 9e3030bc440e07887b787ae4a5bf407ff8548c75 (commit)
via a66541324862703c2442e7f4ca501e9016c26769 (commit)
from f46e514491172d15bd74b4abb1814cd2f05a763e (commit)
- Log -----------------------------------------------------------------
commit 9e3030bc440e07887b787ae4a5bf407ff8548c75
Author: Niklas Haas <[email protected]>
AuthorDate: Wed Sep 24 15:23:04 2025 +0200
Commit: Niklas Haas <[email protected]>
CommitDate: Thu Nov 27 13:27:54 2025 +0100
fftools/ffmpeg_filter: close all no-longer needed inputs
Currently, the thread loop of ffmpeg_filter essentially works like this:
while (1) {
frame, idx = get_from_decoder();
err = send_to_filter_graph(frame);
if (err) { // i.e. EOF
close_input(idx);
continue;
}
while (filtered_frame = get_filtered_frame())
send_to_encoder(filtered_frame);
}
The exact details are not 100% correct since the actual control flow is a
bit
more complicated as a result of the scheduler, but this is the general flow.
Notably, this leaves the possibility of leaving a no-longer-needed input
permanently open if the filter graph starts producing infinite frames
(during
the second loop) *after* it finishes reading from an input, e.g. in a filter
graph like -af atrim,apad.
This patch avoids this issue by always querying the status of all filter
graph
inputs and explicitly closing any that were closed downstream; after each
round
of reading output frames. As a result, information about the filtergraph
being
closed can now propagate back upstream, even if the filter is no longer
requesting any input frames (i.e. input_idx == fg->nb_inputs).
Fixes: https://trac.ffmpeg.org/ticket/11061
See-Also:
https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20457#issuecomment-6208
Backported-from: 38a5fcc02c2ef1bcb37d2e53eddde8eccc0c75ed
During backporting, I had to change the signature of `close_input()` to
`void close_input(FilterGraph *fg, int input_idx)` since this version of
FFmpeg does not contain a reference to the input index in the
InputFilterPriv.
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 3ef6818c72..4eec8fed7b 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -2365,6 +2365,18 @@ finish:
fps->dropped_keyframe |= fps->last_dropped && (frame->flags &
AV_FRAME_FLAG_KEY);
}
+static void close_input(FilterGraph *fg, int input_idx)
+{
+
+ InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[input_idx]);
+ FilterGraphPriv *fgp = fgp_from_fg(ifp->ifilter.graph);
+
+ if (!ifp->eof) {
+ sch_filter_receive_finish(fgp->sch, fgp->sch_idx, input_idx);
+ ifp->eof = 1;
+ }
+}
+
static int close_output(OutputFilterPriv *ofp, FilterGraphThread *fgt)
{
FilterGraphPriv *fgp = fgp_from_fg(ofp->ofilter.graph);
@@ -3035,7 +3047,7 @@ static int filter_thread(void *arg)
if (ret == AVERROR_EOF) {
av_log(fg, AV_LOG_VERBOSE, "Input %u no longer accepts new data\n",
input_idx);
- sch_filter_receive_finish(fgp->sch, fgp->sch_idx, input_idx);
+ close_input(fg, input_idx);
continue;
}
if (ret < 0)
@@ -3052,6 +3064,13 @@ read_frames:
av_err2str(ret));
goto finish;
}
+
+ // ensure all inputs no longer accepting data are closed
+ for (int i = 0; fgt.graph && i < fg->nb_inputs; i++) {
+ InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]);
+ if (av_buffersrc_get_status(ifp->filter))
+ close_input(fg, i);
+ }
}
for (unsigned i = 0; i < fg->nb_outputs; i++) {
commit a66541324862703c2442e7f4ca501e9016c26769
Author: Niklas Haas <[email protected]>
AuthorDate: Wed Sep 24 15:14:29 2025 +0200
Commit: Niklas Haas <[email protected]>
CommitDate: Thu Nov 27 13:21:42 2025 +0100
avfilter/buffersrc: add av_buffersrc_get_status()
There is currently no way for API users to know that a buffersrc is no
longer
accepting input, except by trying to feed it a frame and seeing what
happens.
Of course, this is not possible if the user does not *have* a frame to feed,
but may still wish to know if the filter is still accepting input or not.
Since passing `frame == NULL` to `av_buffersrc_add_frame()` is already
treated
as closing the input, we are left with no choice but to introduce a new
function for this.
We don't explicitly return the result of `ff_outlink_get_status()` to avoid
leaking internal status codes, and instead translate them all to
AVERROR(EOF).
Backported-from: 623669a02cd6cdc5598801bf31fd77199e61bae1
diff --git a/doc/APIchanges b/doc/APIchanges
index 924a2b279e..7795b6b2dd 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2024-03-07
API changes, most recent first:
+2025-09-xx - xxxxxxxxxx - lavfi 10.5.100 - buffersrc.h
+ Add av_buffersrc_get_status().
+
2024-09-23 - 6940a6de2f0 - lavu 59.38.100 - frame.h
Add AV_FRAME_DATA_VIEW_ID.
diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c
index ec5898fcf9..f9b2061948 100644
--- a/libavfilter/buffersrc.c
+++ b/libavfilter/buffersrc.c
@@ -283,6 +283,16 @@ int av_buffersrc_close(AVFilterContext *ctx, int64_t pts,
unsigned flags)
return (flags & AV_BUFFERSRC_FLAG_PUSH) ? push_frame(ctx->graph) : 0;
}
+int av_buffersrc_get_status(AVFilterContext *ctx)
+{
+ BufferSourceContext *s = ctx->priv;
+
+ if (!s->eof && ff_outlink_get_status(ctx->outputs[0]))
+ s->eof = 1;
+
+ return s->eof ? AVERROR(EOF) : 0;
+}
+
static av_cold int init_video(AVFilterContext *ctx)
{
BufferSourceContext *c = ctx->priv;
diff --git a/libavfilter/buffersrc.h b/libavfilter/buffersrc.h
index 6f3344f445..4bc8fba14e 100644
--- a/libavfilter/buffersrc.h
+++ b/libavfilter/buffersrc.h
@@ -208,6 +208,14 @@ int av_buffersrc_add_frame_flags(AVFilterContext
*buffer_src,
*/
int av_buffersrc_close(AVFilterContext *ctx, int64_t pts, unsigned flags);
+/**
+ * Returns 0 or a negative AVERROR code. Currently, this will only ever
+ * return AVERROR(EOF), to indicate that the buffer source has been closed,
+ * either as a result of av_buffersrc_close(), or because the downstream
+ * filter is no longer accepting new data.
+ */
+int av_buffersrc_get_status(AVFilterContext *ctx);
+
/**
* @}
*/
diff --git a/libavfilter/version.h b/libavfilter/version.h
index 4d8f28e512..523a7fe0a6 100644
--- a/libavfilter/version.h
+++ b/libavfilter/version.h
@@ -31,7 +31,7 @@
#include "version_major.h"
-#define LIBAVFILTER_VERSION_MINOR 4
+#define LIBAVFILTER_VERSION_MINOR 5
#define LIBAVFILTER_VERSION_MICRO 100
-----------------------------------------------------------------------
Summary of changes:
doc/APIchanges | 3 +++
fftools/ffmpeg_filter.c | 21 ++++++++++++++++++++-
libavfilter/buffersrc.c | 10 ++++++++++
libavfilter/buffersrc.h | 8 ++++++++
libavfilter/version.h | 2 +-
5 files changed, 42 insertions(+), 2 deletions(-)
hooks/post-receive
--
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]