blob: abfc0f52d79820781214bbd82f935681bc5ab0d8 [file] [log] [blame]
/*
* 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