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

Tentative suggested fix to #24613; more details in the issue description.

When the bitstream does not signal a reorder limit, the decoder derives the 
required delay from observed POC ordering. A reference B-frame may precede 
lower-POC pictures in decoding order.

Reserve one additional reorder slot before selecting an output picture in that 
case. Keep predictive buffer growth at verbose log level while retaining the 
existing warning for growth based on observed ordering.


>From 16ff1e578edd15227826691b719602d3040ab3c4 Mon Sep 17 00:00:00 2001
From: Nil Fons Miret <[email protected]>
Date: Thu, 17 Sep 2026 18:55:36 +0000
Subject: [PATCH] avcodec/h264: account for reference B-frames in reorder depth

When the bitstream does not signal a reorder limit, the decoder derives
the required delay from observed POC ordering. A reference B-frame may
precede lower-POC pictures in decoding order.

Reserve one additional reorder slot before selecting an output picture in
that case. Keep predictive buffer growth at verbose log level while
retaining the existing warning for growth based on observed ordering.
---
 libavcodec/h264_slice.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 0ce8e46c72..278c50f9e5 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -1296,7 +1296,7 @@ static int h264_select_output_frame(H264Context *h)
     const SPS *sps = h->ps.sps;
     H264Picture *out = h->cur_pic_ptr;
     H264Picture *cur = h->cur_pic_ptr;
-    int i, pics, out_of_order, out_idx;
+    int i, pics, out_of_order, out_idx, reference_delay = 0;
 
     cur->mmco_reset = h->mmco_reset;
     h->mmco_reset = 0;
@@ -1316,9 +1316,21 @@ static int h264_select_output_frame(H264Context *h)
         }
     }
     out_of_order = H264_MAX_DPB_FRAMES - i;
-    if(   cur->f->pict_type == AV_PICTURE_TYPE_B
-       || (h->last_pocs[H264_MAX_DPB_FRAMES-2] > INT_MIN && 
h->last_pocs[H264_MAX_DPB_FRAMES-1] - 
(int64_t)h->last_pocs[H264_MAX_DPB_FRAMES-2] > 2))
+    if (cur->f->pict_type == AV_PICTURE_TYPE_B) {
         out_of_order = FFMAX(out_of_order, 1);
+
+        /* A reference B-frame may precede B-frames with a lower POC in
+         * decoding order. Reserve one more slot before outputting it, as
+         * increasing the delay after seeing those frames would be too late. */
+        if (!h->droppable && out_of_order < H264_MAX_DPB_FRAMES - 1) {
+            out_of_order++;
+            reference_delay = 1;
+        }
+    } else if (h->last_pocs[H264_MAX_DPB_FRAMES-2] > INT_MIN &&
+               h->last_pocs[H264_MAX_DPB_FRAMES-1] -
+               (int64_t)h->last_pocs[H264_MAX_DPB_FRAMES-2] > 2) {
+        out_of_order = FFMAX(out_of_order, 1);
+    }
     if (out_of_order == H264_MAX_DPB_FRAMES) {
         av_log(h->avctx, AV_LOG_VERBOSE, "Invalid POC %d<%d\n", cur->poc, 
h->last_pocs[0]);
         for (i = 1; i < H264_MAX_DPB_FRAMES; i++)
@@ -1326,7 +1338,8 @@ static int h264_select_output_frame(H264Context *h)
         h->last_pocs[0] = cur->poc;
         cur->mmco_reset = 1;
     } else if(h->avctx->has_b_frames < out_of_order && 
!sps->bitstream_restriction_flag){
-        int loglevel = h->avctx->frame_num > 1 ? AV_LOG_WARNING : 
AV_LOG_VERBOSE;
+        int loglevel = h->avctx->frame_num > 1 && !reference_delay
+                     ? AV_LOG_WARNING : AV_LOG_VERBOSE;
         av_log(h->avctx, loglevel, "Increasing reorder buffer to %d\n", 
out_of_order);
         h->avctx->has_b_frames = out_of_order;
     }
-- 
2.52.0

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

Reply via email to