PR #25663 opened by Forgejo_Fairy
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25663
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25663.patch

Fixes #25626.

When `update_context_from_thread()` fails while submitting a drain packet, 
`submit_packet()` returns before the worker state and queue indices advance. 
Repeated `avcodec_receive_frame()` calls then retry the same context update 
indefinitely. Mark draining complete after reporting that error, and return EOF 
on subsequent calls.

Tested on AArch64 with the issue’s 35-byte H.264 input. Before the patch, a 
two-second kill timeout returned 137 after 495,023 log lines. After the patch, 
`ffmpeg -err_detect explode -threads 2` exits with code 69 and eight log lines. 
The patched build also finishes with three threads and automatic thread 
selection. The corrupt input without `explode` and a separate H.264 sample 
finish. `git diff --check` passes.

The unpatched release/9.0, release/8.1, release/8.0, and release/7.1 heads all 
reproduce the hang.


From a42fdc78631ae9652ebcfe99fc4f4743d637a8da Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Sun, 1 Nov 2026 20:17:44 +0000
Subject: [PATCH] avcodec/pthread_frame: stop draining after thread context
 update failure

A failed update_thread_context() leaves the worker indices unchanged.
During draining, repeated receive_frame() calls then retry the same
empty packet indefinitely. Mark draining complete after reporting the
error once, and return EOF on subsequent calls.

Assisted-by: Fairy
---
 libavcodec/pthread_frame.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index 8e88dda2ce0..5b1d1f58f6a 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -529,6 +529,10 @@ static int submit_packet(PerThreadContext *p, 
AVCodecContext *user_avctx,
             (codec->capabilities & AV_CODEC_CAP_DELAY)) {
             ret = update_context_from_thread(p->avctx, prev_thread->avctx, 0);
             if (ret) {
+                /* No packet was submitted and the thread indices did not 
advance,
+                 * so retrying the drain packet can repeat this error forever. 
*/
+                if (user_avctx->internal->draining)
+                    user_avctx->internal->draining_done = 1;
                 pthread_mutex_unlock(&p->mutex);
                 return ret;
             }
@@ -562,6 +566,11 @@ int ff_thread_receive_frame(AVCodecContext *avctx, AVFrame 
*frame, unsigned flag
      * go forward while we are in this function */
     async_unlock(fctx);
 
+    if (avctx->internal->draining_done) {
+        ret = AVERROR_EOF;
+        goto finish;
+    }
+
     /* submit packets to threads while there are no buffered results to return 
*/
     while (!fctx->df.nb_f && !fctx->result) {
         PerThreadContext *p;
-- 
2.54.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to