vulkan视频解码之参考帧


 

int8_t VulkanVideoParser::SetPicDpbSlot(vkPicBuffBase* pPicBuf,
    int8_t dpbSlot)
{
    int8_t picIndex = GetPicIdx(pPicBuf);
    assert((picIndex >= 0) && ((uint32_t)picIndex < m_maxNumDecodeSurfaces));
    return SetPicDpbSlot(picIndex, dpbSlot);
}

从vkPicBuffBase取得picIndex,调用SetPicDpbSlot

int8_t VulkanVideoParser::SetPicDpbSlot(int8_t picIndex, int8_t dpbSlot)
{
    int8_t oldDpbSlot = m_pictureToDpbSlotMap[picIndex];
    m_pictureToDpbSlotMap[picIndex] = dpbSlot;
    if (dpbSlot >= 0) {
        m_dpbSlotsMask |= (1 << picIndex);
    } else {
        m_dpbSlotsMask &= ~(1 << picIndex);
        if (oldDpbSlot >= 0) {
            m_dpb.FreeSlot(oldDpbSlot);
        }
    }
    return oldDpbSlot;
}

把dpbSlot存入m_pictureToDpbSlotMap[picIndex]而已

那么什么时候调用这个呢,对于AV1


uint32_t VulkanVideoParser::FillDpbAV1State(
        const VkParserPictureData* pd,
        VkParserAv1PictureData* pin,
        nvVideoDecodeAV1DpbSlotInfo* pDpbSlotInfo,
        StdVideoDecodeAV1PictureInfo*,
        uint32_t,
        VkVideoReferenceSlotInfoKHR* pReferenceSlots,
        int8_t* pGopReferenceImagesIndexes,
        int32_t* pCurrAllocatedSlotIndex)
{

    assert(m_maxNumDpbSlots <= STD_VIDEO_AV1_NUM_REF_FRAMES + 1);
    uint32_t refDpbUsedAndValidMask = 0;
    uint32_t referenceIndex = 0;

    if (m_dumpParserData)
        std::cout << "Ref frames data: " << std::endl;

    if (m_dumpDpbData) {
        printf(";;;; ======= AV1 DPB fill begin %d =======\n", m_nCurrentPictureID);

        printf("m_pictureToDpbSlotMap:picIdx    ");
        for (int i = 0; i < MAX_FRM_CNT; i++) {
            printf("%02d ", i);
        }
        printf("\nm_pictureToDpbSlotMap:DpbSlot   ");
        for (int i = 0; i < MAX_FRM_CNT; i++) {
            printf("%02d ", m_pictureToDpbSlotMap[i]);
        }
        printf("\n");

        printf("ref_frame_idx:idx:       ");
        for (int i = 0; i < 7; i++) printf("%02d ", i);
        printf("\nref_frame_idx:value:     ");
        for (int i = 0; i < 7; i++) {
            printf("%02d ", pin->ref_frame_idx[i]);
        }
        printf("\nref_frame_picture:picIdx ");
        for (int i = 0; i < 7; i++) {
            printf("%02d ", pin->pic_idx[pin->ref_frame_idx[i]]);
        }
        printf("\n\n");

        printf("ref_frame_picture:idx    ");
        for (int32_t inIdx = 0; inIdx < STD_VIDEO_AV1_NUM_REF_FRAMES; inIdx++) {
            printf("%02d ", inIdx);
        }
        printf("\nref_frame_picture:picIdx ");
        for (int32_t inIdx = 0; inIdx < STD_VIDEO_AV1_NUM_REF_FRAMES; inIdx++) {
            int8_t picIdx = pin->pic_idx[inIdx];
            printf("%02d ", picIdx);
        }
        printf("\n");
    }

    bool isKeyFrame = pin->std_info.frame_type == STD_VIDEO_AV1_FRAME_TYPE_KEY;


    int8_t activeReferences[32];
    memset(activeReferences, 0, sizeof(activeReferences));
    for (size_t refName = 0; refName < STD_VIDEO_AV1_REFS_PER_FRAME; refName++) {
        int8_t picIdx = isKeyFrame ? -1 : pin->pic_idx[pin->ref_frame_idx[refName]];
        if (picIdx < 0) {
            //pKhr->referenceNameSlotIndices[refName] = -1;
            continue;
        }
        int8_t dpbSlot = GetPicDpbSlot(picIdx);
        assert(dpbSlot >= 0);
        //pKhr->referenceNameSlotIndices[refName] = dpbSlot;
        activeReferences[dpbSlot]++;
        //hdr.delta_frame_id_minus_1[dpbSlot] = pin->delta_frame_id_minus_1[pin->ref_frame_idx[i]];
    }

    for (int32_t inIdx = 0; inIdx < STD_VIDEO_AV1_NUM_REF_FRAMES; inIdx++) {
        int8_t picIdx = isKeyFrame ? -1 : pin->pic_idx[inIdx];
        int8_t dpbSlot = -1;
        if ((picIdx >= 0) && !(refDpbUsedAndValidMask & (1 << picIdx))) {
            dpbSlot = GetPicDpbSlot(picIdx);

            assert(dpbSlot >= 0); // There is still content hitting this assert.
            if (dpbSlot < 0) {
                continue;
            }

            refDpbUsedAndValidMask |= (1 << picIdx);
            m_dpb[dpbSlot].MarkInUse(m_nCurrentPictureID);
            if (activeReferences[dpbSlot] == 0) {
                continue;
            }

            VkVideoDecodeAV1DpbSlotInfoKHR &dpbSlotInfo = pDpbSlotInfo[referenceIndex].dpbSlotInfo;
            dpbSlotInfo.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_DPB_SLOT_INFO_KHR;
            dpbSlotInfo.pStdReferenceInfo = &pin->dpbSlotInfos[inIdx];
            pReferenceSlots[referenceIndex].sType = VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_INFO_KHR;
            pReferenceSlots[referenceIndex].pNext = &dpbSlotInfo;
            pReferenceSlots[referenceIndex].slotIndex = dpbSlot;
            pGopReferenceImagesIndexes[referenceIndex] = picIdx;

            referenceIndex++;
        }
    }

    if (m_dumpDpbData) {
        printf("                                   picIdx: ");
        for (size_t i = 0; i < referenceIndex; i++) {
            printf("%02d ", pGopReferenceImagesIndexes[i]);
        }
        printf("\npReferenceSlots (%d):GetPicDpbSlot(picIdx): ", referenceIndex);
        for (size_t i =0 ;i < referenceIndex; i++) {
            printf("%02d ", pReferenceSlots[i].slotIndex);
        }

        printf("\n");
    }

    ResetPicDpbSlots(refDpbUsedAndValidMask);

    // Take into account the reference picture now.
    int8_t currPicIdx = GetPicIdx(pd->pCurrPic);
    assert(currPicIdx >= 0);
    if (currPicIdx >= 0) {
        refDpbUsedAndValidMask |= (1 << currPicIdx);
    }

    // NOTE(charlie): Most likely we can consider isReference = refresh_frame_flags != 0;
    // However, the AMD fw interface appears to always need a setup slot & a destination resource,


    int8_t dpbSlot = AllocateDpbSlotForCurrentAV1(GetPic(pd->pCurrPic),
        true /* isReference */, pd->current_dpb_id);

    assert(dpbSlot >= 0);

    *pCurrAllocatedSlotIndex = dpbSlot;
    assert(!(dpbSlot < 0));
    if (dpbSlot >= 0) {
        assert(pd->ref_pic_flag);
    }

    if (m_dumpDpbData) {
        printf("SlotsInUse: ");
        uint32_t slotsInUse = m_dpb.getSlotInUseMask();
        for (int i = 0; i < 9; i++) {
            printf("%02d ", i);
        }
        uint8_t greenSquare[] = { 0xf0, 0x9f,  0x9f, 0xa9, 0x00 };
        uint8_t redSquare[] = { 0xf0, 0x9f,  0x9f, 0xa5, 0x00 };
        uint8_t yellowSquare[] = { 0xf0, 0x9f,  0x9f, 0xa8, 0x00 };
        printf("\nSlotsInUse: ");
        for (int i = 0; i < 9; i++) {
            printf("%-2s ", (slotsInUse & (1<<i)) ? (i == dpbSlot ? (char*)yellowSquare : (char*)greenSquare) : (char*)redSquare); 
        }
        printf("\n");
    }

    return referenceIndex;
}

调用AllocateDpbSlotForCurrentAV1==>SetPicDpbSlot,先分配一个DpbSlot然后保存到数组中


int8_t VulkanVideoParser::AllocateDpbSlotForCurrentAV1(vkPicBuffBase* pPic,
    bool isReference, int8_t /*presetDpbSlot*/)
{
    int8_t dpbSlot = -1;
    int8_t currPicIdx = GetPicIdx(pPic);
    assert(currPicIdx >= 0);
    assert(isReference);
    if (isReference) {
        dpbSlot = GetPicDpbSlot(currPicIdx); // use the associated slot, if not allocate a new slot.
        if (dpbSlot < 0) {
            dpbSlot = m_dpb.AllocateSlot(); 
            assert(dpbSlot >= 0);
            SetPicDpbSlot(currPicIdx, dpbSlot); // Assign the dpbSlot to the current picture index.
            m_dpb[dpbSlot].setPictureResource(pPic, m_nCurrentPictureID); // m_nCurrentPictureID is our main index.
        }
        assert(dpbSlot >= 0);
    }
    return dpbSlot;
}

FillDpbAV1State中用到的pin->pic_idx是BeginPicture时初始化的,关键是下面的代码:

vkPicBuffBase *pb = reinterpret_cast<vkPicBuffBase *>(m_pBuffers[i].buffer);
av1->pic_idx[i] = pb ? pb->m_picIdx : -1;

..........

av1->ref_frame_idx[i] = ref_frame_idx[i];//直接拷贝


// BeginPicture
bool VulkanAV1Decoder::BeginPicture(VkParserPictureData* pnvpd)
{
    VkParserAv1PictureData* const av1 = &pnvpd->CodecSpecific.av1;
    av1_seq_param_s *const sps = m_sps.Get();
    assert(sps != nullptr);

    av1->upscaled_width = upscaled_width;
    av1->frame_width = frame_width;
    av1->frame_height = frame_height;

    VkParserSequenceInfo nvsi = m_ExtSeqInfo;
    nvsi.eCodec         = (VkVideoCodecOperationFlagBitsKHR)VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR;
    nvsi.nChromaFormat  = sps->color_config.flags.mono_chrome ? 0 : (sps->color_config.subsampling_x && sps->color_config.subsampling_y) ? 1 : (!sps->color_config.subsampling_x && !sps->color_config.subsampling_y) ? 3 : 2;
    nvsi.nMaxWidth      = (sps->max_frame_width_minus_1 + 2) & ~1;
    nvsi.nMaxHeight     = (sps->max_fra
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值