/* * Copyright (c) 2017-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_vp8.cpp //! \brief Implements the decode interface extension for VP8. //! \details Implements all functions required by CodecHal for VP8 decoding. //! #include "codechal_decoder.h" #include "codechal_decode_vp8.h" #include "codec_def_vp8_probs.h" #include "codechal_mmc_decode_vp8.h" #include "hal_oca_interface.h" #if USE_CODECHAL_DEBUG_TOOL #include #include #include "codechal_debug.h" #endif void Vp8EntropyState::DecodeFill() { int32_t shift = m_bdValueSize - 8 - (m_count + 8); uint32_t bytesLeft = (uint32_t)(m_bufferEnd - m_buffer); uint32_t bitsLeft = bytesLeft * CHAR_BIT; int32_t num = (int32_t)(shift + CHAR_BIT - bitsLeft); int32_t loopEnd = 0; if (num >= 0) { m_count += m_lotsOfBits; loopEnd = num; } if (num < 0 || bitsLeft) { while (shift >= loopEnd) { m_count += CHAR_BIT; m_value |= (uint32_t)*m_buffer << shift; ++m_buffer; shift -= CHAR_BIT; } } } uint32_t Vp8EntropyState::DecodeBool(int32_t probability) { uint32_t split = 1 + (((m_range - 1) * probability) >> 8); uint32_t bigSplit = (uint32_t)split << (m_bdValueSize - 8); uint32_t origRange = m_range; m_range = split; uint32_t bit = 0; if (m_value >= bigSplit) { m_range = origRange - split; m_value = m_value - bigSplit; bit = 1; } int32_t shift = Norm[m_range]; m_range <<= shift; m_value <<= shift; m_count -= shift; if (m_count < 0) { DecodeFill(); } return bit; } int32_t Vp8EntropyState::DecodeValue(int32_t bits) { int32_t retValue = 0; for (int32_t iBit = bits - 1; iBit >= 0; iBit--) { retValue |= (DecodeBool(0x80) << iBit); } return retValue; } void Vp8EntropyState::ParseFrameHeadInit() { if (m_frameHead->iFrameType == m_keyFrame) { MOS_SecureMemcpy(m_frameHead->FrameContext.MvContext, sizeof(DefaultMvContext), DefaultMvContext, sizeof(DefaultMvContext)); MOS_SecureMemcpy(m_frameHead->FrameContext.YModeProb, sizeof(KfYModeProb), KfYModeProb, sizeof(KfYModeProb)); MOS_SecureMemcpy(m_frameHead->FrameContext.UVModeProb, sizeof(KfUVModeProb), KfUVModeProb, sizeof(KfUVModeProb)); MOS_SecureMemcpy(m_frameHead->FrameContext.CoefProbs, sizeof(DefaultCoefProbs), DefaultCoefProbs, sizeof(DefaultCoefProbs)); MOS_SecureMemcpy(m_frameHead->YModeProbs, sizeof(KfYModeProb), KfYModeProb, sizeof(KfYModeProb)); MOS_SecureMemcpy(m_frameHead->UVModeProbs, sizeof(KfUVModeProb), KfUVModeProb, sizeof(KfUVModeProb)); MOS_SecureMemcpy(m_frameHead->YModeProbs, sizeof(YModeProb), YModeProb, sizeof(YModeProb)); MOS_SecureMemcpy(m_frameHead->UVModeProbs, sizeof(UVModeProb), UVModeProb, sizeof(UVModeProb)); memset(m_frameHead->SegmentFeatureData, 0, sizeof(m_frameHead->SegmentFeatureData)); m_frameHead->u8MbSegementAbsDelta = 0; memset(m_frameHead->RefLFDeltas, 0, sizeof(m_frameHead->RefLFDeltas)); memset(m_frameHead->ModeLFDeltas, 0, sizeof(m_frameHead->ModeLFDeltas)); m_frameHead->iRefreshGoldenFrame = 1; m_frameHead->iRefreshAltFrame = 1; m_frameHead->iCopyBufferToGolden = 0; m_frameHead->iCopyBufferToAlt = 0; m_frameHead->iLastFrameBufferCurrIdx = m_frameHead->iNewFrameBufferIdx; m_frameHead->iGoldenFrameBufferCurrIdx = m_frameHead->iNewFrameBufferIdx; m_frameHead->iAltFrameBufferCurrIdx = m_frameHead->iNewFrameBufferIdx; m_frameHead->RefFrameSignBias[VP8_GOLDEN_FRAME] = 0; m_frameHead->RefFrameSignBias[VP8_ALTREF_FRAME] = 0; } } int32_t Vp8EntropyState::StartEntropyDecode() { m_bufferEnd = m_dataBufferEnd; m_buffer = m_dataBuffer; m_value = 0; m_count = -8; m_range = 255; if ((m_bufferEnd - m_buffer) > 0 && m_buffer == nullptr) { return 1; } DecodeFill(); return 0; } void Vp8EntropyState::SegmentationEnabled() { m_frameHead->u8SegmentationEnabled = (uint8_t)DecodeBool(m_probHalf); if (m_frameHead->u8SegmentationEnabled) { m_frameHead->u8UpdateMbSegmentationMap = (uint8_t)DecodeBool(m_probHalf); m_frameHead->u8UpdateMbSegmentationData = (uint8_t)DecodeBool(m_probHalf); if (m_frameHead->u8UpdateMbSegmentationData) { m_frameHead->u8MbSegementAbsDelta = (uint8_t)DecodeBool(m_probHalf); memset(m_frameHead->SegmentFeatureData, 0, sizeof(m_frameHead->SegmentFeatureData)); for (int32_t i = 0; i < VP8_MB_LVL_MAX; i++) { for (int32_t j = 0; j < VP8_MAX_MB_SEGMENTS; j++) { if (DecodeBool(m_probHalf)) { m_frameHead->SegmentFeatureData[i][j] = (int8_t)DecodeValue(MbFeatureDataBits[i]); if (DecodeBool(m_probHalf)) { m_frameHead->SegmentFeatureData[i][j] = -m_frameHead->SegmentFeatureData[i][j]; } } else { m_frameHead->SegmentFeatureData[i][j] = 0; } } } } if (m_frameHead->u8UpdateMbSegmentationMap) { memset(m_frameHead->MbSegmentTreeProbs, 255, sizeof(m_frameHead->MbSegmentTreeProbs)); for (int32_t i = 0; i < VP8_MB_SEGMENT_TREE_PROBS; i++) { if (DecodeBool(m_probHalf)) { m_frameHead->MbSegmentTreeProbs[i] = (uint8_t)DecodeValue(8); } } } } else { m_frameHead->u8UpdateMbSegmentationMap = 0; m_frameHead->u8UpdateMbSegmentationData = 0; } } void Vp8EntropyState::LoopFilterInit(int32_t defaultFilterLvl) { for (int32_t segmentNum = 0; segmentNum < VP8_MAX_MB_SEGMENTS; segmentNum++) { int32_t segmentLvl = defaultFilterLvl; if (m_frameHead->u8SegmentationEnabled) { if (m_frameHead->u8MbSegementAbsDelta == 1) { m_frameHead->LoopFilterLevel[segmentNum] = segmentLvl = m_frameHead->SegmentFeatureData[VP8_MB_LVL_ALT_LF][segmentNum]; } else { segmentLvl += m_frameHead->SegmentFeatureData[VP8_MB_LVL_ALT_LF][segmentNum]; m_frameHead->LoopFilterLevel[segmentNum] = segmentLvl = (segmentLvl > 0) ? ((segmentLvl > 63) ? 63 : segmentLvl) : 0; } } } } void Vp8EntropyState::LoopFilterEnabled() { m_frameHead->FilterType = (VP8_LF_TYPE)DecodeBool(m_probHalf); m_frameHead->iFilterLevel = DecodeValue(6); m_frameHead->iSharpnessLevel = DecodeValue(3); m_frameHead->u8ModeRefLfDeltaUpdate = 0; m_frameHead->u8ModeRefLfDeltaEnabled = (uint8_t)DecodeBool(m_probHalf); if (m_frameHead->u8ModeRefLfDeltaEnabled) { m_frameHead->u8ModeRefLfDeltaUpdate = (uint8_t)DecodeBool(m_probHalf); if (m_frameHead->u8ModeRefLfDeltaUpdate) { for (int32_t i = 0; i < VP8_MAX_REF_LF_DELTAS; i++) { if (DecodeBool(m_probHalf)) { m_frameHead->RefLFDeltas[i] = (int8_t)DecodeValue(6); if (DecodeBool(m_probHalf)) { m_frameHead->RefLFDeltas[i] = m_frameHead->RefLFDeltas[i] * (-1); } } } for (int32_t i = 0; i < VP8_MAX_MODE_LF_DELTAS; i++) { if (DecodeBool(m_probHalf)) { m_frameHead->ModeLFDeltas[i] = (int8_t)DecodeValue(6); if (DecodeBool(m_probHalf)) { m_frameHead->ModeLFDeltas[i] = m_frameHead->ModeLFDeltas[i] * (-1); } } } } } if (m_frameHead->iFilterLevel) { LoopFilterInit(m_frameHead->iFilterLevel); } } int32_t Vp8EntropyState::GetDeltaQ(int32_t prevVal, int32_t *qupdate) { int32_t retVal = 0; if (DecodeBool(m_probHalf)) { retVal = DecodeValue(4); if (DecodeBool(m_probHalf)) { retVal = -retVal; } } if (retVal != prevVal) { *qupdate = 1; } return retVal; } int32_t Vp8EntropyState::DcQuant(int32_t qindex, int32_t delta) { int32_t retVal; qindex = qindex + delta; if (qindex > 127) { qindex = 127; } else if (qindex < 0) { qindex = 0; } retVal = DcQLookup[qindex]; return retVal; } int32_t Vp8EntropyState::Dc2Quant(int32_t qindex, int32_t delta) { int32_t retVal; qindex = qindex + delta; if (qindex > 127) { qindex = 127; } else if (qindex < 0) { qindex = 0; } retVal = DcQLookup[qindex] * 2; return retVal; } int32_t Vp8EntropyState::DcUVQuant(int32_t qindex, int32_t delta) { int32_t retVal; qindex = qindex + delta; if (qindex > 127) { qindex = 127; } else if (qindex < 0) { qindex = 0; } retVal = DcQLookup[qindex]; if (retVal > 132) { retVal = 132; } return retVal; } int32_t Vp8EntropyState::AcYQuant(int32_t qindex) { int32_t retVal; if (qindex > 127) { qindex = 127; } else if (qindex < 0) { qindex = 0; } retVal = AcQLookup[qindex]; return retVal; } int32_t Vp8EntropyState::Ac2Quant(int32_t qindex, int32_t delta) { int32_t retVal; qindex = qindex + delta; if (qindex > 127) { qindex = 127; } else if (qindex < 0) { qindex = 0; } retVal = (AcQLookup[qindex] * 101581) >> 16; if (retVal < 8) { retVal = 8; } return retVal; } int32_t Vp8EntropyState::AcUVQuant(int32_t qindex, int32_t delta) { int32_t retVal; qindex = qindex + delta; if (qindex > 127) { qindex = 127; } else if (qindex < 0) { qindex = 0; } retVal = AcQLookup[qindex]; return retVal; } void Vp8EntropyState::QuantInit() { for (int32_t i = 0; i < VP8_Q_INDEX_RANGE; i++) { m_frameHead->Y1DeQuant[i][0] = (int16_t)DcQuant(i, m_frameHead->iY1DcDeltaQ); m_frameHead->Y2DeQuant[i][0] = (int16_t)Dc2Quant(i, m_frameHead->iY2DcDeltaQ); m_frameHead->UVDeQuant[i][0] = (int16_t)DcUVQuant(i, m_frameHead->iUVDcDeltaQ); m_frameHead->Y1DeQuant[i][1] = (int16_t)AcYQuant(i); m_frameHead->Y2DeQuant[i][1] = (int16_t)Ac2Quant(i, m_frameHead->iY2AcDeltaQ); m_frameHead->UVDeQuant[i][1] = (int16_t)AcUVQuant(i, m_frameHead->iUVAcDeltaQ); } } void Vp8EntropyState::QuantSetup() { int32_t qupdate = 0; m_frameHead->iBaseQIndex = DecodeValue(7); m_frameHead->iY1DcDeltaQ = GetDeltaQ(m_frameHead->iY1DcDeltaQ, &qupdate); m_frameHead->iY2DcDeltaQ = GetDeltaQ(m_frameHead->iY2DcDeltaQ, &qupdate); m_frameHead->iY2AcDeltaQ = GetDeltaQ(m_frameHead->iY2AcDeltaQ, &qupdate); m_frameHead->iUVDcDeltaQ = GetDeltaQ(m_frameHead->iUVDcDeltaQ, &qupdate); m_frameHead->iUVAcDeltaQ = GetDeltaQ(m_frameHead->iUVAcDeltaQ, &qupdate); if (qupdate) { QuantInit(); } } void Vp8EntropyState::ReadMvContexts(MV_CONTEXT *mvContext) { int32_t i = 0; do { const uint8_t *upProb = MvUpdateProbs[i].MvProb; uint8_t *prob = (uint8_t *)(mvContext + i); uint8_t *const stopProb = prob + 19; do { if (DecodeBool(*upProb++)) { const uint8_t x = (uint8_t)DecodeValue(7); *prob = x ? x << 1 : 1; } } while (++prob < stopProb); } while (++i < 2); } MOS_STATUS Vp8EntropyState::ParseFrameHead(PCODEC_VP8_PIC_PARAMS vp8PicParams) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; ParseFrameHeadInit(); StartEntropyDecode(); if (m_frameHead->iFrameType == m_keyFrame) { DecodeBool(m_probHalf); // Color Space DecodeBool(m_probHalf); // Clamp Type } SegmentationEnabled(); LoopFilterEnabled(); m_frameHead->MultiTokenPartition = (VP8_TOKEN_PARTITION)DecodeValue(2); if (!m_frameHead->bNotFirstCall) { QuantInit(); } QuantSetup(); if (m_frameHead->iFrameType != m_keyFrame) { m_frameHead->iRefreshGoldenFrame = DecodeBool(m_probHalf); m_frameHead->iRefreshAltFrame = DecodeBool(m_probHalf); m_frameHead->iCopyBufferToGolden = 0; if (!m_frameHead->iRefreshGoldenFrame) { m_frameHead->iCopyBufferToGolden = DecodeValue(2); } m_frameHead->iCopyBufferToAlt = 0; if (!m_frameHead->iRefreshAltFrame) { m_frameHead->iCopyBufferToAlt = DecodeValue(2); } m_frameHead->RefFrameSignBias[VP8_GOLDEN_FRAME] = DecodeBool(m_probHalf); m_frameHead->RefFrameSignBias[VP8_ALTREF_FRAME] = DecodeBool(m_probHalf); } if (m_frameHead->bNotFirstCall && m_frameHead->iRefreshEntropyProbs == 0) { MOS_SecureMemcpy(&m_frameHead->FrameContext, sizeof(m_frameHead->FrameContext), &m_frameHead->LastFrameContext, sizeof(m_frameHead->LastFrameContext)); } m_frameHead->iRefreshEntropyProbs = DecodeBool(m_probHalf); if (m_frameHead->iRefreshEntropyProbs == 0) { MOS_SecureMemcpy(&m_frameHead->LastFrameContext, sizeof(m_frameHead->LastFrameContext), &m_frameHead->FrameContext, sizeof(m_frameHead->FrameContext)); } if (m_frameHead->iFrameType == m_keyFrame || DecodeBool(m_probHalf)) { m_frameHead->iRefreshLastFrame = true; } else { m_frameHead->iRefreshLastFrame = false; } for (int32_t i = 0; i < VP8_BLOCK_TYPES; i++) for (int32_t j = 0; j < VP8_COEF_BANDS; j++) for (int32_t k = 0; k < VP8_PREV_COEF_CONTEXTS; k++) for (int32_t l = 0; l < VP8_ENTROPY_NODES; l++) { uint8_t *const p = m_frameHead->FrameContext.CoefProbs[i][j][k] + l; if (DecodeBool(CoefUpdateProbs[i][j][k][l])) { *p = (uint8_t)DecodeValue(8); } } m_frameHead->iMbNoCoeffSkip = (int32_t)DecodeBool(m_probHalf); m_frameHead->iProbSkipFalse = 0; if (m_frameHead->iMbNoCoeffSkip) { m_frameHead->iProbSkipFalse = (uint8_t)DecodeValue(8); } if (m_frameHead->iFrameType != m_keyFrame) { m_frameHead->ProbIntra = (uint8_t)DecodeValue(8); m_frameHead->ProbLast = (uint8_t)DecodeValue(8); m_frameHead->ProbGf = (uint8_t)DecodeValue(8); if (DecodeBool(m_probHalf)) { int32_t i = 0; do { m_frameHead->YModeProbs[i] = m_frameHead->FrameContext.YModeProb[i] = (uint8_t)DecodeValue(8); } while (++i < 4); } if (DecodeBool(m_probHalf)) { int32_t i = 0; do { m_frameHead->UVModeProbs[i] = m_frameHead->FrameContext.UVModeProb[i] = (uint8_t)DecodeValue(8); } while (++i < 3); } MV_CONTEXT MVContext[2]; for (int32_t i = 0; i < 2; i++) { for (int32_t j = 0; j < 19; j++) { MVContext[i].MvProb[j] = vp8PicParams->ucMvUpdateProb[i][j]; } } ReadMvContexts(MVContext); } vp8PicParams->ucP0EntropyCount = 8 - (m_count & 0x07); vp8PicParams->ucP0EntropyValue = (uint8_t)(m_value >> 24); vp8PicParams->uiP0EntropyRange = m_range; uint32_t firstPartitionAndUncompSize; if (m_frameHead->iFrameType == m_keyFrame) { firstPartitionAndUncompSize = vp8PicParams->uiFirstPartitionSize + 10; } else { firstPartitionAndUncompSize = vp8PicParams->uiFirstPartitionSize + 3; } // Partition Size uint32_t partitionNum = 1 << m_frameHead->MultiTokenPartition; uint32_t partitionSizeSum = 0; m_dataBuffer = m_bitstreamBuffer + firstPartitionAndUncompSize; if (partitionNum > 1) { for (int32_t i = 1; i < (int32_t)partitionNum; i++) { vp8PicParams->uiPartitionSize[i] = m_dataBuffer[0] + (m_dataBuffer[1] << 8) + (m_dataBuffer[2] << 16); m_dataBuffer += 3; partitionSizeSum += vp8PicParams->uiPartitionSize[i]; } } uint32_t offsetCounter = ((m_count & 0x18) >> 3) + (((m_count & 0x07) != 0) ? 1 : 0); vp8PicParams->uiFirstMbByteOffset = (uint32_t)(m_buffer - m_bitstreamBuffer) - offsetCounter; vp8PicParams->uiPartitionSize[0] = firstPartitionAndUncompSize - (uint32_t)(m_buffer - m_bitstreamBuffer) + offsetCounter; vp8PicParams->uiPartitionSize[partitionNum] = m_bitstreamBufferSize - firstPartitionAndUncompSize - (partitionNum - 1) * 3 - partitionSizeSum; return eStatus; } void Vp8EntropyState::FrameHeadQuantUpdate( PCODEC_VP8_PIC_PARAMS vp8PicParams) { for (int32_t i = 0; i < VP8_Q_INDEX_RANGE; i++) { m_frameHead->Y1DeQuant[i][0] = (int16_t)DcQuant(i, vp8PicParams->cY1DcDeltaQ); m_frameHead->Y2DeQuant[i][0] = (int16_t)Dc2Quant(i, vp8PicParams->cY2DcDeltaQ); m_frameHead->UVDeQuant[i][0] = (int16_t)DcUVQuant(i, vp8PicParams->cUVDcDeltaQ); m_frameHead->Y1DeQuant[i][1] = (int16_t)AcYQuant(i); m_frameHead->Y2DeQuant[i][1] = (int16_t)Ac2Quant(i, vp8PicParams->cY2AcDeltaQ); m_frameHead->UVDeQuant[i][1] = (int16_t)AcUVQuant(i, vp8PicParams->cUVAcDeltaQ); } } void Vp8EntropyState::Initialize( PCODECHAL_DECODE_VP8_FRAME_HEAD vp8FrameHeadIn, uint8_t* bitstreamBufferIn, uint32_t bitstreamBufferSizeIn) { m_frameHead = vp8FrameHeadIn; m_dataBuffer = bitstreamBufferIn; m_dataBufferEnd = bitstreamBufferIn + bitstreamBufferSizeIn; m_bitstreamBuffer = bitstreamBufferIn; m_bitstreamBufferSize = bitstreamBufferSizeIn; m_frameHead->iFrameType = m_dataBuffer[0] & 1; m_frameHead->iVersion = (m_dataBuffer[0] >> 1) & 7; m_frameHead->iShowframe = (m_dataBuffer[0] >> 4) & 1; m_frameHead->uiFirstPartitionLengthInBytes = (m_dataBuffer[0] | (m_dataBuffer[1] << 8) | (m_dataBuffer[2] << 16)) >> 5; m_dataBuffer += 3; if (m_frameHead->iFrameType == m_keyFrame) { m_dataBuffer += 7; } } MOS_STATUS CodechalDecodeVp8::ParseFrameHead(uint8_t* bitstreamBuffer, uint32_t bitstreamBufferSize) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; CODECHAL_DECODE_CHK_NULL_RETURN(bitstreamBuffer); m_vp8EntropyState.Initialize(&m_vp8FrameHead, bitstreamBuffer, bitstreamBufferSize); eStatus = m_vp8EntropyState.ParseFrameHead(m_vp8PicParams); if (eStatus != MOS_STATUS_SUCCESS) { CODECHAL_DECODE_ASSERTMESSAGE("Fail to parse VP8 Frame Head"); return eStatus; } //------------------------------------------------------Temporary Separator // Loop Filter for (int32_t i = 0; i < VP8_MAX_MB_SEGMENTS; i++) { int32_t segmentLvl = m_vp8PicParams->ucFilterLevel; if (m_vp8PicParams->segmentation_enabled) { if (m_vp8PicParams->mb_segement_abs_delta == 1) { m_vp8PicParams->ucLoopFilterLevel[i] = segmentLvl = m_vp8PicParams->cSegmentFeatureData[VP8_MB_LVL_ALT_LF][i]; } else { segmentLvl += m_vp8PicParams->cSegmentFeatureData[VP8_MB_LVL_ALT_LF][i]; m_vp8PicParams->ucLoopFilterLevel[i] = segmentLvl = (segmentLvl > 0) ? ((segmentLvl > 63) ? 63 : segmentLvl) : 0; } } else { m_vp8PicParams->ucLoopFilterLevel[i] = m_vp8PicParams->ucFilterLevel; } } // Quant Matrix int32_t vp8QIndex[VP8_MAX_MB_SEGMENTS]; if (m_vp8PicParams->segmentation_enabled) { for (int32_t i = 0; i < 4; i++) { if (m_vp8PicParams->mb_segement_abs_delta == 1) { vp8QIndex[i] = (int32_t)m_vp8PicParams->cSegmentFeatureData[VP8_MB_LVL_ALT_Q][i]; } else { vp8QIndex[i] = (int32_t)m_vp8PicParams->ucBaseQIndex + (int32_t)m_vp8PicParams->cSegmentFeatureData[VP8_MB_LVL_ALT_Q][i]; vp8QIndex[i] = (vp8QIndex[i] >= 0) ? ((vp8QIndex[i] <= VP8_MAX_Q) ? vp8QIndex[i] : VP8_MAX_Q) : 0; // Clamp to valid range } } } else { vp8QIndex[0] = (int32_t)m_vp8PicParams->ucBaseQIndex; vp8QIndex[1] = 0; vp8QIndex[2] = 0; vp8QIndex[3] = 0; } m_vp8EntropyState.FrameHeadQuantUpdate(m_vp8PicParams); m_vp8IqMatrixParams->quantization_values[0][0] = m_vp8FrameHead.Y1DeQuant[vp8QIndex[0]][0]; m_vp8IqMatrixParams->quantization_values[0][1] = m_vp8FrameHead.Y1DeQuant[vp8QIndex[0]][1]; m_vp8IqMatrixParams->quantization_values[0][2] = m_vp8FrameHead.UVDeQuant[vp8QIndex[0]][0]; m_vp8IqMatrixParams->quantization_values[0][3] = m_vp8FrameHead.UVDeQuant[vp8QIndex[0]][1]; m_vp8IqMatrixParams->quantization_values[0][4] = m_vp8FrameHead.Y2DeQuant[vp8QIndex[0]][0]; m_vp8IqMatrixParams->quantization_values[0][5] = m_vp8FrameHead.Y2DeQuant[vp8QIndex[0]][1]; if (m_vp8FrameHead.u8SegmentationEnabled) { for (int32_t i = 1; i < 4; i++) { m_vp8IqMatrixParams->quantization_values[i][0] = m_vp8FrameHead.Y1DeQuant[vp8QIndex[i]][0]; m_vp8IqMatrixParams->quantization_values[i][1] = m_vp8FrameHead.Y1DeQuant[vp8QIndex[i]][1]; m_vp8IqMatrixParams->quantization_values[i][2] = m_vp8FrameHead.UVDeQuant[vp8QIndex[i]][0]; m_vp8IqMatrixParams->quantization_values[i][3] = m_vp8FrameHead.UVDeQuant[vp8QIndex[i]][1]; m_vp8IqMatrixParams->quantization_values[i][4] = m_vp8FrameHead.Y2DeQuant[vp8QIndex[i]][0]; m_vp8IqMatrixParams->quantization_values[i][5] = m_vp8FrameHead.Y2DeQuant[vp8QIndex[i]][1]; } } else { for (int32_t i = 1; i < 4; i++) { for (int32_t j = 0; j < 6; j++) { m_vp8IqMatrixParams->quantization_values[i][j] = 0; } } } // Coef Prob if (!Mos_ResourceIsNull(&m_resCoefProbBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resCoefProbBuffer); } CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resCoefProbBuffer, sizeof(m_vp8FrameHead.FrameContext.CoefProbs), "VP8_Coef_Prob"), "Failed to allocate VP8 CoefProb Buffer."); CodechalResLock ResourceLock(m_osInterface, &m_resCoefProbBuffer); auto data = (uint8_t*)ResourceLock.Lock(CodechalResLock::writeOnly); CODECHAL_DECODE_CHK_NULL_RETURN(data); MOS_SecureMemcpy( data, sizeof(m_vp8FrameHead.FrameContext.CoefProbs), (void *)&(m_vp8FrameHead.FrameContext.CoefProbs), sizeof(m_vp8FrameHead.FrameContext.CoefProbs)); m_vp8FrameHead.bNotFirstCall = true; return eStatus; } MOS_STATUS CodechalDecodeVp8::CopyBitstreamBuffer( MOS_RESOURCE srcBitstreamBuffer, PMOS_RESOURCE dstBitstreamBuffer, uint32_t size) { 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 &srcBitstreamBuffer, // presSrc dstBitstreamBuffer, // presDst MOS_ALIGN_CEIL(size, 16), // 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)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd( &cmdBuffer, nullptr)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); m_huCCopyInUse = true; 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)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(m_osInterface, m_videoContext)); return eStatus; } MOS_STATUS CodechalDecodeVp8::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(CodecHalAllocateDataList( m_vp8RefList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP8)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource( m_osInterface, &m_resSyncObjectWaContextInUse)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource( m_osInterface, &m_resSyncObjectVideoContextInUse)); return eStatus; } MOS_STATUS CodechalDecodeVp8::AllocateResourcesVariableSizes() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; if (m_decodeParams.m_bitstreamLockingInUse && (!m_decodeParams.m_bitstreamLockable)) { if (!Mos_ResourceIsNull(&m_resTmpBitstreamBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resTmpBitstreamBuffer); } CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resTmpBitstreamBuffer, m_dataSize, "VP8_BitStream"), "Failed to allocate Bitstream Buffer."); } uint16_t picWidthInMB = MOS_MAX(m_picWidthInMbLastMaxAlloced, (m_vp8PicParams->wFrameWidthInMbsMinus1 + 1)); uint16_t picHeightInMB = MOS_MAX(m_picHeightInMbLastMaxAlloced, (m_vp8PicParams->wFrameHeightInMbsMinus1 + 1)); uint32_t maxWidth = picWidthInMB * CODECHAL_MACROBLOCK_WIDTH; uint32_t maxHeight = picHeightInMB * CODECHAL_MACROBLOCK_HEIGHT; uint32_t numMacroblocks = picWidthInMB * picHeightInMB; if (m_mfxInterface->IsDeblockingFilterRowstoreCacheEnabled() == false) { uint16_t maxMfdDFRowStoreScratchBufferPicWidthInMB; maxMfdDFRowStoreScratchBufferPicWidthInMB = MOS_MAX(m_mfdDeblockingFilterRowStoreScratchBufferPicWidthInMb, (m_vp8PicParams->wFrameWidthInMbsMinus1 + 1)); if ((maxMfdDFRowStoreScratchBufferPicWidthInMB > m_mfdDeblockingFilterRowStoreScratchBufferPicWidthInMb) || 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, maxMfdDFRowStoreScratchBufferPicWidthInMB * 2 * CODECHAL_CACHELINE_SIZE, "DeblockingScratchBuffer"), "Failed to allocate Deblocking Filter Row Store Scratch Buffer."); } //record the width and height used for allocation internal resources. m_mfdDeblockingFilterRowStoreScratchBufferPicWidthInMb = maxMfdDFRowStoreScratchBufferPicWidthInMB; } if (m_mfxInterface->IsIntraRowstoreCacheEnabled() == false) { uint16_t maxMfdIntraRowStoreScratchBufferPicWidthInMB; maxMfdIntraRowStoreScratchBufferPicWidthInMB = MOS_MAX(m_mfdIntraRowStoreScratchBufferPicWidthInMb, (m_vp8PicParams->wFrameWidthInMbsMinus1 + 1)); if ((maxMfdIntraRowStoreScratchBufferPicWidthInMB > 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, maxMfdIntraRowStoreScratchBufferPicWidthInMB * CODECHAL_CACHELINE_SIZE, "IntraScratchBuffer"), "Failed to allocate VP8 BSD Intra Row Store Scratch Buffer."); } //record the width and height used for allocation internal resources. m_mfdIntraRowStoreScratchBufferPicWidthInMb = maxMfdIntraRowStoreScratchBufferPicWidthInMB; } if (m_mfxInterface->IsBsdMpcRowstoreCacheEnabled() == false) { uint16_t maxBsdMpcRowStoreScratchBufferPicWidthInMB; maxBsdMpcRowStoreScratchBufferPicWidthInMB = MOS_MAX(m_bsdMpcRowStoreScratchBufferPicWidthInMb, (m_vp8PicParams->wFrameWidthInMbsMinus1 + 1)); if ((maxBsdMpcRowStoreScratchBufferPicWidthInMB > 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, maxBsdMpcRowStoreScratchBufferPicWidthInMB * CODECHAL_CACHELINE_SIZE * 2, "MpcScratchBuffer"), "Failed to allocate BSD/MPC Row Store Scratch Buffer."); } //record the width and height used for allocation internal resources. m_bsdMpcRowStoreScratchBufferPicWidthInMb = maxBsdMpcRowStoreScratchBufferPicWidthInMB; } if ((picWidthInMB > m_picWidthInMbLastMaxAlloced) || Mos_ResourceIsNull(&m_resMprRowStoreScratchBuffer)) { if (!Mos_ResourceIsNull(&m_resMprRowStoreScratchBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resMprRowStoreScratchBuffer); } // MPR Row Store Scratch buffer // (FrameWidth in MB) * (2) * (CacheLine size per MB) CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resMprRowStoreScratchBuffer, picWidthInMB * CODECHAL_CACHELINE_SIZE * 22, "MprScratchBuffer"), "Failed to allocate MPR Row Store Scratch Buffer."); } if ((numMacroblocks > (uint32_t)m_picWidthInMbLastMaxAlloced * m_picHeightInMbLastMaxAlloced) || Mos_ResourceIsNull(&m_resSegmentationIdStreamBuffer)) { if (!Mos_ResourceIsNull(&m_resSegmentationIdStreamBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_resSegmentationIdStreamBuffer); } // Segmentation ID Stream buffer //(Num MacroBlocks) * (Cachline size) * (2 bit) CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resSegmentationIdStreamBuffer, MOS_MAX(numMacroblocks * CODECHAL_CACHELINE_SIZE * 2 / 8, 64), "SegmentationIdStreamBuffer"), "Failed to allocate Segmentation ID Stream Buffer."); } m_picWidthInMbLastMaxAlloced = picWidthInMB; m_picHeightInMbLastMaxAlloced = picHeightInMB; return eStatus; } CodechalDecodeVp8::~CodechalDecodeVp8() { CODECHAL_DECODE_FUNCTION_ENTER; m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObject); CodecHalFreeDataList(m_vp8RefList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP8); // indicate resCoefProbBuffer is allocated internal, not from m_decodeParams.m_coefProbBuffer if (m_vp8FrameHead.bNotFirstCall == true) { m_osInterface->pfnFreeResource( m_osInterface, &m_resCoefProbBuffer); } m_osInterface->pfnFreeResource( m_osInterface, &m_resTmpBitstreamBuffer); m_osInterface->pfnFreeResource( m_osInterface, &m_resMfdDeblockingFilterRowStoreScratchBuffer); m_osInterface->pfnFreeResource( m_osInterface, &m_resMfdIntraRowStoreScratchBuffer); m_osInterface->pfnFreeResource( m_osInterface, &m_resBsdMpcRowStoreScratchBuffer); m_osInterface->pfnFreeResource( m_osInterface, &m_resMprRowStoreScratchBuffer); m_osInterface->pfnFreeResource( m_osInterface, &m_resSegmentationIdStreamBuffer); m_osInterface->pfnDestroySyncResource( m_osInterface, &m_resSyncObjectWaContextInUse); m_osInterface->pfnDestroySyncResource( m_osInterface, &m_resSyncObjectVideoContextInUse); return; } MOS_STATUS CodechalDecodeVp8::SetFrameStates() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 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_destSurface = *(m_decodeParams.m_destSurface); m_presLastRefSurface = m_decodeParams.m_presNoneRegLastRefFrame; m_presAltRefSurface = m_decodeParams.m_presNoneRegAltRefFrame; m_presGoldenRefSurface = m_decodeParams.m_presNoneRegGoldenRefFrame; m_resDataBuffer = *(m_decodeParams.m_dataBuffer); m_vp8PicParams = (PCODEC_VP8_PIC_PARAMS)m_decodeParams.m_picParams; m_vp8IqMatrixParams = (PCODEC_VP8_IQ_MATRIX_PARAMS)m_decodeParams.m_iqMatrixBuffer; CODECHAL_DECODE_CHK_NULL_RETURN(m_vp8PicParams); PCODEC_REF_LIST destEntry = m_vp8RefList[m_vp8PicParams->CurrPic.FrameIdx]; CODEC_PICTURE currPic = m_vp8PicParams->CurrPic; MOS_ZeroMemory(destEntry, sizeof(CODEC_REF_LIST)); destEntry->RefPic = currPic; destEntry->resRefPic = m_destSurface.OsResource; m_statusReportFeedbackNumber = m_vp8PicParams->uiStatusReportFeedbackNumber; m_deblockingEnabled = !m_vp8PicParams->LoopFilterDisable ? true : false; if (m_mfxInterface->IsRowStoreCachingSupported()) { MHW_VDBOX_ROWSTORE_PARAMS rowstoreParams; MOS_ZeroMemory(&rowstoreParams, sizeof(rowstoreParams)); rowstoreParams.dwPicWidth = m_width; rowstoreParams.bMbaff = false; rowstoreParams.Mode = CODECHAL_DECODE_MODE_VP8VLD; CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->SetRowstoreCachingOffsets(&rowstoreParams)); } CODECHAL_DECODE_CHK_STATUS_RETURN(AllocateResourcesVariableSizes()); if (m_decodeParams.m_bitstreamLockingInUse) { if (m_decodeParams.m_bitstreamLockable) { CodechalResLock ResourceLock(m_osInterface, &m_resDataBuffer); auto bitstreamBuffer = (uint8_t*)ResourceLock.Lock(CodechalResLock::readOnly); CODECHAL_DECODE_CHK_NULL_RETURN(bitstreamBuffer); CODECHAL_DECODE_CHK_STATUS_RETURN(ParseFrameHead(bitstreamBuffer + m_dataOffset, m_dataSize)); } else { CODECHAL_DECODE_CHK_STATUS_RETURN(CopyBitstreamBuffer(m_resDataBuffer, &m_resTmpBitstreamBuffer, m_dataSize)); CodechalResLock ResourceLock(m_osInterface, &m_resTmpBitstreamBuffer); auto bitstreamBuffer = (uint8_t*)ResourceLock.Lock(CodechalResLock::readOnly); CODECHAL_DECODE_CHK_NULL_RETURN(bitstreamBuffer); CODECHAL_DECODE_CHK_STATUS_RETURN(ParseFrameHead(bitstreamBuffer, m_dataSize)); } m_decodeParams.m_coefProbSize = sizeof(m_vp8FrameHead.FrameContext.CoefProbs); } else { m_resCoefProbBuffer = *(m_decodeParams.m_coefProbBuffer); } m_width = (m_vp8PicParams->wFrameWidthInMbsMinus1 + 1) * CODECHAL_MACROBLOCK_WIDTH; m_height = (m_vp8PicParams->wFrameHeightInMbsMinus1 + 1) * CODECHAL_MACROBLOCK_HEIGHT; // Overwrite the actual surface height with the coded height and width of the frame // for VP8 since it's possible for a VP8 frame to change size during playback m_destSurface.dwWidth = m_width; m_destSurface.dwHeight = m_height; m_perfType = m_vp8PicParams->key_frame ? I_TYPE : P_TYPE; m_crrPic = m_vp8PicParams->CurrPic; CODECHAL_DEBUG_TOOL( CODECHAL_DECODE_CHK_NULL_RETURN(m_debugInterface); m_vp8PicParams->CurrPic.PicFlags = PICTURE_FRAME; m_debugInterface->m_currPic = m_crrPic; m_debugInterface->m_frameType = m_perfType; if (m_vp8PicParams) { CODECHAL_DECODE_CHK_STATUS_RETURN(DumpPicParams( m_vp8PicParams)); } if (m_vp8IqMatrixParams) { CODECHAL_DECODE_CHK_STATUS_RETURN(DumpIQParams( m_vp8IqMatrixParams)); } // Dump Vp8CoefProb CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &(m_resCoefProbBuffer), CodechalDbgAttr::attrCoeffProb, "_DEC", m_decodeParams.m_coefProbSize));) return eStatus; } MOS_STATUS CodechalDecodeVp8::DecodeStateLevel() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; if (m_vp8PicParams->key_frame) // reference surface should be nullptr when key_frame == true { m_presLastRefSurface = nullptr; m_presGoldenRefSurface = nullptr; m_presAltRefSurface = nullptr; } else { if((Mos_ResourceIsNull(&m_vp8RefList[m_vp8PicParams->ucLastRefPicIndex]->resRefPic)) && (m_presLastRefSurface)) { m_vp8RefList[m_vp8PicParams->ucLastRefPicIndex]->resRefPic = *m_presLastRefSurface; } else { m_presLastRefSurface = &(m_vp8RefList[m_vp8PicParams->ucLastRefPicIndex]->resRefPic); } if((Mos_ResourceIsNull(&m_vp8RefList[m_vp8PicParams->ucGoldenRefPicIndex]->resRefPic)) && (m_presGoldenRefSurface)) { m_vp8RefList[m_vp8PicParams->ucGoldenRefPicIndex]->resRefPic = *m_presGoldenRefSurface; } else { m_presGoldenRefSurface = &(m_vp8RefList[m_vp8PicParams->ucGoldenRefPicIndex]->resRefPic); } if((Mos_ResourceIsNull(&m_vp8RefList[m_vp8PicParams->ucAltRefPicIndex]->resRefPic)) && (m_presAltRefSurface)) { m_vp8RefList[m_vp8PicParams->ucAltRefPicIndex]->resRefPic = *m_presAltRefSurface; } else { m_presAltRefSurface = &(m_vp8RefList[m_vp8PicParams->ucAltRefPicIndex]->resRefPic); } } 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); MHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams; pipeModeSelectParams.Mode = m_mode; pipeModeSelectParams.bStreamOutEnabled = m_streamOutEnabled; pipeModeSelectParams.bPostDeblockOutEnable = m_deblockingEnabled; pipeModeSelectParams.bPreDeblockOutEnable = !m_deblockingEnabled; pipeModeSelectParams.bShortFormatInUse = m_shortFormatInUse; MHW_VDBOX_SURFACE_PARAMS surfaceParams; MOS_ZeroMemory(&surfaceParams, sizeof(surfaceParams)); surfaceParams.Mode = m_mode; surfaceParams.psSurface = &m_destSurface; MHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams; pipeBufAddrParams.Mode = m_mode; if (m_deblockingEnabled) { pipeBufAddrParams.psPostDeblockSurface = &m_destSurface; } else { pipeBufAddrParams.psPreDeblockSurface = &m_destSurface; } #ifdef _MMC_SUPPORTED CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetPipeBufAddr(&pipeBufAddrParams)); #endif // when there is no last, golden and alternate reference, // the index is set to the destination frame index pipeBufAddrParams.presReferences[CodechalDecodeLastRef] = m_presLastRefSurface; pipeBufAddrParams.presReferences[CodechalDecodeGoldenRef] = m_presGoldenRefSurface; pipeBufAddrParams.presReferences[CodechalDecodeAlternateRef] = m_presAltRefSurface; pipeBufAddrParams.presMfdIntraRowStoreScratchBuffer = &m_resMfdIntraRowStoreScratchBuffer; pipeBufAddrParams.presMfdDeblockingFilterRowStoreScratchBuffer = &m_resMfdDeblockingFilterRowStoreScratchBuffer; if (m_streamOutEnabled) { pipeBufAddrParams.presStreamOutBuffer = &(m_streamOutBuffer[m_streamOutCurrBufIdx]); } // set all ref pic addresses to valid addresses for error concealment purpose for (uint32_t i = 0; i <= CodechalDecodeAlternateRef; i++) { if (pipeBufAddrParams.presReferences[i] == nullptr && MEDIA_IS_WA(m_waTable, WaDummyReference) && !Mos_ResourceIsNull(&m_dummyReference.OsResource)) { pipeBufAddrParams.presReferences[i] = &m_dummyReference.OsResource; } } #ifdef _MMC_SUPPORTED CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->CheckReferenceList(&pipeBufAddrParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetRefrenceSync(m_disableDecodeSyncLock, m_disableLockForTranscode)); #endif MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS indObjBaseAddrParams; MOS_ZeroMemory(&indObjBaseAddrParams, sizeof(indObjBaseAddrParams)); indObjBaseAddrParams.Mode = m_mode; indObjBaseAddrParams.dwDataSize = m_dataSize; indObjBaseAddrParams.dwDataOffset = m_dataOffset; indObjBaseAddrParams.presDataBuffer = &m_resDataBuffer; MHW_VDBOX_BSP_BUF_BASE_ADDR_PARAMS bspBufBaseAddrParams; MOS_ZeroMemory(&bspBufBaseAddrParams, sizeof(bspBufBaseAddrParams)); bspBufBaseAddrParams.presBsdMpcRowStoreScratchBuffer = &m_resBsdMpcRowStoreScratchBuffer; bspBufBaseAddrParams.presMprRowStoreScratchBuffer = &m_resMprRowStoreScratchBuffer; MHW_VDBOX_VP8_PIC_STATE vp8PicState; vp8PicState.pVp8PicParams = m_vp8PicParams; vp8PicState.pVp8IqMatrixParams = m_vp8IqMatrixParams; vp8PicState.presSegmentationIdStreamBuffer = &m_resSegmentationIdStreamBuffer; vp8PicState.dwCoefProbTableOffset = 0; vp8PicState.presCoefProbBuffer = &m_resCoefProbBuffer; CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking( &cmdBuffer, true)); if (m_statusQueryReportingEnabled) { CODECHAL_DECODE_CHK_STATUS_RETURN(StartStatusReport(&cmdBuffer)); } CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeModeSelectCmd(&cmdBuffer, &pipeModeSelectParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxSurfaceCmd(&cmdBuffer, &surfaceParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeBufAddrCmd(&cmdBuffer, &pipeBufAddrParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxIndObjBaseAddrCmd(&cmdBuffer, &indObjBaseAddrParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxBspBufBaseAddrCmd(&cmdBuffer, &bspBufBaseAddrParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxVp8PicCmd(&cmdBuffer, &vp8PicState)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); return eStatus; } MOS_STATUS CodechalDecodeVp8::DecodePrimitiveLevel() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); // Fill BSD Object Commands MHW_VDBOX_VP8_BSD_PARAMS vp8BsdParams; vp8BsdParams.pVp8PicParams = m_vp8PicParams; CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdVp8BsdObjectCmd(&cmdBuffer, &vp8BsdParams)); // 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; 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_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource(&cmdBuffer, &syncParams)); } if (m_statusQueryReportingEnabled) { CodechalDecodeStatusReport decodeStatusReport; decodeStatusReport.m_statusReportNumber = m_statusReportFeedbackNumber; decodeStatusReport.m_currDecodedPic = m_vp8PicParams->CurrPic; decodeStatusReport.m_currDeblockedPic = m_vp8PicParams->CurrPic; decodeStatusReport.m_codecStatus = CODECHAL_STATUS_UNAVAILABLE; decodeStatusReport.m_currDecodedPicRes = m_vp8RefList[m_vp8PicParams->CurrPic.FrameIdx]->resRefPic; CODECHAL_DEBUG_TOOL( decodeStatusReport.m_secondField = CodecHal_PictureIsBottomField(m_vp8PicParams->CurrPic); 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); CODECHAL_DEBUG_TOOL( CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer( &cmdBuffer, CODECHAL_NUM_MEDIA_STATES, "_DEC")); ) if (m_huCCopyInUse) { 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)); m_huCCopyInUse = false; } 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);) if (m_statusQueryReportingEnabled) { CODECHAL_DECODE_CHK_STATUS_RETURN(ResetStatusReport(m_videoContextUsesNullHw)); } // Needs to be re-set for Linux buffer re-use scenarios m_vp8RefList[m_vp8PicParams->ucCurrPicIndex]->resRefPic = m_destSurface.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 CodechalDecodeVp8::InitMmcState() { #ifdef _MMC_SUPPORTED m_mmc = MOS_New(CodechalMmcDecodeVp8, m_hwInterface, this); CODECHAL_DECODE_CHK_NULL_RETURN(m_mmc); #endif return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeVp8::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; m_shortFormatInUse = settings->shortFormatInUse ? true : false; m_huCCopyInUse = false; // Picture Level Commands m_hwInterface->GetMfxStateCommandsDataSize( m_mode, &m_commandBufferSizeNeeded, &m_commandPatchListSizeNeeded, m_shortFormatInUse); // Primitive Level Commands m_hwInterface->GetMfxPrimitiveCommandsDataSize( m_mode, &m_standardDecodeSizeNeeded, &m_standardDecodePatchListSizeNeeded, m_shortFormatInUse); CODECHAL_DECODE_CHK_STATUS_RETURN(AllocateResourcesFixedSizes()); return eStatus; } CodechalDecodeVp8::CodechalDecodeVp8( CodechalHwInterface * hwInterface, CodechalDebugInterface *debugInterface, PCODECHAL_STANDARD_INFO standardInfo) : CodechalDecode(hwInterface, debugInterface, standardInfo), m_picWidthInMbLastMaxAlloced(0), m_picHeightInMbLastMaxAlloced(0), m_shortFormatInUse(false), m_dataSize(0), m_dataOffset(0), m_vp8PicParams(nullptr), m_vp8IqMatrixParams(nullptr), m_presLastRefSurface(nullptr), m_presGoldenRefSurface(nullptr), m_presAltRefSurface(nullptr), m_mfdDeblockingFilterRowStoreScratchBufferPicWidthInMb(0), m_mfdIntraRowStoreScratchBufferPicWidthInMb(0), m_bsdMpcRowStoreScratchBufferPicWidthInMb(0), m_privateInputBufferSize(0), m_coeffProbTableOffset(0), m_deblockingEnabled(false), m_huCCopyInUse(false) { CODECHAL_DECODE_FUNCTION_ENTER; MOS_ZeroMemory(&m_destSurface, sizeof(m_destSurface)); MOS_ZeroMemory(&m_resDataBuffer, sizeof(m_resDataBuffer)); MOS_ZeroMemory(&m_resCoefProbBuffer, sizeof(m_resCoefProbBuffer)); MOS_ZeroMemory(&m_resTmpBitstreamBuffer, sizeof(m_resTmpBitstreamBuffer)); MOS_ZeroMemory(&m_resMfdIntraRowStoreScratchBuffer, sizeof(m_resMfdIntraRowStoreScratchBuffer)); MOS_ZeroMemory(&m_resMfdDeblockingFilterRowStoreScratchBuffer, sizeof(m_resMfdDeblockingFilterRowStoreScratchBuffer)); MOS_ZeroMemory(&m_resBsdMpcRowStoreScratchBuffer, sizeof(m_resBsdMpcRowStoreScratchBuffer)); MOS_ZeroMemory(&m_resMprRowStoreScratchBuffer, sizeof(m_resMprRowStoreScratchBuffer)); MOS_ZeroMemory(&m_resSegmentationIdStreamBuffer, sizeof(m_resSegmentationIdStreamBuffer)); MOS_ZeroMemory(&m_resSyncObject, sizeof(m_resSyncObject)); MOS_ZeroMemory(&m_resPrivateInputBuffer, sizeof(m_resPrivateInputBuffer)); MOS_ZeroMemory(&m_resSyncObjectWaContextInUse, sizeof(m_resSyncObjectWaContextInUse)); MOS_ZeroMemory(&m_resSyncObjectVideoContextInUse, sizeof(m_resSyncObjectVideoContextInUse)); MOS_ZeroMemory(&m_vp8FrameHead, sizeof(m_vp8FrameHead)); m_hwInterface = hwInterface; } #if USE_CODECHAL_DEBUG_TOOL MOS_STATUS CodechalDecodeVp8::DumpPicParams( PCODEC_VP8_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: "<CurrPic.FrameIdx<CurrPic.PicFlags<wFrameWidthInMbsMinus1<wFrameHeightInMbsMinus1<ucCurrPicIndex<ucLastRefPicIndex<ucGoldenRefPicIndex<ucAltRefPicIndex<ucDeblockedPicIndex<ucReserved8Bits<wPicFlags<key_frame<version<segmentation_enabled<update_mb_segmentation_map<update_segment_feature_data<filter_type<sign_bias_golden<sign_bias_alternate<mb_no_coeff_skip<mode_ref_lf_delta_update<CodedCoeffTokenPartition<LoopFilterDisable<loop_filter_adj_enable<ucLoopFilterLevel[i]<cRefLfDelta[i]<cModeLfDelta[i]<ucSharpnessLevel<cMbSegmentTreeProbs[i]<ucProbSkipFalse<ucProbIntra<ucProbLast<ucProbGolden<ucYModeProbs[i]<ucUvModeProbs[i]<ucReserved8Bits1<ucP0EntropyCount<ucP0EntropyValue<uiP0EntropyRange<uiFirstMbByteOffset<ucMvUpdateProb[i][j]<uiPartitionSize[i]<uiStatusReportFeedbackNumber<CreateFileName( "_DEC", CodechalDbgBufferType::bufPicParams, CodechalDbgExtType::txt); std::ofstream ofs(fileName, std::ios::out); ofs << oss.str(); ofs.close(); return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeVp8::DumpIQParams( PCODEC_VP8_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); for(uint8_t i=0;i<4;++i) { for(uint8_t j=0;j<6;++j) { oss<< "quantization_values["<< std::dec<< +i <<"]["<<+j<<"]: "<quantization_values[i][j]<CreateFileName( "_DEC", CodechalDbgBufferType::bufIqParams, CodechalDbgExtType::txt); std::ofstream ofs(fileName, std::ios::out); ofs << oss.str(); ofs.close(); return MOS_STATUS_SUCCESS; } #endif