/* * Copyright (c) 2011-2024, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ //! //! \file codechal_decode_avc.cpp //! \brief This modules implements Render interface layer for AVC decoding to be used on all operating systems/DDIs, across CODECHAL components. //! #include "codechal_decoder.h" #include "codechal_decode_avc.h" #include "codechal_decode_sfc_avc.h" #include "codechal_mmc_decode_avc.h" #include "codechal_secure_decode_interface.h" #include "hal_oca_interface.h" #if USE_CODECHAL_DEBUG_TOOL #include "codechal_debug.h" #endif //Check whether interview prediction is used through POC #define CodecHalAVC_IsInterviewPred(currPic, currPoc, avcRefListIdx) ( ((avcRefListIdx)!=(currPic).FrameIdx) && \ (!CodecHal_PictureIsTopField(currPic) && (pAvcRefList[avcRefListIdx]->iFieldOrderCnt[1] == (currPoc)[1]) || \ !CodecHal_PictureIsBottomField(currPic) && (pAvcRefList[avcRefListIdx]->iFieldOrderCnt[0] == (currPoc)[0])) && \ ((currPic).FrameIdx != 0x7f) ) MOS_STATUS CodechalDecodeAvc::SendSlice( PMHW_VDBOX_AVC_SLICE_STATE avcSliceState, PMOS_COMMAND_BUFFER cmdBuffer) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_CHK_NULL_RETURN(cmdBuffer); CODECHAL_DECODE_CHK_NULL_RETURN(avcSliceState); CODECHAL_DECODE_CHK_NULL_RETURN(avcSliceState->pAvcPicIdx); CODECHAL_DECODE_CHK_NULL_RETURN(avcSliceState->pAvcPicParams); CODECHAL_DECODE_CHK_NULL_RETURN(avcSliceState->pAvcSliceParams); PCODEC_AVC_PIC_PARAMS avcPicParams = avcSliceState->pAvcPicParams; PCODEC_AVC_SLICE_PARAMS slc = avcSliceState->pAvcSliceParams; avcSliceState->ucDisableDeblockingFilterIdc = slc->disable_deblocking_filter_idc; avcSliceState->ucSliceBetaOffsetDiv2 = slc->slice_beta_offset_div2; avcSliceState->ucSliceAlphaC0OffsetDiv2 = slc->slice_alpha_c0_offset_div2; if (avcSliceState->bShortFormatInUse) { // send slice address except last one if (!avcSliceState->bLastSlice) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdAvcSliceAddrCmd( cmdBuffer, avcSliceState)); } } else { MHW_VDBOX_AVC_REF_IDX_PARAMS refIdxParams; MOS_ZeroMemory(&refIdxParams, sizeof(MHW_VDBOX_AVC_REF_IDX_PARAMS)); if (!m_mfxInterface->IsAvcISlice(slc->slice_type)) { refIdxParams.CurrPic = avcPicParams->CurrPic; refIdxParams.uiList = LIST_0; refIdxParams.uiNumRefForList[LIST_0] = slc->num_ref_idx_l0_active_minus1 + 1; CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(MOS_SecureMemcpy( &refIdxParams.RefPicList, sizeof(refIdxParams.RefPicList), &slc->RefPicList, sizeof(slc->RefPicList)), "Failed to copy memory"); refIdxParams.pAvcPicIdx = avcSliceState->pAvcPicIdx; refIdxParams.avcRefList = (void**)m_avcRefList; refIdxParams.bIntelEntrypointInUse = avcSliceState->bIntelEntrypointInUse; refIdxParams.bPicIdRemappingInUse = avcSliceState->bPicIdRemappingInUse; CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcRefIdx(cmdBuffer, nullptr, &refIdxParams)); MHW_VDBOX_AVC_WEIGHTOFFSET_PARAMS weightOffsetParams; if (m_mfxInterface->IsAvcPSlice(slc->slice_type) && avcPicParams->pic_fields.weighted_pred_flag == 1) { weightOffsetParams.uiList = 0; CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(MOS_SecureMemcpy( &weightOffsetParams.Weights, sizeof(weightOffsetParams.Weights), &slc->Weights, sizeof(slc->Weights)), "Failed to copy memory"); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcWeightOffset(cmdBuffer, nullptr, &weightOffsetParams)); } if (m_mfxInterface->IsAvcBSlice(slc->slice_type)) { refIdxParams.uiList = LIST_1; refIdxParams.uiNumRefForList[LIST_1] = slc->num_ref_idx_l1_active_minus1 + 1; CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcRefIdx(cmdBuffer, nullptr, &refIdxParams)); if (avcPicParams->pic_fields.weighted_bipred_idc == 1) { weightOffsetParams.uiList = 0; CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(MOS_SecureMemcpy( &weightOffsetParams.Weights, sizeof(weightOffsetParams.Weights), &slc->Weights, sizeof(slc->Weights)), "Failed to copy memory"); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcWeightOffset(cmdBuffer, nullptr, &weightOffsetParams)); weightOffsetParams.uiList = 1; CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcWeightOffset(cmdBuffer, nullptr, &weightOffsetParams)); } } } else if (MEDIA_IS_WA(m_waTable, WaDummyReference) && !m_osInterface->bSimIsActive) { MHW_VDBOX_AVC_REF_IDX_PARAMS refIdxParams; MOS_ZeroMemory(&refIdxParams, sizeof(MHW_VDBOX_AVC_REF_IDX_PARAMS)); refIdxParams.bDummyReference = true; CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcRefIdx(cmdBuffer, nullptr, &refIdxParams)); } CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcSlice(cmdBuffer, nullptr, avcSliceState)); } CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdAvcBsdObjectCmd( cmdBuffer, avcSliceState)); return eStatus; } MOS_STATUS CodechalDecodeAvc::FormatAvcMonoPicture(PMOS_SURFACE surface) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; PCODEC_AVC_PIC_PARAMS picParams = (PCODEC_AVC_PIC_PARAMS)m_avcPicParams; if (picParams->seq_fields.chroma_format_idc != avcChromaFormatMono) { return MOS_STATUS_SUCCESS; } MOS_SURFACE dstSurface; MOS_ZeroMemory(&dstSurface, sizeof(MOS_SURFACE)); dstSurface.Format = Format_NV12; if(surface != nullptr && !Mos_ResourceIsNull(&surface->OsResource)) { dstSurface.OsResource = surface->OsResource; } else { CODECHAL_DECODE_ASSERTMESSAGE("Surface pointer is NULL!"); return MOS_STATUS_INVALID_PARAMETER; } CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, &dstSurface)); uint32_t height = dstSurface.dwHeight; uint32_t pitch = dstSurface.dwPitch; uint32_t chromaHeight = height / 2; uint32_t frameHeight = MOS_ALIGN_CEIL(height, 16); uint32_t alignedFrameHeight = MOS_ALIGN_CEIL(frameHeight, MOS_YTILE_H_ALIGNMENT); uint32_t alignedChromaHeight = MOS_ALIGN_CEIL(chromaHeight, MOS_YTILE_H_ALIGNMENT); uint32_t frameSize = pitch * MOS_ALIGN_CEIL((frameHeight + chromaHeight), MOS_YTILE_H_ALIGNMENT); uint32_t chromaBufSize = MOS_ALIGN_CEIL(pitch * alignedChromaHeight, MHW_PAGE_SIZE); if (Mos_ResourceIsNull(&m_resMonoPictureChromaBuffer)) { CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resMonoPictureChromaBuffer, chromaBufSize, "MonoPictureChromaBuffer", true, CODECHAL_DECODE_AVC_MONOPIC_CHROMA_DEFAULT), "Failed to allocate MonoPicture Chroma Buffer."); } MOS_COMMAND_BUFFER cmdBuffer; CodechalHucStreamoutParams hucStreamOutParams; if (!m_hwInterface->m_noHuC) { m_osInterface->pfnSetGpuContext(m_osInterface, m_videoContextForWa); m_osInterface->pfnResetOsStates(m_osInterface); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(&cmdBuffer, false)); // use huc stream out to do clear to clear copy MOS_ZeroMemory(&hucStreamOutParams, sizeof(hucStreamOutParams)); hucStreamOutParams.dataBuffer = &m_resMonoPictureChromaBuffer; hucStreamOutParams.streamOutObjectBuffer = &surface->OsResource; } uint32_t uvblockHeight = CODECHAL_MACROBLOCK_HEIGHT; uint32_t uvrowSize = pitch * uvblockHeight * 2; uint32_t dstOffset = 0, x = 0, uvsize = 0; if (frameHeight % MOS_YTILE_H_ALIGNMENT) { dstOffset = LinearToYTiledAddress(x, frameHeight, pitch); if (m_hwInterface->m_noHuC) { CodechalDataCopyParams dataCopyParams; MOS_ZeroMemory(&dataCopyParams, sizeof(CodechalDataCopyParams)); dataCopyParams.srcResource = &m_resMonoPictureChromaBuffer; dataCopyParams.srcSize = uvrowSize; dataCopyParams.srcOffset = 0; dataCopyParams.dstResource = &surface->OsResource; dataCopyParams.dstSize = frameSize; dataCopyParams.dstOffset = dstOffset; CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->CopyDataSourceWithDrv(&dataCopyParams)); } else { CODECHAL_DECODE_CHK_STATUS_RETURN(HucCopy( &cmdBuffer, // pCmdBuffer &m_resMonoPictureChromaBuffer, // presSrc &surface->OsResource, // presDst uvrowSize, // u32CopyLength 0, // u32CopyInputOffset dstOffset)); // u32CopyOutputOffset } } dstOffset = dstSurface.UPlaneOffset.iSurfaceOffset; uvsize = frameSize - pitch * alignedFrameHeight; if (m_hwInterface->m_noHuC) { CodechalDataCopyParams dataCopyParams; MOS_ZeroMemory(&dataCopyParams, sizeof(CodechalDataCopyParams)); dataCopyParams.srcResource = &m_resMonoPictureChromaBuffer; dataCopyParams.srcSize = uvsize; dataCopyParams.srcOffset = 0; dataCopyParams.dstResource = &surface->OsResource; dataCopyParams.dstSize = frameSize; dataCopyParams.dstOffset = dstOffset; CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->CopyDataSourceWithDrv(&dataCopyParams)); } else { CODECHAL_DECODE_CHK_STATUS_RETURN(HucCopy( &cmdBuffer, // pCmdBuffer &m_resMonoPictureChromaBuffer, // presSrc &surface->OsResource, // presDst uvsize, // u32CopyLength 0, // u32CopyInputOffset dstOffset)); // u32CopyOutputOffset MHW_MI_FLUSH_DW_PARAMS flushDwParams; MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(&cmdBuffer, &flushDwParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); MOS_SYNC_PARAMS syncParams; syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContext; syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams)); syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContextForWa; syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_videoContextUsesNullHw)); m_osInterface->pfnSetGpuContext(m_osInterface, m_videoContext); } return eStatus; } MOS_STATUS CodechalDecodeAvc::AllocateInvalidRefBuffer() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; //AlloctateResource if (Mos_ResourceIsNull(&m_resInvalidRefBuffer)) { CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, &m_destSurface)); MOS_MEMCOMP_STATE mmcMode = MOS_MEMCOMP_DISABLED; #ifdef _MMC_SUPPORTED if(m_mmc != nullptr && m_mmc->IsMmcEnabled()) { CODECHAL_DECODE_CHK_STATUS_RETURN( m_osInterface->pfnGetMemoryCompressionMode( m_osInterface, &m_destSurface.OsResource, &mmcMode)); } #endif MOS_SURFACE surface; CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateSurface( &surface, m_destSurface.dwPitch, m_destSurface.dwHeight, "InvalidRefBuffer", Format_NV12, mmcMode != MOS_MEMCOMP_DISABLED ? true : false), "Failed to allocate invalid reference buffer."); m_resInvalidRefBuffer = surface.OsResource; // set all the pixels to 1<<(BitDepth-1) according to the AVC spec CodechalResLock ResourceLock(m_osInterface, &m_resInvalidRefBuffer); auto data = (uint8_t*)ResourceLock.Lock(CodechalResLock::writeOnly); CODECHAL_DECODE_CHK_NULL_RETURN(data); uint32_t size = m_destSurface.dwPitch * m_destSurface.dwHeight * 3 / 2; MOS_FillMemory(data, size, CODECHAL_DECODE_AVC_INVALID_REFPIC_VALUE); //INVALID_REFPIC_VALUE = 1<<(8-1): Intel Graphic only support 8bit AVC output now. } return eStatus; } MOS_STATUS CodechalDecodeAvc::SetAndAllocateDmvBufferIndex( PCODEC_AVC_DMV_LIST avcMVBufList, bool usedForRef, uint8_t frameIdx, uint32_t avcDmvBufferSize, uint8_t *dmvIdx, MOS_RESOURCE *avcDmvBuffers) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_CHK_NULL_RETURN(avcMVBufList); CODECHAL_DECODE_CHK_NULL_RETURN(dmvIdx); CODECHAL_DECODE_CHK_NULL_RETURN(avcDmvBuffers); uint8_t index = 0; if (usedForRef) { uint8_t i; for (i = 0; i < CODEC_AVC_NUM_REF_DMV_BUFFERS; i++) { if (!avcMVBufList[i].bInUse) { index = i; avcMVBufList[i].bInUse = true; avcMVBufList[i].ucFrameId = frameIdx; break; } } if (i == CODEC_AVC_NUM_REF_DMV_BUFFERS) { // Should never happen, something must be wrong CODECHAL_DECODE_ASSERTMESSAGE("No DMV Buffer found."); eStatus = MOS_STATUS_INVALID_PARAMETER; return eStatus; } } else { index = CODEC_AVC_NUM_REF_DMV_BUFFERS; } if (Mos_ResourceIsNull(&avcDmvBuffers[index])) { // Allocate DMV buffer if it has not been allocated already. CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &avcDmvBuffers[index], avcDmvBufferSize, "MvBuffer", true), "Failed to allocate MV Buffer."); } *dmvIdx = index; return eStatus; } MOS_STATUS CodechalDecodeAvc::SetAndAllocateDmvBufferIndexMismatched( uint8_t frameIdx, uint32_t avcDmvBufferSize, uint8_t *dmvIdx, MOS_RESOURCE *avcDmvBuffers) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_CHK_NULL_RETURN(dmvIdx); CODECHAL_DECODE_CHK_NULL_RETURN(avcDmvBuffers); uint8_t index = frameIdx; if (Mos_ResourceIsNull(&avcDmvBuffers[index])) { // Allocate DMV buffer if it has not been allocated already. CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &avcDmvBuffers[index], avcDmvBufferSize, "MvBuffer", true), "Failed to allocate MV Buffer."); } *dmvIdx = index; return eStatus; } MOS_STATUS CodechalDecodeAvc::InitMvcDummyDmvBuffer( uint32_t *mvcWaDummyDmvBuf, uint32_t size, PMOS_RESOURCE mvcDummyDmvBuffer) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( mvcDummyDmvBuffer, size, "MvBuffer"), "Failed to allocate WA Mvc Dummy DMV Buffer."); uint8_t *dummyDmvBuffer = nullptr, *mbDmvBuffer = nullptr; CODECHAL_DECODE_CHK_NULL_RETURN(dummyDmvBuffer = (uint8_t*)MOS_AllocAndZeroMemory(size)); mbDmvBuffer = dummyDmvBuffer; uint32_t i, numMBs = size / 64; for (i = 0; iCurrPic; uint8_t i, ii; if (picParams->pic_fields.field_pic_flag) { // Note: The AVC criteria of second field following first field is not compatible with MVC. // For MVC compatibility, a buffer of 16 frame indexes are used to store // the consecutive first fiels of different views in the same Acess Unit. ii = CODECHAL_DECODE_AVC_MAX_NUM_MVC_VIEWS; // Find if the current field is a second field (no matching first field) for (i = 0; i < CODECHAL_DECODE_AVC_MAX_NUM_MVC_VIEWS; i++) { if (m_firstFieldIdxList[i] == currPic.FrameIdx) { break; } // At the same time, find the first empty entrance to store the frame index. // Used when the current field is a first field. ii = (m_firstFieldIdxList[i] == CODECHAL_DECODE_AVC_INVALID_FRAME_IDX && ii == CODECHAL_DECODE_AVC_MAX_NUM_MVC_VIEWS) ? i : ii; } if ((prevPic.PicFlags != currPic.PicFlags) || (prevPic.FrameIdx != currPic.FrameIdx) || (currPic.PicFlags == PICTURE_INVALID)) { if (i < CODECHAL_DECODE_AVC_MAX_NUM_MVC_VIEWS) { m_isSecondField = true; m_firstFieldIdxList[i] = CODECHAL_DECODE_AVC_INVALID_FRAME_IDX; while (i > 0) // Clear all smaller indexes in case there are missing fields. { m_firstFieldIdxList[--i] = CODECHAL_DECODE_AVC_INVALID_FRAME_IDX; } } else { m_isSecondField = false; if (ii == CODECHAL_DECODE_AVC_MAX_NUM_MVC_VIEWS) { ii = 0; } else { m_firstFieldIdxList[ii++] = currPic.FrameIdx; } // Clear all larger indexes in case there are missing fields. while (ii < CODECHAL_DECODE_AVC_MAX_NUM_MVC_VIEWS) { m_firstFieldIdxList[ii++] = CODECHAL_DECODE_AVC_INVALID_FRAME_IDX; } } } m_height = MOS_ALIGN_CEIL(m_height, MOS_YTILE_H_ALIGNMENT); } else { for (i = 0; i < CODECHAL_DECODE_AVC_MAX_NUM_MVC_VIEWS; i++) { m_firstFieldIdxList[i] = CODECHAL_DECODE_AVC_INVALID_FRAME_IDX; } m_isSecondField = false; } m_statusReportFeedbackNumber = picParams->StatusReportFeedbackNumber; m_currPic = currPic; m_avcRefList[currPic.FrameIdx]->RefPic = m_currPic; m_avcRefList[currPic.FrameIdx]->resRefPic = m_destSurface.OsResource; // Override reference list with ref surface passed from DDI uint8_t surfCount = 0; uint8_t surfIndex = 0; if (m_osInterface->pfnIsMismatchOrderProgrammingSupported()) { while (surfIndex < CODEC_AVC_NUM_UNCOMPRESSED_SURFACE) { if (!Mos_ResourceIsNull(&m_refFrameSurface[surfIndex].OsResource)) { m_avcRefList[surfIndex]->resRefPic = m_refFrameSurface[surfIndex].OsResource; } surfIndex++; } } else { while (surfCount < m_refSurfaceNum && surfIndex < CODEC_AVC_NUM_UNCOMPRESSED_SURFACE) { if (!Mos_ResourceIsNull(&m_refFrameSurface[surfIndex].OsResource)) { m_avcRefList[surfIndex]->resRefPic = m_refFrameSurface[surfIndex].OsResource; surfCount++; } surfIndex++; } } uint8_t index, duplicatedIdx; for (i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++) { if (!CodecHal_PictureIsInvalid(picParams->RefFrameList[i])) { index = picParams->RefFrameList[i].FrameIdx; m_avcRefList[index]->sFrameNumber = picParams->FrameNumList[i]; } } PCODEC_AVC_DMV_LIST avcMVBufList = &m_avcDmvList[0]; uint8_t dmvidx; if (!CodecHal_PictureIsInvalid(prevPic)) { for (i = 0; i < CODEC_AVC_NUM_REF_DMV_BUFFERS; i++) { avcMVBufList[i].bInUse = false; } for (i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++) { if (!CodecHal_PictureIsInvalid(picParams->RefFrameList[i])) { index = picParams->RefFrameList[i].FrameIdx; avcMVBufList[m_avcRefList[index]->ucDMVIdx[0]].bInUse = true; avcMVBufList[m_avcRefList[index]->ucDMVIdx[1]].bInUse = true; } } } else if (m_avcRefList[currPic.FrameIdx]->bUsedAsRef && !m_isSecondField) { dmvidx = m_avcRefList[currPic.FrameIdx]->ucFrameId; if (m_avcFrameStoreId[dmvidx].reUse) { m_avcFrameStoreId[dmvidx].reUse = false; } else { m_avcFrameStoreId[dmvidx].inUse = false; } dmvidx = m_avcRefList[currPic.FrameIdx]->ucDMVIdx[0]; if (m_avcDmvList[dmvidx].bReUse) { m_avcDmvList[dmvidx].bReUse = false; } else { m_avcDmvList[dmvidx].bInUse = false; } dmvidx = m_avcRefList[currPic.FrameIdx]->ucDMVIdx[1]; if (m_avcDmvList[dmvidx].bReUse) { m_avcDmvList[dmvidx].bReUse = false; } else { m_avcDmvList[dmvidx].bInUse = false; } } if (picParams->pic_fields.reference_pic_flag) { if (!m_isSecondField) { m_avcRefList[currPic.FrameIdx]->bUsedAsRef = true; } } else { m_avcRefList[currPic.FrameIdx]->bUsedAsRef = false; } if (!m_isSecondField) { if (m_osInterface->pfnIsMismatchOrderProgrammingSupported()) { for (i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++) { auto frameIdx = picParams->RefFrameList[i].FrameIdx; if (frameIdx != CODECHAL_NUM_UNCOMPRESSED_SURFACE_HEVC) { CODECHAL_DECODE_CHK_STATUS_RETURN(SetAndAllocateDmvBufferIndexMismatched( frameIdx, m_avcDmvBufferSize, &m_avcMvBufferIndex, m_resAvcDmvBuffers)); dmvidx = m_avcMvBufferIndex; m_avcRefList[frameIdx]->ucDMVIdx[0] = dmvidx; m_avcRefList[frameIdx]->ucDMVIdx[1] = dmvidx; } } CODECHAL_DECODE_CHK_STATUS_RETURN(SetAndAllocateDmvBufferIndexMismatched( currPic.FrameIdx, m_avcDmvBufferSize, &m_avcMvBufferIndex, m_resAvcDmvBuffers)); dmvidx = m_avcMvBufferIndex; //first and second field will use the same DMV buffer in field mode m_avcRefList[currPic.FrameIdx]->ucDMVIdx[0] = dmvidx; m_avcRefList[currPic.FrameIdx]->ucDMVIdx[1] = dmvidx; } else { CODECHAL_DECODE_CHK_STATUS_RETURN(SetAndAllocateDmvBufferIndex( &m_avcDmvList[0], (bool)picParams->pic_fields.reference_pic_flag, currPic.FrameIdx, m_avcDmvBufferSize, &m_avcMvBufferIndex, m_resAvcDmvBuffers)); dmvidx = m_avcMvBufferIndex; //first and second field will use the same DMV buffer in field mode m_avcRefList[currPic.FrameIdx]->ucDMVIdx[0] = dmvidx; m_avcRefList[currPic.FrameIdx]->ucDMVIdx[1] = dmvidx; } } else { dmvidx = m_avcRefList[currPic.FrameIdx]->ucDMVIdx[1]; m_avcMvBufferIndex = dmvidx; } m_avcDmvList[dmvidx].ucFrameId = currPic.FrameIdx; for (i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++) { m_avcFrameStoreId[i].inUse = false; } PCODEC_PIC_ID picIdx = &m_avcPicIdx[0]; bool invalidRef = false; for (i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++) { picIdx[i].bValid = false; index = picParams->RefFrameList[i].FrameIdx; if (!CodecHal_PictureIsInvalid(picParams->RefFrameList[i])) { if (Mos_ResourceIsNull(&(m_avcRefList[index]->resRefPic))) { // when I picture has invalid reference pictures, reallocate resource for the referecnce pictures. if (picParams->pic_fields.IntraPicFlag) { eStatus = AllocateInvalidRefBuffer(); if (eStatus != MOS_STATUS_SUCCESS) { invalidRef = true; CODECHAL_DECODE_ASSERTMESSAGE("Can not allocate Invalid Ref Buffer."); continue; } m_avcRefList[index]->RefPic = picParams->RefFrameList[i]; m_avcRefList[index]->resRefPic = m_resInvalidRefBuffer; m_avcRefList[index]->bUsedAsRef = true; m_avcRefList[index]->ucDMVIdx[0] = m_avcRefList[currPic.FrameIdx]->ucDMVIdx[0]; m_avcRefList[index]->ucDMVIdx[1] = m_avcRefList[currPic.FrameIdx]->ucDMVIdx[1]; } else { invalidRef = false; CODECHAL_DECODE_ASSERTMESSAGE("Found Invalid Ref."); continue; } } duplicatedIdx = 0; for (ii = 0; ii < i; ii++) { if (picIdx[ii].bValid && index == picParams->RefFrameList[ii].FrameIdx) { duplicatedIdx = 1; break; } } if (duplicatedIdx) { continue; } m_avcRefList[index]->RefPic.PicFlags = CodecHal_CombinePictureFlags(m_avcRefList[index]->RefPic, picParams->RefFrameList[i]); m_avcRefList[index]->iFieldOrderCnt[0] = picParams->FieldOrderCntList[i][0]; m_avcRefList[index]->iFieldOrderCnt[1] = picParams->FieldOrderCntList[i][1]; picIdx[i].bValid = true; picIdx[i].ucPicIdx = index; if (!CodecHal_PictureIsInvalid(prevPic) && !m_osInterface->pfnIsMismatchOrderProgrammingSupported()) { for (ii = 0; ii < m_avcRefList[prevPic.FrameIdx]->ucNumRef; ii++) { if (index == m_avcRefList[prevPic.FrameIdx]->RefList[ii].FrameIdx) { if (m_avcRefList[index]->ucFrameId == 0x7f) { // Should never happen, something must be wrong CODECHAL_DECODE_ASSERTMESSAGE("Invaid Ref Frame Id Found"); m_avcRefList[index]->ucFrameId = 0; } m_avcFrameStoreId[m_avcRefList[index]->ucFrameId].inUse = true; break; } } if (ii == m_avcRefList[prevPic.FrameIdx]->ucNumRef) { m_avcRefList[index]->ucFrameId = 0x7f; } } else { m_avcDmvList[m_avcRefList[index]->ucDMVIdx[0]].ucFrameId = m_avcDmvList[m_avcRefList[index]->ucDMVIdx[1]].ucFrameId = m_avcRefList[index]->ucFrameId; } picIdx[i].ucDMVOffset[0] = m_avcRefList[index]->ucDMVIdx[0]; picIdx[i].ucDMVOffset[1] = m_avcRefList[index]->ucDMVIdx[1]; } } // Save the current RefList and corresponding reference frame flags ii = 0; uint16_t nonExistingFrameFlags = 0; uint32_t usedForReferenceFlags = 0; for (i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++) { if (picIdx[i].bValid) { m_avcRefList[currPic.FrameIdx]->RefList[ii] = picParams->RefFrameList[i]; nonExistingFrameFlags |= ((picParams->NonExistingFrameFlags >> i) & 1) << ii; usedForReferenceFlags |= ((picParams->UsedForReferenceFlags >> (i * 2)) & 3) << (ii * 2); ii++; } } m_avcRefList[currPic.FrameIdx]->ucNumRef = ii; m_avcRefList[currPic.FrameIdx]->usNonExistingFrameFlags = nonExistingFrameFlags; m_avcRefList[currPic.FrameIdx]->uiUsedForReferenceFlags = usedForReferenceFlags; if (m_osInterface->pfnIsMismatchOrderProgrammingSupported()) { for (uint32_t ii = 0; ii < CODEC_AVC_NUM_UNCOMPRESSED_SURFACE; ii++) { m_avcRefList[ii]->ucFrameId = 0x7f; } } SetFrameStoreIds(currPic.FrameIdx); // Store CurrFieldOrderCnt if (CodecHal_PictureIsBottomField(currPic)) { m_avcRefList[currPic.FrameIdx]->iFieldOrderCnt[1] = picParams->CurrFieldOrderCnt[1]; } else { m_avcRefList[currPic.FrameIdx]->iFieldOrderCnt[0] = picParams->CurrFieldOrderCnt[0]; if (CodecHal_PictureIsFrame(currPic)) { m_avcRefList[currPic.FrameIdx]->iFieldOrderCnt[1] = picParams->CurrFieldOrderCnt[1]; } } //MVC related inter-view reference m_avcRefList[currPic.FrameIdx]->bUsedAsInterViewRef = false; if (m_mvcExtPicParams) { if (m_mvcExtPicParams->inter_view_flag) { m_avcRefList[currPic.FrameIdx]->bUsedAsInterViewRef = true; } } if (invalidRef) { // There was an invalid reference, do not process the picture. return MOS_STATUS_UNKNOWN; } else { return MOS_STATUS_SUCCESS; } } MOS_STATUS CodechalDecodeAvc::AllocateResourcesVariableSizes() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; PCODEC_AVC_PIC_PARAMS picParam = m_avcPicParams; uint32_t numMacroblocks, numSliceRecords; uint16_t picWidthInMB, picHeightInMB; bool invalidSliceNum = false; picWidthInMB = MOS_MAX(m_picWidthInMbLastMaxAlloced, (picParam->pic_width_in_mbs_minus1 + 1)); picHeightInMB = MOS_MAX(m_picHeightInMbLastMaxAlloced, (picParam->pic_height_in_mbs_minus1 + 1)); numMacroblocks = picWidthInMB * picHeightInMB; numSliceRecords = numMacroblocks; if (m_numSlices > numMacroblocks) { invalidSliceNum = true; numSliceRecords = m_numSlices; } if ((numSliceRecords > (uint32_t)m_picWidthInMbLastMaxAlloced * m_picHeightInMbLastMaxAlloced) || (m_vldSliceRecord == nullptr)) { if (m_vldSliceRecord != nullptr) { MOS_FreeMemory(m_vldSliceRecord); } m_vldSliceRecord = (PCODECHAL_VLD_SLICE_RECORD)MOS_AllocAndZeroMemory(numSliceRecords * sizeof(CODECHAL_VLD_SLICE_RECORD)); if (m_vldSliceRecord == nullptr) { CODECHAL_DECODE_ASSERTMESSAGE("Failed to allocate memory."); eStatus = MOS_STATUS_NO_SPACE; return eStatus; } } if (invalidSliceNum == true) { for (uint32_t i = 0; i < numSliceRecords; i++) { m_vldSliceRecord[i].dwSkip = true; } } if ((picWidthInMB > m_picWidthInMbLastMaxAlloced) || Mos_ResourceIsNull(&m_resMfdDeblockingFilterRowStoreScratchBuffer)) { if (!Mos_ResourceIsNull(&m_resMfdDeblockingFilterRowStoreScratchBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resMfdDeblockingFilterRowStoreScratchBuffer); } // Deblocking Filter Row Store Scratch buffer //(Num MacroBlock Width) * (Num Cachlines) * (Cachline size) CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resMfdDeblockingFilterRowStoreScratchBuffer, picWidthInMB * 4 * CODECHAL_CACHELINE_SIZE, "DeblockingScratchBuffer"), "Failed to allocate Deblocking Filter Row Store Scratch Buffer."); } if (m_mfxInterface->IsBsdMpcRowstoreCacheEnabled() == false) { uint16_t tempBsdMpcRowStoreScratchBufferPicWidthInMB; tempBsdMpcRowStoreScratchBufferPicWidthInMB = MOS_MAX(m_bsdMpcRowStoreScratchBufferPicWidthInMb, (picParam->pic_width_in_mbs_minus1 + 1)); if ((tempBsdMpcRowStoreScratchBufferPicWidthInMB > m_bsdMpcRowStoreScratchBufferPicWidthInMb) || Mos_ResourceIsNull(&m_resBsdMpcRowStoreScratchBuffer)) { if (!Mos_ResourceIsNull(&m_resBsdMpcRowStoreScratchBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resBsdMpcRowStoreScratchBuffer); } // BSD/MPC Row Store Scratch buffer // (FrameWidth in MB) * (2) * (CacheLine size per MB) CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resBsdMpcRowStoreScratchBuffer, tempBsdMpcRowStoreScratchBufferPicWidthInMB * 2 * CODECHAL_CACHELINE_SIZE, "MpcScratchBuffer"), "Failed to allocate BSD/MPC Row Store Scratch Buffer."); } //record the width and height used for allocation internal resources. m_bsdMpcRowStoreScratchBufferPicWidthInMb = tempBsdMpcRowStoreScratchBufferPicWidthInMB; } if (m_mfxInterface->IsIntraRowstoreCacheEnabled() == false) { uint16_t tempMfdIntraRowStoreScratchBufferPicWidthInMB; tempMfdIntraRowStoreScratchBufferPicWidthInMB = MOS_MAX(m_mfdIntraRowStoreScratchBufferPicWidthInMb, (picParam->pic_width_in_mbs_minus1 + 1)); if ((tempMfdIntraRowStoreScratchBufferPicWidthInMB > m_mfdIntraRowStoreScratchBufferPicWidthInMb) || Mos_ResourceIsNull(&m_resMfdIntraRowStoreScratchBuffer)) { if (!Mos_ResourceIsNull(&m_resMfdIntraRowStoreScratchBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resMfdIntraRowStoreScratchBuffer); } // Intra Row Store Scratch buffer // (FrameWidth in MB) * (CacheLine size per MB) CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resMfdIntraRowStoreScratchBuffer, tempMfdIntraRowStoreScratchBufferPicWidthInMB * CODECHAL_CACHELINE_SIZE, "IntraScratchBuffer"), "Failed to allocate AVC BSD Intra Row Store Scratch Buffer."); } //record the width and height used for allocation internal resources. m_mfdIntraRowStoreScratchBufferPicWidthInMb = tempMfdIntraRowStoreScratchBufferPicWidthInMB; } if (m_mfxInterface->IsMprRowstoreCacheEnabled() == false) { uint16_t tempMprRowStoreScratchBufferPicWidthInMB; tempMprRowStoreScratchBufferPicWidthInMB = MOS_MAX(m_mprRowStoreScratchBufferPicWidthInMb, (picParam->pic_width_in_mbs_minus1 + 1)); if ((tempMprRowStoreScratchBufferPicWidthInMB > m_mprRowStoreScratchBufferPicWidthInMb) || Mos_ResourceIsNull(&m_resMprRowStoreScratchBuffer)) { if (!Mos_ResourceIsNull(&m_resMprRowStoreScratchBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resMprRowStoreScratchBuffer); } // MPR Row Store Scratch buffer // (FrameWidth in MB) * (CacheLine size per MB) * 2 // IVB+ platforms need to have double MPR size for MBAFF CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resMprRowStoreScratchBuffer, tempMprRowStoreScratchBufferPicWidthInMB * CODECHAL_CACHELINE_SIZE * 2, "MprScratchBuffer"), "Failed to allocate AVC BSD MPR Row Store Scratch Buffer."); } //record the width and height used for allocation internal resources. m_mprRowStoreScratchBufferPicWidthInMb = tempMprRowStoreScratchBufferPicWidthInMB; } uint32_t ctr; if ((picWidthInMB > m_picWidthInMbLastMaxAlloced) || (picHeightInMB > m_picHeightInMbLastMaxAlloced) || (m_avcDmvBufferSize == 0)) { uint32_t maxMvBuf = m_osInterface->pfnIsMismatchOrderProgrammingSupported() ? CODEC_AVC_NUM_UNCOMPRESSED_SURFACE : CODEC_AVC_NUM_DMV_BUFFERS; for (ctr = 0; ctr < maxMvBuf; ctr++) { if (!Mos_ResourceIsNull(&m_resAvcDmvBuffers[ctr])) { m_osInterface->pfnFreeResource( m_osInterface, &m_resAvcDmvBuffers[ctr]); } } // AVC MV buffer, 64 bytes per MB m_avcDmvBufferSize = 64 * picWidthInMB * (uint32_t)(MOS_ALIGN_CEIL(picHeightInMB, 2)); for (ctr = 0; ctr < 4; ctr++) { // Allocate first 3 ref DMV buffers and then grow as needed, always // allocate the last DMV buffer which is used for non referenced pictures. if (ctr == 3) { ctr = CODEC_AVC_NUM_DMV_BUFFERS - 1; } CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resAvcDmvBuffers[ctr], m_avcDmvBufferSize, "MvBuffer", true), "Failed to allocate Linux WA AVC BSD MV Buffer."); } } if (m_secureDecoder) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_secureDecoder->AllocateResource(this)); } //record the width and height used for allocation internal resources. m_picWidthInMbLastMaxAlloced = picWidthInMB; m_picHeightInMbLastMaxAlloced = picHeightInMB; return eStatus; } MOS_STATUS CodechalDecodeAvc::AllocateResourcesFixedSizes() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource( m_osInterface, &m_resSyncObjectWaContextInUse)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource( m_osInterface, &m_resSyncObjectVideoContextInUse)); MOS_LOCK_PARAMS lockFlagsWriteOnly; MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS)); lockFlagsWriteOnly.WriteOnly = 1; CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalAllocateDataList( m_avcRefList, CODEC_AVC_NUM_UNCOMPRESSED_SURFACE)); m_currPic.PicFlags = PICTURE_INVALID; m_currPic.FrameIdx = CODEC_AVC_NUM_UNCOMPRESSED_SURFACE; return eStatus; } MOS_STATUS CodechalDecodeAvc::InitMmcState() { #ifdef _MMC_SUPPORTED m_mmc = MOS_New(CodechalMmcDecodeAvc, m_hwInterface, this); CODECHAL_DECODE_CHK_NULL_RETURN(m_mmc); #endif return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeAvc::InitSfcState() { #ifdef _DECODE_PROCESSING_SUPPORTED m_sfcState = MOS_New(CodechalAvcSfcState); CODECHAL_DECODE_CHK_NULL_RETURN(m_sfcState); CODECHAL_DECODE_CHK_STATUS_RETURN(m_sfcState->InitializeSfcState( this, m_hwInterface, m_osInterface)); #endif return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeAvc::AllocateStandard( CodechalSetting *settings) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; CODECHAL_DECODE_CHK_NULL_RETURN(settings); CODECHAL_DECODE_CHK_STATUS_RETURN(InitMmcState()); if (settings->downsamplingHinted) { bool isComputeContextEnabled = false; MOS_GPUCTX_CREATOPTIONS createOption; #if (_DEBUG || _RELEASE_INTERNAL) MOS_USER_FEATURE_VALUE_DATA userFeatureData; MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData)); MOS_UserFeature_ReadValue_ID( nullptr, __MEDIA_USER_FEATURE_VALUE_DECODE_ENABLE_COMPUTE_CONTEXT_ID, &userFeatureData, m_osInterface->pOsContext); isComputeContextEnabled = (userFeatureData.u32Data) ? true : false; #endif if (!MEDIA_IS_SKU(m_skuTable, FtrCCSNode)) { isComputeContextEnabled = false; } if (isComputeContextEnabled) { // Create Render Context for field scaling CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateGpuContext( m_osInterface, MOS_GPU_CONTEXT_COMPUTE, MOS_GPU_NODE_COMPUTE, &createOption)); m_renderContext = MOS_GPU_CONTEXT_COMPUTE; } else { // Create Render Context for field scaling CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateGpuContext( m_osInterface, MOS_GPU_CONTEXT_RENDER, MOS_GPU_NODE_3D, &createOption)); m_renderContext = MOS_GPU_CONTEXT_RENDER; } } m_intelEntrypointInUse = (settings->intelEntrypointInUse) ? true : false; m_width = settings->width; m_height = settings->height; m_picWidthInMb = (uint16_t)CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_width); m_picHeightInMb = (uint16_t)CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_height); m_shortFormatInUse = (settings->shortFormatInUse) ? true : false; CODECHAL_DECODE_CHK_STATUS_RETURN(InitSfcState()); for (uint8_t i = 0; i < CODECHAL_DECODE_AVC_MAX_NUM_MVC_VIEWS; i++) { m_firstFieldIdxList[i] = CODECHAL_DECODE_AVC_INVALID_FRAME_IDX; } // Picture Level Commands m_hwInterface->GetMfxStateCommandsDataSize( CODECHAL_DECODE_MODE_AVCVLD, &m_commandBufferSizeNeeded, &m_commandPatchListSizeNeeded, m_shortFormatInUse); // Slice Level Commands (cannot be placed in 2nd level batch) m_hwInterface->GetMfxPrimitiveCommandsDataSize( CODECHAL_DECODE_MODE_AVCVLD, &m_standardDecodeSizeNeeded, &m_standardDecodePatchListSizeNeeded, m_shortFormatInUse); CODECHAL_DECODE_CHK_STATUS_RETURN(AllocateResourcesFixedSizes()); return eStatus; } CodechalDecodeAvc::~CodechalDecodeAvc() { CODECHAL_DECODE_FUNCTION_ENTER; CodecHalFreeDataList(m_avcRefList, CODEC_AVC_NUM_UNCOMPRESSED_SURFACE); m_osInterface->pfnDestroySyncResource( m_osInterface, &m_resSyncObjectWaContextInUse); m_osInterface->pfnDestroySyncResource( m_osInterface, &m_resSyncObjectVideoContextInUse); MOS_FreeMemory(m_vldSliceRecord); m_osInterface->pfnFreeResource( m_osInterface, &m_resMfdDeblockingFilterRowStoreScratchBuffer); m_osInterface->pfnFreeResource( m_osInterface, &m_resBsdMpcRowStoreScratchBuffer); m_osInterface->pfnFreeResource( m_osInterface, &m_resMfdIntraRowStoreScratchBuffer); m_osInterface->pfnFreeResource( m_osInterface, &m_resMprRowStoreScratchBuffer); if (!Mos_ResourceIsNull(&m_resMonoPictureChromaBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resMonoPictureChromaBuffer); } uint32_t maxMvBuf = m_osInterface->pfnIsMismatchOrderProgrammingSupported() ? CODEC_AVC_NUM_UNCOMPRESSED_SURFACE : CODEC_AVC_NUM_DMV_BUFFERS; for (uint32_t ctr = 0; ctr < maxMvBuf; ctr++) { m_osInterface->pfnFreeResource( m_osInterface, &m_resAvcDmvBuffers[ctr]); } if (!Mos_ResourceIsNull(&m_resInvalidRefBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resInvalidRefBuffer); } #ifdef _DECODE_PROCESSING_SUPPORTED if (m_sfcState) { MOS_Delete(m_sfcState); m_sfcState = nullptr; } #endif return; } MOS_STATUS CodechalDecodeAvc::SetFrameStates() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; CODECHAL_DECODE_CHK_NULL_RETURN(m_decodeParams.m_destSurface); m_dataSize = m_decodeParams.m_dataSize; m_dataOffset = m_decodeParams.m_dataOffset; m_numSlices = m_decodeParams.m_numSlices; m_avcPicParams = (PCODEC_AVC_PIC_PARAMS)m_decodeParams.m_picParams; m_mvcExtPicParams = (PCODEC_MVC_EXT_PIC_PARAMS)m_decodeParams.m_extPicParams; m_avcSliceParams = (PCODEC_AVC_SLICE_PARAMS)m_decodeParams.m_sliceParams; m_avcIqMatrixParams = (PCODEC_AVC_IQ_MATRIX_PARAMS)m_decodeParams.m_iqMatrixBuffer; m_destSurface = *(m_decodeParams.m_destSurface); m_refFrameSurface = m_decodeParams.m_refFrameSurface; m_refSurfaceNum = m_decodeParams.m_refSurfaceNum; CODECHAL_DECODE_CHK_NULL_RETURN(m_decodeParams.m_dataBuffer); m_resDataBuffer = *(m_decodeParams.m_dataBuffer); m_picIdRemappingInUse = (m_decodeParams.m_picIdRemappingInUse) ? true : false; m_cencBuf = m_decodeParams.m_cencBuf; m_fullFrameData = m_decodeParams.m_bFullFrameData; CODECHAL_DECODE_CHK_NULL_RETURN(m_avcPicParams); CODECHAL_DECODE_CHK_NULL_RETURN(m_avcIqMatrixParams); m_width = (m_avcPicParams->pic_width_in_mbs_minus1 + 1) * CODECHAL_MACROBLOCK_WIDTH; m_height = (m_avcPicParams->pic_height_in_mbs_minus1 + 1) * CODECHAL_MACROBLOCK_HEIGHT; m_deblockingEnabled = false; if (m_shortFormatInUse) { // When HW parses the slice_header, disable_deblocking_filter_idc is not yet known, // so always enable ILDB in this case. m_deblockingEnabled = true; } else { for (uint32_t i = 0; i < m_numSlices; i++) { if (m_avcSliceParams[i].disable_deblocking_filter_idc != 1) { m_deblockingEnabled = true; break; } } } if (m_mfxInterface->IsRowStoreCachingSupported()) { MHW_VDBOX_ROWSTORE_PARAMS rowstoreParams; MOS_ZeroMemory(&rowstoreParams, sizeof(rowstoreParams)); rowstoreParams.Mode = CODECHAL_DECODE_MODE_AVCVLD; rowstoreParams.bMbaff = m_avcPicParams->seq_fields.mb_adaptive_frame_field_flag; rowstoreParams.bIsFrame = m_avcPicParams->seq_fields.frame_mbs_only_flag; rowstoreParams.dwPicWidth = m_width; CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->SetRowstoreCachingOffsets(&rowstoreParams)); } CODECHAL_DECODE_CHK_STATUS_RETURN(AllocateResourcesVariableSizes()); CODECHAL_DECODE_CHK_STATUS_RETURN(SetPictureStructs()); CODECHAL_DECODE_CHK_STATUS_RETURN(FormatAvcMonoPicture(m_decodeParams.m_destSurface)); if (m_avcPicParams->pic_fields.IntraPicFlag) { m_perfType = I_TYPE; } else { // Not possible to determine whether P or B is used for short format. // For long format iterating through all of the slices to determine P vs // B, so in order to avoid this, declare all other pictures MIXED_TYPE. m_perfType = MIXED_TYPE; } #ifdef _DECODE_PROCESSING_SUPPORTED auto decProcessingParams = (DecodeProcessingParams *)m_decodeParams.m_procParams; if (decProcessingParams != nullptr) { if (!decProcessingParams->m_isReferenceOnlyPattern && m_downsamplingHinted) { CODECHAL_DECODE_CHK_NULL_RETURN(m_fieldScalingInterface); } CODECHAL_DECODE_CHK_STATUS_RETURN(m_sfcState->CheckAndInitialize( decProcessingParams, m_avcPicParams, m_width, m_height, m_deblockingEnabled)); if (!((!CodecHal_PictureIsFrame(m_avcPicParams->CurrPic) || m_avcPicParams->seq_fields.mb_adaptive_frame_field_flag) && (m_downsamplingHinted && m_fieldScalingInterface->IsFieldScalingSupported(decProcessingParams))) && m_sfcState->m_sfcPipeOut == false && !decProcessingParams->m_isReferenceOnlyPattern) { m_vdSfcSupported = false; } else { m_vdSfcSupported = true; } } #endif m_crrPic = m_avcPicParams->CurrPic; if(m_fullFieldsFrame == (PICTURE_BOTTOM_FIELD | PICTURE_TOP_FIELD)) { m_fullFieldsFrame = 0; } m_secondField = false; if(CodecHal_PictureIsField(m_avcPicParams->CurrPic)) { if(CodecHal_PictureIsTopField(m_avcPicParams->CurrPic)) { m_fullFieldsFrame |= PICTURE_TOP_FIELD; } if (CodecHal_PictureIsBottomField(m_avcPicParams->CurrPic)) { m_fullFieldsFrame |= PICTURE_BOTTOM_FIELD; } } else { m_fullFieldsFrame = 0; } if(m_fullFieldsFrame == (PICTURE_BOTTOM_FIELD | PICTURE_TOP_FIELD)) { m_secondField = true; } if (m_pCodechalOcaDumper) { m_pCodechalOcaDumper->SetAvcDecodeParam( m_avcPicParams, m_avcSliceParams, m_numSlices); } CODECHAL_DEBUG_TOOL( m_debugInterface->m_currPic = m_crrPic; m_debugInterface->m_secondField = m_secondField; m_debugInterface->m_frameType = m_perfType; if (m_avcPicParams) { CODECHAL_DECODE_CHK_STATUS_RETURN(DumpPicParams( m_avcPicParams)); } if (m_avcIqMatrixParams) { CODECHAL_DECODE_CHK_STATUS_RETURN(DumpIQParams( m_avcIqMatrixParams)); } if (m_mvcExtPicParams) { CODECHAL_DECODE_CHK_STATUS_RETURN(DumpMvcExtPicParams( m_mvcExtPicParams)); } if (m_avcSliceParams) { CODECHAL_DECODE_CHK_STATUS_RETURN(DumpSliceParams( m_avcSliceParams, m_numSlices)); }) return eStatus; } MOS_STATUS CodechalDecodeAvc::InitPicMhwParams( PIC_MHW_PARAMS *picMhwParams) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; PMOS_RESOURCE firstValidFrame = nullptr; if (MEDIA_IS_WA(m_waTable, WaDummyReference) && !Mos_ResourceIsNull(&m_dummyReference.OsResource)) { firstValidFrame = &m_dummyReference.OsResource; } else { firstValidFrame = &m_destSurface.OsResource; } CODECHAL_DECODE_CHK_NULL_RETURN(picMhwParams); picMhwParams->PipeModeSelectParams = {}; picMhwParams->PipeBufAddrParams = {}; picMhwParams->ImgParams = {}; MOS_ZeroMemory(&picMhwParams->SurfaceParams, sizeof(picMhwParams->SurfaceParams)); MOS_ZeroMemory(&picMhwParams->IndObjBaseAddrParams, sizeof(picMhwParams->IndObjBaseAddrParams)); MOS_ZeroMemory(&picMhwParams->BspBufBaseAddrParams, sizeof(picMhwParams->BspBufBaseAddrParams)); MOS_ZeroMemory(&picMhwParams->QmParams, sizeof(picMhwParams->QmParams)); MOS_ZeroMemory(&picMhwParams->PicIdParams, sizeof(picMhwParams->PicIdParams)); MOS_ZeroMemory(&picMhwParams->AvcDirectmodeParams, sizeof(picMhwParams->AvcDirectmodeParams)); picMhwParams->PipeModeSelectParams.Mode = CODECHAL_DECODE_MODE_AVCVLD; //enable decodestreamout if either app or codechal dump need it picMhwParams->PipeModeSelectParams.bStreamOutEnabled = m_decodeParams.m_streamOutEnabled || m_streamOutEnabled; picMhwParams->PipeModeSelectParams.bPostDeblockOutEnable = m_deblockingEnabled; picMhwParams->PipeModeSelectParams.bPreDeblockOutEnable = !m_deblockingEnabled; picMhwParams->PipeModeSelectParams.bShortFormatInUse = m_shortFormatInUse; picMhwParams->SurfaceParams.Mode = CODECHAL_DECODE_MODE_AVCVLD; picMhwParams->SurfaceParams.psSurface = &m_destSurface; picMhwParams->PipeBufAddrParams.Mode = CODECHAL_DECODE_MODE_AVCVLD; if (m_deblockingEnabled) { picMhwParams->PipeBufAddrParams.psPostDeblockSurface = &m_destSurface; } else { picMhwParams->PipeBufAddrParams.psPreDeblockSurface = &m_destSurface; } #ifdef _MMC_SUPPORTED CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetPipeBufAddr(&picMhwParams->PipeBufAddrParams)); #endif picMhwParams->PipeBufAddrParams.presMfdIntraRowStoreScratchBuffer = &m_resMfdIntraRowStoreScratchBuffer; picMhwParams->PipeBufAddrParams.presMfdDeblockingFilterRowStoreScratchBuffer = &m_resMfdDeblockingFilterRowStoreScratchBuffer; //Do not support export decode streamout to app buffer and codechal_dump simultenously //which can lead to extra memory copy //decode streamout to application if (m_decodeParams.m_streamOutEnabled) { picMhwParams->PipeBufAddrParams.presStreamOutBuffer = m_decodeParams.m_externalStreamOutBuffer; } //decode streamout to codechal_dump else if (m_streamOutEnabled) { picMhwParams->PipeBufAddrParams.presStreamOutBuffer = &(m_streamOutBuffer[m_streamOutCurrBufIdx]); CODECHAL_DEBUG_TOOL( // mark the buffer as in-use m_streamOutCurrStatusIdx[m_streamOutCurrBufIdx] = 0; ) } MOS_SURFACE dstSurface; uint8_t firstValidFrameId = CODEC_AVC_MAX_NUM_REF_FRAME; uint8_t activeFrameCnt = 0; uint8_t picIdx, frameId, i; MOS_ZeroMemory(m_presReferences, (sizeof(PMOS_RESOURCE) * CODEC_AVC_MAX_NUM_REF_FRAME)); for (i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++) { if (m_avcPicIdx[i].bValid) { activeFrameCnt++; picIdx = m_avcPicIdx[i].ucPicIdx; frameId = (m_picIdRemappingInUse) ? i : m_avcRefList[picIdx]->ucFrameId; m_presReferences[frameId] = &(m_avcRefList[picIdx]->resRefPic); CODECHAL_DEBUG_TOOL( MOS_ZeroMemory(&dstSurface, sizeof(MOS_SURFACE)); dstSurface.Format = Format_NV12; dstSurface.OsResource = *(m_presReferences[frameId]); CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo( m_osInterface, &dstSurface)); m_debugInterface->m_refIndex = frameId; std::string refSurfName = "RefSurf[" + std::to_string(static_cast(m_debugInterface->m_refIndex)) + "]"; CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface( &dstSurface, CodechalDbgAttr::attrDecodeReferenceSurfaces, refSurfName.data()));) if (frameId < firstValidFrameId) { firstValidFrameId = frameId; firstValidFrame = m_presReferences[frameId]; } } } for (i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++) { // error concealment for the unset reference addresses if (!m_presReferences[i]) { m_presReferences[i] = firstValidFrame; } } #ifdef _MMC_SUPPORTED CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->CheckReferenceList(&picMhwParams->PipeBufAddrParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetRefrenceSync(m_disableDecodeSyncLock, m_disableLockForTranscode)); #endif CODECHAL_DECODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(picMhwParams->PipeBufAddrParams.presReferences, sizeof(PMOS_RESOURCE) * CODEC_AVC_MAX_NUM_REF_FRAME, m_presReferences, sizeof(PMOS_RESOURCE) * CODEC_AVC_MAX_NUM_REF_FRAME)); picMhwParams->IndObjBaseAddrParams.Mode = CODECHAL_DECODE_MODE_AVCVLD; picMhwParams->IndObjBaseAddrParams.presDataBuffer = &m_resDataBuffer; picMhwParams->IndObjBaseAddrParams.dwDataSize = m_dataSize; picMhwParams->IndObjBaseAddrParams.dwDataOffset = m_dataOffset; if (m_secureDecoder) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_secureDecoder->SetBitstreamBuffer(&picMhwParams->IndObjBaseAddrParams)); } picMhwParams->BspBufBaseAddrParams.presBsdMpcRowStoreScratchBuffer = &m_resBsdMpcRowStoreScratchBuffer; picMhwParams->BspBufBaseAddrParams.presMprRowStoreScratchBuffer = &m_resMprRowStoreScratchBuffer; picMhwParams->QmParams.Standard = CODECHAL_AVC; picMhwParams->QmParams.pAvcIqMatrix = (PMHW_VDBOX_AVC_QM_PARAMS)m_avcIqMatrixParams; picMhwParams->PicIdParams.bPicIdRemappingInUse = m_picIdRemappingInUse; picMhwParams->PicIdParams.pAvcPicIdx = &(m_avcPicIdx[0]); picMhwParams->ImgParams.pAvcPicParams = m_avcPicParams; picMhwParams->ImgParams.pMvcExtPicParams = m_mvcExtPicParams; picMhwParams->ImgParams.ucActiveFrameCnt = activeFrameCnt; picMhwParams->AvcDirectmodeParams.CurrPic = m_currPic; picMhwParams->AvcDirectmodeParams.uiUsedForReferenceFlags = m_avcPicParams->UsedForReferenceFlags; picMhwParams->AvcDirectmodeParams.presAvcDmvBuffers = &(m_resAvcDmvBuffers[0]); picMhwParams->AvcDirectmodeParams.ucAvcDmvIdx = m_avcMvBufferIndex; picMhwParams->AvcDirectmodeParams.pAvcDmvList = &(m_avcDmvList[0]); picMhwParams->AvcDirectmodeParams.pAvcPicIdx = &(m_avcPicIdx[0]); picMhwParams->AvcDirectmodeParams.avcRefList = (void**)m_avcRefList; picMhwParams->AvcDirectmodeParams.bPicIdRemappingInUse = m_picIdRemappingInUse; picMhwParams->AvcDirectmodeParams.presMvcDummyDmvBuffer = &(m_resMvcDummyDmvBuffer[(m_avcPicParams->seq_fields.direct_8x8_inference_flag) ? 1 : 0]); CODECHAL_DEBUG_TOOL( CODEC_REF_LIST * *refList; MHW_MI_CHK_NULL(refList = (CODEC_REF_LIST **)picMhwParams->AvcDirectmodeParams.avcRefList); for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME; i++) { if (picMhwParams->AvcDirectmodeParams.pAvcPicIdx[i].bValid) { uint8_t idx = picMhwParams->AvcDirectmodeParams.pAvcPicIdx[i].ucPicIdx; uint8_t picID = picMhwParams->AvcDirectmodeParams.bPicIdRemappingInUse ? i : refList[idx]->ucFrameId; uint8_t mvIdx = refList[idx]->ucDMVIdx[0]; // dump Reference mvdata std::string mvBufDumpName = "_DEC_Ref_MV_" + std::to_string(i); CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &picMhwParams->AvcDirectmodeParams.presAvcDmvBuffers[mvIdx], CodechalDbgAttr::attrMvData, mvBufDumpName.c_str(), m_avcDmvBufferSize)); } } // dump Current mvdata CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &picMhwParams->AvcDirectmodeParams.presAvcDmvBuffers[picMhwParams->AvcDirectmodeParams.ucAvcDmvIdx], CodechalDbgAttr::attrMvData, "DEC_Cur_MV_", m_avcDmvBufferSize)); ); return eStatus; } MOS_STATUS CodechalDecodeAvc::AddPictureCmds( PMOS_COMMAND_BUFFER cmdBuf, PIC_MHW_PARAMS *picMhwParams) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; CODECHAL_DECODE_CHK_NULL_RETURN(cmdBuf); CODECHAL_DECODE_CHK_NULL_RETURN(picMhwParams); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeModeSelectCmd(cmdBuf, &picMhwParams->PipeModeSelectParams)); #ifdef _DECODE_PROCESSING_SUPPORTED CODECHAL_DECODE_CHK_STATUS_RETURN(m_sfcState->AddSfcCommands(cmdBuf)); #endif CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxSurfaceCmd(cmdBuf, &picMhwParams->SurfaceParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeBufAddrCmd(cmdBuf, &picMhwParams->PipeBufAddrParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxIndObjBaseAddrCmd(cmdBuf, &picMhwParams->IndObjBaseAddrParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxBspBufBaseAddrCmd(cmdBuf, &picMhwParams->BspBufBaseAddrParams)); if (m_shortFormatInUse) { MHW_VDBOX_AVC_DPB_PARAMS dpbParams; MOS_ZeroMemory(&dpbParams, sizeof(dpbParams)); dpbParams.pAvcPicParams = m_avcPicParams; dpbParams.pMvcExtPicParams = m_mvcExtPicParams; dpbParams.ppAvcRefList = &(m_avcRefList[0]); dpbParams.pAvcPicIdx = &(m_avcPicIdx[0]); dpbParams.bPicIdRemappingInUse = m_picIdRemappingInUse; CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdAvcDpbCmd(cmdBuf, &dpbParams)); } CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdAvcPicidCmd(cmdBuf, &picMhwParams->PicIdParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcImgCmd(cmdBuf, nullptr, &picMhwParams->ImgParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxQmCmd(cmdBuf, &picMhwParams->QmParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcDirectmodeCmd(cmdBuf, &picMhwParams->AvcDirectmodeParams)); return eStatus; } MOS_STATUS CodechalDecodeAvc::DecodeStateLevel() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; if (m_secureDecoder) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_secureDecoder->Execute(this)); } MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking( &cmdBuffer, true)); PIC_MHW_PARAMS picMhwParams; CODECHAL_DECODE_CHK_STATUS_RETURN(InitPicMhwParams(&picMhwParams)); auto mmioRegisters = m_hwInterface->GetMfxInterface()->GetMmioRegisters(m_vdboxIndex); HalOcaInterface::On1stLevelBBStart(cmdBuffer, *m_osInterface->pOsContext, m_osInterface->CurrentGpuContextHandle, *m_miInterface, *mmioRegisters); if (m_cencBuf && m_cencBuf->checkStatusRequired) { CODECHAL_DECODE_COND_ASSERTMESSAGE((m_vdboxIndex > m_hwInterface->GetMfxInterface()->GetMaxVdboxIndex()), "ERROR - vdbox index exceed the maximum"); CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->GetCpInterface()->CheckStatusReportNum( mmioRegisters, m_cencBuf->bufIdx, m_cencBuf->resStatus, &cmdBuffer)); } if (m_statusQueryReportingEnabled) { CODECHAL_DECODE_CHK_STATUS_RETURN(StartStatusReport(&cmdBuffer)); } CODECHAL_DECODE_CHK_STATUS_RETURN(AddPictureCmds(&cmdBuffer, &picMhwParams)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); return eStatus; } MOS_STATUS CodechalDecodeAvc::ParseSlice( PMOS_COMMAND_BUFFER cmdBuf) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; PCODEC_AVC_SLICE_PARAMS slc = m_avcSliceParams; uint16_t frameInMbs = (m_avcPicParams->pic_height_in_mbs_minus1 + 1) * (m_avcPicParams->pic_width_in_mbs_minus1 + 1); CODECHAL_DECODE_CHK_NULL_RETURN(m_vldSliceRecord); CODECHAL_DECODE_CHK_NULL_RETURN(slc); // Setup static slice state parameters MHW_VDBOX_AVC_SLICE_STATE avcSliceState; MOS_ZeroMemory(&avcSliceState, sizeof(avcSliceState)); avcSliceState.bIntelEntrypointInUse = m_intelEntrypointInUse; avcSliceState.bPicIdRemappingInUse = m_picIdRemappingInUse; avcSliceState.bShortFormatInUse = m_shortFormatInUse; avcSliceState.presDataBuffer = &m_resDataBuffer; avcSliceState.pAvcPicParams = m_avcPicParams; avcSliceState.pMvcExtPicParams = m_mvcExtPicParams; avcSliceState.pAvcPicIdx = &(m_avcPicIdx[0]); avcSliceState.bPhantomSlice = false; avcSliceState.dwTotalBytesConsumed = 0; uint32_t length = 0, slcCount = 0; uint32_t offset = 0; uint32_t lastValidSlice = 0; bool firstValidSlice = true; bool invalidSlicePresent = false; for (slcCount = 0; slcCount < m_numSlices; slcCount++) { if (invalidSlicePresent == true) { break; } if (m_vldSliceRecord[slcCount].dwSkip) { continue; } length = slc->slice_data_size; if (slcCount < m_numSlices - 1) { // Skip remaining slices if the number of MBs already reaches the total before the last slice or slice overlap occurs. if ((!m_shortFormatInUse) && ((slc->first_mb_in_slice + slc->NumMbsForSlice >= frameInMbs) || ((slc + 1)->first_mb_in_slice <= slc->first_mb_in_slice))) { uint32_t count = slcCount + 1; slc->first_mb_in_next_slice = 0; invalidSlicePresent = true; while (count < m_numSlices) { m_vldSliceRecord[count++].dwSkip = true; } } else { slc->first_mb_in_next_slice = (slc + 1)->first_mb_in_slice; } } else { slc->first_mb_in_next_slice = 0; } // error handling for garbage data if (((uint64_t)(slc->slice_data_offset) + length) > m_dataSize) { slc++; m_vldSliceRecord[slcCount].dwSkip = true; continue; } if (!m_shortFormatInUse) { offset = (slc->slice_data_bit_offset >> 3) + m_osInterface->dwNumNalUnitBytesIncluded; if (offset > length) { slc++; m_vldSliceRecord[slcCount].dwSkip = true; continue; } // For first slice, first_mb_in_slice must be 0, otherwise it is corrupted // Skip slice when first_mb_in_slice is corrupted. if ((0 == slcCount && slc->first_mb_in_slice) || (slc->first_mb_in_slice >= frameInMbs) || (m_avcPicParams->seq_fields.mb_adaptive_frame_field_flag && !m_avcPicParams->pic_fields.field_pic_flag && (slc->first_mb_in_slice >= frameInMbs / 2))) { slc++; m_vldSliceRecord[slcCount].dwSkip = true; continue; } if (firstValidSlice && slc->first_mb_in_slice) { uint16_t usStartMbNum, usNextStartMbNum; // ensure that slc->first_mb_in_next_slice is always non-zero for this phantom slice usNextStartMbNum = slc->first_mb_in_next_slice; usStartMbNum = slc->first_mb_in_slice; slc->first_mb_in_slice = 0; slc->first_mb_in_next_slice = usStartMbNum; avcSliceState.pAvcSliceParams = slc; avcSliceState.dwOffset = 0; avcSliceState.dwLength = slc->slice_data_offset; avcSliceState.dwNextOffset = slc->slice_data_offset; avcSliceState.dwNextLength = slc->slice_data_size; CODECHAL_DECODE_CHK_STATUS_RETURN(SendSlice(&avcSliceState, cmdBuf)); slc->first_mb_in_slice = usStartMbNum; slc->first_mb_in_next_slice = usNextStartMbNum; } } firstValidSlice = false; lastValidSlice = slcCount; length -= offset; m_vldSliceRecord[slcCount].dwLength = length; m_vldSliceRecord[slcCount].dwOffset = offset; slc++; } slc = m_avcSliceParams; uint32_t skippedSlc = 0; for (slcCount = 0; slcCount < m_numSlices; slcCount++) { if (m_vldSliceRecord[slcCount].dwSkip) { //For DECE clear bytes calculation: Total bytes in the bit-stream consumed so far avcSliceState.dwTotalBytesConsumed = slc->slice_data_offset + slc->slice_data_size; slc++; skippedSlc++; continue; } if (slcCount < lastValidSlice) { offset = (slc + 1)->slice_data_offset; length = (slc + 1)->slice_data_size; } avcSliceState.pAvcSliceParams = slc; avcSliceState.dwOffset = m_vldSliceRecord[slcCount].dwOffset; avcSliceState.dwLength = m_vldSliceRecord[slcCount].dwLength; avcSliceState.dwNextOffset = offset; avcSliceState.dwNextLength = length; avcSliceState.dwSliceIndex = slcCount; avcSliceState.bLastSlice = (slcCount == lastValidSlice); avcSliceState.bFullFrameData = m_fullFrameData; CODECHAL_DECODE_CHK_STATUS_RETURN(SendSlice(&avcSliceState, cmdBuf)); //For DECE clear bytes calculation: Total bytes in the bit-stream consumed so far avcSliceState.dwTotalBytesConsumed = slc->slice_data_offset + slc->slice_data_size; slc++; } MOS_ZeroMemory(m_vldSliceRecord, (m_numSlices * sizeof(CODECHAL_VLD_SLICE_RECORD))); return eStatus; } MOS_STATUS CodechalDecodeAvc::DecodePrimitiveLevel() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; CODECHAL_DECODE_CHK_NULL_RETURN(m_osInterface); CODECHAL_DECODE_CHK_NULL_RETURN(m_avcPicParams); MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); if (m_cencBuf) { CODECHAL_DECODE_CHK_STATUS_RETURN(SetCencBatchBuffer(&cmdBuffer)); } else { CODECHAL_DECODE_CHK_STATUS_RETURN(ParseSlice(&cmdBuffer)); } // Check if destination surface needs to be synchronized MOS_SYNC_PARAMS syncParams; syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContext; syncParams.presSyncResource = &m_destSurface.OsResource; syncParams.bReadOnly = false; syncParams.bDisableDecodeSyncLock = m_disableDecodeSyncLock; syncParams.bDisableLockForTranscode = m_disableLockForTranscode; if (!CodecHal_PictureIsField(m_avcPicParams->CurrPic) || !m_isSecondField) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(m_osInterface, &syncParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams)); // Update the resource tag (s/w tag) for On-Demand Sync m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams); } MHW_MI_FLUSH_DW_PARAMS flushDwParams; MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd( &cmdBuffer, &flushDwParams)); // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag if (m_osInterface->bTagResourceSync && (!CodecHal_PictureIsField(m_avcPicParams->CurrPic) || m_isSecondField)) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource(&cmdBuffer, &syncParams)); } if (m_statusQueryReportingEnabled) { CodechalDecodeStatusReport decodeStatusReport; decodeStatusReport.m_statusReportNumber = m_statusReportFeedbackNumber; decodeStatusReport.m_currDecodedPic = m_avcPicParams->CurrPic; decodeStatusReport.m_currDeblockedPic = m_avcPicParams->CurrPic; decodeStatusReport.m_codecStatus = CODECHAL_STATUS_UNAVAILABLE; decodeStatusReport.m_currDecodedPicRes = m_avcRefList[m_avcPicParams->CurrPic.FrameIdx]->resRefPic; CODECHAL_DEBUG_TOOL( if (m_streamOutEnabled) { // add current streamout buffer to the report and move onto the next one decodeStatusReport.m_streamOutBuf = &(m_streamOutBuffer[m_streamOutCurrBufIdx]); decodeStatusReport.m_streamoutIdx = m_streamOutCurrBufIdx; if (++m_streamOutCurrBufIdx >= CODECHAL_DECODE_NUM_STREAM_OUT_BUFFERS) { m_streamOutCurrBufIdx = 0; } // check next buffer in the list is free. if (m_streamOutCurrStatusIdx[m_streamOutCurrBufIdx] != CODECHAL_DECODE_STATUS_NUM) { // We've run out of buffers. Temporarily lock the next one down to force a wait. Then mark it as free. CodechalResLock ResourceLock(m_osInterface, &(m_streamOutBuffer[m_streamOutCurrBufIdx])); ResourceLock.Lock(CodechalResLock::readOnly); m_streamOutCurrStatusIdx[m_streamOutCurrBufIdx] = CODECHAL_DECODE_STATUS_NUM; } } decodeStatusReport.m_secondField = m_secondField; decodeStatusReport.m_frameType = m_perfType;) CODECHAL_DECODE_CHK_STATUS_RETURN(EndStatusReport(decodeStatusReport, &cmdBuffer)); } CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); bool syncCompleteFrame = (m_avcPicParams->seq_fields.chroma_format_idc == avcChromaFormatMono && !m_hwInterface->m_noHuC); if (syncCompleteFrame) { syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContextForWa; syncParams.presSyncResource = &m_resSyncObjectWaContextInUse; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams)); syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContext; syncParams.presSyncResource = &m_resSyncObjectWaContextInUse; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams)); } CODECHAL_DEBUG_TOOL( CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer( &cmdBuffer, CODECHAL_NUM_MEDIA_STATES, "_DEC")); //CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHal_DbgReplaceAllCommands( // m_debugInterface, // &cmdBuffer)); ) HalOcaInterface::DumpCodechalParam(cmdBuffer, (MOS_CONTEXT_HANDLE)m_osInterface->pOsContext, m_pCodechalOcaDumper, CODECHAL_AVC); HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_videoContextUsesNullHw)); CODECHAL_DEBUG_TOOL( m_mmc->UpdateUserFeatureKey(&m_destSurface);) #ifdef _DECODE_PROCESSING_SUPPORTED auto decProcessingParams = (DecodeProcessingParams *)m_decodeParams.m_procParams; if (decProcessingParams != nullptr && !m_sfcState->m_sfcPipeOut && (m_isSecondField || m_avcPicParams->seq_fields.mb_adaptive_frame_field_flag)) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_fieldScalingInterface->DoFieldScaling( decProcessingParams, m_renderContext, m_disableDecodeSyncLock, m_disableLockForTranscode)); } else #endif { if (m_statusQueryReportingEnabled) { CODECHAL_DECODE_CHK_STATUS_RETURN(ResetStatusReport(m_videoContextUsesNullHw)); } } // Needs to be re-set for Linux buffer re-use scenarios m_avcRefList[m_avcPicParams->CurrPic.FrameIdx]->resRefPic = m_destSurface.OsResource; // Send the signal to indicate decode completion, in case On-Demand Sync is not present if (!CodecHal_PictureIsField(m_avcPicParams->CurrPic) || m_isSecondField) { syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContext; syncParams.presSyncResource = &m_destSurface.OsResource; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams)); #ifdef _DECODE_PROCESSING_SUPPORTED if (decProcessingParams && !m_sfcState->m_sfcPipeOut) { syncParams = g_cInitSyncParams; syncParams.GpuContext = m_renderContext; syncParams.presSyncResource = &decProcessingParams->m_outputSurface->OsResource; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams)); } #endif } #ifdef _DECODE_PROCESSING_SUPPORTED CODECHAL_DEBUG_TOOL( // Dump out downsampling result if (decProcessingParams && decProcessingParams->m_outputSurface) { MOS_SURFACE dstSurface; MOS_ZeroMemory(&dstSurface, sizeof(dstSurface)); dstSurface.Format = Format_NV12; dstSurface.OsResource = decProcessingParams->m_outputSurface->OsResource; CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo( m_osInterface, &dstSurface)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface( &dstSurface, CodechalDbgAttr::attrSfcOutputSurface, "SfcDstSurf")); } ) #endif return eStatus; } MOS_STATUS CodechalDecodeAvc::CalcDownsamplingParams( void *picParams, uint32_t *refSurfWidth, uint32_t *refSurfHeight, MOS_FORMAT *format, uint8_t *frameIdx) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_CHK_NULL_RETURN(picParams); CODECHAL_DECODE_CHK_NULL_RETURN(refSurfWidth); CODECHAL_DECODE_CHK_NULL_RETURN(refSurfHeight); CODECHAL_DECODE_CHK_NULL_RETURN(format); CODECHAL_DECODE_CHK_NULL_RETURN(frameIdx); PCODEC_AVC_PIC_PARAMS avcPicParams = (PCODEC_AVC_PIC_PARAMS)picParams; *refSurfWidth = 0; *refSurfHeight = 0; *format = Format_NV12; *frameIdx = avcPicParams->CurrPic.FrameIdx; *refSurfWidth = (avcPicParams->pic_width_in_mbs_minus1 + 1) * CODECHAL_MACROBLOCK_WIDTH; *refSurfHeight = (avcPicParams->pic_height_in_mbs_minus1 + 1) * CODECHAL_MACROBLOCK_HEIGHT; return eStatus; } CodechalDecodeAvc::CodechalDecodeAvc( CodechalHwInterface *hwInterface, CodechalDebugInterface* debugInterface, PCODECHAL_STANDARD_INFO standardInfo) : CodechalDecode(hwInterface, debugInterface, standardInfo) { m_mmc = nullptr; m_hwInterface = hwInterface; // Parameters passed by application m_picWidthInMb = 0; m_picHeightInMb = 0; m_picWidthInMbLastMaxAlloced = 0; m_picHeightInMbLastMaxAlloced = 0; m_intelEntrypointInUse = false; m_shortFormatInUse = false; m_picIdRemappingInUse = false; m_dataSize = 0; m_dataOffset = 0; m_numSlices = 0; m_refSurfaceNum = 0; m_avcPicParams = nullptr; m_mvcExtPicParams = nullptr; m_avcSliceParams = nullptr; m_avcIqMatrixParams = nullptr; MOS_ZeroMemory(m_presReferences, (sizeof(PMOS_RESOURCE) * CODEC_AVC_MAX_NUM_REF_FRAME)); MOS_ZeroMemory(&m_resDataBuffer, sizeof(MOS_RESOURCE)); MOS_ZeroMemory(&m_resMonoPictureChromaBuffer, sizeof(MOS_RESOURCE)); MOS_ZeroMemory(&m_resMfdIntraRowStoreScratchBuffer, sizeof(MOS_RESOURCE)); MOS_ZeroMemory(&m_resMfdDeblockingFilterRowStoreScratchBuffer, sizeof(MOS_RESOURCE)); MOS_ZeroMemory(&m_resBsdMpcRowStoreScratchBuffer, sizeof(MOS_RESOURCE)); MOS_ZeroMemory(&m_resMprRowStoreScratchBuffer, sizeof(MOS_RESOURCE)); MOS_ZeroMemory(&m_resAvcDmvBuffers, (sizeof(MOS_RESOURCE) * CODEC_AVC_NUM_UNCOMPRESSED_SURFACE)); MOS_ZeroMemory(&m_resInvalidRefBuffer, sizeof(MOS_RESOURCE)); MOS_ZeroMemory(&m_resMvcDummyDmvBuffer, (sizeof(MOS_RESOURCE) * 2)); MOS_ZeroMemory(&m_destSurface, sizeof(MOS_SURFACE)); MOS_ZeroMemory(&m_resSyncObjectWaContextInUse, sizeof(MOS_RESOURCE)); MOS_ZeroMemory(&m_resSyncObjectVideoContextInUse, sizeof(MOS_RESOURCE)); m_refFrameSurface = nullptr; m_vldSliceRecord = nullptr; m_bsdMpcRowStoreScratchBufferPicWidthInMb = 0; m_mfdIntraRowStoreScratchBufferPicWidthInMb = 0; m_mprRowStoreScratchBufferPicWidthInMb = 0; MOS_ZeroMemory(m_firstFieldIdxList, (sizeof(uint8_t) * CODECHAL_DECODE_AVC_MAX_NUM_MVC_VIEWS)); m_isSecondField = false; m_deblockingEnabled = false; // Decode process usage MOS_ZeroMemory(&m_currPic, sizeof(CODEC_PICTURE)); MOS_ZeroMemory(&m_avcFrameStoreId, (sizeof(CODEC_AVC_FRAME_STORE_ID) * CODEC_AVC_MAX_NUM_REF_FRAME)); m_avcMvBufferIndex = 0; MOS_ZeroMemory(&m_avcDmvList, (sizeof(CODEC_AVC_DMV_LIST) * CODEC_AVC_NUM_DMV_BUFFERS)); MOS_ZeroMemory(&m_avcPicIdx, (sizeof(CODEC_PIC_ID) * CODEC_AVC_MAX_NUM_REF_FRAME)); MOS_ZeroMemory(m_avcRefList, (sizeof(PCODEC_REF_LIST) * CODEC_AVC_NUM_UNCOMPRESSED_SURFACE)); m_avcDmvBufferSize = 0; //Currently, crc calculation is only supported in AVC decoder m_reportFrameCrc = true; m_fullFrameData = false; }; #if USE_CODECHAL_DEBUG_TOOL MOS_STATUS CodechalDecodeAvc::DumpMvcExtPicParams( PCODEC_MVC_EXT_PIC_PARAMS mvcExtPicParams) { CODECHAL_DEBUG_FUNCTION_ENTER; if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrMvcExtPicParams)) { return MOS_STATUS_SUCCESS; } CODECHAL_DEBUG_CHK_NULL(mvcExtPicParams); std::ostringstream oss; oss.setf(std::ios::showbase | std::ios::uppercase); oss << "CurrViewID: " << std::hex << +mvcExtPicParams->CurrViewID << std::endl; oss << "anchor_pic_flag: " << +mvcExtPicParams->anchor_pic_flag << std::endl; oss << "inter_view_flag: " << +mvcExtPicParams->inter_view_flag << std::endl; oss << "NumInterViewRefsL0: " << +mvcExtPicParams->NumInterViewRefsL0 << std::endl; oss << "NumInterViewRefsL1: " << +mvcExtPicParams->NumInterViewRefsL1 << std::endl; oss << "bPicFlags: " << +mvcExtPicParams->bPicFlags << std::endl; oss << "SwitchToAVC: " << +mvcExtPicParams->SwitchToAVC << std::endl; oss << "Reserved7Bits: " << +mvcExtPicParams->Reserved7Bits << std::endl; oss << "Reserved8Bits: " << +mvcExtPicParams->Reserved8Bits << std::endl; //Dump ViewIDList[16] for (uint8_t i = 0; i < 16; ++i) { oss << "ViewIDList[" << +i << "]: " << +mvcExtPicParams->ViewIDList[i] << std::endl; } //Dump InterViewRefList[2][16] for (uint8_t i = 0; i < 16; ++i) { oss << "InterViewRefList[0][" << +i << "]: " << +mvcExtPicParams->InterViewRefList[0][i] << std::endl; oss << "InterViewRefList[1][" << +i << "]: " << +mvcExtPicParams->InterViewRefList[1][i] << std::endl; } const char *fileName = m_debugInterface->CreateFileName( "_DEC", CodechalDbgBufferType::bufMvcPicParams, CodechalDbgExtType::txt); std::ofstream ofs(fileName, std::ios::out); ofs << oss.str(); ofs.close(); return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeAvc::DumpPicParams( PCODEC_AVC_PIC_PARAMS picParams) { CODECHAL_DEBUG_FUNCTION_ENTER; if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrPicParams)) { return MOS_STATUS_SUCCESS; } CODECHAL_DEBUG_CHK_NULL(picParams); std::ostringstream oss; oss.setf(std::ios::showbase | std::ios::uppercase); oss << "CurrPic FrameIdx: " << std::dec << +picParams->CurrPic.FrameIdx << std::endl; oss << "CurrPic PicFlags: " << std::hex << +picParams->CurrPic.PicFlags << std::endl; //Dump RefFrameList[15] for (uint8_t i = 0; i < 15; ++i) { oss << "RefFrameList[" << std::dec << +i << "] FrameIdx:" << +picParams->RefFrameList[i].FrameIdx << std::endl; oss << "RefFrameList[" << +i << "] PicFlags:" << std::hex << +picParams->RefFrameList[i].PicFlags << std::endl; } oss << "pic_width_in_mbs_minus1: " << std::dec << +picParams->pic_width_in_mbs_minus1 << std::endl; oss << "pic_height_in_mbs_minus1: " << +picParams->pic_height_in_mbs_minus1 << std::endl; oss << "bit_depth_luma_minus8: " << +picParams->bit_depth_luma_minus8 << std::endl; oss << "bit_depth_chroma_minus8: " << +picParams->bit_depth_chroma_minus8 << std::endl; oss << "num_ref_frames: " << +picParams->num_ref_frames << std::endl; oss << "CurrFieldOrderCnt: " << +picParams->CurrFieldOrderCnt[0] << std::endl; oss << "CurrFieldOrderCnt: " << +picParams->CurrFieldOrderCnt[1] << std::endl; //Dump FieldOrderCntList (16x2) for (uint8_t i = 0; i < 2; ++i) { oss << "FieldOrderCntList[" << +i << "]:"; for (uint8_t j = 0; j < 16; j++) oss << +picParams->FieldOrderCntList[j][i] << " "; oss << std::endl; } //Dump seq_fields oss << "seq_fields value: " << +picParams->seq_fields.value << std::endl; oss << "chroma_format_idc: " << +picParams->seq_fields.chroma_format_idc << std::endl; oss << "residual_colour_transform_flag: " << std::hex << +picParams->seq_fields.residual_colour_transform_flag << std::endl; oss << "frame_mbs_only_flag: " << std::hex << +picParams->seq_fields.frame_mbs_only_flag << std::endl; oss << "mb_adaptive_frame_field_flag: " << std::hex << +picParams->seq_fields.mb_adaptive_frame_field_flag << std::endl; oss << "direct_8x8_inference_flag: " << std::hex << +picParams->seq_fields.direct_8x8_inference_flag << std::endl; oss << "log2_max_frame_num_minus4: " << std::dec << +picParams->seq_fields.log2_max_frame_num_minus4 << std::endl; oss << "pic_order_cnt_type: " << +picParams->seq_fields.pic_order_cnt_type << std::endl; oss << "log2_max_pic_order_cnt_lsb_minus4: " << +picParams->seq_fields.log2_max_pic_order_cnt_lsb_minus4 << std::endl; oss << "delta_pic_order_always_zero_flag: " << std::hex << +picParams->seq_fields.delta_pic_order_always_zero_flag << std::endl; oss << "num_slice_groups_minus1:" << std::dec << +picParams->num_slice_groups_minus1 << std::endl; oss << "slice_group_map_type:" << std::dec << +picParams->slice_group_map_type << std::endl; oss << "slice_group_change_rate_minus1:" << std::dec << +picParams->slice_group_change_rate_minus1 << std::endl; oss << "pic_init_qp_minus26:" << std::dec << +picParams->pic_init_qp_minus26 << std::endl; oss << "chroma_qp_index_offset:" << std::dec << +picParams->chroma_qp_index_offset << std::endl; oss << "second_chroma_qp_index_offset:" << std::dec << +picParams->second_chroma_qp_index_offset << std::endl; //Dump pic_fields oss << "pic_fields value: " << std::dec << +picParams->pic_fields.value << std::endl; oss << "entropy_coding_mode_flag: " << std::hex << +picParams->pic_fields.entropy_coding_mode_flag << std::endl; oss << "weighted_pred_flag: " << std::hex << +picParams->pic_fields.weighted_pred_flag << std::endl; oss << "weighted_bipred_idc: " << std::dec << +picParams->pic_fields.weighted_bipred_idc << std::endl; oss << "transform_8x8_mode_flag: " << std::hex << +picParams->pic_fields.transform_8x8_mode_flag << std::endl; oss << "field_pic_flag: " << std::hex << +picParams->pic_fields.field_pic_flag << std::endl; oss << "constrained_intra_pred_flag: " << std::hex << +picParams->pic_fields.constrained_intra_pred_flag << std::endl; oss << "pic_order_present_flag: " << std::hex << +picParams->pic_fields.pic_order_present_flag << std::endl; oss << "deblocking_filter_control_present_flag: " << std::hex << +picParams->pic_fields.deblocking_filter_control_present_flag << std::endl; oss << "redundant_pic_cnt_present_flag: " << std::hex << +picParams->pic_fields.redundant_pic_cnt_present_flag << std::endl; oss << "reference_pic_flag: " << std::hex << +picParams->pic_fields.reference_pic_flag << std::endl; oss << "IntraPicFlag: " << std::hex << +picParams->pic_fields.IntraPicFlag << std::endl; //Dump Short format specific oss << "num_ref_idx_l0_active_minus1: " << std::dec << +picParams->num_ref_idx_l0_active_minus1 << std::endl; oss << "num_ref_idx_l1_active_minus1: " << std::dec << +picParams->num_ref_idx_l1_active_minus1 << std::endl; oss << "NonExistingFrameFlags: " << std::hex << +picParams->NonExistingFrameFlags << std::endl; oss << "UsedForReferenceFlags: " << std::hex << +picParams->UsedForReferenceFlags << std::endl; oss << "frame_num: " << std::dec << +picParams->frame_num << std::endl; oss << "StatusReportFeedbackNumber: " << std::dec << +picParams->StatusReportFeedbackNumber << std::endl; //Dump FrameNumList[16] oss << "scaling_list_present_flag_buffer:"; for (uint8_t i = 0; i < 16; i++) oss << std::hex << picParams->FrameNumList[i]; oss << std::endl; const char *fileName = m_debugInterface->CreateFileName( "_DEC", CodechalDbgBufferType::bufPicParams, CodechalDbgExtType::txt); std::ofstream ofs(fileName, std::ios::out); ofs << oss.str(); ofs.close(); return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeAvc::DumpSliceParams( PCODEC_AVC_SLICE_PARAMS sliceParams, uint32_t numSlices) { CODECHAL_DEBUG_FUNCTION_ENTER; if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSlcParams)) { return MOS_STATUS_SUCCESS; } CODECHAL_DEBUG_CHK_NULL(sliceParams); PCODEC_AVC_SLICE_PARAMS sliceControl = nullptr; std::ostringstream oss; oss.setf(std::ios::showbase | std::ios::uppercase); for (uint16_t j = 0; j < numSlices; j++) { sliceControl = &sliceParams[j]; oss << "Data for Slice number = " << std::dec << +j << std::endl; oss << "slice_data_size: " << std::dec << +sliceControl->slice_data_size << std::endl; oss << "slice_data_offset: " << std::dec << +sliceControl->slice_data_offset << std::endl; //Dump Long format specific oss << "slice_data_bit_offset: " << std::dec << +sliceControl->slice_data_bit_offset << std::endl; oss << "first_mb_in_slice: " << std::dec << +sliceControl->first_mb_in_slice << std::endl; oss << "NumMbsForSlice: " << std::dec << +sliceControl->NumMbsForSlice << std::endl; oss << "slice_type: " << std::dec << +sliceControl->slice_type << std::endl; oss << "direct_spatial_mv_pred_flag: " << std::hex << +sliceControl->direct_spatial_mv_pred_flag << std::endl; oss << "num_ref_idx_l0_active_minus1: " << std::dec << +sliceControl->num_ref_idx_l0_active_minus1 << std::endl; oss << "num_ref_idx_l1_active_minus1: " << std::dec << +sliceControl->num_ref_idx_l1_active_minus1 << std::endl; oss << "cabac_init_idc: " << std::dec << +sliceControl->cabac_init_idc << std::endl; oss << "slice_qp_delta: " << std::dec << +sliceControl->slice_qp_delta << std::endl; oss << "disable_deblocking_filter_idc: " << std::dec << +sliceControl->disable_deblocking_filter_idc << std::endl; oss << "slice_alpha_c0_offset_div2: " << std::dec << +sliceControl->slice_alpha_c0_offset_div2 << std::endl; oss << "slice_beta_offset_div2: " << std::dec << +sliceControl->slice_beta_offset_div2 << std::endl; //Dump RefPicList[2][32] for (uint8_t i = 0; i < 32; ++i) { oss << "RefPicList[0][" << std::dec << +i << "] FrameIdx: " << std::dec << +sliceControl->RefPicList[0][i].FrameIdx << std::endl; oss << "RefPicList[0][" << std::dec << +i << "] PicFlags: " << std::hex << +sliceControl->RefPicList[0][i].PicFlags << std::endl; oss << "RefPicList[1][" << std::dec << +i << "] FrameIdx: " << std::dec << +sliceControl->RefPicList[1][i].FrameIdx << std::endl; oss << "RefPicList[1][" << std::dec << +i << "] PicFlags: " << std::hex << +sliceControl->RefPicList[1][i].PicFlags << std::endl; } oss << "luma_log2_weight_denom: " << std::dec << +sliceControl->luma_log2_weight_denom << std::endl; oss << "chroma_log2_weight_denom: " << std::dec << +sliceControl->chroma_log2_weight_denom << std::endl; oss << "slice_id: " << std::dec << +sliceControl->slice_id << std::endl; //Dump Weights[2][32][3][2] for (uint8_t i = 0; i < 32; ++i) { oss << "Weights[0][" << std::dec << +i << "][0][0]: " << std::hex << +sliceControl->Weights[0][i][0][0] << std::endl; oss << "Weights[0][" << std::dec << +i << "][0][1]: " << std::hex << +sliceControl->Weights[0][i][0][1] << std::endl; oss << "Weights[0][" << std::dec << +i << "][1][0]: " << std::hex << +sliceControl->Weights[0][i][1][0] << std::endl; oss << "Weights[0][" << std::dec << +i << "][1][1]: " << std::hex << +sliceControl->Weights[0][i][1][1] << std::endl; oss << "Weights[1][" << std::dec << +i << "][0][0]: " << std::hex << +sliceControl->Weights[1][i][0][0] << std::endl; oss << "Weights[1][" << std::dec << +i << "][0][1]: " << std::hex << +sliceControl->Weights[1][i][0][1] << std::endl; oss << "Weights[1][" << std::dec << +i << "][1][0]: " << std::hex << +sliceControl->Weights[1][i][1][0] << std::endl; oss << "Weights[1][" << std::dec << +i << "][1][1]: " << std::hex << +sliceControl->Weights[1][i][1][1] << std::endl; oss << "Weights[0][" << std::dec << +i << "][2][0]: " << std::hex << +sliceControl->Weights[0][i][2][0] << std::endl; oss << "Weights[0][" << std::dec << +i << "][2][1]: " << std::hex << +sliceControl->Weights[0][i][2][1] << std::endl; oss << "Weights[1][" << std::dec << +i << "][2][0]: " << std::hex << +sliceControl->Weights[1][i][2][0] << std::endl; oss << "Weights[1][" << std::dec << +i << "][2][1]: " << std::hex << +sliceControl->Weights[1][i][2][1] << std::endl; } const char *fileName = m_debugInterface->CreateFileName( "_DEC", CodechalDbgBufferType::bufSlcParams, CodechalDbgExtType::txt); std::ofstream ofs; if (j == 0) { ofs.open(fileName, std::ios::out); } else { ofs.open(fileName, std::ios::app); } ofs << oss.str(); ofs.close(); } return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeAvc::DumpIQParams( PCODEC_AVC_IQ_MATRIX_PARAMS matrixData) { CODECHAL_DEBUG_FUNCTION_ENTER; if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrIqParams)) { return MOS_STATUS_SUCCESS; } CODECHAL_DEBUG_CHK_NULL(matrixData); std::ostringstream oss; oss.setf(std::ios::showbase | std::ios::uppercase); uint32_t idx, idx2; // 4x4 block for (idx2 = 0; idx2 < 6; idx2++) { oss << "Qmatrix_H264_ScalingLists4x4[" << std::dec << +idx2 << "]:" << std::endl; for (idx = 0; idx < 12; idx += 4) { oss << "ScalingList4x4[" << std::dec << +idx / 4 << "]:"; oss << std::hex << +matrixData->ScalingList4x4[idx2][idx] << " "; oss << std::hex << +matrixData->ScalingList4x4[idx2][idx + 1] << " "; oss << std::hex << +matrixData->ScalingList4x4[idx2][idx + 2] << " "; oss << std::hex << +matrixData->ScalingList4x4[idx2][idx + 3] << " "; oss << std::endl; } oss << std::endl; } // 8x8 block for (idx2 = 0; idx2 < 2; idx2++) { oss << "Qmatrix_H264_ScalingLists8x8[" << std::dec << +idx2 << "]:" << std::endl; for (idx = 0; idx < 56; idx += 8) { oss << "ScalingList8x8[" << std::dec << +idx / 8 << "]:"; oss << std::hex << +matrixData->ScalingList8x8[idx2][idx] << " " ; oss << std::hex << +matrixData->ScalingList8x8[idx2][idx + 1] << " " ; oss << std::hex << +matrixData->ScalingList8x8[idx2][idx + 2] << " " ; oss << std::hex << +matrixData->ScalingList8x8[idx2][idx + 3] << " " ; oss << std::hex << +matrixData->ScalingList8x8[idx2][idx + 4] << " " ; oss << std::hex << +matrixData->ScalingList8x8[idx2][idx + 5] << " " ; oss << std::hex << +matrixData->ScalingList8x8[idx2][idx + 6] << " " ; oss << std::hex << +matrixData->ScalingList8x8[idx2][idx + 7] << " " ; oss << std::endl; } oss << std::endl; } const char *fileName = m_debugInterface->CreateFileName( "_DEC", CodechalDbgBufferType::bufIqParams, CodechalDbgExtType::txt); std::ofstream ofs(fileName, std::ios::out); ofs << oss.str(); ofs.close(); return MOS_STATUS_SUCCESS; } #endif MOS_STATUS CodechalDecodeAvc::SetFrameStoreIds(uint8_t frameIdx) { CODECHAL_DECODE_CHK_NULL_RETURN(m_avcFrameStoreId); uint8_t invalidFrame = 0x7f; for (uint8_t i = 0; i < m_avcRefList[frameIdx]->ucNumRef; i++) { uint8_t index; index = m_avcRefList[frameIdx]->RefList[i].FrameIdx; if (m_avcRefList[index]->ucFrameId == invalidFrame) { uint8_t j; for (j = 0; j < CODEC_AVC_MAX_NUM_REF_FRAME; j++) { if (!m_avcFrameStoreId[j].inUse) { m_avcRefList[index]->ucFrameId = j; m_avcFrameStoreId[j].inUse = true; break; } } if (j == CODEC_AVC_MAX_NUM_REF_FRAME) { // should never happen, something must be wrong CODECHAL_PUBLIC_ASSERT(false); m_avcRefList[index]->ucFrameId = 0; m_avcFrameStoreId[0].inUse = true; } } } return MOS_STATUS_SUCCESS; }