/* * Copyright (c) 2012-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_vp9.cpp //! \brief Implements the decode interface extension for VP9. //! \details Implements all functions required by CodecHal for VP9 decoding. //! #include "codechal_decoder.h" #include "codechal_secure_decode_interface.h" #include "codechal_decode_vp9.h" #include "codechal_mmc_decode_vp9.h" #include "hal_oca_interface.h" #if USE_CODECHAL_DEBUG_TOOL #include #include #include "codechal_debug.h" #endif #include "mos_os_cp_interface_specific.h" CodechalDecodeVp9 :: ~CodechalDecodeVp9 () { CODECHAL_DECODE_FUNCTION_ENTER; m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObject); m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObjectWaContextInUse); m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObjectVideoContextInUse); CodecHalFreeDataList(m_vp9RefList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9); if (!Mos_ResourceIsNull(&m_resDeblockingFilterLineRowStoreScratchBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resDeblockingFilterLineRowStoreScratchBuffer); } m_osInterface->pfnFreeResource( m_osInterface, &m_resDeblockingFilterTileRowStoreScratchBuffer); m_osInterface->pfnFreeResource( m_osInterface, &m_resDeblockingFilterColumnRowStoreScratchBuffer); m_osInterface->pfnFreeResource( m_osInterface, &m_resMetadataLineBuffer); m_osInterface->pfnFreeResource( m_osInterface, &m_resMetadataTileLineBuffer); m_osInterface->pfnFreeResource( m_osInterface, &m_resMetadataTileColumnBuffer); if (!Mos_ResourceIsNull(&m_resHvcLineRowstoreBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resHvcLineRowstoreBuffer); } m_osInterface->pfnFreeResource( m_osInterface, &m_resHvcTileRowstoreBuffer); for (uint8_t i = 0; i < CODEC_VP9_NUM_CONTEXTS + 1; i++) { m_osInterface->pfnFreeResource( m_osInterface, &m_resVp9ProbBuffer[i]); } m_osInterface->pfnFreeResource( m_osInterface, &m_resVp9SegmentIdBuffer); m_osInterface->pfnFreeResource( m_osInterface, &m_resSegmentIdBuffReset); for (uint8_t i = 0; i < CODECHAL_VP9_NUM_MV_BUFFERS; i++) { m_osInterface->pfnFreeResource( m_osInterface, &m_resVp9MvTemporalBuffer[i]); } if (!Mos_ResourceIsNull(&m_resCopyDataBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resCopyDataBuffer); } m_osInterface->pfnFreeResource( m_osInterface, &m_resHucSharedBuffer); m_osInterface->pfnFreeResource( m_osInterface, &m_resDmemBuffer); m_osInterface->pfnFreeResource( m_osInterface, &m_resInterProbSaveBuffer); if (m_picMhwParams.PipeModeSelectParams) { MOS_Delete(m_picMhwParams.PipeModeSelectParams); m_picMhwParams.PipeModeSelectParams = nullptr; } for (uint8_t i = 0; i < 4; i++) { if (m_picMhwParams.SurfaceParams[i]) { MOS_Delete(m_picMhwParams.SurfaceParams[i]); m_picMhwParams.SurfaceParams[i] = nullptr; } } if (m_picMhwParams.PipeBufAddrParams) { MOS_Delete(m_picMhwParams.PipeBufAddrParams); m_picMhwParams.PipeBufAddrParams = nullptr; } if (m_picMhwParams.IndObjBaseAddrParams) { MOS_Delete(m_picMhwParams.IndObjBaseAddrParams); m_picMhwParams.IndObjBaseAddrParams = nullptr; } if (m_picMhwParams.Vp9PicState) { MOS_Delete(m_picMhwParams.Vp9PicState); m_picMhwParams.Vp9PicState = nullptr; } if (m_picMhwParams.Vp9SegmentState) { MOS_Delete(m_picMhwParams.Vp9SegmentState); m_picMhwParams.Vp9SegmentState = nullptr; } } CodechalDecodeVp9 ::CodechalDecodeVp9( CodechalHwInterface * hwInterface, CodechalDebugInterface *debugInterface, PCODECHAL_STANDARD_INFO standardInfo) : CodechalDecode(hwInterface, debugInterface, standardInfo), m_usFrameWidthAlignedMinBlk(0), m_usFrameHeightAlignedMinBlk(0), m_vp9DepthIndicator(0), m_chromaFormatinProfile(0), m_dataSize(0), m_dataOffset(0), m_frameCtxIdx(0), m_curMvTempBufIdx(0), m_colMvTempBufIdx(0), m_copyDataBufferSize(0), m_copyDataOffset(0), m_copyDataBufferInUse(false), m_hcpDecPhase(0), m_prevFrmWidth(0), m_prevFrmHeight(0), m_allocatedWidthInSb(0), m_allocatedHeightInSb(0), m_mvBufferSize(0), m_resetSegIdBuffer(false), m_pendingResetPartial(0), m_saveInterProbs(0), m_fullProbBufferUpdate(false), m_dmemBufferSize(0) { CODECHAL_DECODE_FUNCTION_ENTER; MOS_ZeroMemory(&m_resDeblockingFilterLineRowStoreScratchBuffer, sizeof(m_resDeblockingFilterLineRowStoreScratchBuffer)); MOS_ZeroMemory(&m_resDeblockingFilterTileRowStoreScratchBuffer, sizeof(m_resDeblockingFilterTileRowStoreScratchBuffer)); MOS_ZeroMemory(&m_resDeblockingFilterColumnRowStoreScratchBuffer, sizeof(m_resDeblockingFilterColumnRowStoreScratchBuffer)); MOS_ZeroMemory(&m_resMetadataLineBuffer, sizeof(m_resMetadataLineBuffer)); MOS_ZeroMemory(&m_resMetadataTileLineBuffer, sizeof(m_resMetadataTileLineBuffer)); MOS_ZeroMemory(&m_resMetadataTileColumnBuffer, sizeof(m_resMetadataTileColumnBuffer)); MOS_ZeroMemory(&m_resHvcLineRowstoreBuffer, sizeof(m_resHvcLineRowstoreBuffer)); MOS_ZeroMemory(&m_resHvcTileRowstoreBuffer, sizeof(m_resHvcTileRowstoreBuffer)); MOS_ZeroMemory(&m_resVp9SegmentIdBuffer, sizeof(m_resVp9SegmentIdBuffer)); MOS_ZeroMemory(&m_resVp9MvTemporalBuffer, sizeof(m_resVp9MvTemporalBuffer)); MOS_ZeroMemory(&m_resCopyDataBuffer, sizeof(m_resCopyDataBuffer)); MOS_ZeroMemory(&m_segTreeProbs, sizeof(m_segTreeProbs)); MOS_ZeroMemory(&m_segPredProbs, sizeof(m_segPredProbs)); MOS_ZeroMemory(&m_interProbSaved, sizeof(m_interProbSaved)); MOS_ZeroMemory(&m_resDmemBuffer, sizeof(m_resDmemBuffer)); MOS_ZeroMemory(&m_resInterProbSaveBuffer, sizeof(m_resInterProbSaveBuffer)); MOS_ZeroMemory(&m_probUpdateFlags, sizeof(m_probUpdateFlags)); MOS_ZeroMemory(&m_resSegmentIdBuffReset, sizeof(m_resSegmentIdBuffReset)); MOS_ZeroMemory(&m_resHucSharedBuffer, sizeof(m_resHucSharedBuffer)); MOS_ZeroMemory(&m_picMhwParams, sizeof(m_picMhwParams)); MOS_ZeroMemory(&m_destSurface, sizeof(m_destSurface)); MOS_ZeroMemory(&m_lastRefSurface, sizeof(m_lastRefSurface)); MOS_ZeroMemory(&m_goldenRefSurface, sizeof(m_goldenRefSurface)); MOS_ZeroMemory(&m_altRefSurface, sizeof(m_altRefSurface)); MOS_ZeroMemory(&m_resDataBuffer, sizeof(m_resDataBuffer)); MOS_ZeroMemory(&m_resCoefProbBuffer, sizeof(m_resCoefProbBuffer)); MOS_ZeroMemory(&m_resSyncObject, sizeof(m_resSyncObject)); MOS_ZeroMemory(&m_resSyncObjectWaContextInUse, sizeof(m_resSyncObjectWaContextInUse)); MOS_ZeroMemory(&m_resSyncObjectVideoContextInUse, sizeof(m_resSyncObjectVideoContextInUse)); m_prevFrameParams.value = 0; #if (_DEBUG || _RELEASE_INTERNAL) m_reportFrameCrc = true; #endif for (uint8_t i = 0; i < CODEC_VP9_NUM_CONTEXTS; i++) { m_pendingResetFullTables[i] = 0; m_pendingCopySegProbs[i] = 0; } m_hcpInUse = true; m_hwInterface = hwInterface; } MOS_STATUS CodechalDecodeVp9 :: ProbBufferPartialUpdatewithDrv() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; if (m_probUpdateFlags.bSegProbCopy || m_probUpdateFlags.bProbSave || m_probUpdateFlags.bProbReset || m_probUpdateFlags.bProbRestore) { CodechalResLock ResourceLock(m_osInterface, &m_resVp9ProbBuffer[m_frameCtxIdx]); auto data = (uint8_t *)ResourceLock.Lock(CodechalResLock::writeOnly); CODECHAL_DECODE_CHK_NULL_RETURN(data); if (m_probUpdateFlags.bSegProbCopy) { CODECHAL_DECODE_CHK_STATUS_RETURN(MOS_SecureMemcpy( (data + CODEC_VP9_SEG_PROB_OFFSET), 7, m_probUpdateFlags.SegTreeProbs, 7)); CODECHAL_DECODE_CHK_STATUS_RETURN(MOS_SecureMemcpy( (data + CODEC_VP9_SEG_PROB_OFFSET + 7), 3, m_probUpdateFlags.SegPredProbs, 3)); } if (m_probUpdateFlags.bProbSave) { CODECHAL_DECODE_CHK_STATUS_RETURN(MOS_SecureMemcpy( m_interProbSaved, CODECHAL_VP9_INTER_PROB_SIZE, data + CODEC_VP9_INTER_PROB_OFFSET, CODECHAL_VP9_INTER_PROB_SIZE)); } if (m_probUpdateFlags.bProbReset) { if (m_probUpdateFlags.bResetFull) { CODECHAL_DECODE_CHK_STATUS_RETURN(ContextBufferInit( data, (m_probUpdateFlags.bResetKeyDefault ? true : false))); } else { CODECHAL_DECODE_CHK_STATUS_RETURN(CtxBufDiffInit( data, (m_probUpdateFlags.bResetKeyDefault ? true : false))); } } if (m_probUpdateFlags.bProbRestore) { CODECHAL_DECODE_CHK_STATUS_RETURN(MOS_SecureMemcpy( data + CODEC_VP9_INTER_PROB_OFFSET, CODECHAL_VP9_INTER_PROB_SIZE, m_interProbSaved, CODECHAL_VP9_INTER_PROB_SIZE)); } } return eStatus; } MOS_STATUS CodechalDecodeVp9 :: ProbBufFullUpdatewithDrv() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; CodechalResLock ResourceLock(m_osInterface, &m_resVp9ProbBuffer[m_frameCtxIdx]); auto data = (uint8_t*)ResourceLock.Lock(CodechalResLock::writeOnly); CODECHAL_DECODE_CHK_NULL_RETURN(data); CODECHAL_DECODE_CHK_STATUS_RETURN(ContextBufferInit( data, (m_probUpdateFlags.bResetKeyDefault ? true : false))); CODECHAL_DECODE_CHK_STATUS_RETURN(MOS_SecureMemcpy( (data + CODEC_VP9_SEG_PROB_OFFSET), 7, m_probUpdateFlags.SegTreeProbs, 7)); CODECHAL_DECODE_CHK_STATUS_RETURN(MOS_SecureMemcpy( (data + CODEC_VP9_SEG_PROB_OFFSET + 7), 3, m_probUpdateFlags.SegPredProbs, 3)); return eStatus; } MOS_STATUS CodechalDecodeVp9 :: ResetSegIdBufferwithDrv() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; CodechalResLock ResourceLock(m_osInterface, &m_resVp9SegmentIdBuffer); auto data = (uint8_t*)ResourceLock.Lock(CodechalResLock::writeOnly); CODECHAL_DECODE_CHK_NULL_RETURN(data); MOS_ZeroMemory( data, m_allocatedWidthInSb * m_allocatedHeightInSb * CODECHAL_CACHELINE_SIZE); return eStatus; } MOS_STATUS CodechalDecodeVp9 :: ProbBufFullUpdatewithHucStreamout( PMOS_COMMAND_BUFFER cmdBuffer) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; m_osInterface->pfnSetPerfTag( m_osInterface, (uint16_t)(((m_mode << 4) & 0xF0) | COPY_TYPE)); m_osInterface->pfnResetPerfBufferID(m_osInterface); uint32_t bufSize = CODEC_VP9_PROB_MAX_NUM_ELEM; // 16 byte aligned CodechalResLock ResourceLock(m_osInterface, &m_resVp9ProbBuffer[CODEC_VP9_NUM_CONTEXTS]); auto data = (uint8_t*)ResourceLock.Lock(CodechalResLock::writeOnly); CODECHAL_DECODE_CHK_NULL_RETURN(data); CODECHAL_DECODE_CHK_STATUS_RETURN(ContextBufferInit( data, (m_probUpdateFlags.bResetKeyDefault ? true : false))); CODECHAL_DECODE_CHK_STATUS_RETURN(MOS_SecureMemcpy( (data + CODEC_VP9_SEG_PROB_OFFSET), 7, m_probUpdateFlags.SegTreeProbs, 7)); CODECHAL_DECODE_CHK_STATUS_RETURN(MOS_SecureMemcpy( (data + CODEC_VP9_SEG_PROB_OFFSET + 7), 3, m_probUpdateFlags.SegPredProbs, 3)); CODECHAL_DECODE_CHK_STATUS_RETURN(HucCopy( cmdBuffer, // cmdBuffer &m_resVp9ProbBuffer[CODEC_VP9_NUM_CONTEXTS], // presSrc &m_resVp9ProbBuffer[m_frameCtxIdx], // presDst bufSize, // u32CopyLength 0, // u32CopyInputOffset 0)); // u32CopyOutputOffset MHW_MI_FLUSH_DW_PARAMS flushDwParams; MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd( cmdBuffer, &flushDwParams)); return eStatus; } MOS_STATUS CodechalDecodeVp9 :: ResetSegIdBufferwithHucStreamout( PMOS_COMMAND_BUFFER cmdBuffer) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; m_osInterface->pfnSetPerfTag( m_osInterface, (uint16_t)(((m_mode << 4) & 0xF0) | COPY_TYPE)); m_osInterface->pfnResetPerfBufferID(m_osInterface); uint32_t bufSize = m_allocatedWidthInSb * m_allocatedHeightInSb * CODECHAL_CACHELINE_SIZE; // 16 byte aligned CODECHAL_DECODE_CHK_STATUS_RETURN(HucCopy( cmdBuffer, // cmdBuffer &m_resSegmentIdBuffReset, // presSrc &m_resVp9SegmentIdBuffer, // presDst bufSize, // u32CopyLength 0, // u32CopyInputOffset 0)); // u32CopyOutputOffset MHW_MI_FLUSH_DW_PARAMS flushDwParams; MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd( cmdBuffer, &flushDwParams)); return eStatus; } MOS_STATUS CodechalDecodeVp9 :: DetermineInternalBufferUpdate() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; bool keyFrame = !m_vp9PicParams->PicFlags.fields.frame_type; bool intraOnly = m_vp9PicParams->PicFlags.fields.intra_only; uint8_t curFrameCtxIdx = (uint8_t)m_vp9PicParams->PicFlags.fields.frame_context_idx; bool isScaling = (m_destSurface.dwWidth == m_prevFrmWidth) && (m_destSurface.dwHeight == m_prevFrmHeight) ? false : true; bool resetAll = (keyFrame | m_vp9PicParams->PicFlags.fields.error_resilient_mode || (m_vp9PicParams->PicFlags.fields.reset_frame_context == 3 && m_vp9PicParams->PicFlags.fields.intra_only)); bool resetSpecified = (m_vp9PicParams->PicFlags.fields.reset_frame_context == 2 && m_vp9PicParams->PicFlags.fields.intra_only); bool copySegProbs = false; // indicating if current frame's prob buffer need to update seg tree/pred probs. bool resetFullTbl = false; // indicating if current frame will do full frame context table reset bool resetPartialTbl = false; // indicating if current frame need to do partial reset from offset 1667 to 2010. bool restoreInterProbs = false; // indicating if current frame need to restore offset 1667 to 2010 from saved one, this is only for prob buffer 0. bool saveInterProbsTmp = false; // indicating if current frame need to save offset from 1667 to 2010 for prob buffer 0. m_resetSegIdBuffer = keyFrame || isScaling || m_vp9PicParams->PicFlags.fields.error_resilient_mode || m_vp9PicParams->PicFlags.fields.intra_only; m_frameCtxIdx = curFrameCtxIdx; //indicate which prob buffer need to be used by current frame decode if (!m_vp9PicParams->PicFlags.fields.frame_type || m_vp9PicParams->PicFlags.fields.intra_only || m_vp9PicParams->PicFlags.fields.error_resilient_mode) { //always use frame context idx 0 in this case m_frameCtxIdx = 0; } //check if seg tree/pred probs need to be updated in prob buffer of current frame //and also mark the flag bPendingResetSegProbs for other prob buffers if (m_vp9PicParams->PicFlags.fields.segmentation_enabled && m_vp9PicParams->PicFlags.fields.segmentation_update_map) { copySegProbs = true; for ( uint8_t ctxIdx = 0; ctxIdx < CODEC_VP9_NUM_CONTEXTS; ctxIdx++) { m_pendingCopySegProbs[ctxIdx] = true; } //set current frame's prob buffer pending copy to false m_pendingCopySegProbs[m_frameCtxIdx] = false; //save probs for pending copy MOS_SecureMemcpy(m_segTreeProbs, 7, m_vp9PicParams->SegTreeProbs, 7); MOS_SecureMemcpy(m_segPredProbs, 3, m_vp9PicParams->SegPredProbs, 3); } else if (m_vp9PicParams->PicFlags.fields.segmentation_enabled && m_pendingCopySegProbs[m_frameCtxIdx]) { copySegProbs = true; m_pendingCopySegProbs[m_frameCtxIdx] = false; } //check if probs in frame context table need to be updated for current frame's prob buffer //and also mark the flag bPendingResetFullTables for other prob buffers if (resetAll) { resetFullTbl = true; m_pendingResetPartial = (keyFrame || intraOnly); //prob buffer 0 will be used for current frame decoding for ( uint8_t ctxIdx = 1; ctxIdx < CODEC_VP9_NUM_CONTEXTS; ctxIdx++) { m_pendingResetFullTables[ctxIdx] = true; } m_saveInterProbs = false; } else if (resetSpecified) { //intra only frame:prob buffer 0 will always be used for current frame decoding if (curFrameCtxIdx == 0) { //do prob table 0 reset resetFullTbl = true; m_pendingResetPartial = true; m_saveInterProbs = false; } else { //not do reset right now, pending the reset full table of specified ctx until a later frame use it to do decode m_pendingResetFullTables[curFrameCtxIdx] = true; if (!m_pendingResetPartial) { if (!m_saveInterProbs) { saveInterProbsTmp = true; m_saveInterProbs = true; } resetPartialTbl = true; } } } else if (intraOnly) { //prob buffer 0 will be used for current frame decoding if (!m_pendingResetPartial) { if (!m_saveInterProbs) { saveInterProbsTmp = true; m_saveInterProbs = true; } resetPartialTbl = true; } } else if (m_pendingResetFullTables[curFrameCtxIdx]) { //here curFrameCtxIdx != 0, frame is inter frame resetFullTbl = true; m_pendingResetFullTables[curFrameCtxIdx] = false; } else if (curFrameCtxIdx == 0 && m_pendingResetPartial) { //here curFrameCtxIdx = 0, frame is inter frame resetPartialTbl = true; m_pendingResetPartial = false; } else if (curFrameCtxIdx == 0 && m_saveInterProbs) { //here curFrameCtxIdx = 0, frame is inter frame restoreInterProbs = true; m_saveInterProbs = false; } //decide if prob buffer need to do a full udpate or partial upate if (resetFullTbl && copySegProbs) { //update the whole prob buffer m_fullProbBufferUpdate = true; } else { //partial buffer update m_fullProbBufferUpdate = false; } //propogate ProbUpdateFlags MOS_ZeroMemory(&m_probUpdateFlags, sizeof(m_probUpdateFlags)); if (copySegProbs) { m_probUpdateFlags.bSegProbCopy = true; MOS_SecureMemcpy(m_probUpdateFlags.SegTreeProbs, 7, m_segTreeProbs, 7); MOS_SecureMemcpy(m_probUpdateFlags.SegPredProbs, 3, m_segPredProbs, 3); } m_probUpdateFlags.bProbReset = resetFullTbl || resetPartialTbl; m_probUpdateFlags.bResetFull = resetFullTbl; m_probUpdateFlags.bResetKeyDefault = (keyFrame || intraOnly); m_probUpdateFlags.bProbSave = saveInterProbsTmp; m_probUpdateFlags.bProbRestore = restoreInterProbs; return eStatus; } MOS_STATUS CodechalDecodeVp9 :: AllocateResourcesFixedSizes() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource( m_osInterface, &m_resSyncObject)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource( m_osInterface, &m_resSyncObjectWaContextInUse)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource( m_osInterface, &m_resSyncObjectVideoContextInUse)); CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalAllocateDataList( m_vp9RefList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9)); // VP9 Probability buffer for (uint8_t i = 0; i < CODEC_VP9_NUM_CONTEXTS + 1; i++) { CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resVp9ProbBuffer[i], MOS_ALIGN_CEIL(CODEC_VP9_PROB_MAX_NUM_ELEM, CODECHAL_PAGE_SIZE), "Vp9ProbabilityBuffer"), "Failed to allocate VP9 probability Buffer."); CodechalResLock ResourceLock(m_osInterface, &m_resVp9ProbBuffer[i]); auto data = (uint8_t*)ResourceLock.Lock(CodechalResLock::writeOnly); CODECHAL_DECODE_CHK_NULL_RETURN(data); MOS_ZeroMemory(data, CODEC_VP9_PROB_MAX_NUM_ELEM); //initialize seg_tree_prob and seg_pred_prob MOS_FillMemory((data + CODEC_VP9_SEG_PROB_OFFSET), 7, CODEC_VP9_MAX_PROB); MOS_FillMemory((data + CODEC_VP9_SEG_PROB_OFFSET + 7), 3, CODEC_VP9_MAX_PROB); } // DMEM buffer send to HuC FW m_dmemBufferSize = MOS_ALIGN_CEIL(sizeof(CODECHAL_DECODE_VP9_PROB_UPDATE), CODECHAL_CACHELINE_SIZE); CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resDmemBuffer, m_dmemBufferSize, "DmemBuffer"), "Failed to allocate Dmem Buffer."); // VP9 Interprobs save buffer CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resInterProbSaveBuffer, MOS_ALIGN_CEIL(CODECHAL_VP9_INTER_PROB_SIZE, CODECHAL_PAGE_SIZE), "VP9InterProbsSaveBuffer"), "Failed to allocate VP9 inter probability save Buffer."); // VP9 shared buffer with HuC FW, mapping to region 15 CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resHucSharedBuffer, MOS_ALIGN_CEIL(CODEC_VP9_PROB_MAX_NUM_ELEM, CODECHAL_PAGE_SIZE), "VP9HucSharedBuffer"), "Failed to allocate VP9 Huc shared Buffer."); return eStatus; } MOS_STATUS CodechalDecodeVp9 :: AllocateResourcesVariableSizes() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; uint32_t widthInSb = MOS_ROUNDUP_DIVIDE(m_width, CODEC_VP9_SUPER_BLOCK_WIDTH); uint32_t heightInSb = MOS_ROUNDUP_DIVIDE(m_height, CODEC_VP9_SUPER_BLOCK_HEIGHT); uint8_t maxBitDepth = 8 + m_vp9DepthIndicator * 2; uint8_t chromaFormat = m_chromaFormatinProfile; MHW_VDBOX_HCP_BUFFER_SIZE_PARAMS hcpBufSizeParam; MOS_ZeroMemory(&hcpBufSizeParam, sizeof(hcpBufSizeParam)); hcpBufSizeParam.ucMaxBitDepth = maxBitDepth; hcpBufSizeParam.ucChromaFormat = chromaFormat; hcpBufSizeParam.dwPicWidth = widthInSb; hcpBufSizeParam.dwPicHeight = heightInSb; MHW_VDBOX_HCP_BUFFER_REALLOC_PARAMS reallocParam; MOS_ZeroMemory(&reallocParam, sizeof(reallocParam)); reallocParam.ucMaxBitDepth = maxBitDepth; reallocParam.ucChromaFormat = chromaFormat; reallocParam.dwPicWidth = widthInSb; reallocParam.dwPicWidthAlloced = m_allocatedWidthInSb; reallocParam.dwPicHeight = heightInSb; reallocParam.dwPicHeightAlloced = m_allocatedHeightInSb; if (!m_hcpInterface->IsVp9DfRowstoreCacheEnabled()) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->IsVp9BufferReallocNeeded( MHW_VDBOX_HCP_INTERNAL_BUFFER_DBLK_LINE, &reallocParam)); if (reallocParam.bNeedBiggerSize || Mos_ResourceIsNull(&m_resDeblockingFilterLineRowStoreScratchBuffer)) { if (!Mos_ResourceIsNull(&m_resDeblockingFilterLineRowStoreScratchBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resDeblockingFilterLineRowStoreScratchBuffer); } // Deblocking Filter Line Row Store Scratch data surface CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->GetVp9BufferSize( MHW_VDBOX_HCP_INTERNAL_BUFFER_DBLK_LINE, &hcpBufSizeParam)); CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resDeblockingFilterLineRowStoreScratchBuffer, hcpBufSizeParam.dwBufferSize, "DeblockingLineScratchBuffer"), "Failed to allocate deblocking line scratch Buffer."); } } CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->IsVp9BufferReallocNeeded( MHW_VDBOX_HCP_INTERNAL_BUFFER_DBLK_TILE_LINE, &reallocParam)); if (reallocParam.bNeedBiggerSize || Mos_ResourceIsNull(&m_resDeblockingFilterTileRowStoreScratchBuffer)) { if (!Mos_ResourceIsNull(&m_resDeblockingFilterTileRowStoreScratchBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resDeblockingFilterTileRowStoreScratchBuffer); } // Deblocking Filter Tile Row Store Scratch data surface CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->GetVp9BufferSize( MHW_VDBOX_HCP_INTERNAL_BUFFER_DBLK_TILE_LINE, &hcpBufSizeParam)); CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resDeblockingFilterTileRowStoreScratchBuffer, hcpBufSizeParam.dwBufferSize, "DeblockingTileScratchBuffer"), "Failed to allocate deblocking tile scratch Buffer."); } CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->IsVp9BufferReallocNeeded( MHW_VDBOX_HCP_INTERNAL_BUFFER_DBLK_TILE_COL, &reallocParam)); if (reallocParam.bNeedBiggerSize || Mos_ResourceIsNull(&m_resDeblockingFilterColumnRowStoreScratchBuffer)) { if (!Mos_ResourceIsNull(&m_resDeblockingFilterColumnRowStoreScratchBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resDeblockingFilterColumnRowStoreScratchBuffer); } // Deblocking Filter Column Row Store Scratch data surface CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->GetVp9BufferSize( MHW_VDBOX_HCP_INTERNAL_BUFFER_DBLK_TILE_COL, &hcpBufSizeParam)); CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resDeblockingFilterColumnRowStoreScratchBuffer, hcpBufSizeParam.dwBufferSize, "DeblockingColumnScratchBuffer"), "Failed to allocate deblocking column scratch Buffer."); } if (!m_hcpInterface->IsVp9DatRowstoreCacheEnabled()) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->IsVp9BufferReallocNeeded( MHW_VDBOX_HCP_INTERNAL_BUFFER_META_LINE, &reallocParam)); if (reallocParam.bNeedBiggerSize || Mos_ResourceIsNull(&m_resMetadataLineBuffer)) { if (!Mos_ResourceIsNull(&m_resMetadataLineBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resMetadataLineBuffer); } // Metadata Line buffer CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->GetVp9BufferSize( MHW_VDBOX_HCP_INTERNAL_BUFFER_META_LINE, &hcpBufSizeParam)); CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resMetadataLineBuffer, hcpBufSizeParam.dwBufferSize, "MetadataLineBuffer"), "Failed to allocate meta data line Buffer."); } } CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->IsVp9BufferReallocNeeded( MHW_VDBOX_HCP_INTERNAL_BUFFER_META_TILE_LINE, &reallocParam)); if (reallocParam.bNeedBiggerSize || Mos_ResourceIsNull(&m_resMetadataTileLineBuffer)) { if (!Mos_ResourceIsNull(&m_resMetadataTileLineBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resMetadataTileLineBuffer); } // Metadata Tile Line buffer CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->GetVp9BufferSize( MHW_VDBOX_HCP_INTERNAL_BUFFER_META_TILE_LINE, &hcpBufSizeParam)); CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resMetadataTileLineBuffer, hcpBufSizeParam.dwBufferSize, "MetadataTileLineBuffer"), "Failed to allocate meta data tile line Buffer."); } CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->IsVp9BufferReallocNeeded( MHW_VDBOX_HCP_INTERNAL_BUFFER_META_TILE_COL, &reallocParam)); if (reallocParam.bNeedBiggerSize || Mos_ResourceIsNull(&m_resMetadataTileColumnBuffer)) { if (!Mos_ResourceIsNull(&m_resMetadataTileColumnBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resMetadataTileColumnBuffer); } // Metadata Tile Column buffer CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->GetVp9BufferSize( MHW_VDBOX_HCP_INTERNAL_BUFFER_META_TILE_COL, &hcpBufSizeParam)); CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resMetadataTileColumnBuffer, hcpBufSizeParam.dwBufferSize, "MetadataTileColumnBuffer"), "Failed to allocate meta data tile column Buffer."); } if (!m_hcpInterface->IsVp9HvdRowstoreCacheEnabled()) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->IsVp9BufferReallocNeeded( MHW_VDBOX_VP9_INTERNAL_BUFFER_HVD_LINE, &reallocParam)); if (reallocParam.bNeedBiggerSize || Mos_ResourceIsNull(&m_resHvcLineRowstoreBuffer)) { if (!Mos_ResourceIsNull(&m_resHvcLineRowstoreBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resHvcLineRowstoreBuffer); } // HVC Line Row Store Buffer CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->GetVp9BufferSize( MHW_VDBOX_VP9_INTERNAL_BUFFER_HVD_LINE, &hcpBufSizeParam)); CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resHvcLineRowstoreBuffer, hcpBufSizeParam.dwBufferSize, "HvcLineRowStoreBuffer"), "Failed to allocate Hvc line row store Buffer."); } } CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->IsVp9BufferReallocNeeded( MHW_VDBOX_VP9_INTERNAL_BUFFER_HVD_TILE, &reallocParam)); if (reallocParam.bNeedBiggerSize || Mos_ResourceIsNull(&m_resHvcTileRowstoreBuffer)) { if (!Mos_ResourceIsNull(&m_resHvcTileRowstoreBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resHvcTileRowstoreBuffer); } // HVC Tile Row Store Buffer CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->GetVp9BufferSize( MHW_VDBOX_VP9_INTERNAL_BUFFER_HVD_TILE, &hcpBufSizeParam)); CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resHvcTileRowstoreBuffer, hcpBufSizeParam.dwBufferSize, "HvcTileRowStoreBuffer"), "Failed to allocate Hvc tile row store Buffer."); } CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->IsVp9BufferReallocNeeded( MHW_VDBOX_VP9_INTERNAL_BUFFER_SEGMENT_ID, &reallocParam)); if (reallocParam.bNeedBiggerSize || Mos_ResourceIsNull(&m_resVp9SegmentIdBuffer)) { if (!Mos_ResourceIsNull(&m_resVp9SegmentIdBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resVp9SegmentIdBuffer); } // VP9 Segment ID buffer CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->GetVp9BufferSize( MHW_VDBOX_VP9_INTERNAL_BUFFER_SEGMENT_ID, &hcpBufSizeParam)); CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resVp9SegmentIdBuffer, hcpBufSizeParam.dwBufferSize, "Vp9SegmentIdBuffer"), "Failed to allocate VP9 segment ID Buffer."); } CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->IsVp9BufferReallocNeeded( MHW_VDBOX_VP9_INTERNAL_BUFFER_SEGMENT_ID, &reallocParam)); if (reallocParam.bNeedBiggerSize || Mos_ResourceIsNull(&m_resSegmentIdBuffReset)) { if (!Mos_ResourceIsNull(&m_resSegmentIdBuffReset)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resSegmentIdBuffReset); } // VP9 Segment ID Reset buffer CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->GetVp9BufferSize( MHW_VDBOX_VP9_INTERNAL_BUFFER_SEGMENT_ID, &hcpBufSizeParam)); CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resSegmentIdBuffReset, hcpBufSizeParam.dwBufferSize, "SegmentIdBuffreset", true, 0), "Failed to allocate segment ID reset Buffer."); } CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->IsVp9BufferReallocNeeded( MHW_VDBOX_HCP_INTERNAL_BUFFER_CURR_MV_TEMPORAL, &reallocParam)); if (reallocParam.bNeedBiggerSize || m_mvBufferSize == 0) { for (uint8_t i = 0; i < CODECHAL_VP9_NUM_MV_BUFFERS; i++) { if (!Mos_ResourceIsNull(&m_resVp9MvTemporalBuffer[i])) { m_osInterface->pfnFreeResource( m_osInterface, &m_resVp9MvTemporalBuffer[i]); } } // VP9 MV Temporal buffers CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->GetVp9BufferSize( MHW_VDBOX_HCP_INTERNAL_BUFFER_CURR_MV_TEMPORAL, &hcpBufSizeParam)); for (uint8_t i = 0; i < CODECHAL_VP9_NUM_MV_BUFFERS; i++) { CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resVp9MvTemporalBuffer[i], hcpBufSizeParam.dwBufferSize, "MvTemporalBuffer"), "Failed to allocate Mv temporal Buffer."); } m_mvBufferSize = hcpBufSizeParam.dwBufferSize; } if (m_secureDecoder) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_secureDecoder->AllocateResource(this)); } //backup allocated memory size m_allocatedWidthInSb = widthInSb; m_allocatedHeightInSb = heightInSb; return eStatus; } MOS_STATUS CodechalDecodeVp9 :: InitializeBeginFrame() { CODECHAL_DECODE_FUNCTION_ENTER; m_incompletePicture = false; m_copyDataBufferInUse = false; m_copyDataOffset = 0; return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeVp9 :: CopyDataSurface() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext( m_osInterface, m_videoContextForWa)); m_osInterface->pfnResetOsStates(m_osInterface); m_osInterface->pfnSetPerfTag( m_osInterface, (uint16_t)(((m_mode << 4) & 0xF0) | COPY_TYPE)); m_osInterface->pfnResetPerfBufferID(m_osInterface); MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer( m_osInterface, &cmdBuffer, 0)); // Send command buffer header at the beginning (OS dependent) CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking( &cmdBuffer, false)); CODECHAL_DECODE_CHK_STATUS_RETURN(HucCopy( &cmdBuffer, // pCmdBuffer &m_resDataBuffer, // presSrc &m_resCopyDataBuffer, // presDst m_dataSize, // u32CopyLength m_dataOffset, // u32CopyInputOffset m_copyDataOffset)); // u32CopyOutputOffset m_copyDataOffset += MOS_ALIGN_CEIL(m_dataSize, MHW_CACHELINE_SIZE); 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); // sync resource if (!m_incompletePicture) { MOS_SYNC_PARAMS 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_videoContextForWaUsesNullHw)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext( m_osInterface, m_videoContext)); return eStatus; } MOS_STATUS CodechalDecodeVp9 :: CheckAndCopyBitStream() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; uint32_t badSliceChopping = 0; // No pVp9SliceParams is set from APP. if (m_vp9SliceParams == nullptr) { badSliceChopping = 0; } else { badSliceChopping = m_vp9SliceParams->wBadSliceChopping; } // No BSBytesInBuffer is sent from App, driver here just give an estimation. if (badSliceChopping != 0) { m_vp9PicParams->BSBytesInBuffer = (m_vp9PicParams->FrameWidthMinus1 + 1) * (m_vp9PicParams->FrameHeightMinus1 + 1) * 6; } if (IsFirstExecuteCall()) // first exec call { if (m_dataSize < m_vp9PicParams->BSBytesInBuffer) // Current bitstream buffer is not big enough { // Allocate or reallocate the copy data buffer. if (m_copyDataBufferSize < MOS_ALIGN_CEIL(m_vp9PicParams->BSBytesInBuffer, 64)) { if (!Mos_ResourceIsNull(&m_resCopyDataBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resCopyDataBuffer); } m_copyDataBufferSize = MOS_ALIGN_CEIL(m_vp9PicParams->BSBytesInBuffer, 64); CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resCopyDataBuffer, m_copyDataBufferSize, "Vp9CopyDataBuffer"), "Failed to allocate Vp9 copy data Buffer."); } // Copy bitstream into the copy buffer if (m_dataSize) { CODECHAL_DECODE_CHK_STATUS_RETURN(CopyDataSurface()); m_copyDataBufferInUse = true; } m_incompletePicture = true; } } else // second and later exec calls { CODECHAL_DECODE_CHK_COND_RETURN( (m_copyDataOffset + m_dataSize > m_copyDataBufferSize), "Bitstream size exceeds copy data buffer size!"); // Copy bitstream into the copy buffer if (m_dataSize) { CODECHAL_DECODE_CHK_STATUS_RETURN(CopyDataSurface()); } if (m_copyDataOffset >= m_vp9PicParams->BSBytesInBuffer || badSliceChopping == 2) { m_incompletePicture = false; } } return eStatus; } MOS_STATUS CodechalDecodeVp9 :: InitializeDecodeMode () { //do nothing for VP9 Base class. will be overloaded by inherited class to support dynamic mode switch return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeVp9::InitSfcState() { // Default no SFC support return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeVp9::SetFrameStates () { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; PERF_UTILITY_AUTO(__FUNCTION__, PERF_DECODE, PERF_LEVEL_HAL); CODECHAL_DECODE_FUNCTION_ENTER; CODECHAL_DECODE_CHK_NULL_RETURN(m_decodeParams.m_destSurface); CODECHAL_DECODE_CHK_NULL_RETURN(m_decodeParams.m_dataBuffer); m_dataSize = m_decodeParams.m_dataSize; m_dataOffset = m_decodeParams.m_dataOffset; m_vp9PicParams = (PCODEC_VP9_PIC_PARAMS)m_decodeParams.m_picParams; m_vp9SegmentParams = (PCODEC_VP9_SEGMENT_PARAMS)m_decodeParams.m_iqMatrixBuffer; m_vp9SliceParams = (PCODEC_VP9_SLICE_PARAMS)m_decodeParams.m_sliceParams; CODECHAL_DECODE_CHK_NULL_RETURN(m_vp9SegmentParams); m_destSurface = *(m_decodeParams.m_destSurface); m_resDataBuffer = *(m_decodeParams.m_dataBuffer); if (m_decodeParams.m_coefProbBuffer) // This is an optional buffer passed from App. To be removed once VP9 FF Decode Driver is mature. { m_resCoefProbBuffer = *(m_decodeParams.m_coefProbBuffer); } if (IsFirstExecuteCall()) { CODECHAL_DECODE_CHK_STATUS_RETURN(InitializeBeginFrame()); } CODECHAL_DECODE_CHK_STATUS_RETURN(CheckAndCopyBitStream()); m_cencBuf = m_decodeParams.m_cencBuf; // Bitstream is incomplete, don't do any decoding work. if (m_incompletePicture) { eStatus = MOS_STATUS_SUCCESS; return eStatus; } CODECHAL_DEBUG_TOOL( CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( m_copyDataBufferInUse ? &m_resCopyDataBuffer : &m_resDataBuffer, CodechalDbgAttr::attrDecodeBitstream, "_DEC", m_copyDataBufferInUse ? m_copyDataBufferSize : m_dataSize, m_copyDataBufferInUse ? 0 : m_dataOffset, CODECHAL_NUM_MEDIA_STATES));) m_statusReportFeedbackNumber = m_vp9PicParams->StatusReportFeedbackNumber; m_width = MOS_MAX(m_width, (uint32_t)(m_vp9PicParams->FrameWidthMinus1 + 1)); m_height = MOS_MAX(m_height, (uint32_t)(m_vp9PicParams->FrameHeightMinus1 + 1)); m_usFrameWidthAlignedMinBlk = MOS_ALIGN_CEIL(m_vp9PicParams->FrameWidthMinus1 + 1, CODEC_VP9_MIN_BLOCK_WIDTH); m_usFrameHeightAlignedMinBlk = MOS_ALIGN_CEIL(m_vp9PicParams->FrameHeightMinus1 + 1, CODEC_VP9_MIN_BLOCK_WIDTH); // Overwrite the actual surface height with the coded height and width of the frame // for VP9 since it's possible for a VP9 frame to change size during playback m_destSurface.dwWidth = m_vp9PicParams->FrameWidthMinus1 + 1; m_destSurface.dwHeight = m_vp9PicParams->FrameHeightMinus1 + 1; PCODEC_REF_LIST destEntry = m_vp9RefList[m_vp9PicParams->CurrPic.FrameIdx]; // Clear FilterLevel Array inside segment data when filter_level inside picparam is zero if (m_cencBuf == nullptr) { MOS_ZeroMemory(destEntry, sizeof(CODEC_REF_LIST)); // Clear FilterLevel Array inside segment data when filter_level inside picparam is zero if ((!m_vp9PicParams->filter_level)) { PCODEC_VP9_SEG_PARAMS vp9SegData = &m_vp9SegmentParams->SegData[0]; for (uint8_t i = 0; i < 8; i++) { *((uint32_t *)&vp9SegData->FilterLevel[0][0]) = 0; *((uint32_t *)&vp9SegData->FilterLevel[2][0]) = 0; vp9SegData++; // Go on to next record. } } } destEntry->resRefPic = m_destSurface.OsResource; destEntry->dwFrameWidth = m_vp9PicParams->FrameWidthMinus1 + 1; destEntry->dwFrameHeight = m_vp9PicParams->FrameHeightMinus1 + 1; if (m_hcpInterface->IsRowStoreCachingSupported() && m_usFrameWidthAlignedMinBlk != MOS_ALIGN_CEIL(m_prevFrmWidth, CODEC_VP9_MIN_BLOCK_WIDTH)) { MHW_VDBOX_ROWSTORE_PARAMS rowstoreParams; uint8_t usChromaSamplingFormat; if (m_vp9PicParams->subsampling_x == 1 && m_vp9PicParams->subsampling_y == 1) { usChromaSamplingFormat = HCP_CHROMA_FORMAT_YUV420; } else if (m_vp9PicParams->subsampling_x == 0 && m_vp9PicParams->subsampling_y == 0) { usChromaSamplingFormat = HCP_CHROMA_FORMAT_YUV444; } else { CODECHAL_DECODE_ASSERTMESSAGE("Invalid Chroma sampling format!"); eStatus = MOS_STATUS_INVALID_PARAMETER; return eStatus; } MOS_ZeroMemory(&rowstoreParams, sizeof(rowstoreParams)); rowstoreParams.dwPicWidth = m_usFrameWidthAlignedMinBlk; rowstoreParams.bMbaff = false; rowstoreParams.Mode = CODECHAL_DECODE_MODE_VP9VLD; rowstoreParams.ucBitDepthMinus8 = m_vp9PicParams->BitDepthMinus8; rowstoreParams.ucChromaFormat = usChromaSamplingFormat; CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->SetRowstoreCachingOffsets(&rowstoreParams)); } CODECHAL_DECODE_CHK_STATUS_RETURN(InitializeDecodeMode()); CODECHAL_DECODE_CHK_STATUS_RETURN(InitSfcState()); // Allocate internal buffer or reallocate When current resolution is bigger than allocated internal buffer size CODECHAL_DECODE_CHK_STATUS_RETURN(AllocateResourcesVariableSizes()); CODECHAL_DECODE_CHK_STATUS_RETURN(DetermineInternalBufferUpdate()); m_hcpDecPhase = CodechalHcpDecodePhaseInitialized; m_perfType = m_vp9PicParams->PicFlags.fields.frame_type ? P_TYPE : I_TYPE; m_crrPic = m_vp9PicParams->CurrPic; if (m_vp9PicParams->PicFlags.fields.frame_type == CODEC_VP9_INTER_FRAME && !m_vp9PicParams->PicFlags.fields.intra_only) { m_curMvTempBufIdx = (m_curMvTempBufIdx + 1) % CODECHAL_VP9_NUM_MV_BUFFERS; m_colMvTempBufIdx = (m_curMvTempBufIdx < 1) ? (CODECHAL_VP9_NUM_MV_BUFFERS - 1) : (m_curMvTempBufIdx - 1); } CODECHAL_DEBUG_TOOL( CODECHAL_DECODE_CHK_NULL_RETURN(m_debugInterface); m_vp9PicParams->CurrPic.PicFlags = PICTURE_FRAME; m_debugInterface->m_currPic = m_crrPic; m_debugInterface->m_frameType = m_perfType; CODECHAL_DECODE_CHK_STATUS_RETURN(DumpDecodePicParams( m_vp9PicParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(DumpDecodeSliceParams( m_vp9SliceParams)); if (m_vp9SegmentParams) { CODECHAL_DECODE_CHK_STATUS_RETURN(DumpDecodeSegmentParams( m_vp9SegmentParams)); }) return eStatus; } MOS_STATUS CodechalDecodeVp9 :: DetermineDecodePhase() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; uint32_t curPhase = m_hcpDecPhase; switch (curPhase) { case CodechalHcpDecodePhaseInitialized: m_hcpDecPhase = CodechalHcpDecodePhaseLegacyLong; break; default: eStatus = MOS_STATUS_INVALID_PARAMETER; CODECHAL_DECODE_ASSERTMESSAGE("invalid decode phase."); return eStatus; } return eStatus; } MOS_STATUS CodechalDecodeVp9 :: InitPicStateMhwParams() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; PMOS_RESOURCE usedDummyReference = nullptr; CODECHAL_DECODE_FUNCTION_ENTER; // Reset all pic Mhw Params *m_picMhwParams.PipeModeSelectParams = {}; *m_picMhwParams.PipeBufAddrParams = {}; MOS_ZeroMemory(m_picMhwParams.IndObjBaseAddrParams, sizeof(MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS)); MOS_ZeroMemory(m_picMhwParams.Vp9PicState, sizeof(MHW_VDBOX_VP9_PIC_STATE)); MOS_ZeroMemory(m_picMhwParams.Vp9SegmentState, sizeof(MHW_VDBOX_VP9_SEGMENT_STATE)); PCODEC_PICTURE refFrameList = &(m_vp9PicParams->RefFrameList[0]); uint8_t lastRefPicIndex = m_vp9PicParams->PicFlags.fields.LastRefIdx; uint8_t goldenRefPicIndex = m_vp9PicParams->PicFlags.fields.GoldenRefIdx; uint8_t altRefPicIndex = m_vp9PicParams->PicFlags.fields.AltRefIdx; if (m_vp9PicParams->PicFlags.fields.frame_type == CODEC_VP9_KEY_FRAME || m_vp9PicParams->PicFlags.fields.intra_only) { // reference surface should be nullptr when key_frame == true or intra only frame m_presLastRefSurface = nullptr; m_presGoldenRefSurface = nullptr; m_presAltRefSurface = nullptr; } else { if (lastRefPicIndex > 7 || goldenRefPicIndex > 7 || altRefPicIndex > 7) { CODECHAL_DECODE_ASSERTMESSAGE("invalid ref index (should be in [0,7]) in pic parameter!"); eStatus = MOS_STATUS_INVALID_PARAMETER; return eStatus; } if (refFrameList[lastRefPicIndex].FrameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9) { refFrameList[lastRefPicIndex].FrameIdx = CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9 - 1; } if (refFrameList[goldenRefPicIndex].FrameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9) { refFrameList[goldenRefPicIndex].FrameIdx = CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9 - 1; } if (refFrameList[altRefPicIndex].FrameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9) { refFrameList[altRefPicIndex].FrameIdx = CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9 - 1; } PCODEC_REF_LIST *vp9RefList = &(m_vp9RefList[0]); m_presLastRefSurface = &(vp9RefList[refFrameList[lastRefPicIndex].FrameIdx]->resRefPic); m_presGoldenRefSurface = &(vp9RefList[refFrameList[goldenRefPicIndex].FrameIdx]->resRefPic); m_presAltRefSurface = &(vp9RefList[refFrameList[altRefPicIndex].FrameIdx]->resRefPic); } uint16_t usChromaSamplingFormat; if (m_vp9PicParams->subsampling_x == 1 && m_vp9PicParams->subsampling_y == 1) { usChromaSamplingFormat = HCP_CHROMA_FORMAT_YUV420; } else if (m_vp9PicParams->subsampling_x == 0 && m_vp9PicParams->subsampling_y == 0) { usChromaSamplingFormat = HCP_CHROMA_FORMAT_YUV444; } else { CODECHAL_DECODE_ASSERTMESSAGE("Invalid Chroma sampling format!"); eStatus = MOS_STATUS_INVALID_PARAMETER; return eStatus; } m_picMhwParams.PipeModeSelectParams->Mode = m_mode; m_picMhwParams.PipeModeSelectParams->bStreamOutEnabled = m_streamOutEnabled; // Populate surface param for decoded picture m_picMhwParams.SurfaceParams[0]->Mode = m_mode; m_picMhwParams.SurfaceParams[0]->psSurface = &m_destSurface; m_picMhwParams.SurfaceParams[0]->ChromaType = (uint8_t)usChromaSamplingFormat; m_picMhwParams.SurfaceParams[0]->ucSurfaceStateId = CODECHAL_HCP_DECODED_SURFACE_ID; m_picMhwParams.SurfaceParams[0]->ucBitDepthLumaMinus8 = m_vp9PicParams->BitDepthMinus8; m_picMhwParams.SurfaceParams[0]->ucBitDepthChromaMinus8 = m_vp9PicParams->BitDepthMinus8; m_picMhwParams.SurfaceParams[0]->dwUVPlaneAlignment = 8; if (MEDIA_IS_WA(m_waTable, WaDummyReference) && !Mos_ResourceIsNull(&m_dummyReference.OsResource)) { usedDummyReference = &m_dummyReference.OsResource; } else { usedDummyReference = &m_destSurface.OsResource; } // Populate surface param for reference pictures if (m_vp9PicParams->PicFlags.fields.frame_type == CODEC_VP9_INTER_FRAME && !m_vp9PicParams->PicFlags.fields.intra_only && m_presLastRefSurface != nullptr && m_presGoldenRefSurface != nullptr && m_presAltRefSurface != nullptr) { if (Mos_ResourceIsNull(m_presLastRefSurface)) { m_presLastRefSurface = usedDummyReference; } if (Mos_ResourceIsNull(m_presGoldenRefSurface)) { m_presGoldenRefSurface = usedDummyReference; } if (Mos_ResourceIsNull(m_presAltRefSurface)) { m_presAltRefSurface = usedDummyReference; } //MOS_SURFACE lastRefSurface; CODECHAL_DECODE_CHK_STATUS_RETURN(MOS_SecureMemcpy( &m_lastRefSurface.OsResource, sizeof(MOS_RESOURCE), m_presLastRefSurface, sizeof(MOS_RESOURCE))); CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo( m_osInterface, &m_lastRefSurface)); //MOS_SURFACE goldenRefSurface; CODECHAL_DECODE_CHK_STATUS_RETURN(MOS_SecureMemcpy( &m_goldenRefSurface.OsResource, sizeof(MOS_RESOURCE), m_presGoldenRefSurface, sizeof(MOS_RESOURCE))); CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo( m_osInterface, &m_goldenRefSurface)); //MOS_SURFACE altRefSurface; CODECHAL_DECODE_CHK_STATUS_RETURN(MOS_SecureMemcpy( &m_altRefSurface.OsResource, sizeof(MOS_RESOURCE), m_presAltRefSurface, sizeof(MOS_RESOURCE))); CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo( m_osInterface, &m_altRefSurface)); for (uint8_t i = 1; i < 4; i++) { m_picMhwParams.SurfaceParams[i]->Mode = m_mode; m_picMhwParams.SurfaceParams[i]->ChromaType = (uint8_t)usChromaSamplingFormat; m_picMhwParams.SurfaceParams[i]->dwUVPlaneAlignment = 8; switch (i) { case 1: m_picMhwParams.SurfaceParams[i]->psSurface = &m_lastRefSurface; m_picMhwParams.SurfaceParams[i]->ucSurfaceStateId = CODECHAL_HCP_LAST_SURFACE_ID; break; case 2: m_picMhwParams.SurfaceParams[i]->psSurface = &m_goldenRefSurface; m_picMhwParams.SurfaceParams[i]->ucSurfaceStateId = CODECHAL_HCP_GOLDEN_SURFACE_ID; break; case 3: m_picMhwParams.SurfaceParams[i]->psSurface = &m_altRefSurface; m_picMhwParams.SurfaceParams[i]->ucSurfaceStateId = CODECHAL_HCP_ALTREF_SURFACE_ID; break; } } } m_picMhwParams.PipeBufAddrParams->Mode = m_mode; m_picMhwParams.PipeBufAddrParams->psPreDeblockSurface = &m_destSurface; m_picMhwParams.PipeBufAddrParams->presReferences[CodechalDecodeLastRef] = m_presLastRefSurface; m_picMhwParams.PipeBufAddrParams->presReferences[CodechalDecodeGoldenRef] = m_presGoldenRefSurface; m_picMhwParams.PipeBufAddrParams->presReferences[CodechalDecodeAlternateRef] = m_presAltRefSurface; // set all ref pic addresses in HCP_PIPE_BUF_ADDR_STATE command to valid addresses for error concealment purpose, set the unused ones to the first used one for (uint8_t i = 0; i < CODECHAL_DECODE_VP9_MAX_NUM_REF_FRAME; i++) { if (!m_picMhwParams.PipeBufAddrParams->presReferences[i]) { m_picMhwParams.PipeBufAddrParams->presReferences[i] = usedDummyReference; } } #ifdef _MMC_SUPPORTED CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetPipeBufAddr(m_picMhwParams.PipeBufAddrParams)); #endif if (m_streamOutEnabled) { m_picMhwParams.PipeBufAddrParams->presStreamOutBuffer = &(m_streamOutBuffer[m_streamOutCurrBufIdx]); } #ifdef _MMC_SUPPORTED CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->CheckReferenceList(m_picMhwParams.PipeBufAddrParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetRefrenceSync(m_disableDecodeSyncLock, m_disableLockForTranscode)); #endif m_picMhwParams.PipeBufAddrParams->presMfdDeblockingFilterRowStoreScratchBuffer = &m_resDeblockingFilterLineRowStoreScratchBuffer; m_picMhwParams.PipeBufAddrParams->presDeblockingFilterTileRowStoreScratchBuffer = &m_resDeblockingFilterTileRowStoreScratchBuffer; m_picMhwParams.PipeBufAddrParams->presDeblockingFilterColumnRowStoreScratchBuffer = &m_resDeblockingFilterColumnRowStoreScratchBuffer; m_picMhwParams.PipeBufAddrParams->presMetadataLineBuffer = &m_resMetadataLineBuffer; m_picMhwParams.PipeBufAddrParams->presMetadataTileLineBuffer = &m_resMetadataTileLineBuffer; m_picMhwParams.PipeBufAddrParams->presMetadataTileColumnBuffer = &m_resMetadataTileColumnBuffer; m_picMhwParams.PipeBufAddrParams->presVp9ProbBuffer = &m_resVp9ProbBuffer[m_frameCtxIdx]; m_picMhwParams.PipeBufAddrParams->presVp9SegmentIdBuffer = &m_resVp9SegmentIdBuffer; m_picMhwParams.PipeBufAddrParams->presHvdLineRowStoreBuffer = &m_resHvcLineRowstoreBuffer; m_picMhwParams.PipeBufAddrParams->presHvdTileRowStoreBuffer = &m_resHvcTileRowstoreBuffer; if (m_vp9PicParams->PicFlags.fields.frame_type == CODEC_VP9_INTER_FRAME && !m_vp9PicParams->PicFlags.fields.intra_only) { m_picMhwParams.PipeBufAddrParams->presCurMvTempBuffer = &m_resVp9MvTemporalBuffer[m_curMvTempBufIdx]; if (!m_prevFrameParams.fields.KeyFrame && !m_prevFrameParams.fields.IntraOnly) { // For VP9, only index 0 is required to be filled m_picMhwParams.PipeBufAddrParams->presColMvTempBuffer[0] = &m_resVp9MvTemporalBuffer[m_colMvTempBufIdx]; } } m_picMhwParams.IndObjBaseAddrParams->Mode = m_mode; m_picMhwParams.IndObjBaseAddrParams->dwDataSize = m_copyDataBufferInUse ? m_copyDataBufferSize : m_dataSize; m_picMhwParams.IndObjBaseAddrParams->dwDataOffset = m_copyDataBufferInUse ? 0 : m_dataOffset; m_picMhwParams.IndObjBaseAddrParams->presDataBuffer = m_copyDataBufferInUse ? &m_resCopyDataBuffer : &m_resDataBuffer; if (m_secureDecoder) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_secureDecoder->SetBitstreamBuffer(m_picMhwParams.IndObjBaseAddrParams)); } m_picMhwParams.Vp9PicState->pVp9PicParams = m_vp9PicParams; m_picMhwParams.Vp9PicState->ppVp9RefList = &(m_vp9RefList[0]); m_picMhwParams.Vp9PicState->PrevFrameParams.value = m_prevFrameParams.value; m_picMhwParams.Vp9PicState->dwPrevFrmWidth = m_prevFrmWidth; m_picMhwParams.Vp9PicState->dwPrevFrmHeight = m_prevFrmHeight; m_prevFrameParams.fields.KeyFrame = !m_vp9PicParams->PicFlags.fields.frame_type; m_prevFrameParams.fields.IntraOnly = m_vp9PicParams->PicFlags.fields.intra_only; m_prevFrameParams.fields.Display = m_vp9PicParams->PicFlags.fields.show_frame; m_prevFrmWidth = m_vp9PicParams->FrameWidthMinus1 + 1; m_prevFrmHeight = m_vp9PicParams->FrameHeightMinus1 + 1; m_picMhwParams.Vp9SegmentState->Mode = m_mode; m_picMhwParams.Vp9SegmentState->pVp9SegmentParams = m_vp9SegmentParams; CODECHAL_DEBUG_TOOL( if (m_vp9PicParams->PicFlags.fields.frame_type == CODEC_VP9_INTER_FRAME) { for (uint16_t n = 0; n < CODECHAL_MAX_CUR_NUM_REF_FRAME_VP9; n++) { if (m_picMhwParams.PipeBufAddrParams->presReferences[n]) { MOS_SURFACE dstSurface; MOS_ZeroMemory(&dstSurface, sizeof(MOS_SURFACE)); dstSurface.OsResource = *(m_picMhwParams.PipeBufAddrParams->presReferences[n]); CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo( m_osInterface, &dstSurface)); m_debugInterface->m_refIndex = n; 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.c_str())); } } } if (m_picMhwParams.PipeBufAddrParams->presColMvTempBuffer[0]) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( m_picMhwParams.PipeBufAddrParams->presColMvTempBuffer[0], CodechalDbgAttr::attrMvData, "DEC_Col_MV_", m_mvBufferSize)); } if (m_picMhwParams.PipeBufAddrParams->presCurMvTempBuffer) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( m_picMhwParams.PipeBufAddrParams->presCurMvTempBuffer, CodechalDbgAttr::attrMvData, "DEC_Cur_MV_", m_mvBufferSize)); }; ); return eStatus; } MOS_STATUS CodechalDecodeVp9 :: AddPicStateMhwCmds( PMOS_COMMAND_BUFFER cmdBuffer) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; CODECHAL_DECODE_CHK_NULL_RETURN(cmdBuffer); CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpPipeModeSelectCmd( cmdBuffer, m_picMhwParams.PipeModeSelectParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpSurfaceCmd( cmdBuffer, m_picMhwParams.SurfaceParams[0])); // For non-key frame, send extra surface commands for reference pictures if (m_vp9PicParams->PicFlags.fields.frame_type == CODEC_VP9_INTER_FRAME && !m_vp9PicParams->PicFlags.fields.intra_only) { for (uint8_t i = 1; i < 4; i++) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpSurfaceCmd( cmdBuffer, m_picMhwParams.SurfaceParams[i])); } } CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpPipeBufAddrCmd( cmdBuffer, m_picMhwParams.PipeBufAddrParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpIndObjBaseAddrCmd( cmdBuffer, m_picMhwParams.IndObjBaseAddrParams)); if (m_cencBuf) { CODECHAL_DECODE_CHK_STATUS_RETURN(SetCencBatchBuffer(cmdBuffer)); } else { for (uint8_t i = 0; i < CODEC_VP9_MAX_SEGMENTS; i++) { // Error handling for illegal programming on segmentation fields @ KEY/INTRA_ONLY frames PCODEC_VP9_SEG_PARAMS vp9SegData = &(m_picMhwParams.Vp9SegmentState->pVp9SegmentParams->SegData[i]); if (vp9SegData->SegmentFlags.fields.SegmentReferenceEnabled && (!m_vp9PicParams->PicFlags.fields.frame_type || m_vp9PicParams->PicFlags.fields.intra_only)) { vp9SegData->SegmentFlags.fields.SegmentReference = CODECHAL_DECODE_VP9_INTRA_FRAME; } m_picMhwParams.Vp9SegmentState->ucCurrentSegmentId = i; CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpVp9SegmentStateCmd( cmdBuffer, nullptr, m_picMhwParams.Vp9SegmentState)); if (m_vp9PicParams->PicFlags.fields.segmentation_enabled == 0) { break; } } CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpVp9PicStateCmd( cmdBuffer, nullptr, m_picMhwParams.Vp9PicState)); if (m_secureDecoder) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_secureDecoder->AddHcpSecureState( cmdBuffer, this)); } } return eStatus; } MOS_STATUS CodechalDecodeVp9 :: UpdatePicStateBuffers( PMOS_COMMAND_BUFFER cmdBuffe) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; if (m_resetSegIdBuffer) { if (m_osInterface->osCpInterface->IsHMEnabled()) { if (m_secureDecoder) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_secureDecoder->ResetVP9SegIdBufferWithHuc(this, cmdBuffe)); } } else { CODECHAL_DECODE_CHK_STATUS_RETURN(ResetSegIdBufferwithDrv()); } } if (m_osInterface->osCpInterface->IsHMEnabled()) { if (m_secureDecoder) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_secureDecoder->UpdateVP9ProbBufferWithHuc(m_fullProbBufferUpdate, this, cmdBuffe)); } } else { if (m_fullProbBufferUpdate) { CODECHAL_DECODE_CHK_STATUS_RETURN(ProbBufFullUpdatewithDrv()); } else { CODECHAL_DECODE_CHK_STATUS_RETURN(ProbBufferPartialUpdatewithDrv()); } } CODECHAL_DEBUG_TOOL( CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &m_resVp9SegmentIdBuffer, CodechalDbgAttr::attrSegId, "SegId_beforeHCP", (m_allocatedWidthInSb * m_allocatedHeightInSb * CODECHAL_CACHELINE_SIZE))); CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &(m_resVp9ProbBuffer[m_frameCtxIdx]), CodechalDbgAttr::attrCoefProb, "PakHwCoeffProbs_beforeHCP", CODEC_VP9_PROB_MAX_NUM_ELEM));) return eStatus; } MOS_STATUS CodechalDecodeVp9 :: DecodeStateLevel() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; PERF_UTILITY_AUTO(__FUNCTION__, PERF_DECODE, PERF_LEVEL_HAL); CODECHAL_DECODE_FUNCTION_ENTER; if (m_secureDecoder && m_hcpDecPhase == CodechalHcpDecodePhaseInitialized) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_secureDecoder->Execute(this)); } //HCP Decode Phase State Machine DetermineDecodePhase(); MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer( m_osInterface, &cmdBuffer, 0)); auto mmioRegisters = m_hwInterface->GetMfxInterface()->GetMmioRegisters(m_vdboxIndex); HalOcaInterface::On1stLevelBBStart(cmdBuffer, *m_osInterface->pOsContext, m_osInterface->CurrentGpuContextHandle, *m_miInterface, *mmioRegisters); //Frame tracking functionality is called at the start of a command buffer. //Called at FE decode phase, since BE decode phase will only construct BE batch buffers. CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking( &cmdBuffer, true)); CODECHAL_DECODE_CHK_STATUS_RETURN(InitPicStateMhwParams()); CODECHAL_DECODE_CHK_STATUS_RETURN(UpdatePicStateBuffers(&cmdBuffer)); if (m_statusQueryReportingEnabled) { CODECHAL_DECODE_CHK_STATUS_RETURN( StartStatusReport(&cmdBuffer)); } CODECHAL_DECODE_CHK_STATUS_RETURN(AddPicStateMhwCmds( &cmdBuffer)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); return eStatus; } MOS_STATUS CodechalDecodeVp9 :: DecodePrimitiveLevel() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; PERF_UTILITY_AUTO(__FUNCTION__, PERF_DECODE, PERF_LEVEL_HAL); CODECHAL_DECODE_FUNCTION_ENTER; // Bitstream is incomplete, don't do any decoding work. if (m_incompletePicture) { eStatus = MOS_STATUS_SUCCESS; return eStatus; } CODECHAL_DECODE_CHK_COND_RETURN( (m_vdboxIndex > m_mfxInterface->GetMaxVdboxIndex()), "ERROR - vdbox index exceed the maximum"); m_osInterface->pfnSetPerfTag( m_osInterface, (uint16_t)(((m_mode << 4) & 0xF0) | (m_perfType & 0xF))); m_osInterface->pfnResetPerfBufferID(m_osInterface); MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer( m_osInterface, &cmdBuffer, 0)); if (m_cencBuf == nullptr) { MHW_VDBOX_HCP_BSD_PARAMS bsdParams; MOS_ZeroMemory(&bsdParams, sizeof(bsdParams)); bsdParams.dwBsdDataLength = m_vp9PicParams->BSBytesInBuffer - m_vp9PicParams->UncompressedHeaderLengthInBytes; bsdParams.dwBsdDataStartOffset = m_vp9PicParams->UncompressedHeaderLengthInBytes; CODECHAL_DECODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpBsdObjectCmd( &cmdBuffer, &bsdParams)); } // Send VD Pipe Flush command for SKL+ MHW_VDBOX_VD_PIPE_FLUSH_PARAMS vdpipeFlushParams; MOS_ZeroMemory(&vdpipeFlushParams, sizeof(vdpipeFlushParams)); vdpipeFlushParams.Flags.bWaitDoneHEVC = 1; vdpipeFlushParams.Flags.bFlushHEVC = 1; vdpipeFlushParams.Flags.bWaitDoneVDCmdMsgParser = 1; CODECHAL_DECODE_CHK_STATUS_RETURN(m_vdencInterface->AddVdPipelineFlushCmd( &cmdBuffer, &vdpipeFlushParams)); MHW_MI_FLUSH_DW_PARAMS flushDwParams; MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd( &cmdBuffer, &flushDwParams)); 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; 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); // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag if (m_osInterface->bTagResourceSync) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource( &cmdBuffer, &syncParams)); } if (m_statusQueryReportingEnabled) { CodechalDecodeStatusReport decodeStatusReport; decodeStatusReport.m_statusReportNumber = m_statusReportFeedbackNumber; decodeStatusReport.m_currDecodedPic = m_vp9PicParams->CurrPic; decodeStatusReport.m_currDeblockedPic = m_vp9PicParams->CurrPic; decodeStatusReport.m_codecStatus = CODECHAL_STATUS_UNAVAILABLE; decodeStatusReport.m_numMbsAffected = m_usFrameWidthAlignedMinBlk * m_usFrameHeightAlignedMinBlk; decodeStatusReport.m_currDecodedPicRes = m_vp9RefList[m_vp9PicParams->CurrPic.FrameIdx]->resRefPic; // VP9 plug-in/out was NOT fully enabled; this is just to make sure driver would not crash in CodecHal_DecodeEndFrame(), // which requires the value of DecodeStatusReport.presCurrDecodedPic CODECHAL_DEBUG_TOOL( decodeStatusReport.m_frameType = m_perfType; ) CODECHAL_DECODE_CHK_STATUS_RETURN(EndStatusReport( decodeStatusReport, &cmdBuffer)); } 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); 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)); m_mmc->UpdateUserFeatureKey(&m_destSurface);) bool syncCompleteFrame = m_copyDataBufferInUse; if (syncCompleteFrame) { //Sync up complete frame MOS_SYNC_PARAMS copyDataSyncParams = g_cInitSyncParams; copyDataSyncParams.GpuContext = m_videoContextForWa; copyDataSyncParams.presSyncResource = &m_resSyncObjectWaContextInUse; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, ©DataSyncParams)); copyDataSyncParams = g_cInitSyncParams; copyDataSyncParams.GpuContext = m_videoContext; copyDataSyncParams.presSyncResource = &m_resSyncObjectWaContextInUse; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, ©DataSyncParams)); } uint32_t renderingFlags = m_videoContextUsesNullHw; HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface); //submit command buffer CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer( m_osInterface, &cmdBuffer, renderingFlags)); // Reset status report if (m_statusQueryReportingEnabled) { CODECHAL_DECODE_CHK_STATUS_RETURN(ResetStatusReport( m_videoContextUsesNullHw)); } #ifdef CODECHAL_HUC_KERNEL_DEBUG CODECHAL_DEBUG_TOOL( CODECHAL_DECODE_CHK_STATUS(m_debugInterface->DumpHucRegion( &pVp9State->resHucSharedBuffer, 0, CODEC_VP9_PROB_MAX_NUM_ELEM, 15, "", false, 0, CodechalHucRegionDumpType::hucRegionDumpDefault)); ) #endif CODECHAL_DEBUG_TOOL( CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &m_resVp9SegmentIdBuffer, CodechalDbgAttr::attrSegId, "SegId", (m_allocatedWidthInSb * m_allocatedHeightInSb * CODECHAL_CACHELINE_SIZE))); CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &(m_resVp9ProbBuffer[m_frameCtxIdx]), CodechalDbgAttr::attrCoefProb, "PakHwCoeffProbs", CODEC_VP9_PROB_MAX_NUM_ELEM));) // Needs to be re-set for Linux buffer re-use scenarios // pVp9RefList[pVp9PicParams->ucCurrPicIndex]->resRefPic = // sDestSurface.OsResource; // Send the signal to indicate decode completion, in case On-Demand Sync is not present CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams)); return eStatus; } MOS_STATUS CodechalDecodeVp9::InitMmcState() { #ifdef _MMC_SUPPORTED m_mmc = MOS_New(CodechalMmcDecodeVp9, m_hwInterface, this); CODECHAL_DECODE_CHK_NULL_RETURN(m_mmc); #endif return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeVp9 :: 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()); m_width = settings->width; m_height = settings->height; if (settings->lumaChromaDepth & CODECHAL_LUMA_CHROMA_DEPTH_8_BITS) m_vp9DepthIndicator = 0; if (settings->lumaChromaDepth & CODECHAL_LUMA_CHROMA_DEPTH_10_BITS) m_vp9DepthIndicator = 1; if (settings->lumaChromaDepth & CODECHAL_LUMA_CHROMA_DEPTH_12_BITS) m_vp9DepthIndicator = 2; m_chromaFormatinProfile = settings->chromaFormat; MHW_VDBOX_STATE_CMDSIZE_PARAMS stateCmdSizeParams; stateCmdSizeParams.bHucDummyStream = false; // Picture Level Commands m_hwInterface->GetHxxStateCommandSize( m_mode, &m_commandBufferSizeNeeded, &m_commandPatchListSizeNeeded, &stateCmdSizeParams); // Primitive Level Commands m_hwInterface->GetHxxPrimitiveCommandSize( m_mode, &m_standardDecodeSizeNeeded, &m_standardDecodePatchListSizeNeeded, false); CODECHAL_DECODE_CHK_STATUS_RETURN(AllocateResourcesFixedSizes()); // Prepare Pic Params m_picMhwParams.PipeModeSelectParams = MOS_New(MHW_VDBOX_PIPE_MODE_SELECT_PARAMS); m_picMhwParams.PipeBufAddrParams = MOS_New(MHW_VDBOX_PIPE_BUF_ADDR_PARAMS); m_picMhwParams.IndObjBaseAddrParams = MOS_New(MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS); m_picMhwParams.Vp9PicState = MOS_New(MHW_VDBOX_VP9_PIC_STATE); m_picMhwParams.Vp9SegmentState = MOS_New(MHW_VDBOX_VP9_SEGMENT_STATE); MOS_ZeroMemory(m_picMhwParams.IndObjBaseAddrParams, sizeof(MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS)); MOS_ZeroMemory(m_picMhwParams.Vp9PicState, sizeof(MHW_VDBOX_VP9_PIC_STATE)); MOS_ZeroMemory(m_picMhwParams.Vp9SegmentState, sizeof(MHW_VDBOX_VP9_SEGMENT_STATE)); for (uint16_t i = 0; i < 4; i++) { m_picMhwParams.SurfaceParams[i] = MOS_New(MHW_VDBOX_SURFACE_PARAMS); MOS_ZeroMemory(m_picMhwParams.SurfaceParams[i], sizeof(MHW_VDBOX_SURFACE_PARAMS)); } return eStatus; } #if USE_CODECHAL_DEBUG_TOOL MOS_STATUS CodechalDecodeVp9::DumpDecodePicParams( PCODEC_VP9_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::hex << +picParams->CurrPic.FrameIdx << std::endl; oss << "CurrPic PicFlags: " << std::hex << +picParams->CurrPic.PicFlags << std::endl; for (uint8_t i = 0; i < 8; ++i) { oss << "RefFrameList["<<+i<<"] FrameIdx:" << std::hex << +picParams->RefFrameList[i].FrameIdx << std::endl; oss << "RefFrameList["<<+i<<"] PicFlags:" << std::hex << +picParams->RefFrameList[i].PicFlags << std::endl; } oss << "FrameWidthMinus1: " << std::hex << +picParams->FrameWidthMinus1 << std::endl; oss << "FrameHeightMinus1: " << std::hex << +picParams->FrameHeightMinus1 << std::endl; oss << "PicFlags value: " << std::hex << +picParams->PicFlags.value << std::endl; oss << "frame_type: " << std::hex << +picParams->PicFlags.fields.frame_type << std::endl; oss << "show_frame: " << std::hex << +picParams->PicFlags.fields.show_frame << std::endl; oss << "error_resilient_mode: " << std::hex << +picParams->PicFlags.fields.error_resilient_mode << std::endl; oss << "intra_only: " << std::hex << +picParams->PicFlags.fields.intra_only << std::endl; oss << "LastRefIdx: " << std::hex << +picParams->PicFlags.fields.LastRefIdx << std::endl; oss << "LastRefSignBias: " << std::hex << +picParams->PicFlags.fields.LastRefSignBias << std::endl; oss << "GoldenRefIdx: " << std::hex << +picParams->PicFlags.fields.GoldenRefIdx << std::endl; oss << "GoldenRefSignBias: " << std::hex << +picParams->PicFlags.fields.GoldenRefSignBias << std::endl; oss << "AltRefIdx: " << std::hex << +picParams->PicFlags.fields.AltRefIdx << std::endl; oss << "AltRefSignBias: " << std::hex << +picParams->PicFlags.fields.AltRefSignBias << std::endl; oss << "allow_high_precision_mv: " << std::hex << +picParams->PicFlags.fields.allow_high_precision_mv << std::endl; oss << "mcomp_filter_type: " << std::hex << +picParams->PicFlags.fields.mcomp_filter_type << std::endl; oss << "frame_parallel_decoding_mode: " << std::hex << +picParams->PicFlags.fields.frame_parallel_decoding_mode << std::endl; oss << "segmentation_enabled: " << std::hex << +picParams->PicFlags.fields.segmentation_enabled << std::endl; oss << "segmentation_temporal_update: " << std::hex << +picParams->PicFlags.fields.segmentation_temporal_update << std::endl; oss << "segmentation_update_map: " << std::hex << +picParams->PicFlags.fields.segmentation_update_map << std::endl; oss << "reset_frame_context: " << std::hex << +picParams->PicFlags.fields.reset_frame_context << std::endl; oss << "refresh_frame_context: " << std::hex << +picParams->PicFlags.fields.refresh_frame_context << std::endl; oss << "frame_context_idx: " << std::hex << +picParams->PicFlags.fields.frame_context_idx << std::endl; oss << "LosslessFlag: " << std::hex << +picParams->PicFlags.fields.LosslessFlag << std::endl; oss << "ReservedField: " << std::hex << +picParams->PicFlags.fields.ReservedField << std::endl; oss << "filter_level: " << std::hex << +picParams->filter_level << std::endl; oss << "sharpness_level: " << std::hex << +picParams->sharpness_level << std::endl; oss << "log2_tile_rows: " << std::hex << +picParams->log2_tile_rows << std::endl; oss << "log2_tile_columns: " << std::hex << +picParams->log2_tile_columns << std::endl; oss << "UncompressedHeaderLengthInBytes: " << std::hex << +picParams->UncompressedHeaderLengthInBytes << std::endl; oss << "FirstPartitionSize: " << std::hex << +picParams->FirstPartitionSize << std::endl; oss << "profile: " << std::hex << +picParams->profile << std::endl; oss << "BitDepthMinus8: " << std::hex << +picParams->BitDepthMinus8 << std::endl; oss << "subsampling_x: " << std::hex << +picParams->subsampling_x << std::endl; oss << "subsampling_y: " << std::hex << +picParams->subsampling_y << std::endl; for (uint8_t i = 0; i < 7; ++i) { oss << "SegTreeProbs["<<+i<<"]: " << std::hex << +picParams->SegTreeProbs[i] << std::endl; } for (uint8_t i = 0; i < 3; ++i) { oss << "SegPredProbs["<<+i<<"]: " << std::hex << +picParams->SegPredProbs[i] << std::endl; } oss << "BSBytesInBuffer: " << std::hex << +picParams->BSBytesInBuffer << std::endl; oss << "StatusReportFeedbackNumber: " << std::hex << +picParams->StatusReportFeedbackNumber << 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 CodechalDecodeVp9::DumpDecodeSliceParams(CODEC_VP9_SLICE_PARAMS *slcParams) { CODECHAL_DEBUG_FUNCTION_ENTER; if (slcParams == nullptr) { return MOS_STATUS_SUCCESS; } if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSlcParams)) { const char *fileName = m_debugInterface->CreateFileName( "_DEC", CodechalDbgBufferType::bufSlcParams, CodechalDbgExtType::txt); DumpDecodeVp9SliceParams(slcParams, fileName); } return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeVp9::DumpDecodeSegmentParams( PCODEC_VP9_SEGMENT_PARAMS segmentParams) { CODECHAL_DEBUG_FUNCTION_ENTER; if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSegmentParams)) { return MOS_STATUS_SUCCESS; } CODECHAL_DEBUG_CHK_NULL(segmentParams); std::ostringstream oss; oss.setf(std::ios::showbase | std::ios::uppercase); for (uint8_t i = 0; i < 8; ++i) { oss << "SegData["<<+i<<"] SegmentFlags value: " << std::hex << +segmentParams->SegData[i].SegmentFlags.value << std::endl; oss << "SegData["<<+i<<"] SegmentReferenceEnabled: " << std::hex << +segmentParams->SegData[i].SegmentFlags.fields.SegmentReferenceEnabled << std::endl; oss << "SegData["<<+i<<"] SegmentReference: " << std::hex << +segmentParams->SegData[i].SegmentFlags.fields.SegmentReference << std::endl; oss << "SegData["<<+i<<"] SegmentReferenceSkipped: " << std::hex << +segmentParams->SegData[i].SegmentFlags.fields.SegmentReferenceSkipped << std::endl; oss << "SegData["<<+i<<"] ReservedField3: " << std::hex << +segmentParams->SegData[i].SegmentFlags.fields.ReservedField3 << std::endl; for (uint8_t j = 0; j < 4; ++j) { oss << "SegData["<<+i<<"] FilterLevel["<<+j<<"]:"; oss << std::hex << +segmentParams->SegData[i].FilterLevel[j][0]<<" "; oss << std::hex<< +segmentParams->SegData[i].FilterLevel[j][1] << std::endl; } oss << "SegData["<<+i<<"] LumaACQuantScale: " << std::hex << +segmentParams->SegData[i].LumaACQuantScale << std::endl; oss << "SegData["<<+i<<"] LumaDCQuantScale: " << std::hex << +segmentParams->SegData[i].LumaDCQuantScale << std::endl; oss << "SegData["<<+i<<"] ChromaACQuantScale: " << std::hex << +segmentParams->SegData[i].ChromaACQuantScale << std::endl; oss << "SegData["<<+i<<"] ChromaDCQuantScale: " << std::hex << +segmentParams->SegData[i].ChromaDCQuantScale << std::endl; } const char* fileName = m_debugInterface->CreateFileName( "_DEC", CodechalDbgBufferType::bufSegmentParams, CodechalDbgExtType::txt); std::ofstream ofs(fileName, std::ios::out); ofs << oss.str(); ofs.close(); return MOS_STATUS_SUCCESS; } #endif MOS_STATUS CodechalDecodeVp9::CtxBufDiffInit( uint8_t *ctxBuffer, bool setToKey) { int32_t i, j; uint32_t byteCnt = CODEC_VP9_INTER_PROB_OFFSET; //inter mode probs. have to be zeros for Key frame for (i = 0; i < CODEC_VP9_INTER_MODE_CONTEXTS; i++) { for (j = 0; j < CODEC_VP9_INTER_MODES - 1; j++) { if (!setToKey) { ctxBuffer[byteCnt++] = DefaultInterModeProbs[i][j]; } else { //zeros for key frame byteCnt++; } } } //switchable interprediction probs for (i = 0; i < CODEC_VP9_SWITCHABLE_FILTERS + 1; i++) { for (j = 0; j < CODEC_VP9_SWITCHABLE_FILTERS - 1; j++) { if (!setToKey) { ctxBuffer[byteCnt++] = DefaultSwitchableInterpProb[i][j]; } else { //zeros for key frame byteCnt++; } } } //intra inter probs for (i = 0; i < CODEC_VP9_INTRA_INTER_CONTEXTS; i++) { if (!setToKey) { ctxBuffer[byteCnt++] = DefaultIntraInterProb[i]; } else { //zeros for key frame byteCnt++; } } //comp inter probs for (i = 0; i < CODEC_VP9_COMP_INTER_CONTEXTS; i++) { if (!setToKey) { ctxBuffer[byteCnt++] = DefaultCompInterProb[i]; } else { //zeros for key frame byteCnt++; } } //single ref probs for (i = 0; i < CODEC_VP9_REF_CONTEXTS; i++) { for (j = 0; j < 2; j++) { if (!setToKey) { ctxBuffer[byteCnt++] = DefaultSingleRefProb[i][j]; } else { //zeros for key frame byteCnt++; } } } //comp ref probs for (i = 0; i < CODEC_VP9_REF_CONTEXTS; i++) { if (!setToKey) { ctxBuffer[byteCnt++] = DefaultCompRefProb[i]; } else { //zeros for key frame byteCnt++; } } //y mode probs for (i = 0; i < CODEC_VP9_BLOCK_SIZE_GROUPS; i++) { for (j = 0; j < CODEC_VP9_INTRA_MODES - 1; j++) { if (!setToKey) { ctxBuffer[byteCnt++] = DefaultIFYProb[i][j]; } else { //zeros for key frame, since HW will not use this buffer, but default right buffer. byteCnt++; } } } //partition probs, key & intra-only frames use key type, other inter frames use inter type for (i = 0; i < CODECHAL_VP9_PARTITION_CONTEXTS; i++) { for (j = 0; j < CODEC_VP9_PARTITION_TYPES - 1; j++) { if (setToKey) { ctxBuffer[byteCnt++] = DefaultKFPartitionProb[i][j]; } else { ctxBuffer[byteCnt++] = DefaultPartitionProb[i][j]; } } } //nmvc joints for (i = 0; i < (CODEC_VP9_MV_JOINTS - 1); i++) { if (!setToKey) { ctxBuffer[byteCnt++] = DefaultNmvContext.joints[i]; } else { //zeros for key frame byteCnt++; } } //nmvc comps for (i = 0; i < 2; i++) { if (!setToKey) { ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].sign; for (j = 0; j < (CODEC_VP9_MV_CLASSES - 1); j++) { ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].classes[j]; } for (j = 0; j < (CODECHAL_VP9_CLASS0_SIZE - 1); j++) { ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].class0[j]; } for (j = 0; j < CODECHAL_VP9_MV_OFFSET_BITS; j++) { ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].bits[j]; } } else { byteCnt += 1; byteCnt += (CODEC_VP9_MV_CLASSES - 1); byteCnt += (CODECHAL_VP9_CLASS0_SIZE - 1); byteCnt += (CODECHAL_VP9_MV_OFFSET_BITS); } } for (i = 0; i < 2; i++) { if (!setToKey) { for (j = 0; j < CODECHAL_VP9_CLASS0_SIZE; j++) { for (int32_t k = 0; k < (CODEC_VP9_MV_FP_SIZE - 1); k++) { ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].class0_fp[j][k]; } } for (j = 0; j < (CODEC_VP9_MV_FP_SIZE - 1); j++) { ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].fp[j]; } } else { byteCnt += (CODECHAL_VP9_CLASS0_SIZE * (CODEC_VP9_MV_FP_SIZE - 1)); byteCnt += (CODEC_VP9_MV_FP_SIZE - 1); } } for (i = 0; i < 2; i++) { if (!setToKey) { ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].class0_hp; ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].hp; } else { byteCnt += 2; } } //47 bytes of zeros byteCnt += 47; //uv mode probs for (i = 0; i < CODEC_VP9_INTRA_MODES; i++) { for (j = 0; j < CODEC_VP9_INTRA_MODES - 1; j++) { if (setToKey) { ctxBuffer[byteCnt++] = DefaultKFUVModeProb[i][j]; } else { ctxBuffer[byteCnt++] = DefaultIFUVProbs[i][j]; } } } return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeVp9::ContextBufferInit( uint8_t *ctxBuffer, bool setToKey) { MOS_ZeroMemory(ctxBuffer, CODEC_VP9_SEG_PROB_OFFSET); int32_t i, j; uint32_t byteCnt = 0; //TX probs for (i = 0; i < CODEC_VP9_TX_SIZE_CONTEXTS; i++) { for (j = 0; j < CODEC_VP9_TX_SIZES - 3; j++) { ctxBuffer[byteCnt++] = DefaultTxProbs.p8x8[i][j]; } } for (i = 0; i < CODEC_VP9_TX_SIZE_CONTEXTS; i++) { for (j = 0; j < CODEC_VP9_TX_SIZES - 2; j++) { ctxBuffer[byteCnt++] = DefaultTxProbs.p16x16[i][j]; } } for (i = 0; i < CODEC_VP9_TX_SIZE_CONTEXTS; i++) { for (j = 0; j < CODEC_VP9_TX_SIZES - 1; j++) { ctxBuffer[byteCnt++] = DefaultTxProbs.p32x32[i][j]; } } //52 bytes of zeros byteCnt += 52; uint8_t blocktype = 0; uint8_t reftype = 0; uint8_t coeffbands = 0; uint8_t unConstrainedNodes = 0; uint8_t prevCoefCtx = 0; //coeff probs for (blocktype = 0; blocktype < CODEC_VP9_BLOCK_TYPES; blocktype++) { for (reftype = 0; reftype < CODEC_VP9_REF_TYPES; reftype++) { for (coeffbands = 0; coeffbands < CODEC_VP9_COEF_BANDS; coeffbands++) { uint8_t numPrevCoeffCtxts = (coeffbands == 0) ? 3 : CODEC_VP9_PREV_COEF_CONTEXTS; for (prevCoefCtx = 0; prevCoefCtx < numPrevCoeffCtxts; prevCoefCtx++) { for (unConstrainedNodes = 0; unConstrainedNodes < CODEC_VP9_UNCONSTRAINED_NODES; unConstrainedNodes++) { ctxBuffer[byteCnt++] = DefaultCoefProbs4x4[blocktype][reftype][coeffbands][prevCoefCtx][unConstrainedNodes]; } } } } } for (blocktype = 0; blocktype < CODEC_VP9_BLOCK_TYPES; blocktype++) { for (reftype = 0; reftype < CODEC_VP9_REF_TYPES; reftype++) { for (coeffbands = 0; coeffbands < CODEC_VP9_COEF_BANDS; coeffbands++) { uint8_t numPrevCoeffCtxts = (coeffbands == 0) ? 3 : CODEC_VP9_PREV_COEF_CONTEXTS; for (prevCoefCtx = 0; prevCoefCtx < numPrevCoeffCtxts; prevCoefCtx++) { for (unConstrainedNodes = 0; unConstrainedNodes < CODEC_VP9_UNCONSTRAINED_NODES; unConstrainedNodes++) { ctxBuffer[byteCnt++] = DefaultCoefPprobs8x8[blocktype][reftype][coeffbands][prevCoefCtx][unConstrainedNodes]; } } } } } for (blocktype = 0; blocktype < CODEC_VP9_BLOCK_TYPES; blocktype++) { for (reftype = 0; reftype < CODEC_VP9_REF_TYPES; reftype++) { for (coeffbands = 0; coeffbands < CODEC_VP9_COEF_BANDS; coeffbands++) { uint8_t numPrevCoeffCtxts = (coeffbands == 0) ? 3 : CODEC_VP9_PREV_COEF_CONTEXTS; for (prevCoefCtx = 0; prevCoefCtx < numPrevCoeffCtxts; prevCoefCtx++) { for (unConstrainedNodes = 0; unConstrainedNodes < CODEC_VP9_UNCONSTRAINED_NODES; unConstrainedNodes++) { ctxBuffer[byteCnt++] = DefaultCoefProbs16x16[blocktype][reftype][coeffbands][prevCoefCtx][unConstrainedNodes]; } } } } } for (blocktype = 0; blocktype < CODEC_VP9_BLOCK_TYPES; blocktype++) { for (reftype = 0; reftype < CODEC_VP9_REF_TYPES; reftype++) { for (coeffbands = 0; coeffbands < CODEC_VP9_COEF_BANDS; coeffbands++) { uint8_t numPrevCoeffCtxts = (coeffbands == 0) ? 3 : CODEC_VP9_PREV_COEF_CONTEXTS; for (prevCoefCtx = 0; prevCoefCtx < numPrevCoeffCtxts; prevCoefCtx++) { for (unConstrainedNodes = 0; unConstrainedNodes < CODEC_VP9_UNCONSTRAINED_NODES; unConstrainedNodes++) { ctxBuffer[byteCnt++] = DefaultCoefProbs32x32[blocktype][reftype][coeffbands][prevCoefCtx][unConstrainedNodes]; } } } } } //16 bytes of zeros byteCnt += 16; // mb skip probs for (i = 0; i < CODEC_VP9_MBSKIP_CONTEXTS; i++) { ctxBuffer[byteCnt++] = DefaultMbskipProbs[i]; } // populate prob values which are different between Key and Non-Key frame CtxBufDiffInit(ctxBuffer, setToKey); //skip Seg tree/pred probs, updating not done in this function. byteCnt = CODEC_VP9_SEG_PROB_OFFSET; byteCnt += 7; byteCnt += 3; //28 bytes of zeros for (i = 0; i < 28; i++) { ctxBuffer[byteCnt++] = 0; } //Just a check. if (byteCnt > CODEC_VP9_PROB_MAX_NUM_ELEM) { CODECHAL_PUBLIC_ASSERTMESSAGE("Error: FrameContext array out-of-bounds, byteCnt = %d!\n", byteCnt); return MOS_STATUS_NO_SPACE; } else { return MOS_STATUS_SUCCESS; } }