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