| /* |
| * Copyright (c) 2011-2017, 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_mpeg2.cpp |
| //! \brief Implements the decode interface extension for MPEG2. |
| //! \details Implements all functions and constants required by CodecHal for MPEG2 decoding. |
| //! |
| |
| #include "codechal_decoder.h" |
| #include "codechal_decode_mpeg2.h" |
| #include "codechal_secure_decode.h" |
| #include "codechal_mmc_decode_mpeg2.h" |
| #if USE_CODECHAL_DEBUG_TOOL |
| #include <sstream> |
| #include <fstream> |
| #include "codechal_debug.h" |
| #endif |
| |
| #define CODECHAL_DECODE_MPEG2_IDCTBLOCK_SIZE 64 |
| |
| // One MB size (16x16) intra MB, color = RGB[4, 4, 4] |
| const uint32_t CODECHAL_DECODE_MPEG2_WaDummyBitstream[] = |
| {0x01010000, 0x54e29752, 0x002022a5, //Dummy Slice 0, q_scale_type = 0, intra_vlc_format = 0 |
| 0x01010000, 0x4de29752, 0x8661341a, //Dummy Slice 1, q_scale_type = 0, intra_vlc_format = 1 |
| 0x01010000, 0x54e2a772, 0x002022a5, //Dummy Slice 2, q_scale_type = 1, intra_vlc_format = 0 |
| 0x01010000, 0x4de2a772, 0x8661341a //Dummy Slice 3, q_scale_type = 1, intra_vlc_format = 1 |
| }; |
| |
| const uint32_t CODECHAL_DECODE_MPEG2_WaDummySliceLengths[] = {0x8, 0x8, 0x8, 0x8}; |
| const uint32_t CODECHAL_DECODE_MPEG2_WaDummySliceOffsets[] = {0x4, 0x10, 0x1c, 0x28}; |
| |
| bool CodechalDecodeMpeg2::DetectSliceError( |
| uint16_t slcNum, |
| uint32_t prevSliceMbEnd, |
| bool firstValidSlice) |
| { |
| bool result = false; |
| CODECHAL_VLD_SLICE_RECORD currSliceRecord = m_vldSliceRecord[slcNum]; |
| |
| if (currSliceRecord.dwLength == 0 || currSliceRecord.dwLength > (1 << (sizeof(uint32_t) * 8 - 1))) |
| { |
| result = true; |
| } |
| else if ((m_sliceParams[slcNum].m_sliceDataOffset + currSliceRecord.dwLength) > |
| m_dataSize) |
| { |
| // error handling for garbage data |
| result = true; |
| } |
| else if (m_slicesInvalid) |
| { |
| // If cp copy failed for this interation due to lack of buffer space, cannot use any |
| // slices in this iteration since there is no bitstream data for them |
| result = true; |
| } |
| else if (prevSliceMbEnd > currSliceRecord.dwSliceStartMbOffset || |
| m_sliceParams[slcNum].m_sliceVerticalPosition >= m_picHeightInMb || |
| m_sliceParams[slcNum].m_sliceHorizontalPosition >= m_picWidthInMb) |
| { |
| result = true; |
| m_slicesInvalid = true; |
| } |
| else if (!m_sliceParams[slcNum].m_numMbsForSlice) |
| { |
| // For SNB HW will not process BSD objects where the MbCount is 0, and if an invalid |
| // slice start position has been detected or the number of MBs in the current slice |
| // is invalid, the rest of the data may be garbage since SNB does not have |
| // robust error concealment for MPEG2 VLD, skipping these slices prevents HW hangs |
| |
| result = true; |
| m_slicesInvalid = true; |
| } |
| else if (m_sliceParams[slcNum].m_numMbsForSliceOverflow) |
| { |
| // Special case for last slice of an incomplete frame |
| if ((slcNum == m_numSlices - 1) && |
| !firstValidSlice && |
| ((currSliceRecord.dwSliceStartMbOffset + m_sliceParams[slcNum].m_numMbsForSlice) < |
| (uint32_t)(m_picHeightInMb * m_picWidthInMb))) |
| { |
| m_sliceParams[slcNum].m_numMbsForSlice = m_picWidthInMb; |
| } |
| else |
| { |
| result = true; |
| m_slicesInvalid = true; |
| } |
| } |
| |
| return result; |
| } |
| |
| MOS_STATUS CodechalDecodeMpeg2::InsertDummySlices( |
| PMHW_BATCH_BUFFER batchBuffer, |
| uint16_t startMB, |
| uint16_t endMB) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| bool cpEnable = false; |
| |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| CODECHAL_DECODE_CHK_NULL_RETURN(batchBuffer); |
| CODECHAL_DECODE_CHK_NULL_RETURN(m_osInterface); |
| CODECHAL_DECODE_CHK_NULL_RETURN(m_osInterface->osCpInterface); |
| |
| // A copied data buffer must be present |
| if (m_nextCopiedDataOffset && !m_dummySliceDataPresent) |
| { |
| // slice header uses 4 bytes |
| CODECHAL_DECODE_CHK_STATUS_RETURN(CopyDataSurface( |
| sizeof(CODECHAL_DECODE_MPEG2_WaDummyBitstream), |
| m_resMpeg2DummyBistream, |
| &m_resCopiedDataBuffer[m_currCopiedData], |
| &m_dummySliceDataOffset)); |
| |
| m_dummySliceDataPresent = true; |
| } |
| |
| // force disable cp for dummy slices |
| cpEnable = m_osInterface->osCpInterface->IsCpEnabled(); |
| if (cpEnable) |
| { |
| m_osInterface->osCpInterface->SetCpEnabled(false); |
| } |
| |
| uint16_t intraVLDFormat = m_picParams->W0.m_intraVlcFormat; |
| uint16_t quantizerScaleType = m_picParams->W0.m_quantizerScaleType; |
| uint16_t dummySliceIndex = quantizerScaleType * 2 + intraVLDFormat; |
| |
| MHW_VDBOX_MPEG2_SLICE_STATE mpeg2SliceState; |
| mpeg2SliceState.presDataBuffer = nullptr; |
| mpeg2SliceState.wPicWidthInMb = m_picWidthInMb; |
| mpeg2SliceState.wPicHeightInMb = m_picHeightInMb; |
| mpeg2SliceState.dwLength = |
| CODECHAL_DECODE_MPEG2_WaDummySliceLengths[dummySliceIndex]; |
| mpeg2SliceState.dwOffset = |
| m_dummySliceDataOffset + CODECHAL_DECODE_MPEG2_WaDummySliceOffsets[dummySliceIndex]; |
| |
| bool isLastSlice = false; |
| uint16_t expectedEndMB = m_picWidthInMb * m_picHeightInMb; |
| |
| CodecDecodeMpeg2SliceParams slc; |
| MOS_ZeroMemory(&slc, sizeof(CodecDecodeMpeg2SliceParams)); |
| |
| while (startMB < endMB) |
| { |
| slc.m_macroblockOffset = 6; |
| slc.m_sliceHorizontalPosition = startMB % m_picWidthInMb; |
| slc.m_sliceVerticalPosition = startMB / m_picWidthInMb; |
| slc.m_quantiserScaleCode = 10; |
| slc.m_numMbsForSlice = 1; |
| |
| isLastSlice = ((startMB + 1) == expectedEndMB); |
| |
| mpeg2SliceState.pMpeg2SliceParams = &slc; |
| mpeg2SliceState.dwSliceStartMbOffset = startMB; |
| mpeg2SliceState.bLastSlice = isLastSlice; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdMpeg2BsdObject( |
| nullptr, |
| batchBuffer, |
| &mpeg2SliceState)); |
| |
| startMB++; |
| } |
| |
| // restore Cp state |
| if (cpEnable) |
| { |
| m_osInterface->osCpInterface->SetCpEnabled(true); |
| } |
| |
| if (isLastSlice) |
| { |
| m_incompletePicture = false; |
| } |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalDecodeMpeg2::CopyDataSurface( |
| uint32_t dataSize, |
| MOS_RESOURCE sourceSurface, |
| PMOS_RESOURCE copiedSurface, |
| uint32_t *currOffset) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| if (Mos_ResourceIsNull(copiedSurface)) |
| { |
| // Allocate resCopiedDataBuffer if not already allocated. |
| CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( |
| copiedSurface, |
| m_copiedDataBufferSize, |
| "CopiedDataBuffer"), |
| "Failed to allocate copied residual data buffer."); |
| } |
| |
| // initialize lock flags |
| MOS_LOCK_PARAMS lockFlagsWriteOnly; |
| MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS)); |
| lockFlagsWriteOnly.WriteOnly = 1; |
| |
| uint32_t size = MOS_ALIGN_CEIL(dataSize, 16); // 16 byte aligned |
| |
| // HuC is not supported on BDW |
| if (m_hwInterface->m_noHuC) |
| { |
| CodechalDataCopyParams dataCopyParams; |
| MOS_ZeroMemory(&dataCopyParams, sizeof(CodechalDataCopyParams)); |
| dataCopyParams.srcResource = &sourceSurface; |
| dataCopyParams.srcSize = size; |
| dataCopyParams.srcOffset = 0; |
| dataCopyParams.dstResource = copiedSurface; |
| dataCopyParams.dstSize = size; |
| dataCopyParams.dstOffset = m_nextCopiedDataOffset; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->CopyDataSourceWithDrv( |
| &dataCopyParams)); |
| |
| *currOffset = m_nextCopiedDataOffset; |
| m_nextCopiedDataOffset += MOS_ALIGN_CEIL(size, MHW_CACHELINE_SIZE); // 64-byte aligned |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| if ((m_nextCopiedDataOffset + dataSize) > m_copiedDataBufferSize) |
| { |
| CODECHAL_DECODE_ASSERTMESSAGE("Copied data buffer is not large enough."); |
| |
| m_slicesInvalid = true; |
| return MOS_STATUS_UNKNOWN; |
| } |
| |
| 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)); |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking( |
| &cmdBuffer, |
| false)); |
| |
| // Use huc stream out to do the copy |
| CODECHAL_DECODE_CHK_STATUS_RETURN(HucCopy( |
| &cmdBuffer, // pCmdBuffer |
| &sourceSurface, // presSrc |
| copiedSurface, // presDst |
| size, // u32CopyLength |
| 0, // u32CopyInputOffset |
| m_nextCopiedDataOffset)); // 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); |
| |
| 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)); |
| |
| *currOffset = m_nextCopiedDataOffset; |
| m_nextCopiedDataOffset += MOS_ALIGN_CEIL(size, 64); // offsets are 64-byte aligned |
| |
| return eStatus; |
| } |
| |
| /*-------------------------------------------------------------------------- |
| | Name : CodecHalMpeg2Decode_InitializeBeginFrame |
| | Purpose : Initialize MPEG2 incomplete frame values in the DecodeBeginFrame |
| | Arguments : IN -> pMpeg2State : the pointer to mpeg2 state |
| IN -> pDecoder : the pointer to codechal decoder structure |
| | Returns : MOS_STATUS_SUCCESS : Function successfully completed its task |
| | MOS_STATUS_UNKNOWN: Error condition encountered (frame will not be rendered) |
| \---------------------------------------------------------------------------*/ |
| MOS_STATUS CodechalDecodeMpeg2::InitializeBeginFrame() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| m_incompletePicture = false; |
| m_copiedDataBufferInUse = false; |
| m_copiedDataOffset = 0; |
| m_nextCopiedDataOffset = 0; |
| m_lastMbAddress = 0; |
| m_slicesInvalid = false; |
| |
| m_currCopiedData = |
| (m_currCopiedData + 1) % CODECHAL_DECODE_MPEG2_COPIED_SURFACES; |
| m_dummySliceDataPresent = false; |
| m_dummySliceDataOffset = 0; |
| m_bbInUsePerFrame = 0; |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalDecodeMpeg2::AllocateResources () |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource( |
| m_osInterface, |
| &m_resSyncObjectWaContextInUse)); |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource( |
| m_osInterface, |
| &m_resSyncObjectVideoContextInUse)); |
| |
| CodecHalAllocateDataList( |
| m_mpeg2RefList, |
| CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2); |
| |
| for (uint32_t i = 0; i < CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2; i++) |
| { |
| m_mpeg2RefList[i]->RefPic.PicFlags = PICTURE_INVALID; |
| } |
| |
| uint32_t numMacroblocks = m_picWidthInMb * m_picHeightInMb; |
| |
| if (m_mode == CODECHAL_DECODE_MODE_MPEG2VLD) |
| { |
| m_vldSliceRecord = |
| (PCODECHAL_VLD_SLICE_RECORD)MOS_AllocAndZeroMemory(numMacroblocks * sizeof(CODECHAL_VLD_SLICE_RECORD)); |
| CODECHAL_DECODE_CHK_NULL_RETURN(m_vldSliceRecord); |
| } |
| |
| for (uint16_t i = 0; i < m_bbAllocated; i++) |
| { |
| MOS_ZeroMemory(&m_mediaObjectBatchBuffer[i], sizeof(MHW_BATCH_BUFFER)); |
| uint32_t size = (m_standardDecodeSizeNeeded * numMacroblocks) + m_hwInterface->m_sizeOfCmdBatchBufferEnd; |
| CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_AllocateBb( |
| m_osInterface, |
| &m_mediaObjectBatchBuffer[i], |
| nullptr, |
| size)); |
| } |
| |
| // Deblocking Filter Row Store Scratch buffer |
| //(Num MacroBlock Width) * (Num Cachlines) * (Cachline size) |
| CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( |
| &m_resMfdDeblockingFilterRowStoreScratchBuffer, |
| m_picWidthInMb * 7 * CODECHAL_CACHELINE_SIZE, |
| "DeblockingFilterScratch"), |
| "Failed to allocate BSD/MPC Row Store Scratch Buffer."); |
| |
| // MPR Row Store Scratch buffer |
| // (FrameWidth in MB) * (CacheLine size per MB) * 2 |
| // IVB+ platforms need to have double MPR size for MBAFF |
| CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( |
| &m_resBsdMpcRowStoreScratchBuffer, |
| ((uint32_t)(m_picWidthInMb * CODECHAL_CACHELINE_SIZE)) * 2, |
| "MprScratchBuffer"), |
| "Failed to allocate AVC BSD MPR Row Store Scratch Buffer."); |
| |
| m_consecutiveMbErrorConcealmentInUse = true; |
| |
| // Dummy slice buffer |
| if (m_mode == CODECHAL_DECODE_MODE_MPEG2VLD) |
| { |
| uint32_t size = MOS_ALIGN_CEIL(sizeof(CODECHAL_DECODE_MPEG2_WaDummyBitstream), 64); |
| CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( |
| &m_resMpeg2DummyBistream, |
| size, |
| "Mpeg2DummyBitstream"), |
| "Failed to allocate MPEG2 bitstream buffer for format switching WA."); |
| |
| CodechalResLock DummyBitstreamLock(m_osInterface, &m_resMpeg2DummyBistream); |
| auto data = DummyBitstreamLock.Lock(CodechalResLock::writeOnly); |
| |
| CODECHAL_DECODE_CHK_NULL_RETURN(data); |
| |
| MOS_ZeroMemory(data, size); |
| CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(MOS_SecureMemcpy( |
| data, |
| size, |
| (void *)CODECHAL_DECODE_MPEG2_WaDummyBitstream, |
| sizeof(CODECHAL_DECODE_MPEG2_WaDummyBitstream)), |
| "Failed to copy memory."); |
| |
| } |
| |
| if (m_mode == CODECHAL_DECODE_MODE_MPEG2IDCT) |
| { |
| // The common indirect IT-COEFF data structure is defined as a uint32_t. |
| m_copiedDataBufferSize = (numMacroblocks + 2) * |
| (CODEC_NUM_BLOCK_PER_MB * CODECHAL_DECODE_MPEG2_IDCTBLOCK_SIZE * sizeof(uint32_t)); |
| } |
| else |
| { |
| // Bitstream buffer size = height * width + dummy slice + 512 (for padding) |
| m_copiedDataBufferSize = |
| (m_picWidthInMb * m_picHeightInMb * CODECHAL_DECODE_MPEG2_BYTES_PER_MB) + |
| sizeof(CODECHAL_DECODE_MPEG2_WaDummyBitstream) + |
| 512; |
| } |
| |
| return eStatus; |
| } |
| |
| CodechalDecodeMpeg2::~CodechalDecodeMpeg2 () |
| { |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| CODECHAL_DECODE_CHK_NULL_NO_STATUS_RETURN(m_osInterface); |
| |
| m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObjectWaContextInUse); |
| m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObjectVideoContextInUse); |
| |
| CodecHalFreeDataList(m_mpeg2RefList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2); |
| |
| MOS_FreeMemory(m_vldSliceRecord); |
| |
| for (uint32_t i = 0; i < m_bbAllocated; i++) |
| { |
| Mhw_FreeBb(m_osInterface, &m_mediaObjectBatchBuffer[i], nullptr); |
| } |
| |
| m_osInterface->pfnFreeResource( |
| m_osInterface, |
| &m_resMfdDeblockingFilterRowStoreScratchBuffer); |
| |
| m_osInterface->pfnFreeResource( |
| m_osInterface, |
| &m_resBsdMpcRowStoreScratchBuffer); |
| |
| // Dummy slice buffer |
| if (!Mos_ResourceIsNull(&m_resMpeg2DummyBistream)) |
| { |
| m_osInterface->pfnFreeResource( |
| m_osInterface, |
| &m_resMpeg2DummyBistream); |
| } |
| |
| for (uint32_t i = 0; i < CODECHAL_DECODE_MPEG2_COPIED_SURFACES; i++) |
| { |
| m_osInterface->pfnFreeResource( |
| m_osInterface, |
| &m_resCopiedDataBuffer[i]); |
| } |
| } |
| |
| MOS_STATUS CodechalDecodeMpeg2::SetFrameStates () |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| uint32_t totalMBInFrame = 0; |
| |
| CODECHAL_DECODE_CHK_NULL_RETURN(m_decodeParams.m_destSurface); |
| CODECHAL_DECODE_CHK_NULL_RETURN(m_decodeParams.m_dataBuffer); |
| CODECHAL_DECODE_CHK_NULL_RETURN(m_decodeParams.m_picParams); |
| |
| m_dataSize = m_decodeParams.m_dataSize; |
| m_dataOffset = m_decodeParams.m_dataOffset; |
| m_numSlices = m_decodeParams.m_numSlices; |
| m_picParams = (CodecDecodeMpeg2PicParams *)m_decodeParams.m_picParams; |
| m_sliceParams = (CodecDecodeMpeg2SliceParams *)m_decodeParams.m_sliceParams; |
| m_iqMatrixBuffer = (CodecMpeg2IqMatrix *)m_decodeParams.m_iqMatrixBuffer; |
| m_destSurface = *m_decodeParams.m_destSurface; |
| m_resDataBuffer = *m_decodeParams.m_dataBuffer; |
| m_numMacroblocks = m_decodeParams.m_numMacroblocks; |
| m_mbParams = (CodecDecodeMpeg2MbParmas *)m_decodeParams.m_macroblockParams; |
| m_mpeg2ISliceConcealmentMode = m_decodeParams.m_mpeg2ISliceConcealmentMode; |
| m_mpeg2PbSliceConcealmentMode = m_decodeParams.m_mpeg2PBSliceConcealmentMode; |
| m_mpeg2PbSlicePredBiDirMvTypeOverride = m_decodeParams.m_mpeg2PBSlicePredBiDirMVTypeOverride; |
| m_mpeg2PbSlicePredMvOverride = m_decodeParams.m_mpeg2PBSlicePredMVOverride; |
| |
| m_picWidthInMb = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_picParams->m_horizontalSize); |
| m_picHeightInMb = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_picParams->m_verticalSize); |
| |
| // For some corrupted mpeg2 streams, need to use dwHeight or dwWidth because they are updated at decode create time. |
| // Horizontal_size or vertical_size may be different and wrong in first pic parameter. |
| totalMBInFrame = (m_picParams->m_currPic.PicFlags == PICTURE_FRAME) ? (CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_width) * CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_height)) |
| : (CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_width) * CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_height) / 2); |
| |
| if (m_numSlices > totalMBInFrame) |
| { |
| CODECHAL_DECODE_ASSERTMESSAGE("Invalid slice number due to larger than MB number."); |
| return MOS_STATUS_INVALID_PARAMETER; |
| } |
| |
| PCODEC_REF_LIST destEntry = m_mpeg2RefList[m_picParams->m_currPic.FrameIdx]; |
| MOS_ZeroMemory(destEntry, sizeof(CODEC_REF_LIST)); |
| destEntry->RefPic = m_picParams->m_currPic; |
| destEntry->resRefPic = m_destSurface.OsResource; |
| |
| m_statusReportFeedbackNumber = m_picParams->m_statusReportFeedbackNumber; |
| |
| MOS_ZeroMemory(m_vldSliceRecord, (m_numSlices * sizeof(CODECHAL_VLD_SLICE_RECORD))); |
| |
| if (m_firstExecuteCall) |
| { |
| CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(InitializeBeginFrame(), |
| "Initial Beginframe in CodecHal failed."); |
| } |
| |
| uint32_t firstMbAddress = 0; |
| bool skippedSlicePresent = false; |
| bool invalidFrame = true; |
| uint32_t numMBs = 0; |
| |
| // Determine the number of MBs for MPEG2 VLD |
| if (m_mode == CODECHAL_DECODE_MODE_MPEG2VLD) |
| { |
| CODECHAL_DECODE_CHK_NULL_RETURN(m_sliceParams); |
| |
| CodecDecodeMpeg2SliceParams *slc = m_sliceParams; |
| |
| if (m_numSlices == 0) |
| { |
| CODECHAL_DECODE_ASSERTMESSAGE( |
| "MPEG2 VLD slice data invalid, unable to determine final MB address."); |
| numMBs = m_lastMbAddress = 0; |
| return MOS_STATUS_INVALID_PARAMETER; |
| } |
| else |
| { |
| uint16_t lastSlice = 0; |
| uint32_t prevSliceMbEnd = m_lastMbAddress; |
| bool firstValidSlice = m_incompletePicture ? true : false; |
| |
| for (uint16_t i = 0; i < m_numSlices; i++) |
| { |
| uint32_t sliceStartMbOffset = |
| slc->m_sliceHorizontalPosition + |
| (slc->m_sliceVerticalPosition * m_picWidthInMb); |
| |
| uint32_t slcLength = ((slc->m_sliceDataSize + 0x0007) >> 3); |
| |
| // HW limitation and won't be fixed |
| if (slcLength > 0x1FFE0) |
| { |
| slcLength = 0x1FFE0; |
| } |
| |
| uint32_t u32Offset = ((slc ->m_macroblockOffset & 0x0000fff8) >> 3); // #of bytes of header data in bitstream buffer (before video data) |
| |
| slcLength -= u32Offset; |
| m_vldSliceRecord[i].dwLength = slcLength; |
| m_vldSliceRecord[i].dwOffset = u32Offset; |
| m_vldSliceRecord[i].dwSliceStartMbOffset = sliceStartMbOffset; |
| |
| if (DetectSliceError(i, prevSliceMbEnd, firstValidSlice)) |
| { |
| m_vldSliceRecord[i].dwSkip = true; |
| skippedSlicePresent = true; |
| } |
| else |
| { |
| if (firstValidSlice) |
| { |
| // First MB Address |
| firstMbAddress = |
| slc->m_sliceHorizontalPosition + |
| (slc->m_sliceVerticalPosition * m_picWidthInMb); |
| } |
| |
| lastSlice = i; |
| firstValidSlice = false; |
| invalidFrame = false; |
| } |
| |
| prevSliceMbEnd = |
| m_vldSliceRecord[i].dwSliceStartMbOffset + |
| slc->m_numMbsForSlice; |
| |
| slc++; |
| } |
| |
| slc -= m_numSlices; |
| m_vldSliceRecord[lastSlice].bIsLastSlice = true; |
| |
| // Last MB Address |
| slc += lastSlice; |
| |
| numMBs = |
| (uint16_t)(m_vldSliceRecord[lastSlice].dwSliceStartMbOffset + |
| slc->m_numMbsForSlice); |
| } |
| } |
| else if (m_mode == CODECHAL_DECODE_MODE_MPEG2IDCT) |
| { |
| CODECHAL_DECODE_CHK_NULL_RETURN(m_mbParams); |
| numMBs = m_numMacroblocks; |
| } |
| |
| // It means all slices in the frame are wrong, we just need skip decoding for this frame |
| // and don't insert any dummy slices |
| if (m_mode == CODECHAL_DECODE_MODE_MPEG2VLD && |
| invalidFrame && m_numSlices && !m_incompletePicture) |
| { |
| CODECHAL_DECODE_ASSERTMESSAGE("Current frame is invalid."); |
| return MOS_STATUS_UNKNOWN; |
| } |
| |
| // MPEG2 Error Concealment for Gen6+ |
| // Applicable for both IT and VLD modes |
| bool copiedDataNeeded = (m_incompletePicture || |
| (numMBs != (m_picWidthInMb * m_picHeightInMb))); |
| |
| if (m_mode == CODECHAL_DECODE_MODE_MPEG2VLD) |
| { |
| copiedDataNeeded |= (skippedSlicePresent || firstMbAddress); |
| } |
| |
| if (copiedDataNeeded) |
| { |
| if (m_dataSize) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(CopyDataSurface( |
| m_dataSize, |
| m_resDataBuffer, |
| &m_resCopiedDataBuffer[m_currCopiedData], |
| &m_copiedDataOffset)); |
| } |
| |
| m_copiedDataBufferInUse = true; |
| } |
| |
| m_perfType = (uint16_t)m_picParams->m_pictureCodingType; |
| |
| m_crrPic = m_picParams->m_currPic; |
| m_secondField = m_picParams->m_secondField ? true : false; |
| |
| CODECHAL_DEBUG_TOOL( |
| CODECHAL_DECODE_CHK_NULL_RETURN(m_debugInterface); |
| m_debugInterface->m_currPic = m_crrPic; |
| m_debugInterface->m_secondField = m_secondField; |
| m_debugInterface->m_frameType = m_perfType; |
| |
| if (m_picParams) { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(DumpPicParams( |
| m_picParams)); |
| } |
| |
| if (m_iqMatrixBuffer) { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(DumpIQParams( |
| m_iqMatrixBuffer)); |
| } |
| |
| if (m_sliceParams) { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(DumpSliceParams( |
| m_sliceParams, |
| m_numSlices)); |
| } |
| |
| if (m_mbParams) { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(DumpMbParams( |
| m_mbParams)); |
| } |
| |
| ) |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalDecodeMpeg2::DecodeStateLevel() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| uint8_t fwdRefIdx = (uint8_t)m_picParams->m_forwardRefIdx; |
| uint8_t bwdRefIdx = (uint8_t)m_picParams->m_backwardRefIdx; |
| |
| // Do not use data that has not been initialized |
| if (CodecHal_PictureIsInvalid(m_mpeg2RefList[fwdRefIdx]->RefPic)) |
| { |
| fwdRefIdx = m_picParams->m_currPic.FrameIdx; |
| } |
| if (CodecHal_PictureIsInvalid(m_mpeg2RefList[bwdRefIdx]->RefPic)) |
| { |
| bwdRefIdx = m_picParams->m_currPic.FrameIdx; |
| } |
| |
| MOS_COMMAND_BUFFER cmdBuffer; |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); |
| |
| MHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams; |
| MOS_ZeroMemory(&pipeModeSelectParams, sizeof(pipeModeSelectParams)); |
| pipeModeSelectParams.Mode = m_mode; |
| pipeModeSelectParams.bStreamOutEnabled = m_streamOutEnabled; |
| pipeModeSelectParams.bPostDeblockOutEnable = m_deblockingEnabled; |
| pipeModeSelectParams.bPreDeblockOutEnable = !m_deblockingEnabled; |
| |
| 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; |
| MOS_ZeroMemory(&pipeBufAddrParams, sizeof(pipeBufAddrParams)); |
| pipeBufAddrParams.Mode = m_mode; |
| if (m_deblockingEnabled) |
| { |
| pipeBufAddrParams.psPostDeblockSurface = &m_destSurface; |
| } |
| else |
| { |
| pipeBufAddrParams.psPreDeblockSurface = &m_destSurface; |
| } |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetPipeBufAddr(&pipeBufAddrParams)); |
| |
| // when there is not a forward or backward reference, |
| // the index is set to the destination frame index |
| m_presReferences[CodechalDecodeFwdRefTop] = |
| m_presReferences[CodechalDecodeFwdRefBottom] = |
| m_presReferences[CodechalDecodeBwdRefTop] = |
| m_presReferences[CodechalDecodeBwdRefBottom] = &m_destSurface.OsResource; |
| |
| if (fwdRefIdx < CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2) |
| { |
| m_presReferences[CodechalDecodeFwdRefTop] = |
| m_presReferences[CodechalDecodeFwdRefBottom] = &m_mpeg2RefList[fwdRefIdx]->resRefPic; |
| } |
| if (bwdRefIdx < CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2) |
| { |
| m_presReferences[CodechalDecodeBwdRefTop] = |
| m_presReferences[CodechalDecodeBwdRefBottom] = &m_mpeg2RefList[bwdRefIdx]->resRefPic; |
| } |
| |
| // special case for second fields |
| if (m_picParams->m_secondField && m_picParams->m_pictureCodingType == P_TYPE) |
| { |
| if (m_picParams->m_topFieldFirst) |
| { |
| m_presReferences[CodechalDecodeFwdRefTop] = |
| &m_destSurface.OsResource; |
| } |
| else |
| { |
| m_presReferences[CodechalDecodeFwdRefBottom] = |
| &m_destSurface.OsResource; |
| } |
| } |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(MOS_SecureMemcpy( |
| pipeBufAddrParams.presReferences, |
| sizeof(PMOS_RESOURCE) * CODEC_MAX_NUM_REF_FRAME_NON_AVC, |
| m_presReferences, |
| sizeof(PMOS_RESOURCE) * CODEC_MAX_NUM_REF_FRAME_NON_AVC)); |
| |
| pipeBufAddrParams.presMfdDeblockingFilterRowStoreScratchBuffer = |
| &m_resMfdDeblockingFilterRowStoreScratchBuffer; |
| |
| if (m_streamOutEnabled) |
| { |
| pipeBufAddrParams.presStreamOutBuffer = |
| &(m_streamOutBuffer[m_streamOutCurrBufIdx]); |
| } |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->CheckReferenceList(&pipeBufAddrParams)); |
| |
| CODECHAL_DEBUG_TOOL( |
| for (uint32_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_NON_AVC; i++) |
| { |
| if (pipeBufAddrParams.presReferences[i]) |
| { |
| MOS_SURFACE dstSurface; |
| |
| MOS_ZeroMemory(&dstSurface, sizeof(MOS_SURFACE)); |
| dstSurface.Format = Format_NV12; |
| dstSurface.OsResource = *(pipeBufAddrParams.presReferences[i]); |
| CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo( |
| m_osInterface, |
| &dstSurface)); |
| |
| m_debugInterface->m_refIndex = (uint16_t)i; |
| std::string refSurfName = "RefSurf" + std::to_string(static_cast<uint32_t>(m_debugInterface->m_refIndex)); |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface( |
| &dstSurface, |
| CodechalDbgAttr::attrReferenceSurfaces, |
| refSurfName.data())); |
| } |
| } |
| ) |
| |
| //set correctly indirect BSD object base address. |
| PMOS_RESOURCE indObjBase; |
| if (m_copiedDataBufferInUse) |
| { |
| indObjBase = &m_resCopiedDataBuffer[m_currCopiedData]; |
| } |
| else |
| { |
| indObjBase = &m_resDataBuffer; |
| } |
| |
| MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS indObjBaseAddrParams; |
| MOS_ZeroMemory(&indObjBaseAddrParams, sizeof(indObjBaseAddrParams)); |
| indObjBaseAddrParams.Mode = m_mode; |
| indObjBaseAddrParams.dwDataSize = |
| m_copiedDataBufferInUse ? m_copiedDataBufferSize : m_dataSize; |
| indObjBaseAddrParams.presDataBuffer = indObjBase; |
| |
| MHW_VDBOX_BSP_BUF_BASE_ADDR_PARAMS bspBufBaseAddrParams; |
| MOS_ZeroMemory(&bspBufBaseAddrParams, sizeof(bspBufBaseAddrParams)); |
| bspBufBaseAddrParams.presBsdMpcRowStoreScratchBuffer = &m_resBsdMpcRowStoreScratchBuffer; |
| |
| MHW_VDBOX_MPEG2_PIC_STATE mpeg2PicState; |
| mpeg2PicState.Mode = m_mode; |
| mpeg2PicState.pMpeg2PicParams = m_picParams; |
| mpeg2PicState.bDeblockingEnabled = m_deblockingEnabled; |
| mpeg2PicState.dwMPEG2ISliceConcealmentMode = m_mpeg2ISliceConcealmentMode; |
| mpeg2PicState.dwMPEG2PBSliceConcealmentMode = m_mpeg2PbSliceConcealmentMode; |
| mpeg2PicState.dwMPEG2PBSlicePredBiDirMVTypeOverride = m_mpeg2PbSlicePredBiDirMvTypeOverride; |
| mpeg2PicState.dwMPEG2PBSlicePredMVOverride = m_mpeg2PbSlicePredMvOverride; |
| |
| MHW_VDBOX_QM_PARAMS qmParams; |
| qmParams.Standard = CODECHAL_MPEG2; |
| qmParams.pMpeg2IqMatrix = m_iqMatrixBuffer; |
| |
| 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)); |
| |
| if (CodecHalIsDecodeModeVLD(m_mode)) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxBspBufBaseAddrCmd( |
| &cmdBuffer, |
| &bspBufBaseAddrParams)); |
| } |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxMpeg2PicCmd( |
| &cmdBuffer, |
| &mpeg2PicState)); |
| |
| if (CodecHalIsDecodeModeVLD(m_mode)) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxQmCmd( |
| &cmdBuffer, |
| &qmParams)); |
| } |
| |
| m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalDecodeMpeg2::DecodePrimitiveLevel() |
| { |
| if (m_mode == CODECHAL_DECODE_MODE_MPEG2VLD) |
| { |
| return SliceLevel(); |
| } |
| else |
| { |
| return MacroblockLevel(); |
| } |
| } |
| |
| MOS_STATUS CodechalDecodeMpeg2::SliceLevel() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| if ((m_decodePhantomMbs) || (m_incompletePicture)) |
| { |
| if (m_bbInUsePerFrame >= m_bbAllocated / CODECHAL_DECODE_MPEG2_BATCH_BUFFERS_PER_GROUP) |
| { |
| m_bbAllocated += CODECHAL_DECODE_MPEG2_BATCH_BUFFERS_PER_GROUP; |
| if (m_bbAllocated >= CODECHAL_DECODE_MPEG2_MAXIMUM_BATCH_BUFFERS) |
| { |
| CODECHAL_DECODE_ASSERTMESSAGE( |
| "The number of MPEG2 second level batch buffer is not big enough to hold the whole frame."); |
| return MOS_STATUS_EXCEED_MAX_BB_SIZE; |
| } |
| |
| for (uint32_t i = 0; i < CODECHAL_DECODE_MPEG2_BATCH_BUFFERS_PER_GROUP; i++) |
| { |
| uint32_t j = m_bbAllocated - i - 1; |
| MOS_ZeroMemory(&m_mediaObjectBatchBuffer[j], sizeof(MHW_BATCH_BUFFER)); |
| |
| uint32_t u32Size = m_standardDecodeSizeNeeded * CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_width) * CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_height) + |
| m_hwInterface->m_sizeOfCmdBatchBufferEnd; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_AllocateBb( |
| m_osInterface, |
| &m_mediaObjectBatchBuffer[j], |
| nullptr, |
| u32Size)); |
| m_mediaObjectBatchBuffer[j].bSecondLevel = true; |
| } |
| } |
| } |
| |
| MOS_COMMAND_BUFFER cmdBuffer; |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer( |
| m_osInterface, |
| &cmdBuffer, |
| 0)); |
| |
| MHW_BATCH_BUFFER batchBuffer = m_mediaObjectBatchBuffer[m_bbInUse]; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd( |
| &cmdBuffer, |
| &batchBuffer)); |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_LockBb( |
| m_osInterface, |
| &batchBuffer)); |
| |
| if (m_decodePhantomMbs) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(InsertDummySlices( |
| &batchBuffer, |
| m_lastMbAddress, |
| m_picWidthInMb * m_picHeightInMb)); |
| } |
| else |
| { |
| CodecDecodeMpeg2SliceParams *slc = m_sliceParams; |
| |
| uint16_t prevSliceMBEnd = m_lastMbAddress; |
| |
| for (uint16_t slcCount = 0; slcCount < m_numSlices; slcCount++) |
| { |
| if (!m_vldSliceRecord[slcCount].dwSkip) |
| { |
| if (prevSliceMBEnd != m_vldSliceRecord[slcCount].dwSliceStartMbOffset) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(InsertDummySlices( |
| &batchBuffer, |
| prevSliceMBEnd, |
| (uint16_t)m_vldSliceRecord[slcCount].dwSliceStartMbOffset)); |
| } |
| |
| if (m_vldSliceRecord[slcCount].bIsLastSlice) |
| { |
| uint16_t expectedFinalMb = m_picWidthInMb * m_picHeightInMb; |
| |
| m_lastMbAddress = |
| (uint16_t)(m_vldSliceRecord[slcCount].dwSliceStartMbOffset + |
| slc->m_numMbsForSlice); |
| |
| if (m_lastMbAddress < expectedFinalMb) |
| { |
| m_incompletePicture = true; |
| m_vldSliceRecord[slcCount].bIsLastSlice = false; |
| } |
| else |
| { |
| //Indicate It's complete picture now |
| m_incompletePicture = false; |
| } |
| } |
| |
| // static MPEG2 slice parameters |
| MHW_VDBOX_MPEG2_SLICE_STATE mpeg2SliceState; |
| mpeg2SliceState.presDataBuffer = &m_resDataBuffer; |
| mpeg2SliceState.wPicWidthInMb = m_picWidthInMb; |
| mpeg2SliceState.wPicHeightInMb = m_picHeightInMb; |
| mpeg2SliceState.pMpeg2SliceParams = slc; |
| mpeg2SliceState.dwLength = m_vldSliceRecord[slcCount].dwLength; |
| mpeg2SliceState.dwOffset = |
| m_vldSliceRecord[slcCount].dwOffset + m_copiedDataOffset; |
| mpeg2SliceState.dwSliceStartMbOffset = m_vldSliceRecord[slcCount].dwSliceStartMbOffset; |
| mpeg2SliceState.bLastSlice = m_vldSliceRecord[slcCount].bIsLastSlice; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdMpeg2BsdObject( |
| nullptr, |
| &batchBuffer, |
| &mpeg2SliceState)); |
| |
| prevSliceMBEnd = |
| (uint16_t)(m_vldSliceRecord[slcCount].dwSliceStartMbOffset + |
| slc->m_numMbsForSlice); |
| } |
| |
| slc++; |
| } |
| } |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd( |
| nullptr, |
| &batchBuffer)); |
| |
| CODECHAL_DEBUG_TOOL( |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->Dump2ndLvlBatch( |
| &batchBuffer, |
| CODECHAL_NUM_MEDIA_STATES, |
| "_DEC")); |
| ) |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_UnlockBb( |
| m_osInterface, |
| &batchBuffer, |
| true)); |
| |
| m_bbInUse = (m_bbInUse + 1) % m_bbAllocated; |
| m_bbInUsePerFrame++; |
| |
| if (!m_incompletePicture) |
| { |
| // Check if destination surface needs to be synchronized |
| MOS_SYNC_PARAMS syncParams = g_cInitSyncParams; |
| syncParams.GpuContext = m_videoContext; |
| syncParams.presSyncResource = &m_destSurface.OsResource; |
| syncParams.bReadOnly = false; |
| syncParams.bDisableDecodeSyncLock = m_disableDecodeSyncLock; |
| syncParams.bDisableLockForTranscode = m_disableLockForTranscode; |
| |
| if (!CodecHal_PictureIsField(m_picParams->m_currPic) || |
| !m_picParams->m_secondField) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync( |
| m_osInterface, |
| &syncParams)); |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait( |
| m_osInterface, |
| &syncParams)); |
| |
| // Update the resource tag (s/w tag) for On-Demand Sync |
| m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams); |
| } |
| |
| MHW_MI_FLUSH_DW_PARAMS flushDwParams; |
| MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd( |
| &cmdBuffer, |
| &flushDwParams)); |
| |
| // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag |
| if (m_osInterface->bTagResourceSync && |
| (!CodecHal_PictureIsField(m_picParams->m_currPic) || m_picParams->m_secondField)) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource( |
| &cmdBuffer, |
| &syncParams)); |
| } |
| |
| if (m_statusQueryReportingEnabled) |
| { |
| CodechalDecodeStatusReport decodeStatusReport; |
| |
| decodeStatusReport.m_statusReportNumber = m_statusReportFeedbackNumber; |
| decodeStatusReport.m_currDecodedPic = m_picParams->m_currPic; |
| decodeStatusReport.m_currDeblockedPic = m_picParams->m_currPic; |
| decodeStatusReport.m_codecStatus = CODECHAL_STATUS_UNAVAILABLE; |
| decodeStatusReport.m_currDecodedPicRes = m_mpeg2RefList[m_picParams->m_currPic.FrameIdx]->resRefPic; |
| |
| CODECHAL_DEBUG_TOOL( |
| decodeStatusReport.m_secondField = m_picParams->m_secondField ? true : false; |
| 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")); |
| |
| //CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHal_DbgReplaceAllCommands( |
| // m_debugInterface, |
| // &cmdBuffer)); |
| ) |
| |
| //Sync up complete frame |
| syncParams = g_cInitSyncParams; |
| syncParams.GpuContext = m_videoContextForWa; |
| syncParams.presSyncResource = &m_resSyncObjectWaContextInUse; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams)); |
| |
| syncParams = g_cInitSyncParams; |
| syncParams.GpuContext = m_videoContext; |
| syncParams.presSyncResource = &m_resSyncObjectWaContextInUse; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams)); |
| |
| CODECHAL_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_mpeg2RefList[m_picParams->m_currPic.FrameIdx]->resRefPic = |
| m_destSurface.OsResource; |
| |
| // Send the signal to indicate decode completion, in case On-Demand Sync is not present |
| if (!CodecHal_PictureIsField(m_picParams->m_currPic) || m_picParams->m_secondField) |
| { |
| syncParams = g_cInitSyncParams; |
| syncParams.GpuContext = m_videoContext; |
| syncParams.presSyncResource = &m_destSurface.OsResource; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams)); |
| } |
| } |
| else |
| { |
| m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); |
| } |
| |
| return eStatus; |
| } |
| |
| void CodechalDecodeMpeg2::PackMotionVectors( |
| CODEC_PICTURE_FLAG pic_flag, |
| PMHW_VDBOX_MPEG2_MB_STATE mpeg2MbState) |
| { |
| CodecDecodeMpeg2MbParmas *mbParams = mpeg2MbState->pMBParams; |
| |
| uint16_t motionType = mbParams->MBType.m_motionType; |
| uint16_t intelMotionType = CODECHAL_MPEG2_IMT_NONE; |
| |
| //convert to Intel Motion Type |
| if (pic_flag == PICTURE_FRAME) |
| { |
| switch(motionType) |
| { |
| case CodechalDecodeMcFrame: |
| intelMotionType = CODECHAL_MPEG2_IMT_FRAME_FRAME; |
| break; |
| case CodechalDecodeMcField: |
| intelMotionType = CODECHAL_MPEG2_IMT_FRAME_FIELD; |
| break; |
| case CodechalDecodeMcDmv: |
| intelMotionType = CODECHAL_MPEG2_IMT_FRAME_DUAL_PRIME; |
| break; |
| default: |
| break; |
| } |
| } |
| else // must be field picture... |
| { |
| switch(motionType) |
| { |
| case CodechalDecodeMcField: |
| intelMotionType = CODECHAL_MPEG2_IMT_FIELD_FIELD; |
| break; |
| case CodechalDecodeMcDmv: |
| intelMotionType = CODECHAL_MPEG2_IMT_FIELD_DUAL_PRIME; |
| break; |
| case CodechalDecodeMc16x8: |
| intelMotionType = CODECHAL_MPEG2_IMT_16X8; |
| break; |
| default: |
| break; |
| } |
| } |
| |
| int16_t *mv = mbParams->m_motionVectors; |
| |
| switch (intelMotionType) |
| { |
| case CODECHAL_MPEG2_IMT_16X8: |
| case CODECHAL_MPEG2_IMT_FIELD_FIELD: |
| case CODECHAL_MPEG2_IMT_FRAME_FRAME: |
| case CODECHAL_MPEG2_IMT_FIELD_DUAL_PRIME: |
| mpeg2MbState->sPackedMVs0[0] = (short)mv[CodechalDecodeRstFirstForwHorz]; |
| mpeg2MbState->sPackedMVs0[1] = (short)mv[CodechalDecodeRstFirstForwVert]; |
| mpeg2MbState->sPackedMVs0[2] = (short)mv[CodechalDecodeRstFirstBackHorz]; |
| mpeg2MbState->sPackedMVs0[3] = (short)mv[CodechalDecodeRstFirstBackVert]; |
| break; |
| |
| case CODECHAL_MPEG2_IMT_FRAME_FIELD: |
| case CODECHAL_MPEG2_IMT_FRAME_DUAL_PRIME: |
| mpeg2MbState->sPackedMVs0[0] = (short)mv[CodechalDecodeRstFirstForwHorz]; |
| mpeg2MbState->sPackedMVs0[1] = (short)(mv[CodechalDecodeRstFirstForwVert] >> 1) ; |
| mpeg2MbState->sPackedMVs0[2] = (short)mv[CodechalDecodeRstFirstBackHorz]; |
| mpeg2MbState->sPackedMVs0[3] = (short)(mv[CodechalDecodeRstFirstBackVert] >> 1); |
| break; |
| |
| default: |
| break; |
| } |
| |
| switch (intelMotionType) |
| { |
| case CODECHAL_MPEG2_IMT_16X8: |
| mpeg2MbState->sPackedMVs1[0] = (short)mv[CodechalDecodeRstSecndForwHorz]; |
| mpeg2MbState->sPackedMVs1[1] = (short)mv[CodechalDecodeRstSecndForwVert]; |
| mpeg2MbState->sPackedMVs1[2] = (short)mv[CodechalDecodeRstSecndBackHorz]; |
| mpeg2MbState->sPackedMVs1[3] = (short)mv[CodechalDecodeRstSecndBackVert]; |
| break; |
| |
| case CODECHAL_MPEG2_IMT_FRAME_DUAL_PRIME: |
| mpeg2MbState->sPackedMVs1[0] = (short)mv[CodechalDecodeRstFirstForwHorz]; |
| mpeg2MbState->sPackedMVs1[1] = (short)(mv[CodechalDecodeRstFirstForwVert] >> 1); |
| mpeg2MbState->sPackedMVs1[2] = (short)mv[CodechalDecodeRstSecndBackHorz]; |
| mpeg2MbState->sPackedMVs1[3] = (short)(mv[CodechalDecodeRstSecndBackVert] >> 1); |
| break; |
| |
| case CODECHAL_MPEG2_IMT_FRAME_FIELD: |
| mpeg2MbState->sPackedMVs1[0] = (short)mv[CodechalDecodeRstSecndForwHorz]; |
| mpeg2MbState->sPackedMVs1[1] = (short)(mv[CodechalDecodeRstSecndForwVert] >> 1); |
| mpeg2MbState->sPackedMVs1[2] = (short)mv[CodechalDecodeRstSecndBackHorz]; |
| mpeg2MbState->sPackedMVs1[3] = (short)(mv[CodechalDecodeRstSecndBackVert] >> 1); |
| break; |
| |
| default: |
| break; |
| } |
| } |
| MOS_STATUS CodechalDecodeMpeg2::InsertSkippedMacroblocks( |
| PMHW_BATCH_BUFFER batchBuffer, |
| PMHW_VDBOX_MPEG2_MB_STATE params, |
| uint16_t nextMBStart, |
| uint16_t skippedMBs) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| CODECHAL_DECODE_CHK_NULL_RETURN(batchBuffer); |
| CODECHAL_DECODE_CHK_NULL_RETURN(params); |
| CODECHAL_DECODE_CHK_NULL_RETURN(params->pMBParams); |
| |
| //save the original MB params, and restore the orignal MB params when function exit. |
| CodechalDecodeRestoreData<CodecDecodeMpeg2MbParmas> MBParamsRestore(params->pMBParams); |
| |
| params->dwDCTLength = 0; |
| params->dwITCoffDataAddrOffset = 0; |
| params->pMBParams->m_codedBlockPattern = 0; |
| |
| MOS_ZeroMemory(params->sPackedMVs0,sizeof(params->sPackedMVs0)); |
| MOS_ZeroMemory(params->sPackedMVs1,sizeof(params->sPackedMVs1)); |
| |
| for (uint16_t i = 0; i < skippedMBs; i++) |
| { |
| params->pMBParams->m_mbAddr = nextMBStart + i; |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdMpeg2ITObject( |
| nullptr, |
| batchBuffer, |
| params)); |
| } |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalDecodeMpeg2::MacroblockLevel() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| if ((m_decodePhantomMbs) || (m_incompletePicture)) |
| { |
| if (m_bbInUsePerFrame >= m_bbAllocated / CODECHAL_DECODE_MPEG2_BATCH_BUFFERS_PER_GROUP) |
| { |
| m_bbAllocated += CODECHAL_DECODE_MPEG2_BATCH_BUFFERS_PER_GROUP; |
| if (m_bbAllocated >= CODECHAL_DECODE_MPEG2_MAXIMUM_BATCH_BUFFERS) |
| { |
| CODECHAL_DECODE_ASSERTMESSAGE( |
| "The number of MPEG2 second level batch buffer is not big enough to hold the whole frame."); |
| return MOS_STATUS_EXCEED_MAX_BB_SIZE; |
| } |
| |
| for (uint32_t i = 0; i < CODECHAL_DECODE_MPEG2_BATCH_BUFFERS_PER_GROUP; i++) |
| { |
| uint32_t j = m_bbAllocated - i - 1; |
| MOS_ZeroMemory(&m_mediaObjectBatchBuffer[j], sizeof(MHW_BATCH_BUFFER)); |
| |
| uint32_t u32Size = m_standardDecodeSizeNeeded * m_picWidthInMb * m_picHeightInMb + |
| m_hwInterface->m_sizeOfCmdBatchBufferEnd; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_AllocateBb( |
| m_osInterface, |
| &m_mediaObjectBatchBuffer[j], |
| nullptr, |
| u32Size)); |
| m_mediaObjectBatchBuffer[j].bSecondLevel = true; |
| } |
| } |
| } |
| |
| MOS_COMMAND_BUFFER cmdBuffer; |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer( |
| m_osInterface, |
| &cmdBuffer, |
| 0)); |
| |
| MHW_BATCH_BUFFER batchBuffer = m_mediaObjectBatchBuffer[m_bbInUse]; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd( |
| &cmdBuffer, |
| &batchBuffer)); |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_LockBb(m_osInterface, &batchBuffer)); |
| |
| //static member |
| MHW_VDBOX_MPEG2_MB_STATE mpeg2MbState; |
| mpeg2MbState.wPicWidthInMb = m_picWidthInMb; |
| mpeg2MbState.wPicHeightInMb = m_picHeightInMb; |
| mpeg2MbState.wPicCodingType = (uint16_t)m_picParams->m_pictureCodingType; |
| |
| if (m_decodePhantomMbs) |
| { |
| uint16_t u16NextMBStart = m_savedMpeg2MbParam.m_mbAddr + 1; // = 1 + saved last MB's address in this picture. |
| uint16_t numMBs = (mpeg2MbState.wPicWidthInMb * mpeg2MbState.wPicHeightInMb) - u16NextMBStart; |
| |
| mpeg2MbState.pMBParams = &m_savedMpeg2MbParam; //use saved last MB param to insert Skipped MBs. |
| CODECHAL_DECODE_CHK_STATUS_RETURN(InsertSkippedMacroblocks( |
| &batchBuffer, |
| &mpeg2MbState, |
| u16NextMBStart, |
| numMBs)); |
| m_incompletePicture = false; |
| } |
| else |
| { |
| uint16_t expectedMBAddress = (m_incompletePicture) ? m_lastMbAddress : 0; |
| |
| for (uint16_t mbcount = 0; mbcount < m_numMacroblocks; mbcount++) |
| { |
| if (m_mbParams[mbcount].m_mbAddr >= expectedMBAddress) |
| { |
| uint16_t skippedMBs = m_mbParams[mbcount].m_mbAddr - expectedMBAddress; |
| |
| if (skippedMBs) |
| { |
| //insert skipped Macroblock, use the first available MB params to insert skipped MBs. |
| mpeg2MbState.pMBParams = &(m_mbParams[mbcount]); |
| CODECHAL_DECODE_CHK_STATUS_RETURN(InsertSkippedMacroblocks( |
| &batchBuffer, |
| &mpeg2MbState, |
| expectedMBAddress, |
| skippedMBs)); |
| } |
| } |
| |
| //common field for MBs in I picture and PB picture . |
| mpeg2MbState.pMBParams = &m_mbParams[mbcount]; |
| mpeg2MbState.dwDCTLength = 0; |
| for (uint32_t i = 0; i < CODEC_NUM_BLOCK_PER_MB; i++) |
| { |
| mpeg2MbState.dwDCTLength += m_mbParams[mbcount].m_numCoeff[i]; |
| } |
| |
| mpeg2MbState.dwITCoffDataAddrOffset = m_copiedDataOffset + (m_mbParams[mbcount].m_mbDataLoc << 2); // byte offset |
| |
| //only for MB in PB picture. |
| if (mpeg2MbState.wPicCodingType != I_TYPE) |
| { |
| bool intraMB = mpeg2MbState.pMBParams->MBType.m_intraMb? true: false; |
| |
| MOS_ZeroMemory(mpeg2MbState.sPackedMVs0,sizeof(mpeg2MbState.sPackedMVs0)); |
| MOS_ZeroMemory(mpeg2MbState.sPackedMVs1,sizeof(mpeg2MbState.sPackedMVs1)); |
| if ((!intraMB) && (mpeg2MbState.pMBParams->MBType.m_value & |
| (CODECHAL_DECODE_MPEG2_MB_MOTION_BACKWARD | CODECHAL_DECODE_MPEG2_MB_MOTION_FORWARD))) |
| { |
| PackMotionVectors(m_picParams->m_currPic.PicFlags, &mpeg2MbState); |
| } |
| } |
| |
| // add IT OBJECT command for each macroblock |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdMpeg2ITObject( |
| nullptr, |
| &batchBuffer, |
| &mpeg2MbState)); |
| |
| if (mpeg2MbState.wPicCodingType != I_TYPE && m_mbParams[mbcount].m_mbSkipFollowing) |
| { |
| uint16_t skippedMBs = m_mbParams[mbcount].m_mbSkipFollowing; |
| uint16_t skippedMBSart = m_mbParams[mbcount].m_mbAddr + 1; |
| |
| // Insert Skipped MBs |
| CODECHAL_DECODE_CHK_STATUS_RETURN(InsertSkippedMacroblocks( |
| &batchBuffer, |
| &mpeg2MbState, |
| skippedMBSart, |
| skippedMBs)); |
| |
| m_mbParams[mbcount].m_mbAddr += skippedMBs; |
| } |
| |
| //save the last MB's parameters for later use to insert skipped MBs. |
| m_savedMpeg2MbParam = m_mbParams[mbcount]; |
| |
| expectedMBAddress = m_mbParams[mbcount].m_mbAddr + 1; |
| |
| // insert extra MBs to ensure expected number of MBs sent to HW |
| if (mbcount + 1 == m_numMacroblocks) |
| { |
| uint16_t expectedFinalMB = m_picWidthInMb * m_picHeightInMb; |
| |
| if (expectedMBAddress != expectedFinalMB) |
| { |
| m_incompletePicture = true; |
| m_lastMbAddress = expectedMBAddress; |
| } |
| else |
| { |
| m_incompletePicture = false; |
| } |
| } |
| } |
| } |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd( |
| nullptr, |
| &batchBuffer)); |
| |
| CODECHAL_DEBUG_TOOL( |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->Dump2ndLvlBatch( |
| &batchBuffer, |
| CODECHAL_NUM_MEDIA_STATES, |
| "_DEC")); |
| ) |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_UnlockBb(m_osInterface, &batchBuffer, true)); |
| |
| m_bbInUse = (m_bbInUse + 1) % m_bbAllocated; |
| m_bbInUsePerFrame++; |
| |
| if (!m_incompletePicture) |
| { |
| // Check if destination surface needs to be synchronized |
| MOS_SYNC_PARAMS syncParams = g_cInitSyncParams; |
| syncParams.GpuContext = m_videoContext; |
| syncParams.presSyncResource = &m_destSurface.OsResource; |
| syncParams.bReadOnly = false; |
| syncParams.bDisableDecodeSyncLock = m_disableDecodeSyncLock; |
| syncParams.bDisableLockForTranscode = m_disableLockForTranscode; |
| |
| if (!CodecHal_PictureIsField(m_picParams->m_currPic) || |
| !m_picParams->m_secondField) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync( |
| m_osInterface, |
| &syncParams)); |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait( |
| m_osInterface, |
| &syncParams)); |
| |
| // Update the resource tag (s/w tag) for On-Demand Sync |
| m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams); |
| } |
| |
| MHW_MI_FLUSH_DW_PARAMS flushDwParams; |
| MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd( |
| &cmdBuffer, |
| &flushDwParams)); |
| |
| // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag |
| if (m_osInterface->bTagResourceSync && |
| (!CodecHal_PictureIsField(m_picParams->m_currPic) || m_picParams->m_secondField)) |
| { |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource( |
| &cmdBuffer, |
| &syncParams)); |
| } |
| |
| if (m_statusQueryReportingEnabled) |
| { |
| CodechalDecodeStatusReport decodeStatusReport; |
| |
| decodeStatusReport.m_statusReportNumber = m_statusReportFeedbackNumber; |
| decodeStatusReport.m_currDecodedPic = m_picParams->m_currPic; |
| decodeStatusReport.m_currDeblockedPic = m_picParams->m_currPic; |
| decodeStatusReport.m_codecStatus = CODECHAL_STATUS_UNAVAILABLE; |
| decodeStatusReport.m_currDecodedPicRes = |
| m_mpeg2RefList[m_picParams->m_currPic.FrameIdx]->resRefPic; |
| |
| CODECHAL_DEBUG_TOOL( |
| decodeStatusReport.m_secondField = m_picParams->m_secondField ? true : false; |
| 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")); |
| |
| //CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHal_DbgReplaceAllCommands( |
| // m_debugInterface, |
| // &cmdBuffer)); |
| ) |
| |
| //Sync up complete frame |
| syncParams = g_cInitSyncParams; |
| syncParams.GpuContext = m_videoContextForWa; |
| syncParams.presSyncResource = &m_resSyncObjectWaContextInUse; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams)); |
| |
| syncParams = g_cInitSyncParams; |
| syncParams.GpuContext = m_videoContext; |
| syncParams.presSyncResource = &m_resSyncObjectWaContextInUse; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams)); |
| |
| CODECHAL_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_mpeg2RefList[m_picParams->m_currPic.FrameIdx]->resRefPic = m_destSurface.OsResource; |
| |
| // Send the signal to indicate decode completion, in case On-Demand Sync is not present |
| if (!CodecHal_PictureIsField(m_picParams->m_currPic) || m_picParams->m_secondField) |
| { |
| syncParams = g_cInitSyncParams; |
| syncParams.GpuContext = m_videoContext; |
| syncParams.presSyncResource = &m_destSurface.OsResource; |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams)); |
| } |
| } |
| else |
| { |
| m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); |
| } |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalDecodeMpeg2::InitMmcState() |
| { |
| #ifdef _MMC_SUPPORTED |
| m_mmc = MOS_New(CodechalMmcDecodeMpeg2, m_hwInterface, this); |
| CODECHAL_DECODE_CHK_NULL_RETURN(m_mmc); |
| #endif |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalDecodeMpeg2::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_picWidthInMb = (uint16_t)CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_width); |
| m_picHeightInMb = (uint16_t)CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_height); |
| m_bbAllocated = CODECHAL_DECODE_MPEG2_BATCH_BUFFERS_PER_GROUP; |
| |
| // Picture Level Commands |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->GetMfxStateCommandsDataSize( |
| m_mode, |
| &m_commandBufferSizeNeeded, |
| &m_commandPatchListSizeNeeded, |
| 0)); |
| |
| // Primitive Level Commands |
| CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->GetMfxPrimitiveCommandsDataSize( |
| m_mode, |
| &m_standardDecodeSizeNeeded, |
| &m_standardDecodePatchListSizeNeeded, |
| 0)); |
| |
| CODECHAL_DECODE_CHK_STATUS_RETURN(AllocateResources()); |
| |
| return eStatus; |
| } |
| |
| CodechalDecodeMpeg2::CodechalDecodeMpeg2 ( |
| CodechalHwInterface *hwInterface, |
| CodechalDebugInterface* debugInterface, |
| PCODECHAL_STANDARD_INFO standardInfo) : |
| CodechalDecode(hwInterface, debugInterface, standardInfo) |
| { |
| CODECHAL_DECODE_FUNCTION_ENTER; |
| |
| MOS_ZeroMemory(&m_destSurface, sizeof(m_destSurface)); |
| MOS_ZeroMemory(m_presReferences, sizeof(m_presReferences)); |
| MOS_ZeroMemory(&m_resDataBuffer, sizeof(m_resDataBuffer)); |
| MOS_ZeroMemory(&m_resMfdDeblockingFilterRowStoreScratchBuffer, sizeof(m_resMfdDeblockingFilterRowStoreScratchBuffer)); |
| MOS_ZeroMemory(&m_resBsdMpcRowStoreScratchBuffer, sizeof(m_resBsdMpcRowStoreScratchBuffer)); |
| MOS_ZeroMemory(m_mpeg2RefList, sizeof(m_mpeg2RefList)); |
| MOS_ZeroMemory(m_mediaObjectBatchBuffer, sizeof(m_mediaObjectBatchBuffer)); |
| MOS_ZeroMemory(&m_resMpeg2DummyBistream, sizeof(m_resMpeg2DummyBistream)); |
| MOS_ZeroMemory(m_resCopiedDataBuffer, sizeof(m_resCopiedDataBuffer)); |
| MOS_ZeroMemory(&m_resSyncObjectWaContextInUse, sizeof(m_resSyncObjectWaContextInUse)); |
| MOS_ZeroMemory(&m_resSyncObjectVideoContextInUse, sizeof(m_resSyncObjectVideoContextInUse)); |
| MOS_ZeroMemory(&m_savedMpeg2MbParam, sizeof(m_savedMpeg2MbParam)); |
| } |
| |
| #if USE_CODECHAL_DEBUG_TOOL |
| MOS_STATUS CodechalDecodeMpeg2::DumpPicParams( |
| CodecDecodeMpeg2PicParams *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 << "m_currPic FrameIdx: " << +picParams->m_currPic.FrameIdx << std::endl; |
| oss << "m_currPic PicFlags: " << +picParams->m_currPic.PicFlags << std::endl; |
| oss << "m_forwardRefIdx: " << +picParams->m_forwardRefIdx << std::endl; |
| oss << "m_backwardRefIdx: " << +picParams->m_backwardRefIdx << std::endl; |
| oss << "m_topFieldFirst: " << +picParams->m_topFieldFirst << std::endl; |
| oss << "m_secondField: " << +picParams->m_secondField << std::endl; |
| oss << "m_statusReportFeedbackNumber: " << +picParams->m_statusReportFeedbackNumber << std::endl; |
| //Dump union w0 |
| oss << "w0 m_value: " << +picParams->W0.m_value << std::endl; |
| oss << "m_scanOrder: " << +picParams->W0.m_scanOrder << std::endl; |
| oss << "m_intraVlcFormat: " << +picParams->W0.m_intraVlcFormat << std::endl; |
| oss << "m_quantizerScaleType: " << +picParams->W0.m_quantizerScaleType << std::endl; |
| oss << "m_concealmentMVFlag: " << +picParams->W0.m_concealmentMVFlag << std::endl; |
| oss << "m_frameDctPrediction: " << +picParams->W0.m_frameDctPrediction << std::endl; |
| oss << "m_topFieldFirst: " << +picParams->W0.m_topFieldFirst << std::endl; |
| oss << "m_intraDCPrecision: " << +picParams->W0.m_intraDCPrecision << std::endl; |
| //Dump union w1 |
| oss << "w1 m_value: " << +picParams->W1.m_value << std::endl; |
| oss << "m_fcode11: " << +picParams->W1.m_fcode11 << std::endl; |
| oss << "m_fcode10: " << +picParams->W1.m_fcode10 << std::endl; |
| oss << "m_fcode01: " << +picParams->W1.m_fcode01 << std::endl; |
| oss << "m_fcode00: " << +picParams->W1.m_fcode00 << std::endl; |
| oss << "m_horizontalSize: " << +picParams->m_horizontalSize << std::endl; |
| oss << "m_verticalSize: " << +picParams->m_verticalSize << std::endl; |
| oss << "m_pictureCodingType: " << +picParams->m_pictureCodingType << 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 CodechalDecodeMpeg2::DumpSliceParams( |
| CodecDecodeMpeg2SliceParams *sliceParams, |
| uint32_t numSlices) |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSlcParams)) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| CODECHAL_DEBUG_CHK_NULL(sliceParams); |
| |
| const char *fileName = m_debugInterface->CreateFileName( |
| "_DEC", |
| CodechalDbgBufferType::bufSlcParams, |
| CodechalDbgExtType::txt); |
| |
| std::ostringstream oss; |
| oss.setf(std::ios::showbase | std::ios::uppercase); |
| |
| CodecDecodeMpeg2SliceParams *sliceControl = nullptr; |
| |
| for (uint16_t i = 0; i < numSlices; i++) |
| { |
| sliceControl = &sliceParams[i]; |
| |
| oss << "====================================================================================================" << std::endl; |
| oss << "Data for Slice number = " << +i << std::endl; |
| oss << "m_sliceDataSize: " << +sliceControl->m_sliceDataSize << std::endl; |
| oss << "m_sliceDataOffset: " << +sliceControl->m_sliceDataOffset << std::endl; |
| oss << "m_macroblockOffset: " << +sliceControl->m_macroblockOffset << std::endl; |
| oss << "m_sliceHorizontalPosition: " << +sliceControl->m_sliceHorizontalPosition << std::endl; |
| oss << "m_sliceVerticalPosition: " << +sliceControl->m_sliceVerticalPosition << std::endl; |
| oss << "m_quantiserScaleCode: " << +sliceControl->m_quantiserScaleCode << std::endl; |
| oss << "m_numMbsForSlice: " << +sliceControl->m_numMbsForSlice << std::endl; |
| oss << "m_numMbsForSliceOverflow: " << +sliceControl->m_numMbsForSliceOverflow << std::endl; |
| oss << "m_reservedBits: " << +sliceControl->m_reservedBits << std::endl; |
| oss << "m_startCodeBitOffset: " << +sliceControl->m_startCodeBitOffset << std::endl; |
| |
| std::ofstream ofs; |
| if (i == 0) |
| { |
| ofs.open(fileName, std::ios::out); |
| } |
| else |
| { |
| ofs.open(fileName, std::ios::app); |
| } |
| ofs << oss.str(); |
| ofs.close(); |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalDecodeMpeg2::DumpIQParams( |
| CodecMpeg2IqMatrix *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); |
| |
| if (matrixData->m_loadIntraQuantiserMatrix) |
| { |
| oss << "intra_QmatrixData:" << std::endl; |
| |
| for (uint8_t i = 0; i < 56; i += 8) |
| { |
| oss << "Qmatrix[" << +i / 8 << "]: "; |
| for (uint8_t j = 0; j < 8; j++) |
| oss << +matrixData->m_intraQuantiserMatrix[i + j] << " "; |
| oss << std::endl; |
| } |
| } |
| if (matrixData->m_loadNonIntraQuantiserMatrix) |
| { |
| oss << "non_intra_QmatrixData:" << std::endl; |
| |
| for (uint8_t i = 0; i < 56; i += 8) |
| { |
| oss << "Qmatrix[" << +i / 8 << "]: "; |
| for (uint8_t j = 0; j < 8; j++) |
| oss << +matrixData->m_nonIntraQuantiserMatrix[i + j] << " "; |
| oss << std::endl; |
| } |
| } |
| if (matrixData->m_loadChromaIntraQuantiserMatrix) |
| { |
| oss << "chroma_intra_QmatrixData:" << std::endl; |
| |
| for (uint8_t i = 0; i < 56; i += 8) |
| { |
| oss << "Qmatrix[" << +i / 8 << "]: "; |
| for (uint8_t j = 0; j < 8; j++) |
| oss << +matrixData->m_chromaIntraQuantiserMatrix[i + j] << " "; |
| oss << std::endl; |
| } |
| } |
| if (matrixData->m_loadChromaNonIntraQuantiserMatrix) |
| { |
| oss << "chroma_non_intra_QmatrixData:" << std::endl; |
| |
| for (uint8_t i = 0; i < 56; i += 8) |
| { |
| oss << "Qmatrix[" << +i / 8 << "]: "; |
| for (uint8_t j = 0; j < 8; j++) |
| oss << +matrixData->m_chromaNonIntraQuantiserMatrix[i + j] << " "; |
| oss << std::endl; |
| } |
| } |
| |
| const char *fileName = m_debugInterface->CreateFileName( |
| "_DEC", |
| CodechalDbgBufferType::bufIqParams, |
| CodechalDbgExtType::txt); |
| |
| std::ofstream ofs(fileName, std::ios::out); |
| ofs << oss.str(); |
| ofs.close(); |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalDecodeMpeg2::DumpMbParams( |
| CodecDecodeMpeg2MbParmas *mbParams) |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrMbParams)) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| CODECHAL_DEBUG_CHK_NULL(mbParams); |
| |
| std::ostringstream oss; |
| oss.setf(std::ios::showbase | std::ios::uppercase); |
| |
| oss << "m_mbAddr: " << +mbParams->m_mbAddr << std::endl; |
| //Dump union MBType |
| oss << "MBType.m_intraMb: " << +mbParams->MBType.m_intraMb << std::endl; |
| oss << "MBType.m_motionFwd: " << +mbParams->MBType.m_motionFwd << std::endl; |
| oss << "MBType.m_motionBwd: " << +mbParams->MBType.m_motionBwd << std::endl; |
| oss << "MBType.m_motion4mv: " << +mbParams->MBType.m_motion4mv << std::endl; |
| oss << "MBType.m_h261Lpfilter: " << +mbParams->MBType.m_h261Lpfilter << std::endl; |
| oss << "MBType.m_fieldResidual: " << +mbParams->MBType.m_fieldResidual << std::endl; |
| oss << "MBType.m_mbScanMethod: " << +mbParams->MBType.m_mbScanMethod << std::endl; |
| oss << "MBType.m_motionType: " << +mbParams->MBType.m_motionType << std::endl; |
| oss << "MBType.m_hostResidualDiff: " << +mbParams->MBType.m_hostResidualDiff << std::endl; |
| oss << "MBType.m_mvertFieldSel: " << +mbParams->MBType.m_mvertFieldSel << std::endl; |
| oss << "m_mbSkipFollowing: " << +mbParams->m_mbSkipFollowing << std::endl; |
| oss << "m_mbDataLoc: " << +mbParams->m_mbDataLoc << std::endl; |
| oss << "m_codedBlockPattern: " << +mbParams->m_codedBlockPattern << std::endl; |
| |
| //Dump NumCoeff[CODEC_NUM_BLOCK_PER_MB] |
| for (uint16_t i = 0; i < CODEC_NUM_BLOCK_PER_MB; ++i) |
| { |
| oss << "m_numCoeff[" << +i << "]: " << +mbParams->m_numCoeff[i] << std::endl; |
| } |
| |
| //Dump motion_vectors[8],printing them in 4 value chunks per line |
| for (uint8_t i = 0; i < 2; ++i) |
| { |
| oss << "m_motionVectors[" << +i * 4 << "-" << (+i * 4) + 3 << "]: "; |
| for (uint8_t j = 0; j < 4; j++) |
| oss << +mbParams->m_motionVectors[i * 4 + j] << " "; |
| oss << std::endl; |
| } |
| |
| const char *fileName = m_debugInterface->CreateFileName( |
| "_DEC", |
| CodechalDbgBufferType::bufMbParams, |
| CodechalDbgExtType::txt); |
| |
| std::ofstream ofs(fileName, std::ios::out); |
| ofs << oss.str(); |
| ofs.close(); |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| #endif |