[PR] avcodec/h264dec: decode late SEI before finishing frame threading setup (PR #24201)

Kacper Michajłow via ffmpeg-devel <[email protected]>
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <[email protected]>
PR #24201 opened by Kacper Michajłow (kasper93)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24201
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24201.patch


From f5a0bbafaa9d00c5a0bce641a1968318c84616f0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]>
Date: Tue, 18 Aug 2026 15:55:51 +0200
Subject: [PATCH 1/2] avcodec/h264dec: defer execution of queued slices to the
 end of packet
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This allows all non-VCL NAL units to be parsed and frame threading
setup to finish before the bulk of the decoding work is done.

Signed-off-by: Kacper Michajłow <[email protected]>
---
 libavcodec/h264dec.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index b78b7989ea..1def45e0c0 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -621,7 +621,7 @@ static int decode_nal_units(H264Context *h, AVBufferRef *buf_ref,
 
     for (i = 0; i < h->pkt.nb_nals; i++) {
         H2645NAL *nal = &h->pkt.nals[i];
-        int max_slice_ctx, err;
+        int err;
 
         if (avctx->skip_frame >= AVDISCARD_NONREF &&
             nal->ref_idc == 0 && nal->type != H264_NAL_SEI)
@@ -649,6 +649,14 @@ static int decode_nal_units(H264Context *h, AVBufferRef *buf_ref,
         case H264_NAL_SLICE:
             h->has_slice = 1;
 
+            /* Execution of queued slices is deferred until the slice context
+             * queue is full or the end of the packet is reached. */
+            if (!avctx->hwaccel && h->nb_slice_ctx_queued == h->nb_slice_ctx) {
+                ret = ff_h264_execute_decode_slices(h);
+                if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
+                    goto end;
+            }
+
             if ((err = ff_h264_queue_decode_slice(h, nal))) {
                 H264SliceContext *sl = h->slice_ctx + h->nb_slice_ctx_queued;
                 sl->ref_count[0] = sl->ref_count[1] = 0;
@@ -668,13 +676,9 @@ static int decode_nal_units(H264Context *h, AVBufferRef *buf_ref,
                     goto end;
             }
 
-            max_slice_ctx = avctx->hwaccel ? 1 : h->nb_slice_ctx;
-            if (h->nb_slice_ctx_queued == max_slice_ctx) {
-                if (h->avctx->hwaccel) {
-                    ret = FF_HW_CALL(avctx, decode_slice, nal->raw_data, nal->raw_size);
-                    h->nb_slice_ctx_queued = 0;
-                } else
-                    ret = ff_h264_execute_decode_slices(h);
+            if (avctx->hwaccel && h->nb_slice_ctx_queued) {
+                ret = FF_HW_CALL(avctx, decode_slice, nal->raw_data, nal->raw_size);
+                h->nb_slice_ctx_queued = 0;
                 if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
                     goto end;
             }
-- 
2.52.0


From cd36dbe84d17c27a47b26e0ab8d3ea7ab515ab72 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]>
Date: Tue, 18 Aug 2026 16:01:30 +0200
Subject: [PATCH 2/2] avcodec/h264dec: decode late SEI before finishing frame
 threading setup
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

SEI NAL units following a slice were skipped with frame threading,
because decoding them into the SEI context after
ff_thread_finish_setup() would race with the context copy in
ff_h264_update_thread_context(). Delay the setup finish until such SEI
is decoded instead.

Fixes: https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/21348
Fixes: https://github.com/mpv-player/mpv/issues/18104

Signed-off-by: Kacper Michajłow <[email protected]>
---
 libavcodec/h264dec.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index 1def45e0c0..4bd4ca4de3 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -519,6 +519,10 @@ static int get_last_needed_nal(H264Context *h)
         case H264_NAL_PPS:
             nals_needed = i;
             break;
+        case H264_NAL_SEI:
+            if (first_slice)
+                nals_needed = i;
+            break;
         case H264_NAL_DPA:
         case H264_NAL_IDR_SLICE:
         case H264_NAL_SLICE:
@@ -699,6 +703,13 @@ static int decode_nal_units(H264Context *h, AVBufferRef *buf_ref,
                 debug_green_metadata(&h->sei.green_metadata, h->avctx);
             if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
                 goto end;
+
+            if (avctx->active_thread_type & FF_THREAD_FRAME &&
+                i >= nals_needed && !h->setup_finished &&
+                h->current_slice && h->cur_pic_ptr) {
+                ff_thread_finish_setup(avctx);
+                h->setup_finished = 1;
+            }
             break;
         case H264_NAL_SPS: {
             GetBitContext tmp_gb = nal->gb;
-- 
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.