* [FFmpeg-devel] [PATCH] Fix for `apad` output getting stuck issue (PR #20600)
@ 2025-09-24 13:44 Niklas Haas via ffmpeg-devel
0 siblings, 0 replies; only message in thread
From: Niklas Haas via ffmpeg-devel @ 2025-09-24 13:44 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
PR #20600 opened by Niklas Haas (haasn)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20600
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20600.patch
>From b0cc8e1e7902a7fa8a46b295a8f88ef46407dd54 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 24 Sep 2025 15:14:29 +0200
Subject: [PATCH 1/3] 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 tranlate them all to AVERROR(EOF).
---
doc/APIchanges | 3 +++
libavfilter/buffersrc.c | 10 ++++++++++
libavfilter/buffersrc.h | 8 ++++++++
libavfilter/version.h | 2 +-
4 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/doc/APIchanges b/doc/APIchanges
index 9d629f766f..506049eb03 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2025-03-28
API changes, most recent first:
+2025-09-xx - xxxxxxxxxx - lavfi 11.10.100 - buffersrc.h
+ Add av_buffersrc_get_status().
+
2025-09-xx - xxxxxxxxxx - lavu 60.13.100 - hwcontext_d3d12va.h
Add resource_flags and heap_flags to AVD3D12VADeviceContext
Add heap_flags to AVD3D12VAFramesContext
diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c
index 30f4df83a1..b18d3f24dd 100644
--- a/libavfilter/buffersrc.c
+++ b/libavfilter/buffersrc.c
@@ -286,6 +286,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 54de1fd1f2..c7225b6752 100644
--- a/libavfilter/buffersrc.h
+++ b/libavfilter/buffersrc.h
@@ -216,6 +216,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 77f38cb9b4..4a69d6be98 100644
--- a/libavfilter/version.h
+++ b/libavfilter/version.h
@@ -31,7 +31,7 @@
#include "version_major.h"
-#define LIBAVFILTER_VERSION_MINOR 9
+#define LIBAVFILTER_VERSION_MINOR 10
#define LIBAVFILTER_VERSION_MICRO 100
--
2.49.1
>From 2db129d55e0b5fc28b7ea466f0b352b6533c26e0 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 24 Sep 2025 15:23:04 +0200
Subject: [PATCH 2/3] fftools/ffmpeg_filter: close all no-longer needed inputs
Currently, the thread loop of ffmpeg_filter works like this:
while (1) {
frame, idx = get_from_decoder();
ret = send_to_filter_graph(frame);
if (ret) {
close_input(idx);
continue;
}
while (filtered_frame = get_filtered_frame())
send_to_encoder(filtered_frame);
}
However, this leaves the possibility of leaving a no-longer-needed input
permanently open if the filter graph starts producing infinite frames 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. As a result,
information about the filtergraph being closed can now propagate back upstream,
where the scheduler will no longer try to send frames to that filter graph
input.
Fixes: https://trac.ffmpeg.org/ticket/11061
See-Also: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20457#issuecomment-6208
---
fftools/ffmpeg_filter.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 2dae6400c8..1624b3afa3 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -2452,6 +2452,16 @@ finish:
fps->dropped_keyframe |= fps->last_dropped && (frame->flags & AV_FRAME_FLAG_KEY);
}
+static void close_input(InputFilterPriv *ifp)
+{
+ FilterGraphPriv *fgp = fgp_from_fg(ifp->ifilter.graph);
+
+ if (!ifp->eof) {
+ sch_filter_receive_finish(fgp->sch, fgp->sch_idx, ifp->ifilter.index);
+ ifp->eof = 1;
+ }
+}
+
static int close_output(OutputFilterPriv *ofp, FilterGraphThread *fgt)
{
FilterGraphPriv *fgp = fgp_from_fg(ofp->ofilter.graph);
@@ -2725,6 +2735,13 @@ static int read_frames(FilterGraph *fg, FilterGraphThread *fgt,
fgt->next_in = fg->nb_inputs;
did_step = 1;
+
+ // ensure all inputs no longer accepting data are closed
+ for (int i = 0; i < fg->nb_inputs; i++) {
+ InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]);
+ if (av_buffersrc_get_status(ifp->ifilter.filter))
+ close_input(ifp);
+ }
}
return AVERROR_EOF;
@@ -3156,7 +3173,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(ifp);
continue;
}
if (ret < 0)
--
2.49.1
>From f940f769696ff5ab4134d33cbaab5163869b2b01 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 24 Sep 2025 15:40:59 +0200
Subject: [PATCH 3/3] tests/fate: add apad stuck regression test
Reproduces the issue solved in the previous commit.
---
tests/fate/filter-audio.mak | 3 ++
tests/ref/fate/filter-apad-stuck | 76 ++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+)
create mode 100644 tests/ref/fate/filter-apad-stuck
diff --git a/tests/fate/filter-audio.mak b/tests/fate/filter-audio.mak
index eee0209c59..06b9d36546 100644
--- a/tests/fate/filter-audio.mak
+++ b/tests/fate/filter-audio.mak
@@ -432,6 +432,9 @@ fate-filter-crazychannels: tests/data/filtergraphs/crazychannels
fate-filter-crazychannels: CMD = framecrc -auto_conversion_filters -/filter_complex $(TARGET_PATH)/tests/data/filtergraphs/crazychannels
FATE_AFILTER-$(call FILTERFRAMECRC, ARESAMPLE SINE JOIN ATRIM CHANNELMAP CHANNELSPLIT, FILE_PROTOCOL) += fate-filter-crazychannels
+fate-filter-apad-stuck: CMD = framecrc -f lavfi -i "testsrc=d=2[out0];sine=d=2[out1]" -af "atrim=end=0.1,apad=pad_dur=1"
+FATE_AFILTER-$(call FILTERFRAMECRC, TESTSRC SINE ATRIM APAD, PIPE_PROTOCOL) += fate-filter-apad-stuck
+
FATE_AFILTER-yes += fate-filter-formats
fate-filter-formats: libavfilter/tests/formats$(EXESUF)
fate-filter-formats: CMD = run libavfilter/tests/formats$(EXESUF)
diff --git a/tests/ref/fate/filter-apad-stuck b/tests/ref/fate/filter-apad-stuck
new file mode 100644
index 0000000000..86581800f6
--- /dev/null
+++ b/tests/ref/fate/filter-apad-stuck
@@ -0,0 +1,76 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 1/1
+#tb 1: 1/44100
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 44100
+#channel_layout_name 1: mono
+0, 0, 0, 1, 230400, 0x88c4d19a
+1, 0, 0, 1024, 2048, 0x2096f45b
+1, 1024, 1024, 1024, 2048, 0x2262f6ec
+0, 1, 1, 1, 230400, 0xc4740ad1
+1, 2048, 2048, 1024, 2048, 0xaa83fe05
+1, 3072, 3072, 1024, 2048, 0x487e06b5
+0, 2, 2, 1, 230400, 0xb6dd3deb
+1, 4096, 4096, 314, 628, 0x135c404b
+1, 4410, 4410, 4096, 8192, 0x00000000
+0, 3, 3, 1, 230400, 0x936e6bb1
+0, 4, 4, 1, 230400, 0x59759369
+1, 8506, 8506, 4096, 8192, 0x00000000
+0, 5, 5, 1, 230400, 0x0930b896
+0, 6, 6, 1, 230400, 0xc86bd3b6
+0, 7, 7, 1, 230400, 0x4cc2e982
+1, 12602, 12602, 4096, 8192, 0x00000000
+0, 8, 8, 1, 230400, 0x7b75f95f
+0, 9, 9, 1, 230400, 0x15c00454
+1, 16698, 16698, 4096, 8192, 0x00000000
+0, 10, 10, 1, 230400, 0x754f0815
+0, 11, 11, 1, 230400, 0x08d505a9
+1, 20794, 20794, 4096, 8192, 0x00000000
+0, 12, 12, 1, 230400, 0x2f24fdf9
+0, 13, 13, 1, 230400, 0x8ecfedfd
+0, 14, 14, 1, 230400, 0x1678da5f
+1, 24890, 24890, 4096, 8192, 0x00000000
+0, 15, 15, 1, 230400, 0x0916c018
+0, 16, 16, 1, 230400, 0x503fa09c
+1, 28986, 28986, 4096, 8192, 0x00000000
+0, 17, 17, 1, 230400, 0xe6f776b6
+0, 18, 18, 1, 230400, 0xf5d34ac1
+1, 33082, 33082, 4096, 8192, 0x00000000
+0, 19, 19, 1, 230400, 0xc6a918fc
+0, 20, 20, 1, 230400, 0x28d1e139
+0, 21, 21, 1, 230400, 0x6c02a0ae
+1, 37178, 37178, 4096, 8192, 0x00000000
+0, 22, 22, 1, 230400, 0xe83865b5
+0, 23, 23, 1, 230400, 0x85b62adb
+1, 41274, 41274, 4096, 8192, 0x00000000
+0, 24, 24, 1, 230400, 0xcc7def95
+0, 25, 25, 1, 230400, 0xddc9f26f
+1, 45370, 45370, 3140, 6280, 0x00000000
+0, 26, 26, 1, 230400, 0x6894b947
+0, 27, 27, 1, 230400, 0x4311862d
+0, 28, 28, 1, 230400, 0x38ba5867
+0, 29, 29, 1, 230400, 0x4b5830af
+0, 30, 30, 1, 230400, 0x76700b82
+0, 31, 31, 1, 230400, 0x9ba9f053
+0, 32, 32, 1, 230400, 0x01f2da87
+0, 33, 33, 1, 230400, 0xc2f6caaa
+0, 34, 34, 1, 230400, 0x1e31bfc4
+0, 35, 35, 1, 230400, 0xbad2bc03
+0, 36, 36, 1, 230400, 0x296abe6f
+0, 37, 37, 1, 230400, 0x0b19c610
+0, 38, 38, 1, 230400, 0xbaa1d60c
+0, 39, 39, 1, 230400, 0x475fe9aa
+0, 40, 40, 1, 230400, 0x6eab0400
+0, 41, 41, 1, 230400, 0x475b237c
+0, 42, 42, 1, 230400, 0xda1d4d62
+0, 43, 43, 1, 230400, 0xf7367957
+0, 44, 44, 1, 230400, 0x5891ab1c
+0, 45, 45, 1, 230400, 0x2dcfe2d0
+0, 46, 46, 1, 230400, 0x2b86236a
+0, 47, 47, 1, 230400, 0xea3a5e63
+0, 48, 48, 1, 230400, 0x8748993d
+0, 49, 49, 1, 230400, 0x7bb8d474
--
2.49.1
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2025-09-24 13:44 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-09-24 13:44 [FFmpeg-devel] [PATCH] Fix for `apad` output getting stuck issue (PR #20600) Niklas Haas via ffmpeg-devel
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror http://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ http://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git