[PR] Revert "fftools/ffmpeg_sched: allow throttling decoder outputs" (PR #24194)

mkver via ffmpeg-devel <[email protected]>
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <[email protected]>
PR #24194 opened by mkver
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24194
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24194.patch

This reverts commit 03dfac563018e6e8b81e331ebae0732d8edfe754.
Said commit led to numerous regressions, namely:
a) It can lead to wrong output interleavement (issue #23731
and (presumably) #24162).
b) It can lead to streams stopping prematurely (issue #24008
and (presumably) #23988 and #24135).
c) It can lead to extreme memory usage even when the input files
are fine, especially mkvmerge files (see issue #24168).

(cherry picked from commit 43284b61a39a7d35633ebbc637db50ff4e97c57e)



>From 92e1f4211ee16bcab7bad2581b2d29342f24eeb9 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <[email protected]>
Date: Mon, 17 Aug 2026 00:15:36 +0200
Subject: [PATCH] Revert "fftools/ffmpeg_sched: allow throttling decoder
 outputs"

This reverts commit 03dfac563018e6e8b81e331ebae0732d8edfe754.
Said commit led to numerous regressions, namely:
a) It can lead to wrong output interleavement (issue #23731
and (presumably) #24162).
b) It can lead to streams stopping prematurely (issue #24008
and (presumably) #23988 and #24135).
c) It can lead to extreme memory usage even when the input files
are fine, especially mkvmerge files (see issue #24168).

Reviewed-by: Niklas Haas <[email protected]>
Signed-off-by: Andreas Rheinhardt <[email protected]>
(cherry picked from commit 43284b61a39a7d35633ebbc637db50ff4e97c57e)
---
 fftools/ffmpeg_sched.c | 70 +++++-------------------------------------
 1 file changed, 7 insertions(+), 63 deletions(-)

diff --git a/fftools/ffmpeg_sched.c b/fftools/ffmpeg_sched.c
index 8ec3bdaf80..dddd1d2c67 100644
--- a/fftools/ffmpeg_sched.c
+++ b/fftools/ffmpeg_sched.c
@@ -32,7 +32,6 @@
 #include "libavcodec/packet.h"
 
 #include "libavutil/avassert.h"
-#include "libavutil/container_fifo.h"
 #include "libavutil/error.h"
 #include "libavutil/fifo.h"
 #include "libavutil/frame.h"
@@ -87,7 +86,6 @@ typedef struct SchDec {
     unsigned         nb_outputs;
 
     SchTask             task;
-    SchWaiter           waiter;
     // Queue for receiving input packets, one stream.
     ThreadQueue        *queue;
 
@@ -97,9 +95,6 @@ typedef struct SchDec {
 
     // temporary storage used by sch_dec_send()
     AVFrame            *send_frame;
-
-    // internal queue of undecoded packets used by sch_dec_receive()
-    AVContainerFifo    *overflow;
 } SchDec;
 
 typedef struct SchSyncQueue {
@@ -553,7 +548,6 @@ void sch_free(Scheduler **psch)
         tq_free(&dec->queue);
 
         av_thread_message_queue_free(&dec->queue_end_ts);
-        av_container_fifo_free(&dec->overflow);
 
         for (unsigned j = 0; j < dec->nb_outputs; j++) {
             SchDecOutput *o = &dec->outputs[j];
@@ -565,8 +559,6 @@ void sch_free(Scheduler **psch)
         av_freep(&dec->outputs);
 
         av_frame_free(&dec->send_frame);
-
-        waiter_uninit(&dec->waiter);
     }
     av_freep(&sch->dec);
 
@@ -817,14 +809,6 @@ int sch_add_dec(Scheduler *sch, SchThreadFunc func, void *ctx, int send_end_ts)
             return ret;
     }
 
-    dec->overflow = av_container_fifo_alloc_avpacket(0);
-    if (!dec->overflow)
-        return AVERROR(ENOMEM);
-
-    ret = waiter_init(&dec->waiter);
-    if (ret < 0)
-        return ret;
-
     return idx;
 }
 
@@ -1321,9 +1305,8 @@ int sch_mux_sub_heartbeat_add(Scheduler *sch, unsigned mux_idx, unsigned stream_
 enum {
     UNCHOKE_DEMUX  = (1 << 0),
     UNCHOKE_FILTER = (1 << 1),
-    UNCHOKE_DECODE = (1 << 2),
 
-    UNCHOKE_ALL = UNCHOKE_DEMUX | UNCHOKE_FILTER | UNCHOKE_DECODE,
+    UNCHOKE_ALL = UNCHOKE_DEMUX | UNCHOKE_FILTER,
 };
 
 static void unchoke_for_stream(Scheduler *sch, SchedulerNode src, int flags);
@@ -1338,10 +1321,8 @@ static void unchoke_downstream(Scheduler *sch, SchedulerNode *dst)
     switch (dst->type) {
     case SCH_NODE_TYPE_DEC:
         dec = &sch->dec[dst->idx];
-        if (!dec->waiter.choked_next) {
-            for (int i = 0; i < dec->nb_outputs; i++)
-                unchoke_downstream(sch, dec->outputs[i].dst);
-        }
+        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];
@@ -1372,7 +1353,6 @@ static void unchoke_for_stream(Scheduler *sch, SchedulerNode src, int flags)
     while (1) {
         SchFilterGraph *fg;
         SchDemux *demux;
-        SchDec *dec;
         switch (src.type) {
         case SCH_NODE_TYPE_DEMUX:
             // fed directly by a demuxer (i.e. not through a filtergraph)
@@ -1386,11 +1366,7 @@ static void unchoke_for_stream(Scheduler *sch, SchedulerNode src, int flags)
             }
             return;
         case SCH_NODE_TYPE_DEC:
-            dec = &sch->dec[src.idx];
-            if (!(flags & UNCHOKE_DECODE))
-                return;
-            dec->waiter.choked_next = 0;
-            src = dec->src;
+            src = sch->dec[src.idx].src;
             continue;
         case SCH_NODE_TYPE_ENC:
             src = sch->enc[src.idx].src;
@@ -1469,7 +1445,6 @@ static void schedule_update_locked(Scheduler *sch)
 
     RESET_WAITER(demux);
     RESET_WAITER(filters);
-    RESET_WAITER(dec);
 
     // figure out the sources that are allowed to proceed
     for (unsigned i = 0; i < sch->nb_mux; i++) {
@@ -1480,11 +1455,8 @@ static void schedule_update_locked(Scheduler *sch)
 
             // unblock sources for output streams that are not finished
             // and not too far ahead of the trailing stream
-            if (ms->source_finished) {
-                // still allow decoders to drain
-                unchoke_for_stream(sch, ms->src, UNCHOKE_DECODE);
+            if (ms->source_finished)
                 continue;
-            }
             if (dts == AV_NOPTS_VALUE && ms->last_dts != AV_NOPTS_VALUE)
                 continue;
             if (dts != AV_NOPTS_VALUE && ms->last_dts - dts >= SCHEDULE_TOLERANCE)
@@ -1538,7 +1510,6 @@ static void schedule_update_locked(Scheduler *sch)
 
     UPDATE_WAITER(demux);
     UPDATE_WAITER(filters);
-    UPDATE_WAITER(dec);
 }
 
 enum {
@@ -2341,12 +2312,6 @@ int sch_dec_receive(Scheduler *sch, unsigned dec_idx, AVPacket *pkt)
     av_assert0(dec_idx < sch->nb_dec);
     dec = &sch->dec[dec_idx];
 
-retry:
-    // Pull a packet from the overflow FIFO while unchoked or expecting EOF ts
-    if (av_container_fifo_can_read(dec->overflow) &&
-        (!atomic_load(&dec->waiter.choked) || dec->expect_end_ts))
-        return av_container_fifo_read(dec->overflow, pkt, 0);
-
     // the decoder should have given us post-flush end timestamp in pkt
     if (dec->expect_end_ts) {
         Timestamp ts = (Timestamp){ .ts = pkt->pts, .tb = pkt->time_base };
@@ -2360,29 +2325,11 @@ retry:
     ret = tq_receive(dec->queue, &dummy, pkt, 0);
     av_assert0(dummy <= 0);
 
-    // drain packets from overflow queue before returning EOF
-    if (ret == AVERROR_EOF && av_container_fifo_can_read(dec->overflow)) {
-        int terminate = waiter_wait(sch, &dec->waiter);
-        if (terminate)
-            return ret;
-        return av_container_fifo_read(dec->overflow, pkt, 0);
-    } else if (ret < 0)
-        return ret;
-
     // got a flush packet, on the next call to this function the decoder
-    // should give us post-flush end timestamp (after draining overflow fifo)
-    if (!pkt->data && !pkt->side_data_elems && dec->queue_end_ts)
+    // will give us post-flush end timestamp
+    if (ret >= 0 && !pkt->data && !pkt->side_data_elems && dec->queue_end_ts)
         dec->expect_end_ts = 1;
 
-    // we got a packet, but we're currently choked or have existing overflow
-    // packets; so push it to the FIFO first
-    if (atomic_load(&dec->waiter.choked) || av_container_fifo_can_read(dec->overflow)) {
-        ret = av_container_fifo_write(dec->overflow, pkt, 0);
-        if (ret < 0)
-            return ret;
-        goto retry;
-    }
-
     return ret;
 }
 
@@ -2838,9 +2785,6 @@ int sch_stop(Scheduler *sch, int64_t *finish_ts)
                 choke_demux(sch, i, 0); // unfreeze to allow draining
         }
 
-    for (unsigned i = 0; i < sch->nb_dec; i++)
-        waiter_set(&sch->dec[i].waiter, 0); // unfreeze to allow draining
-
     pthread_mutex_unlock(&sch->schedule_lock);
 
     for (unsigned i = 0; i < sch->nb_demux; i++) {
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.