This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 82a2875192b6e6d45ee3ed8d0baf03e91dcca532
Author:     Lynne <[email protected]>
AuthorDate: Sun Sep 20 13:58:48 2026 +0900
Commit:     Lynne <[email protected]>
CommitDate: Sun Sep 20 14:45:56 2026 +0900

    vulkan_h264: give each picture a persistent DPB slot instead of its DPB 
index
    
    A frame_num gap dummy shares the duplicated picture's hwaccel state, and
    with it the DPB slot that picture was decoded into, which can differ from
    the dummy's own index into h->DPB: the dummy and the picture it duplicates
    are distinct H264Picture entries. Deriving the Vulkan slot from the DPB
    index, as before, could then bind the dummy at an index nothing was ever
    decoded into, or one currently in use by an unrelated picture.
    
    Assign the slot once, when a picture is first decoded, to the lowest index
    no current reference holds, and keep it for as long as the picture (or a
    dummy sharing its state) remains referenced. ff_ctz(0) is undefined, so
    guard the case where every slot is taken rather than fall into it.
    
    A slot can still end up requested twice in the same scope: once for the
    original picture, once for a dummy sharing its state. Detect that by
    identity on the shared hwaccel state rather than by DPB index, since the
    two no longer coincide.
---
 libavcodec/vulkan_h264.c | 47 +++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 39 insertions(+), 8 deletions(-)

diff --git a/libavcodec/vulkan_h264.c b/libavcodec/vulkan_h264.c
index 6be0f957e9..aa173a0511 100644
--- a/libavcodec/vulkan_h264.c
+++ b/libavcodec/vulkan_h264.c
@@ -37,7 +37,8 @@ const FFVulkanDecodeDescriptor ff_vk_dec_h264_desc = {
 typedef struct H264VulkanDecodePicture {
     FFVulkanDecodePicture           vp;
 
-    /* PICT_* mask of what was actually decoded into the picture's DPB slot */
+    /* DPB slot the picture was decoded into, and a PICT_* mask of what was */
+    int                             slot;
     int                             decoded;
 
     /* Current picture */
@@ -70,16 +71,46 @@ static int vk_h264_fill_pict(AVCodecContext *avctx, 
H264Picture **ref_src,
     FFVulkanDecodeShared *ctx = dec->shared_ctx;
     H264VulkanDecodePicture *hp = pic->hwaccel_picture_private;
     FFVulkanDecodePicture *vkpic = &hp->vp;
-    const int dpb_slot_index = pic - h->DPB;
     int err;
 
-    /* A slot only holds what was decoded into it: not the pictures the
-     * decoder synthesizes to fill frame_num gaps or to stand in for missing
-     * references, nor fields lost to a seek. */
-    if (!is_current) {
+    if (is_current) {
+        /* Frame num gap dummies carry the duplicated picture's state, and with
+         * it its slot, which thus outlives that picture's DPB entry. Slots
+         * cannot follow DPB indices then: take the lowest one no reference
+         * holds when the picture is first decoded. */
+        if (!hp->decoded) {
+            uint32_t used = 0, free_slots;
+
+            for (int i = 0; i < H264_MAX_PICTURE_COUNT; i++) {
+                const H264VulkanDecodePicture *p = 
h->DPB[i].hwaccel_picture_private;
+                if ((h->DPB[i].reference & PICT_FRAME) && p && p->decoded)
+                    used |= 1U << p->slot;
+            }
+
+            /* ff_ctz(0) is undefined; a fully-set mask means no slot is free 
*/
+            free_slots = ~used;
+            hp->slot = free_slots ? ff_ctz(free_slots) : ctx->caps.maxDpbSlots;
+            if (hp->slot >= ctx->caps.maxDpbSlots) {
+                av_log(avctx, AV_LOG_ERROR, "Not enough DPB slots for the "
+                       "stream's references\n");
+                return AVERROR(ENOTSUP);
+            }
+        }
+    } else {
+        H264VulkanDecodePicture *cur = h->cur_pic_ptr->hwaccel_picture_private;
+
+        /* A slot only holds what was decoded into it: not the pictures the
+         * decoder synthesizes to fill frame_num gaps or to stand in for
+         * missing references, nor fields lost to a seek. */
         picture_structure &= hp->decoded;
         if (!picture_structure)
             return 0;
+
+        /* Frame_num gap dummies share the duplicated picture's state, and a
+         * slot can only be bound once. */
+        for (H264Picture **p = cur->ref_src; p < ref_src; p++)
+            if ((*p)->hwaccel_picture_private == hp)
+                return 0;
     }
 
     err = ff_vk_decode_prepare_frame(dec, pic->f, vkpic, is_current,
@@ -114,14 +145,14 @@ static int vk_h264_fill_pict(AVCodecContext *avctx, 
H264Picture **ref_src,
         .sType = VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_INFO_KHR,
         .codedOffset = (VkOffset2D){ 0, 0 },
         .codedExtent = (VkExtent2D){ pic->f->width, pic->f->height },
-        .baseArrayLayer = ctx->common.layered_dpb ? dpb_slot_index : 0,
+        .baseArrayLayer = ctx->common.layered_dpb ? hp->slot : 0,
         .imageViewBinding = vkpic->view.ref,
     };
 
     *ref_slot = (VkVideoReferenceSlotInfoKHR) {
         .sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR,
         .pNext = vkh264_ref,
-        .slotIndex = dpb_slot_index,
+        .slotIndex = hp->slot,
         .pPictureResource = ref,
     };
 

-- 
To stop receiving notification emails like this one, please contact
[email protected].
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to