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]

Reply via email to