* [FFmpeg-devel] [PATCH] fftools/ffmpeg_sched: prevent demuxers from getting stuck (PR #20631)
@ 2025-09-30 11:22 Niklas Haas via ffmpeg-devel
0 siblings, 0 replies; only message in thread
From: Niklas Haas via ffmpeg-devel @ 2025-09-30 11:22 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
PR #20631 opened by Niklas Haas (haasn)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20631
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20631.patch
When the furthest-behind stream is being fed by a demuxer that is also
feeding packets to a choked filter graph, we need to unchoke that filter
graph to prevent the demuxer from getting stuck trying to write packets to
the choked filter graph.
This situation can also apply recursively - if the demuxer is also writing
to a filtergraph that is also reading from a choked demuxer, there is a
similar deadlock.
Solve all such deadlocks by just brute-force recursively unchoking all
nodes that can somehow prevent this demuxer from writing packets. This
should normally not result in any change in behavior, unless audio/video
streams are badly desynchronized, in which case it may result in extra
memory usage from the too-far-ahead stream buffering packets inside the
muxer. (But this is, of course, preferable to a deadlock)
Fixes: https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/20611
>From aa593acdfdb1e9285619b944781fcf92b0652865 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Sat, 27 Sep 2025 20:02:07 +0200
Subject: [PATCH] fftools/ffmpeg_sched: prevent demuxers from getting stuck
When the furthest-behind stream is being fed by a demuxer that is also
feeding packets to a choked filter graph, we need to unchoke that filter
graph to prevent the demuxer from getting stuck trying to write packets to
the choked filter graph.
This situation can also apply recursively - if the demuxer is also writing
to a filtergraph that is also reading from a choked demuxer, there is a
similar deadlock.
Solve all such deadlocks by just brute-force recursively unchoking all
nodes that can somehow prevent this demuxer from writing packets. This
should normally not result in any change in behavior, unless audio/video
streams are badly desynchronized, in which case it may result in extra
memory usage from the too-far-ahead stream buffering packets inside the
muxer. (But this is, of course, preferable to a deadlock)
Fixes: https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/20611
---
fftools/ffmpeg_sched.c | 47 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 46 insertions(+), 1 deletion(-)
diff --git a/fftools/ffmpeg_sched.c b/fftools/ffmpeg_sched.c
index d08f4a061d..20daa0b3e2 100644
--- a/fftools/ffmpeg_sched.c
+++ b/fftools/ffmpeg_sched.c
@@ -1262,14 +1262,59 @@ int sch_mux_sub_heartbeat_add(Scheduler *sch, unsigned mux_idx, unsigned stream_
return 0;
}
+static void unchoke_for_stream(Scheduler *sch, SchedulerNode src);
+
+// Unchoke any filter graphs that are downstream of this node, to prevent it
+// from getting stuck trying to push data to a full queue
+static void unchoke_downstream(Scheduler *sch, SchedulerNode *dst)
+{
+ SchFilterGraph *fg;
+ SchDec *dec;
+ SchEnc *enc;
+ switch (dst->type) {
+ case SCH_NODE_TYPE_DEC:
+ dec = &sch->dec[dst->idx];
+ for (int i = 0; i < dec->nb_outputs; i++)
+ unchoke_downstream(sch, dec->outputs[i].dst);
+ break;
+ case SCH_NODE_TYPE_ENC:
+ enc = &sch->enc[dst->idx];
+ for (int i = 0; i < enc->nb_dst; i++)
+ unchoke_downstream(sch, &enc->dst[i]);
+ break;
+ case SCH_NODE_TYPE_MUX:
+ // muxers are never choked
+ break;
+ case SCH_NODE_TYPE_FILTER_IN:
+ fg = &sch->filters[dst->idx];
+ if (fg->best_input == fg->nb_inputs) {
+ fg->waiter.choked_next = 0;
+ } else {
+ // ensure that this filter graph is not stuck waiting for
+ // input from a different upstream demuxer
+ unchoke_for_stream(sch, fg->inputs[fg->best_input].src);
+ }
+ break;
+ default:
+ av_unreachable("Invalid destination node type?");
+ break;
+ }
+}
+
static void unchoke_for_stream(Scheduler *sch, SchedulerNode src)
{
while (1) {
SchFilterGraph *fg;
+ SchDemux *demux;
switch (src.type) {
case SCH_NODE_TYPE_DEMUX:
// fed directly by a demuxer (i.e. not through a filtergraph)
- sch->demux[src.idx].waiter.choked_next = 0;
+ demux = &sch->demux[src.idx];
+ if (demux->waiter.choked_next == 0)
+ return; // prevent infinite loop
+ demux->waiter.choked_next = 0;
+ for (int i = 0; i < demux->nb_streams; i++)
+ unchoke_downstream(sch, demux->streams[i].dst);
return;
case SCH_NODE_TYPE_DEC:
src = sch->dec[src.idx].src;
--
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-30 11:22 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-09-30 11:22 [FFmpeg-devel] [PATCH] fftools/ffmpeg_sched: prevent demuxers from getting stuck (PR #20631) 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