| /* |
| * Copyright (c) 2011-2020, 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_SURFACE surface; |
| CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateSurface( |
| &surface, |
| m_destSurface.dwPitch, |
| m_destSurface.dwHeight, |
| "InvalidRefBuffer"), |
| "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::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; i<numMBs; i++) |
| { |
| eStatus = (MOS_STATUS)MOS_SecureMemcpy(mbDmvBuffer, 64, mvcWaDummyDmvBuf, 64); |
| if (eStatus != MOS_STATUS_SUCCESS) |
| { |
| MOS_SafeFreeMemory(dummyDmvBuffer); |
| CODECHAL_DECODE_CHK_STATUS_RETURN(eStatus); |
| } |
| mbDmvBuffer += 64; |
| } |
| |
| CodechalResLock ResourceLock(m_osInterface, mvcDummyDmvBuffer); |
| auto data = (uint8_t*)ResourceLock.Lock(CodechalResLock::writeOnly); |
| |
| if (data == nullptr) |
| { |
| MOS_FreeMemory(dummyDmvBuffer); |
| CODECHAL_DECODE_CHK_NULL_RETURN(nullptr); |
| } |
| |
| eStatus = (MOS_STATUS)MOS_SecureMemcpy(data, size, (void*)dummyDmvBuffer, size); |
| if (eStatus != MOS_STATUS_SUCCESS) |
| { |
| MOS_SafeFreeMemory(dummyDmvBuffer); |
| CODECHAL_DECODE_CHK_STATUS_RETURN(eStatus); |
| } |
| |
| MOS_FreeMemAndSetNull(dummyDmvBuffer); |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalDecodeAvc::SetPictureStructs() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| PCODEC_AVC_PIC_PARAMS picParams = m_avcPicParams; |
| CODEC_PICTURE prevPic = m_currPic; |
| CODEC_PICTURE currPic = picParams->CurrPic; |
| |
| 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 |
| for (i = 0; i < m_refSurfaceNum; i++) |
| { |
| m_avcRefList[i]->resRefPic = m_refFrameSurface[i].OsResource; |
| } |
| |
| 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) |
| { |
| 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)) |
| { |
| 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; |
| |
| 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)) |
| { |
| for (ctr = 0; ctr < CODEC_AVC_NUM_DMV_BUFFERS; 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); |
| } |
| |
| for (uint32_t ctr = 0; ctr < CODEC_AVC_NUM_DMV_BUFFERS; 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; |
| } |
| |
| 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<uint32_t>(m_debugInterface->m_refIndex)); |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface( |
| &dstSurface, |
| CodechalDbgAttr::attrReferenceSurfaces, |
| 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]); |
| |
| 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::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; |
| |
| // 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_DMV_BUFFERS)); |
| 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; |
| } |