blob: 4c697ad729531153a373c79711e4460ef4f9e7ab [file] [log] [blame]
/*
* Copyright (c) 2011-2020, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
//!
//! \file codechal_decoder.cpp
//! \brief Implements the decode interface for CodecHal.
//! \details The decode interface is further sub-divided by standard, this file is for the base interface which is shared by all decode standards.
//!
#include "codechal_decoder.h"
#include "codechal_secure_decode_interface.h"
#include "mos_solo_generic.h"
#include "codechal_debug.h"
#include "codechal_decode_histogram.h"
#ifdef _HEVC_DECODE_SUPPORTED
#include "codechal_decode_hevc.h"
#endif
#ifdef _VP9_DECODE_SUPPORTED
#include "codechal_decode_vp9.h"
#endif
#ifdef _HYBRID_HEVC_DECODE_SUPPORTED
#include "codechal_decode_hybrid_hevc.h"
#endif
#ifdef _HYBRID_VP9_DECODE_SUPPORTED
#include "codechal_decode_hybrid_vp9.h"
#endif
#ifdef _AVC_DECODE_SUPPORTED
#include "codechal_decode_avc.h"
#endif
#ifdef _JPEG_DECODE_SUPPORTED
#include "codechal_decode_jpeg.h"
#endif
#ifdef _VC1_DECODE_SUPPORTED
#include "codechal_decode_vc1.h"
#endif
#ifdef _VP8_DECODE_SUPPORTED
#include "codechal_decode_vp8.h"
#endif
#ifdef _MPEG2_DECODE_SUPPORTED
#include "codechal_decode_mpeg2.h"
#endif
#if USE_CODECHAL_DEBUG_TOOL
#include <sstream>
#include <fstream>
#include "codechal_debug.h"
#endif
MOS_STATUS CodechalDecode::AllocateBuffer(
PMOS_RESOURCE resource,
uint32_t size,
const char *name,
bool initialize,
uint8_t value,
bool bPersistent)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_DECODE_FUNCTION_ENTER;
CODECHAL_DECODE_CHK_NULL_RETURN(m_osInterface);
CODECHAL_DECODE_CHK_NULL_RETURN(resource);
MOS_ALLOC_GFXRES_PARAMS allocParams;
MOS_ZeroMemory(&allocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS));
allocParams.Type = MOS_GFXRES_BUFFER;
allocParams.TileType = MOS_TILE_LINEAR;
allocParams.Format = Format_Buffer;
allocParams.dwBytes = size;
allocParams.pBufName = name;
allocParams.bIsPersistent = bPersistent;
CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParams,
resource),
"Failed to allocate %s.", name);
if (initialize)
{
CodechalResLock ResourceLock(m_osInterface, resource);
auto data = (uint8_t*)ResourceLock.Lock(CodechalResLock::writeOnly);
CODECHAL_DECODE_CHK_NULL_RETURN(data);
MOS_FillMemory(data, size, value);
}
return eStatus;
}
MOS_STATUS CodechalDecode::AllocateSurface(
PMOS_SURFACE surface,
uint32_t width,
uint32_t height,
const char *name,
MOS_FORMAT format,
bool isCompressible)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_DECODE_FUNCTION_ENTER;
CODECHAL_DECODE_CHK_NULL_RETURN(m_osInterface);
CODECHAL_DECODE_CHK_NULL_RETURN(surface);
MOS_ALLOC_GFXRES_PARAMS allocParams;
MOS_ZeroMemory(&allocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS));
allocParams.Type = MOS_GFXRES_2D;
allocParams.TileType = MOS_TILE_Y;
allocParams.Format = format;
allocParams.dwWidth = width;
allocParams.dwHeight = height;
allocParams.dwArraySize = 1;
allocParams.pBufName = name;
allocParams.bIsCompressible = isCompressible;
CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParams,
&surface->OsResource),
"Failed to allocate %s.", name);
CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(
m_osInterface,
surface));
return eStatus;
}
MOS_STATUS CodechalDecode::HucCopy(
PMOS_COMMAND_BUFFER cmdBuffer,
PMOS_RESOURCE src,
PMOS_RESOURCE dst,
uint32_t copyLength,
uint32_t copyInputOffset,
uint32_t copyOutputOffset)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_DECODE_FUNCTION_ENTER;
CODECHAL_DECODE_CHK_NULL_RETURN(cmdBuffer);
CODECHAL_DECODE_CHK_NULL_RETURN(src);
CODECHAL_DECODE_CHK_NULL_RETURN(dst);
CodechalHucStreamoutParams hucStreamOutParams;
MOS_ZeroMemory(&hucStreamOutParams, sizeof(hucStreamOutParams));
// Ind Obj Addr command
hucStreamOutParams.dataBuffer = src;
hucStreamOutParams.dataSize = copyLength + copyInputOffset;
hucStreamOutParams.dataOffset = MOS_ALIGN_FLOOR(copyInputOffset, MHW_PAGE_SIZE);
hucStreamOutParams.streamOutObjectBuffer = dst;
hucStreamOutParams.streamOutObjectSize = copyLength + copyOutputOffset;
hucStreamOutParams.streamOutObjectOffset = MOS_ALIGN_FLOOR(copyOutputOffset, MHW_PAGE_SIZE);
// Stream object params
hucStreamOutParams.indStreamInLength = copyLength;
hucStreamOutParams.inputRelativeOffset = copyInputOffset - hucStreamOutParams.dataOffset;
hucStreamOutParams.outputRelativeOffset = copyOutputOffset - hucStreamOutParams.streamOutObjectOffset;
CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->PerformHucStreamOut(
&hucStreamOutParams,
cmdBuffer));
return eStatus;
}
uint32_t CodechalDecode::LinearToYTiledAddress(
uint32_t x,
uint32_t y,
uint32_t pitch)
{
uint32_t tileW = 128;
uint32_t tileH = 32;
uint32_t tileSize = tileW * tileH;
uint32_t rowSize = (pitch / tileW) * tileSize;
uint32_t xOffWithinTile = x % tileW;
uint32_t yOffWithinTile = y % tileH;
uint32_t tileNumberInX = x / tileW;
uint32_t tileNumberInY = y / tileH;
uint32_t tileOffset =
rowSize * tileNumberInY +
tileSize * tileNumberInX +
tileH * 16 * (xOffWithinTile / 16) +
yOffWithinTile * 16 +
(xOffWithinTile % 16);
return tileOffset;
}
CodechalDecode::CodechalDecode (
CodechalHwInterface *hwInterface,
CodechalDebugInterface *debugInterface,
PCODECHAL_STANDARD_INFO standardInfo):
Codechal(hwInterface, debugInterface)
{
CODECHAL_DECODE_FUNCTION_ENTER;
MOS_ZeroMemory(&m_dummyReference, sizeof(MOS_SURFACE));
CODECHAL_DECODE_CHK_NULL_NO_STATUS_RETURN(hwInterface);
CODECHAL_DECODE_CHK_NULL_NO_STATUS_RETURN(hwInterface->GetOsInterface());
CODECHAL_DECODE_CHK_NULL_NO_STATUS_RETURN(hwInterface->GetMiInterface());
CODECHAL_DECODE_CHK_NULL_NO_STATUS_RETURN(hwInterface->GetCpInterface());
CODECHAL_DECODE_CHK_NULL_NO_STATUS_RETURN(standardInfo);
m_mfxInterface = hwInterface->GetMfxInterface();
m_hcpInterface = hwInterface->GetHcpInterface();
m_hucInterface = hwInterface->GetHucInterface();
m_vdencInterface = hwInterface->GetVdencInterface();
m_miInterface = hwInterface->GetMiInterface();
m_cpInterface = hwInterface->GetCpInterface();
PLATFORM platform;
m_osInterface->pfnGetPlatform(m_osInterface, &platform);
m_waTable = m_osInterface->pfnGetWaTable(m_osInterface);
CODECHAL_DECODE_CHK_NULL_NO_STATUS_RETURN(m_waTable);
m_skuTable = m_osInterface->pfnGetSkuTable(m_osInterface);
CODECHAL_DECODE_CHK_NULL_NO_STATUS_RETURN(m_skuTable);
m_mode = standardInfo->Mode;
m_isHybridDecoder = standardInfo->bIsHybridCodec ? true : false;
}
MOS_STATUS CodechalDecode::SetGpuCtxCreatOption(
CodechalSetting * codecHalSetting)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MOS_UNUSED(codecHalSetting);
m_gpuCtxCreatOpt = MOS_New(MOS_GPUCTX_CREATOPTIONS);
CODECHAL_DECODE_CHK_NULL_RETURN(m_gpuCtxCreatOpt);
return eStatus;
}
MOS_STATUS CodechalDecode::CreateGpuContexts(
CodechalSetting *codecHalSettings)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_DECODE_CHK_NULL_RETURN(codecHalSettings);
MHW_VDBOX_GPUNODE_LIMIT gpuNodeLimit;
gpuNodeLimit.bHuCInUse = false;
gpuNodeLimit.bHcpInUse = m_hcpInUse;
gpuNodeLimit.bSfcInUse = IsSfcInUse(codecHalSettings);
CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->FindGpuNodeToUse(
&gpuNodeLimit));
m_videoGpuNode = (MOS_GPU_NODE)(gpuNodeLimit.dwGpuNodeToUse);
CODECHAL_UPDATE_VDBOX_USER_FEATURE(m_videoGpuNode, m_osInterface->pOsContext);
CodecHalDecodeMapGpuNodeToGpuContex(m_videoGpuNode, m_videoContext, false);
CODECHAL_DECODE_CHK_STATUS_RETURN(SetGpuCtxCreatOption(codecHalSettings));
CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateGpuContext(
m_osInterface,
m_videoContext,
m_videoGpuNode,
m_gpuCtxCreatOpt));
// Create Video2 Context for MPEG2 WA and JPEG incomplete bitstream & VP9 / HEVC DRC support
// For decode device, we use VDBOX0 always for the WA context
// For AVC,VC1,VP9, use WA context for huc stream out copy
if (Mos_Solo_IsInUse(m_osInterface))
{
Mos_Solo_DecodeMapGpuNodeToGpuContex(MOS_GPU_NODE_VIDEO, m_videoContextForWa, true, false);
}
else
{
CodecHalDecodeMapGpuNodeToGpuContex(MOS_GPU_NODE_VIDEO, m_videoContextForWa, true);
}
MOS_GPUCTX_CREATOPTIONS_ENHANCED createOption;
createOption.UsingSFC = codecHalSettings->sfcInUseHinted && codecHalSettings->downsamplingHinted
&& (MEDIA_IS_SKU(m_skuTable, FtrSFCPipe)) && !(MEDIA_IS_SKU(m_skuTable, FtrDisableVDBox2SFC));
eStatus = (MOS_STATUS)m_osInterface->pfnCreateGpuContext(
m_osInterface,
m_videoContextForWa,
MOS_GPU_NODE_VIDEO,
&createOption);
if (eStatus != MOS_STATUS_SUCCESS)
{
// use context Video1. It should be valid
if (Mos_Solo_IsInUse(m_osInterface))
{
Mos_Solo_DecodeMapGpuNodeToGpuContex(MOS_GPU_NODE_VIDEO, m_videoContextForWa, false, false);
}
else
{
CodecHalDecodeMapGpuNodeToGpuContex(MOS_GPU_NODE_VIDEO, m_videoContextForWa, false);
}
CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnIsGpuContextValid(
m_osInterface,
m_videoContextForWa));
}
// Do not need to create render context here, it will be created by standard specific decoder
return eStatus;
}
// Decoder Public Interface Functions
MOS_STATUS CodechalDecode::Allocate (CodechalSetting * codecHalSettings)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_DECODE_FUNCTION_ENTER;
CODECHAL_DECODE_CHK_STATUS_RETURN(Codechal::Allocate(codecHalSettings));
m_standard = codecHalSettings->standard;
m_mode = codecHalSettings->mode;
m_disableDecodeSyncLock = codecHalSettings->disableDecodeSyncLock ? true : false;
m_disableLockForTranscode = MEDIA_IS_WA(m_waTable, WaDisableLockForTranscodePerf);
// register cp params via codechal_Setting
m_cpInterface->RegisterParams(codecHalSettings->GetCpParams());
{
MOS_USER_FEATURE_VALUE_DATA userFeatureData;
MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
userFeatureData.u32Data = MOS_STATUS_REPORT_DEFAULT;
userFeatureData.i32DataFlag = MOS_USER_FEATURE_VALUE_DATA_FLAG_CUSTOM_DEFAULT_VALUE_TYPE;
MOS_UserFeature_ReadValue_ID(
nullptr,
__MEDIA_USER_FEATURE_VALUE_STATUS_REPORTING_ENABLE_ID,
&userFeatureData,
m_osInterface->pOsContext);
m_statusQueryReportingEnabled = (userFeatureData.u32Data) ? true : false;
#if (_DEBUG || _RELEASE_INTERNAL)
if (m_statusQueryReportingEnabled)
{
MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
MOS_UserFeature_ReadValue_ID(
nullptr,
__MEDIA_USER_FEATURE_VALUE_STREAM_OUT_ENABLE_ID,
&userFeatureData,
m_osInterface->pOsContext);
m_streamOutEnabled = (userFeatureData.u32Data) ? true : false;
}
MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
MOS_UserFeature_ReadValue_ID(
nullptr,
__MEDIA_USER_FEATURE_VALUE_PERF_PROFILER_FE_BE_TIMING,
&userFeatureData,
m_osInterface->pOsContext);
m_perfFEBETimingEnabled = userFeatureData.bData;
#endif // _DEBUG || _RELEASE_INTERNAL
}
//#if (_DEBUG || _RELEASE_INTERNAL)
//#ifdef _MD5_DEBUG_SUPPORTED
// {
// // For multi-thread decoder case, MD5 kernel will share the same context with hybrid decoder.
// // And it will be initialized in decoder worker thread function.
// if ((!m_isHybridDecoder || (m_isHybridDecoder && !IsFrameMTEnabled())) &&
// m_debugInterface != nullptr)
// {
// CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHal_DbgInitMD5Context(
// m_debugInterface,
// nullptr));
// if (m_debugInterface->pMD5Context)
// {
// m_debugInterface->bMD5DDIThreadExecute = true;
// }
// }
// }
//#endif // _MD5_DEBUG_SUPPORTED
//#endif // _DEBUG || _RELEASE_INTERNAL
// Set decoder running flag to OS context so that VPP driver can query this flag and use
// this flag to decide if disable VPP DNDI feature in VEBOX for power saving.
CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetHybridDecoderRunningFlag(
m_osInterface,
m_isHybridDecoder));
// eStatus Query reporting
if (m_statusQueryReportingEnabled)
{
uint32_t statusBufferSize = sizeof(CodechalDecodeStatus) * CODECHAL_DECODE_STATUS_NUM + sizeof(uint32_t) * 2;
CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer(
&m_decodeStatusBuf.m_statusBuffer,
statusBufferSize,
"StatusQueryBuffer"),
"Failed to allocate decode eStatus buffer.");
MOS_LOCK_PARAMS lockFlagsNoOverWrite;
MOS_ZeroMemory(&lockFlagsNoOverWrite, sizeof(MOS_LOCK_PARAMS));
lockFlagsNoOverWrite.WriteOnly = 1;
lockFlagsNoOverWrite.NoOverWrite = 1;
uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(
m_osInterface,
&m_decodeStatusBuf.m_statusBuffer,
&lockFlagsNoOverWrite);
MOS_ZeroMemory(data, statusBufferSize);
m_decodeStatusBuf.m_data = (uint32_t *)data;
m_decodeStatusBuf.m_decodeStatus = (CodechalDecodeStatus *)(data + sizeof(uint32_t) * 2);
m_decodeStatusBuf.m_currIndex = 0;
m_decodeStatusBuf.m_firstIndex = 0;
m_decodeStatusBuf.m_swStoreData = 1;
m_decodeStatusBuf.m_storeDataOffset = 0;
m_decodeStatusBuf.m_decErrorStatusOffset = CODECHAL_OFFSETOF(CodechalDecodeStatus, m_mmioErrorStatusReg);
m_decodeStatusBuf.m_decFrameCrcOffset = CODECHAL_OFFSETOF(CodechalDecodeStatus, m_mmioFrameCrcReg);
m_decodeStatusBuf.m_decMBCountOffset = CODECHAL_OFFSETOF(CodechalDecodeStatus, m_mmioMBCountReg);
m_decodeStatusBuf.m_csEngineIdOffset = CODECHAL_OFFSETOF(CodechalDecodeStatus, m_mmioCsEngineIdReg);
m_decodeStatusBuf.m_hucErrorStatus2MaskOffset = CODECHAL_OFFSETOF(CodechalDecodeStatus, m_hucErrorStatus2);
m_decodeStatusBuf.m_hucErrorStatus2RegOffset = CODECHAL_OFFSETOF(CodechalDecodeStatus, m_hucErrorStatus2) + sizeof(uint32_t);
m_decodeStatusBuf.m_hucErrorStatusMaskOffset = CODECHAL_OFFSETOF(CodechalDecodeStatus, m_hucErrorStatus);
m_decodeStatusBuf.m_hucErrorStatusRegOffset = CODECHAL_OFFSETOF(CodechalDecodeStatus, m_hucErrorStatus) + sizeof(uint32_t);
// Set IMEM Loaded bit (in DW1) to 1 by default in the first status buffer
// This bit will be changed later after storing register
if (m_hucInterface)
{
m_decodeStatusBuf.m_decodeStatus->m_hucErrorStatus2 = (uint64_t)m_hucInterface->GetHucStatus2ImemLoadedMask() << 32;
}
//if kernels are used update the media state heap with status pointers to keep track of when buffers are done
if (m_hwInterface->GetRenderInterface() != nullptr &&
m_hwInterface->GetRenderInterface()->m_stateHeapInterface != nullptr)
{
PMHW_STATE_HEAP_INTERFACE pStateHeapInterface =
m_hwInterface->GetRenderInterface()->m_stateHeapInterface;
CODECHAL_DECODE_CHK_STATUS_RETURN(pStateHeapInterface->pfnSetCmdBufStatusPtr(
pStateHeapInterface,
m_decodeStatusBuf.m_data));
}
// StreamOut Buffer Allocation
if (m_streamOutEnabled)
{
uint32_t numMacroblocks =
(codecHalSettings->height / CODECHAL_MACROBLOCK_HEIGHT) *
(codecHalSettings->width / CODECHAL_MACROBLOCK_WIDTH);
uint32_t streamOutBufSize = MOS_ALIGN_CEIL(numMacroblocks * CODEC_SIZE_MFX_STREAMOUT_DATA, 64);
m_streamOutCurrBufIdx = 0;
for (auto i = 0; i < CODECHAL_DECODE_NUM_STREAM_OUT_BUFFERS; i++)
{
CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer(
&(m_streamOutBuffer[i]),
streamOutBufSize,
"StreamOutBuffer",
true,
0),
"Failed to allocate streamout buffer.");
m_streamOutCurrStatusIdx[i] = CODECHAL_DECODE_STATUS_NUM;
}
}
}
CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer(
&m_predicationBuffer,
sizeof(uint32_t),
"PredicationBuffer",
true,
0),
"Failed to allocate predication buffer.");
CODECHAL_DECODE_CHK_STATUS_RETURN(AllocateStandard(codecHalSettings));
if(!m_isHybridDecoder)
{
// Create Video Contexts
CODECHAL_DECODE_CHK_STATUS_RETURN(CreateGpuContexts(codecHalSettings));
// Set Vdbox index in use
m_vdboxIndex = (m_videoGpuNode == MOS_GPU_NODE_VIDEO2)? MHW_VDBOX_NODE_2 : MHW_VDBOX_NODE_1;
// Set FrameCrc reg offset
if (m_standard == CODECHAL_HEVC)
{
m_hcpFrameCrcRegOffset = m_hcpInterface->GetMmioRegisters(m_vdboxIndex)->hcpFrameCrcRegOffset;
}
}
if (!m_mmc)
{
m_mmc = MOS_New(CodecHalMmcState, m_hwInterface);
CODECHAL_DECODE_CHK_NULL_RETURN(m_mmc);
}
if (codecHalSettings->secureMode)
{
m_secureDecoder = Create_SecureDecodeInterface(codecHalSettings, m_hwInterface);
}
#ifdef _DECODE_PROCESSING_SUPPORTED
m_downsamplingHinted = codecHalSettings->downsamplingHinted ? true : false;
if (CodecHalIsEnableFieldScaling(codecHalSettings->codecFunction, m_standard, m_downsamplingHinted))
{
CODECHAL_DECODE_CHK_NULL_RETURN(m_fieldScalingInterface);
CODECHAL_DECODE_CHK_STATUS_RETURN(m_fieldScalingInterface->InitializeKernelState(
this,
m_hwInterface,
m_osInterface));
}
#endif
m_renderContextUsesNullHw = m_useNullHw[m_renderContext];
if(!m_isHybridDecoder)
{
m_videoContextUsesNullHw = m_useNullHw[m_videoContext];
m_videoContextForWaUsesNullHw = m_useNullHw[m_videoContextForWa];
CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnRegisterBBCompleteNotifyEvent(
m_osInterface,
m_videoContext));
}
if (!m_perfProfiler)
{
m_perfProfiler = MediaPerfProfiler::Instance();
CODECHAL_DECODE_CHK_NULL_RETURN(m_perfProfiler);
CODECHAL_DECODE_CHK_STATUS_RETURN(m_perfProfiler->Initialize((void*)this, m_osInterface));
}
return eStatus;
}
MOS_STATUS CodechalDecode::AllocateRefSurfaces(
uint32_t allocWidth,
uint32_t allocHeight,
MOS_FORMAT format)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_DECODE_FUNCTION_ENTER;
if (allocWidth == 0 || allocHeight == 0)
{
CODECHAL_DECODE_ASSERTMESSAGE("Invalid Downsampling Reference Frame Width or Height !");
return MOS_STATUS_INVALID_PARAMETER;
}
m_refSurfaces = (MOS_SURFACE*)MOS_AllocAndZeroMemory(sizeof(MOS_SURFACE) * m_refFrmCnt);
CODECHAL_DECODE_CHK_NULL_RETURN(m_refSurfaces);
CODECHAL_DEBUG_TOOL(
m_downsampledSurfaces = (MOS_SURFACE*)MOS_AllocAndZeroMemory(m_refFrmCnt * sizeof(MOS_SURFACE));
)
for (uint32_t i = 0; i < m_refFrmCnt; i++)
{
eStatus = AllocateSurface(
&m_refSurfaces[i],
allocWidth,
allocHeight,
"DownsamplingRefSurface",
format,
m_mmc->IsMmcEnabled());
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_DECODE_ASSERTMESSAGE("Failed to allocate decode downsampling reference surface.");
DeallocateRefSurfaces();
return eStatus;
}
}
return MOS_STATUS_SUCCESS;
}
bool CodechalDecode::isSyncFreeNeededForMMCSurface(PMOS_SURFACE surface)
{
if (nullptr == surface || nullptr == m_osInterface)
{
return false;
}
//Compressed surface aux table update is after resource dealloction, aux table update need wait the WLs complete
//the sync deallocation flag will make sure deallocation API return after all surface related WL been completed and resource been destroyed by OS
auto *pSkuTable = m_hwInterface->GetSkuTable();
GMM_RESOURCE_FLAG gmmFlags;
bool hasAuxSurf = false;
gmmFlags = (&surface->OsResource)->pGmmResInfo->GetResFlags();
hasAuxSurf = (gmmFlags.Gpu.CCS || gmmFlags.Info.MediaCompressed) && gmmFlags.Gpu.UnifiedAuxSurface;
if (pSkuTable &&
MEDIA_IS_SKU(pSkuTable, FtrE2ECompression) && //Compression enabled platform
!MEDIA_IS_SKU(pSkuTable, FtrFlatPhysCCS) && //NOT DGPU compression
(surface->bCompressible) && ((surface->CompressionMode != MOS_MMC_DISABLED) || hasAuxSurf)) //Compressed enabled surface
{
return true;
}
return false;
}
MOS_STATUS CodechalDecode::DestroySurface(PMOS_SURFACE surface)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MOS_GFXRES_FREE_FLAGS resFreeFlags = {0};
CODECHAL_DECODE_FUNCTION_ENTER;
if (nullptr == surface)
{
return MOS_STATUS_SUCCESS;
}
if (surface && isSyncFreeNeededForMMCSurface(surface))
{
resFreeFlags.SynchronousDestroy = 1;
CODECHAL_DECODE_NORMALMESSAGE("Set SynchronousDestroy flag for compressed resource\n");
}
m_osInterface->pfnFreeResourceWithFlag(m_osInterface, &surface->OsResource, resFreeFlags.Value);
surface = nullptr;
return eStatus;
}
MOS_STATUS CodechalDecode::RefSurfacesResize(
uint32_t frameIdx,
uint32_t width,
uint32_t height,
MOS_FORMAT format)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_DECODE_FUNCTION_ENTER;
if (m_refSurfaces[frameIdx].dwWidth == 0 || m_refSurfaces[frameIdx].dwHeight == 0)
{
CODECHAL_DECODE_ASSERTMESSAGE("Invalid Downsampling Reference Frame Width or Height !");
return MOS_STATUS_INVALID_PARAMETER;
}
DeallocateSpecificRefSurfaces(frameIdx);
eStatus = AllocateSurface(
&m_refSurfaces[frameIdx],
width,
height,
"DownsamplingRefSurface",
format,
m_mmc->IsMmcEnabled());
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_DECODE_ASSERTMESSAGE("Failed to allocate decode downsampling reference surface.");
DeallocateRefSurfaces();
return eStatus;
}
return MOS_STATUS_SUCCESS;
}
void CodechalDecode::DeallocateSpecificRefSurfaces(uint32_t frameIdx)
{
CODECHAL_DECODE_FUNCTION_ENTER;
if (m_refSurfaces != nullptr)
{
if (!Mos_ResourceIsNull(&m_refSurfaces[frameIdx].OsResource))
{
DestroySurface(&m_refSurfaces[frameIdx]);
}
}
}
void CodechalDecode::DeallocateRefSurfaces()
{
CODECHAL_DECODE_FUNCTION_ENTER;
if (m_refSurfaces != nullptr && m_refFrmCnt != 0)
{
CODECHAL_DEBUG_TOOL(
MOS_FreeMemAndSetNull(m_downsampledSurfaces);
)
for (uint32_t i = 0; i < m_refFrmCnt; i++)
{
if (!Mos_ResourceIsNull(&m_refSurfaces[i].OsResource))
{
DestroySurface(&m_refSurfaces[i]);
}
}
MOS_FreeMemory(m_refSurfaces);
m_refSurfaces = nullptr;
}
}
MOS_STATUS CodechalDecode::SetDummyReference()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
if (MEDIA_IS_WA(m_waTable, WaDummyReference))
{
// If can't find valid dummy reference, create one or use current decode output surface
if (Mos_ResourceIsNull(&m_dummyReference.OsResource))
{
// If MMC enabled
if (m_mmc != nullptr && m_mmc->IsMmcEnabled() &&
!m_mmc->IsMmcExtensionEnabled() &&
m_decodeParams.m_destSurface->bIsCompressed)
{
if (m_mode == CODECHAL_DECODE_MODE_HEVCVLD)
{
eStatus = AllocateSurface(
&m_dummyReference,
m_decodeParams.m_destSurface->dwWidth,
m_decodeParams.m_destSurface->dwHeight,
"dummy reference resource",
m_decodeParams.m_destSurface->Format,
m_decodeParams.m_destSurface->bIsCompressed);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_DECODE_ASSERTMESSAGE("Failed to create dummy reference!");
return eStatus;
}
else
{
m_dummyReferenceStatus = CODECHAL_DUMMY_REFERENCE_ALLOCATED;
CODECHAL_DECODE_VERBOSEMESSAGE("Dummy reference is created!");
}
}
}
else // Use decode output surface as dummy reference
{
m_dummyReference.OsResource = m_decodeParams.m_destSurface->OsResource;
m_dummyReferenceStatus = CODECHAL_DUMMY_REFERENCE_DEST_SURFACE;
}
}
}
return eStatus;
}
CodechalDecode::~CodechalDecode()
{
CODECHAL_DECODE_FUNCTION_ENTER;
Delete_SecureDecodeInterface(m_secureDecoder);
m_secureDecoder = nullptr;
if (m_mmc)
{
MOS_Delete(m_mmc);
m_mmc = nullptr;
}
// Destroy decode histogram
if (m_decodeHistogram != nullptr)
{
MOS_Delete(m_decodeHistogram);
m_decodeHistogram = nullptr;
}
if (MEDIA_IS_SKU(m_skuTable, FtrVcs2) && (m_videoGpuNode < MOS_GPU_NODE_MAX))
{
// Destroy decode video node association
m_osInterface->pfnDestroyVideoNodeAssociation(m_osInterface, m_videoGpuNode);
}
if (m_statusQueryReportingEnabled)
{
m_osInterface->pfnUnlockResource(
m_osInterface,
&(m_decodeStatusBuf.m_statusBuffer));
m_osInterface->pfnFreeResource(
m_osInterface,
&(m_decodeStatusBuf.m_statusBuffer));
if (m_streamOutEnabled)
{
for (auto i = 0; i < CODECHAL_DECODE_NUM_STREAM_OUT_BUFFERS; i++)
{
m_osInterface->pfnFreeResource(
m_osInterface,
&(m_streamOutBuffer[i]));
}
}
}
if (m_gpuCtxCreatOpt)
{
MOS_Delete(m_gpuCtxCreatOpt);
}
m_osInterface->pfnFreeResource(
m_osInterface,
&m_predicationBuffer);
DeallocateRefSurfaces();
#ifdef _DECODE_PROCESSING_SUPPORTED
if (CodecHalIsEnableFieldScaling(CODECHAL_FUNCTION_DECODE, m_standard, m_downsamplingHinted))
{
if (m_fieldScalingInterface != nullptr)
{
MOS_Delete(m_fieldScalingInterface);
m_fieldScalingInterface = nullptr;
}
}
#endif
if (m_perfProfiler)
{
MediaPerfProfiler::Destroy(m_perfProfiler, (void*)this, m_osInterface);
m_perfProfiler = nullptr;
}
if (m_dummyReferenceStatus == CODECHAL_DUMMY_REFERENCE_ALLOCATED &&
!Mos_ResourceIsNull(&m_dummyReference.OsResource))
{
m_osInterface->pfnFreeResource(m_osInterface, &m_dummyReference.OsResource);
}
}
void CodechalDecode::CalcRequestedSpace(
uint32_t &requestedSize,
uint32_t &additionalSizeNeeded,
uint32_t &requestedPatchListSize)
{
requestedSize = m_commandBufferSizeNeeded +
(m_standardDecodeSizeNeeded * (m_decodeParams.m_numSlices + 1));
requestedPatchListSize = m_commandPatchListSizeNeeded +
(m_standardDecodePatchListSizeNeeded * (m_decodeParams.m_numSlices + 1));
additionalSizeNeeded = COMMAND_BUFFER_RESERVED_SPACE;
}
MOS_STATUS CodechalDecode::VerifySpaceAvailable ()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_DECODE_FUNCTION_ENTER;
uint32_t requestedSize = 0, additionalSizeNeeded = 0, requestedPatchListSize = 0;
CalcRequestedSpace(requestedSize, additionalSizeNeeded, requestedPatchListSize);
uint32_t primRequestedSize = RequestedSpaceSize(requestedSize);
// Try a maximum of 3 attempts to request the required sizes from OS
// OS could reset the sizes if necessary, therefore, requires to re-verify
for (auto i = 0; i < 3; i++)
{
if (m_osInterface->bUsesPatchList || MEDIA_IS_SKU(m_skuTable, FtrMediaPatchless))
{
eStatus = (MOS_STATUS)m_osInterface->pfnVerifyPatchListSize(
m_osInterface,
requestedPatchListSize);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->ResizeCommandBufferAndPatchList(
0,
requestedPatchListSize));
}
}
eStatus = (MOS_STATUS)m_osInterface->pfnVerifyCommandBufferSize(
m_osInterface,
primRequestedSize,
0);
if (eStatus == MOS_STATUS_SUCCESS)
{
break;
}
else
{
CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->ResizeCommandBufferAndPatchList(
primRequestedSize + additionalSizeNeeded,
0));
}
}
CODECHAL_DECODE_CHK_STATUS_RETURN(VerifyExtraSpace(requestedSize, additionalSizeNeeded));
return eStatus;
}
MOS_STATUS CodechalDecode::EndFrame ()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_DECODE_FUNCTION_ENTER;
CODECHAL_DEBUG_TOOL(
CodechalDecodeStatusReport * decodeStatusReport;
auto tempSurfNum = m_debugInterface->m_decodeSurfDumpFrameNum; // to handle BB_END data not written case
uint16_t preIndex = m_debugInterface->m_preIndex;
uint32_t numReportsAvailable = (m_decodeStatusBuf.m_currIndex - preIndex) & (CODECHAL_DECODE_STATUS_NUM - 1);
CODECHAL_DECODE_VERBOSEMESSAGE("NumReportsAvailable = %d", numReportsAvailable);
for (uint32_t i = 0; i < numReportsAvailable; i++) {
uint16_t index = (m_debugInterface->m_preIndex + i) % CODECHAL_DECODE_STATUS_NUM;
decodeStatusReport =
&(m_decodeStatusBuf.m_decodeStatus[index].m_decodeStatusReport);
// record SurfDumpFrameNum to handle BB_END data not written case
if (CodecHal_PictureIsFrame(decodeStatusReport->m_currDecodedPic) ||
CodecHal_PictureIsInterlacedFrame(decodeStatusReport->m_currDecodedPic) ||
decodeStatusReport->m_secondField)
{
tempSurfNum++;
}
if (m_standard == CODECHAL_HEVC &&
m_isHybridDecoder &&
(m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrReferenceSurfaces)|| m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDecodeOutputSurface)))
{
CODECHAL_DECODE_CHK_STATUS_BREAK(DecodeGetHybridStatus(
m_decodeStatusBuf.m_decodeStatus, index, CODECHAL_STATUS_QUERY_START_FLAG));
}
auto tempFrameNum = m_debugInterface->m_bufferDumpFrameNum;
auto tempPic = m_debugInterface->m_currPic;
auto tempFrameType = m_debugInterface->m_frameType;
m_debugInterface->m_bufferDumpFrameNum = m_debugInterface->m_decodeSurfDumpFrameNum;
m_debugInterface->m_currPic = decodeStatusReport->m_currDecodedPic;
m_debugInterface->m_frameType = decodeStatusReport->m_frameType;
bool olpDump = false;
MOS_SURFACE dstSurface;
if ((CodecHal_PictureIsFrame(decodeStatusReport->m_currDecodedPic) ||
CodecHal_PictureIsInterlacedFrame(decodeStatusReport->m_currDecodedPic) ||
CodecHal_PictureIsField(decodeStatusReport->m_currDecodedPic)) &&
(m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDecodeBltOutput) ||
m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDecodeOutputSurface) ||
m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrStreamOut)))
{
MOS_ZeroMemory(&dstSurface, sizeof(dstSurface));
dstSurface.Format = Format_NV12;
dstSurface.OsResource = decodeStatusReport->m_currDecodedPicRes;
CODECHAL_DECODE_CHK_STATUS_BREAK(CodecHalGetResourceInfo(
m_osInterface,
&dstSurface));
m_debugInterface->DumpBltOutput(
&dstSurface,
CodechalDbgAttr::attrDecodeBltOutput);
CODECHAL_DECODE_CHK_STATUS_BREAK(m_debugInterface->DumpYUVSurface(
&dstSurface,
CodechalDbgAttr::attrDecodeOutputSurface,
"DstSurf"));
if (m_streamOutEnabled)
{
//dump streamout buffer
CODECHAL_DECODE_CHK_STATUS_BREAK(m_debugInterface->DumpBuffer(
decodeStatusReport->m_streamOutBuf,
CodechalDbgAttr::attrStreamOut,
"StreamOut",
dstSurface.dwWidth));
// reset the capture status of the streamout buffer
m_streamOutCurrStatusIdx[decodeStatusReport->m_streamoutIdx] = CODECHAL_DECODE_STATUS_NUM;
}
olpDump = true;
}
MOS_USER_FEATURE_VALUE_DATA userFeatureData;
MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
MOS_UserFeature_ReadValue_ID(
nullptr,
__MEDIA_USER_FEATURE_VALUE_DECOMPRESS_DECODE_OUTPUT_ID,
&userFeatureData,
m_osInterface->pOsContext);
if (userFeatureData.u32Data)
{
CODECHAL_DECODE_VERBOSEMESSAGE("force ve decompress decode output");
MOS_ZeroMemory(&dstSurface, sizeof(dstSurface));
dstSurface.Format = Format_NV12;
dstSurface.OsResource = decodeStatusReport->m_currDecodedPicRes;
CODECHAL_DECODE_CHK_STATUS_BREAK(CodecHalGetResourceInfo(
m_osInterface,
&dstSurface));
MOS_LOCK_PARAMS lockFlags {};
lockFlags.ReadOnly = 1;
lockFlags.TiledAsTiled = 1;
lockFlags.NoDecompress = 0;
m_osInterface->pfnLockResource(m_osInterface, &dstSurface.OsResource, &lockFlags);
m_osInterface->pfnUnlockResource(m_osInterface, &dstSurface.OsResource);
}
if (m_standard == CODECHAL_VC1 &&
decodeStatusReport->m_olpNeeded &&
olpDump &&
m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDecodeOutputSurface))
{
MOS_ZeroMemory(&dstSurface, sizeof(dstSurface));
dstSurface.Format = Format_NV12;
dstSurface.OsResource = decodeStatusReport->m_deblockedPicResOlp;
CODECHAL_DECODE_CHK_STATUS_BREAK(CodecHalGetResourceInfo(
m_osInterface,
&dstSurface));
CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
&dstSurface,
CodechalDbgAttr::attrDecodeOutputSurface,
"OLP_DstSurf"));
}
if ((m_standard == CODECHAL_HEVC || m_standard == CODECHAL_VP9) &&
(decodeStatusReport->m_currSfcOutputPicRes != nullptr) &&
m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSfcOutputSurface))
{
MOS_ZeroMemory(&dstSurface, sizeof(dstSurface));
dstSurface.Format = Format_NV12;
dstSurface.OsResource = *decodeStatusReport->m_currSfcOutputPicRes;
CODECHAL_DECODE_CHK_STATUS_BREAK(CodecHalGetResourceInfo(
m_osInterface,
&dstSurface));
CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
&dstSurface,
CodechalDbgAttr::attrSfcOutputSurface,
"SfcDstSurf"));
}
MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
MOS_UserFeature_ReadValue_ID(
nullptr,
__MEDIA_USER_FEATURE_VALUE_DECOMPRESS_DECODE_SFC_OUTPUT_ID,
&userFeatureData,
m_osInterface->pOsContext);
if (userFeatureData.u32Data)
{
CODECHAL_DECODE_VERBOSEMESSAGE("force ve decompress sfc output");
MOS_ZeroMemory(&dstSurface, sizeof(dstSurface));
dstSurface.Format = Format_NV12;
dstSurface.OsResource = *decodeStatusReport->m_currSfcOutputPicRes;
CODECHAL_DECODE_CHK_STATUS_BREAK(CodecHalGetResourceInfo(
m_osInterface,
&dstSurface));
MOS_LOCK_PARAMS lockFlags {};
lockFlags.ReadOnly = 1;
lockFlags.TiledAsTiled = 1;
lockFlags.NoDecompress = 0;
m_osInterface->pfnLockResource(m_osInterface, &dstSurface.OsResource, &lockFlags);
m_osInterface->pfnUnlockResource(m_osInterface, &dstSurface.OsResource);
}
if (CodecHal_PictureIsFrame(decodeStatusReport->m_currDecodedPic) ||
CodecHal_PictureIsInterlacedFrame(decodeStatusReport->m_currDecodedPic) ||
CodecHal_PictureIsField(decodeStatusReport->m_currDecodedPic))
{
CODECHAL_DECODE_CHK_STATUS_BREAK(m_debugInterface->DeleteCfgLinkNode(m_debugInterface->m_decodeSurfDumpFrameNum));
m_debugInterface->m_decodeSurfDumpFrameNum = tempSurfNum;
}
m_debugInterface->m_bufferDumpFrameNum = tempFrameNum;
m_debugInterface->m_currPic = tempPic;
m_debugInterface->m_frameType = tempFrameType;
if (m_decodeStatusBuf.m_decodeStatus[index].m_hwStoredData == CODECHAL_STATUS_QUERY_END_FLAG)
{
// report the CS Engine ID to user feature
for (auto j = 0; j < CODECHAL_CS_INSTANCE_ID_MAX; j++)
{
CODECHAL_CS_ENGINE_ID csEngineIdValue;
csEngineIdValue.value = m_decodeStatusBuf.m_decodeStatus[index].m_mmioCsEngineIdReg[j];
//validate the user feature value
if (csEngineIdValue.value)
{
CODECHAL_DECODE_ASSERT(csEngineIdValue.fields.ClassId == CODECHAL_CLASS_ID_VIDEO_ENGINE);
CODECHAL_DECODE_ASSERT(csEngineIdValue.fields.InstanceId < CODECHAL_CS_INSTANCE_ID_MAX);
CODECHAL_UPDATE_USED_VDBOX_ID_USER_FEATURE(csEngineIdValue.fields.InstanceId, m_osInterface->pOsContext);
}
}
preIndex = index + 1;
}
}
m_debugInterface->m_preIndex = preIndex;
)
if (m_consecutiveMbErrorConcealmentInUse &&
m_incompletePicture)
{
CODECHAL_DECODE_VERBOSEMESSAGE("Processing incomplete frame MBs");
if (!m_isHybridDecoder)
{
m_osInterface->pfnSetGpuContext(m_osInterface, m_videoContext);
}
m_decodePhantomMbs = true;
CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(DecodePrimitiveLevel(),
"Primitive level decoding failed.");
}
m_decodePhantomMbs = false;
return eStatus;
}
MOS_STATUS CodechalDecode::Execute(void *params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
PERF_UTILITY_AUTO(__FUNCTION__, PERF_DECODE, PERF_LEVEL_HAL);
CODECHAL_DECODE_FUNCTION_ENTER;
CODECHAL_DECODE_CHK_STATUS_RETURN(Codechal::Execute(params));
CodechalDecodeParams *decodeParams = (CodechalDecodeParams *)params;
m_executeCallIndex = decodeParams->m_executeCallIndex;
// MSDK event handling
Mos_Solo_SetGpuAppTaskEvent(m_osInterface, decodeParams->m_gpuAppTaskEvent);
#if (_DEBUG || _RELEASE_INTERNAL)
MOS_TraceEvent(EVENT_CODEC_DECODE, EVENT_TYPE_START, &m_standard, sizeof(uint32_t), &m_frameNum, sizeof(uint32_t));
#endif // _DEBUG || _RELEASE_INTERNAL
CODECHAL_DEBUG_TOOL(
m_debugInterface->m_bufferDumpFrameNum = m_frameNum;)
if (m_cencBuf!= nullptr)
{
CODECHAL_DECODE_CHK_STATUS_RETURN(Mos_Solo_DisableAubcaptureOptimizations(
m_osInterface,
IsFirstExecuteCall()));
}
#ifdef _DECODE_PROCESSING_SUPPORTED
if (decodeParams->m_refFrameCnt != 0)
{
DecodeProcessingParams *procParams;
uint32_t allocWidth;
uint32_t allocHeight;
MOS_FORMAT format;
uint8_t frameIdx;
CODECHAL_DECODE_CHK_NULL_RETURN(decodeParams->m_picParams);
CODECHAL_DECODE_CHK_NULL_RETURN(decodeParams->m_procParams);
procParams = (DecodeProcessingParams *)decodeParams->m_procParams;
CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(
m_osInterface,
procParams->m_outputSurface));
if (procParams->m_isSourceSurfAllocated)
{
procParams->m_outputSurfaceRegion.m_width = procParams->m_outputSurface->dwWidth;
procParams->m_outputSurfaceRegion.m_height = procParams->m_outputSurface->dwHeight;
frameIdx = 0;
m_refSurfaces = procParams->m_inputSurface;
CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(
m_osInterface,
m_refSurfaces));
procParams->m_inputSurfaceRegion.m_x = 0;
procParams->m_inputSurfaceRegion.m_y = 0;
procParams->m_inputSurfaceRegion.m_width = m_refSurfaces->dwWidth;
procParams->m_inputSurfaceRegion.m_height = m_refSurfaces->dwHeight;
}
else
{
CODECHAL_DECODE_CHK_STATUS_RETURN(CalcDownsamplingParams(
decodeParams->m_picParams, &allocWidth, &allocHeight, &format, &frameIdx));
if (frameIdx >= decodeParams->m_refFrameCnt)
{
CODECHAL_DECODE_ASSERTMESSAGE("Invalid Downsampling Reference Frame Index !");
return MOS_STATUS_INVALID_PARAMETER;
}
if (m_refSurfaces == nullptr)
{
m_refFrmCnt = decodeParams->m_refFrameCnt;
CODECHAL_DECODE_CHK_STATUS_RETURN(AllocateRefSurfaces(allocWidth, allocHeight, format));
}
else
{
PMOS_SURFACE currSurface = &m_refSurfaces[frameIdx];
if (currSurface->dwHeight < allocHeight || currSurface->dwWidth < allocWidth)
{
CODECHAL_DECODE_CHK_STATUS_RETURN(RefSurfacesResize(frameIdx, allocWidth, allocHeight, format));
}
}
procParams->m_inputSurfaceRegion.m_x = 0;
procParams->m_inputSurfaceRegion.m_y = 0;
procParams->m_inputSurfaceRegion.m_width = allocWidth;
procParams->m_inputSurfaceRegion.m_height = allocHeight;
procParams->m_inputSurface = &m_refSurfaces[frameIdx];
}
decodeParams->m_destSurface = &m_refSurfaces[frameIdx];
}
#endif
m_decodeParams = *decodeParams;
CODECHAL_DECODE_CHK_STATUS_RETURN(Mos_Solo_PreProcessDecode(
m_osInterface,
m_decodeParams.m_destSurface));
CODECHAL_DECODE_CHK_STATUS_RETURN(m_cpInterface->UpdateParams(true));
CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(
m_osInterface,
decodeParams->m_destSurface));
if(!m_isHybridDecoder)
{
CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(
m_osInterface,
m_videoContext));
}
if (!m_incompletePicture)
{
m_osInterface->pfnResetOsStates(m_osInterface);
}
CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(SetFrameStates(),
"Decoding initialization failed.");
CODECHAL_DECODE_CHK_STATUS_RETURN(VerifySpaceAvailable());
CODECHAL_DECODE_CHK_STATUS_RETURN(SetDummyReference());
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->SetWatchdogTimerThreshold(m_width, m_height, false));
if ((!m_incompletePicture) && (!m_isHybridDecoder))
{
m_osInterface->pfnIncPerfFrameID(m_osInterface);
m_osInterface->pfnSetPerfTag(
m_osInterface,
(uint16_t)(((m_mode << 4) & 0xF0) | (m_perfType & 0xF)));
m_osInterface->pfnResetPerfBufferID(m_osInterface);
}
CODECHAL_DEBUG_TOOL(
if (decodeParams->m_dataBuffer &&
(m_standard != CODECHAL_JPEG && m_cencBuf == nullptr) &&
!(m_standard == CODECHAL_HEVC && m_isHybridDecoder) &&
!(m_standard == CODECHAL_HEVC && (m_incompletePicture || !IsFirstExecuteCall())))
{
if (m_mode == CODECHAL_DECODE_MODE_MPEG2VLD ||
m_mode == CODECHAL_DECODE_MODE_VC1VLD ||
m_mode == CODECHAL_DECODE_MODE_AVCVLD ||
m_mode == CODECHAL_DECODE_MODE_VP8VLD ||
m_mode == CODECHAL_DECODE_MODE_HEVCVLD ||
m_mode == CODECHAL_DECODE_MODE_VP9VLD)
{
CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
decodeParams->m_dataBuffer,
CodechalDbgAttr::attrBitstream,
"_DEC",
decodeParams->m_dataSize,
decodeParams->m_dataOffset,
CODECHAL_NUM_MEDIA_STATES
));
}
else
{
// Dump ResidualDifference
CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
decodeParams->m_dataBuffer,
CodechalDbgAttr::attrResidualDifference,
"_DEC",
decodeParams->m_dataSize));
}
}
)
#ifdef _DECODE_PROCESSING_SUPPORTED
CODECHAL_DEBUG_TOOL(
if (decodeParams->m_procParams)
{
CODECHAL_DECODE_CHK_STATUS_RETURN(DumpProcessingParams(
(DecodeProcessingParams *)decodeParams->m_procParams));
}
)
#endif
for(auto i = 0; i < m_decodePassNum; i++)
{
if (!m_incompletePicture)
{
CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(DecodeStateLevel(),
"State level decoding failed.");
}
CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(DecodePrimitiveLevel(),
"Primitive level decoding failed.");
}
if (m_secureDecoder != nullptr)
{
CODECHAL_DECODE_CHK_STATUS_RETURN(m_secureDecoder->UpdateHuCStreamoutBufferIndex());
}
*decodeParams = m_decodeParams;
if (m_decodeHistogram != nullptr)
{
CODECHAL_DECODE_CHK_STATUS_RETURN(m_decodeHistogram->RenderHistogram(this, m_decodeParams.m_destSurface));
}
//#if (_DEBUG || _RELEASE_INTERNAL)
//#ifdef _MD5_DEBUG_SUPPORTED
// if (CodecHal_PictureIsFrame(m_debugInterface->CurrPic) ||
// CodecHal_PictureIsInterlacedFrame(m_debugInterface->CurrPic) ||
// m_debugInterface->bSecondField ||
// m_isHybridDecoder)
// {
// if (m_debugInterface->pMD5Context != nullptr)
// {
// if (m_debugInterface->bMD5DDIThreadExecute)
// {
// //calculate md5 hash for each RT surface
// CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHal_DbgExecuteMD5Hash(
// m_debugInterface,
// &decodeParams->m_destSurface->OsResource,
// nullptr,
// 0,
// 0));
// }
// }
// }
//#endif // _MD5_DEBUG_SUPPORTED
//#endif // _DEBUG || _RELEASE_INTERNAL
CODECHAL_DEBUG_TOOL(
if (CodecHal_PictureIsFrame(m_debugInterface->m_currPic) ||
CodecHal_PictureIsInterlacedFrame(m_debugInterface->m_currPic) ||
m_debugInterface->m_secondField) {
if (!m_statusQueryReportingEnabled)
{
CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DeleteCfgLinkNode(m_debugInterface->m_bufferDumpFrameNum));
}
})
if (CodecHal_PictureIsFrame(m_crrPic) ||
CodecHal_PictureIsInterlacedFrame(m_crrPic) ||
m_secondField)
{
m_frameNum++;
}
CODECHAL_DECODE_CHK_STATUS_RETURN(Mos_Solo_PostProcessDecode(m_osInterface, m_decodeParams.m_destSurface));
#if (_DEBUG || _RELEASE_INTERNAL)
MOS_TraceEvent(EVENT_CODEC_DECODE, EVENT_TYPE_END, &eStatus, sizeof(eStatus), nullptr, 0);
#endif // _DEBUG || _RELEASE_INTERNAL
return eStatus;
}
MOS_STATUS CodechalDecode::StartStatusReport(
PMOS_COMMAND_BUFFER cmdBuffer)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_DECODE_FUNCTION_ENTER;
CODECHAL_DECODE_CHK_NULL_RETURN(cmdBuffer);
uint32_t offset =
(m_decodeStatusBuf.m_currIndex * sizeof(CodechalDecodeStatus)) +
m_decodeStatusBuf.m_storeDataOffset +
sizeof(uint32_t) * 2;
MHW_MI_STORE_DATA_PARAMS params;
params.pOsResource = &m_decodeStatusBuf.m_statusBuffer;
params.dwResourceOffset = offset;
params.dwValue = CODECHAL_STATUS_QUERY_START_FLAG;
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(
cmdBuffer,
&params));
CODECHAL_DECODE_CHK_STATUS_RETURN(m_perfProfiler->AddPerfCollectStartCmd((void *)this, m_osInterface, m_miInterface, cmdBuffer));
CODECHAL_DECODE_CHK_STATUS_RETURN(NullHW::StartPredicate(m_miInterface, cmdBuffer));
return eStatus;
}
MOS_STATUS CodechalDecode::EndStatusReport(
CodechalDecodeStatusReport &decodeStatusReport,
PMOS_COMMAND_BUFFER cmdBuffer)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_DECODE_FUNCTION_ENTER;
CODECHAL_DECODE_CHK_COND_RETURN((m_vdboxIndex > m_mfxInterface->GetMaxVdboxIndex()),
"ERROR - vdbox index exceed the maximum");
auto mmioRegistersMfx = m_hwInterface->SelectVdboxAndGetMmioRegister(m_vdboxIndex, cmdBuffer);
auto mmioRegistersHcp = m_hcpInterface ? m_hcpInterface->GetMmioRegisters(m_vdboxIndex) : nullptr;
CODECHAL_DECODE_CHK_STATUS_RETURN(NullHW::StopPredicate(m_miInterface, cmdBuffer));
uint32_t currIndex = m_decodeStatusBuf.m_currIndex;
//Error Status report
uint32_t errStatusOffset =
currIndex * sizeof(CodechalDecodeStatus) +
m_decodeStatusBuf.m_decErrorStatusOffset +
sizeof(uint32_t) * 2;
MHW_MI_STORE_REGISTER_MEM_PARAMS regParams;
regParams.presStoreBuffer = &m_decodeStatusBuf.m_statusBuffer;
regParams.dwOffset = errStatusOffset;
regParams.dwRegister = ((m_standard == CODECHAL_HEVC || m_standard == CODECHAL_VP9) && mmioRegistersHcp) ?
mmioRegistersHcp->hcpCabacStatusRegOffset : mmioRegistersMfx->mfxErrorFlagsRegOffset;
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(
cmdBuffer,
&regParams));
//Frame CRC
if (m_reportFrameCrc)
{
uint32_t frameCrcOffset =
currIndex * sizeof(CodechalDecodeStatus) +
m_decodeStatusBuf.m_decFrameCrcOffset +
sizeof(uint32_t) * 2;
regParams.presStoreBuffer = &m_decodeStatusBuf.m_statusBuffer;
regParams.dwOffset = frameCrcOffset;
if (m_standard == CODECHAL_AVC)
{
regParams.dwRegister = mmioRegistersMfx->mfxFrameCrcRegOffset;
}
else if(m_standard == CODECHAL_HEVC)
{
regParams.dwRegister = m_hcpFrameCrcRegOffset;
}
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(
cmdBuffer,
&regParams));
}
//MB Count
uint32_t mbCountOffset =
currIndex * sizeof(CodechalDecodeStatus) +
m_decodeStatusBuf.m_decMBCountOffset +
sizeof(uint32_t) * 2;
regParams.presStoreBuffer = &m_decodeStatusBuf.m_statusBuffer;
regParams.dwOffset = mbCountOffset;
regParams.dwRegister = ((m_standard == CODECHAL_HEVC || m_standard == CODECHAL_VP9) && mmioRegistersHcp) ?
mmioRegistersHcp->hcpDecStatusRegOffset : mmioRegistersMfx->mfxMBCountRegOffset;
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(
cmdBuffer,
&regParams));
// First copy all the SW data in to the eStatus buffer
m_decodeStatusBuf.m_decodeStatus[currIndex].m_swStoredData = m_decodeStatusBuf.m_swStoreData;
m_decodeStatusBuf.m_decodeStatus[currIndex].m_decodeStatusReport = decodeStatusReport;
uint32_t storeDataOffset =
currIndex * sizeof(CodechalDecodeStatus) +
m_decodeStatusBuf.m_storeDataOffset +
sizeof(uint32_t) * 2;
MHW_MI_STORE_DATA_PARAMS dataParams;
dataParams.pOsResource = &m_decodeStatusBuf.m_statusBuffer;
dataParams.dwResourceOffset = storeDataOffset;
dataParams.dwValue = CODECHAL_STATUS_QUERY_END_FLAG;
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(
cmdBuffer,
&dataParams));
m_decodeStatusBuf.m_currIndex = (m_decodeStatusBuf.m_currIndex + 1) % CODECHAL_DECODE_STATUS_NUM;
CodechalDecodeStatus *decodeStatus = &m_decodeStatusBuf.m_decodeStatus[m_decodeStatusBuf.m_currIndex];
MOS_ZeroMemory(decodeStatus, sizeof(CodechalDecodeStatus));
CODECHAL_DECODE_CHK_STATUS_RETURN(m_perfProfiler->AddPerfCollectEndCmd((void*)this, m_osInterface, m_miInterface, cmdBuffer));
if (!m_osInterface->bEnableKmdMediaFrameTracking && m_osInterface->bInlineCodecStatusUpdate)
{
MHW_MI_FLUSH_DW_PARAMS flushDwParams;
// Send MI_FLUSH with protection bit off, which will FORCE exit protected mode for MFX
MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
flushDwParams.bVideoPipelineCacheInvalidate = true;
flushDwParams.pOsResource = &m_decodeStatusBuf.m_statusBuffer;
flushDwParams.dwDataDW1 = m_decodeStatusBuf.m_swStoreData;
MHW_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
cmdBuffer,
&flushDwParams));
}
return eStatus;
}
MOS_STATUS CodechalDecode::ResetStatusReport(
bool nullHwInUse)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_DECODE_FUNCTION_ENTER;
if (!m_osInterface->bEnableKmdMediaFrameTracking &&
!m_osInterface->bInlineCodecStatusUpdate)
{
MOS_COMMAND_BUFFER cmdBuffer;
CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(
m_osInterface,
&cmdBuffer,
0));
// initialize command buffer attributes
cmdBuffer.Attributes.bTurboMode = m_hwInterface->m_turboMode;
CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(
&cmdBuffer,
false));
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(
&cmdBuffer,
nullptr));
m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(
m_osInterface,
&cmdBuffer,
nullHwInUse));
}
m_decodeStatusBuf.m_swStoreData++;
return eStatus;
}
MOS_STATUS CodechalDecode::GetStatusReport(
void *status,
uint16_t numStatus)
{
uint16_t reportsGenerated = 0;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_DECODE_FUNCTION_ENTER;
CODECHAL_DECODE_CHK_NULL_RETURN(status);
CodechalDecodeStatusReport *codecStatus = (CodechalDecodeStatusReport *)status;
uint32_t numReportsAvailable =
(m_decodeStatusBuf.m_currIndex - m_decodeStatusBuf.m_firstIndex) &
(CODECHAL_DECODE_STATUS_NUM - 1);
uint32_t globalHWStoredData = *(m_decodeStatusBuf.m_data);
uint32_t globalCount = m_decodeStatusBuf.m_swStoreData - globalHWStoredData;
CODECHAL_DECODE_VERBOSEMESSAGE(" numStatus = %d, numReportsAvailable = %d.",
numStatus, numReportsAvailable);
CODECHAL_DECODE_VERBOSEMESSAGE(" HWStoreData = %d, globalCount = %d",
globalHWStoredData, globalCount);
if (numReportsAvailable < numStatus)
{
for (auto i = numReportsAvailable ; i < numStatus && i < CODECHAL_DECODE_STATUS_NUM ; i ++)
{
// These buffers are not yet received by driver. Just don't report anything back.
codecStatus[i].m_codecStatus = CODECHAL_STATUS_UNAVAILABLE;
}
numStatus = (uint16_t)numReportsAvailable;
}
if (numReportsAvailable == 0)
{
CODECHAL_DECODE_ASSERTMESSAGE("No reports available, m_currIndex = %d, m_firstIndex = %d",
m_decodeStatusBuf.m_currIndex,
m_decodeStatusBuf.m_firstIndex);
return eStatus;
}
if (m_videoContextUsesNullHw ||
m_videoContextForWaUsesNullHw ||
m_renderContextUsesNullHw)
{
for (auto j = 0 ; j < numStatus ; j++)
{
uint32_t i = (m_decodeStatusBuf.m_firstIndex + numStatus - j - 1) & (CODECHAL_DECODE_STATUS_NUM - 1);
codecStatus[j] = m_decodeStatusBuf.m_decodeStatus[i].m_decodeStatusReport;
codecStatus[j].m_codecStatus = CODECHAL_STATUS_SUCCESSFUL;
reportsGenerated++;
}
m_decodeStatusBuf.m_firstIndex =
(m_decodeStatusBuf.m_firstIndex + reportsGenerated) % CODECHAL_DECODE_STATUS_NUM;
return eStatus;
}
// Report eStatus in reverse temporal order
for (auto j = 0; j < numStatus; j ++)
{
uint32_t i = (m_decodeStatusBuf.m_firstIndex + numStatus - j - 1) & (CODECHAL_DECODE_STATUS_NUM - 1);
CodechalDecodeStatusReport decodeStatusReport = m_decodeStatusBuf.m_decodeStatus[i].m_decodeStatusReport;
uint32_t localCount = m_decodeStatusBuf.m_decodeStatus[i].m_swStoredData - globalHWStoredData;
if (m_isHybridDecoder)
{
codecStatus[j] = decodeStatusReport;
// Consider the decode finished if the event dosen't present.
CODECHAL_DECODE_CHK_STATUS_RETURN(DecodeGetHybridStatus(
m_decodeStatusBuf.m_decodeStatus, i, CODECHAL_STATUS_QUERY_END_FLAG));
if (m_decodeStatusBuf.m_decodeStatus[i].m_hwStoredData == CODECHAL_STATUS_QUERY_END_FLAG)
{
codecStatus[j].m_codecStatus = CODECHAL_STATUS_SUCCESSFUL;
reportsGenerated ++;
}
else
{
codecStatus[j].m_codecStatus = CODECHAL_STATUS_INCOMPLETE;
}
}
else
{
if (localCount == 0 || localCount > globalCount)
{
codecStatus[j] = decodeStatusReport;
// HW execution of these commands is complete.
if (m_osInterface->pfnIsGPUHung(m_osInterface))
{
codecStatus[j].m_codecStatus = CODECHAL_STATUS_INCOMPLETE;
}
else if (m_decodeStatusBuf.m_decodeStatus[i].m_hwStoredData == CODECHAL_STATUS_QUERY_END_FLAG)
{
// No problem in execution
codecStatus[j].m_codecStatus = CODECHAL_STATUS_SUCCESSFUL;
if (m_standard == CODECHAL_HEVC || m_standard == CODECHAL_VP9)
{
if ((m_decodeStatusBuf.m_decodeStatus[i].m_mmioErrorStatusReg &
m_hcpInterface->GetHcpCabacErrorFlagsMask()) != 0)
{
codecStatus[j].m_codecStatus = CODECHAL_STATUS_ERROR;
codecStatus[j].m_numMbsAffected =
(m_decodeStatusBuf.m_decodeStatus[i].m_mmioMBCountReg & 0xFFFC0000) >> 18;
}
if (m_reportFrameCrc)
{
codecStatus[j].m_frameCrc = m_decodeStatusBuf.m_decodeStatus[i].m_mmioFrameCrcReg;
CODECHAL_DECODE_NORMALMESSAGE("HCP CRC:: %d\n", codecStatus[j].m_frameCrc);
}
}
else
{
// Check to see if decoding error occurs
if (m_standard != CODECHAL_JPEG)
{
if ((m_decodeStatusBuf.m_decodeStatus[i].m_mmioErrorStatusReg &
m_mfxInterface->GetMfxErrorFlagsMask()) != 0)
{
codecStatus[j].m_codecStatus = CODECHAL_STATUS_ERROR;
}
//MB Count bit[15:0] is error concealment MB count for none JPEG decoder.
codecStatus[j].m_numMbsAffected =
m_decodeStatusBuf.m_decodeStatus[i].m_mmioMBCountReg & 0xFFFF;
}
if (m_standard == CODECHAL_AVC)
{
codecStatus[j].m_frameCrc = m_decodeStatusBuf.m_decodeStatus[i].m_mmioFrameCrcReg;
}
}
}
else if (m_decodeStatusBuf.m_decodeStatus[i].m_hwStoredData == CODECHAL_STATUS_QUERY_SKIPPED)
{
// In the case of AVC PR3.0 it is possible to drop a batch buffer execution
CODECHAL_DECODE_NORMALMESSAGE("Decode skipped.");
codecStatus[j].m_codecStatus = CODECHAL_STATUS_SUCCESSFUL;
}
else
{
// BB_END data not written. Media reset might have occurred.
CODECHAL_DECODE_NORMALMESSAGE("Media reset may have occured.");
codecStatus[j].m_codecStatus = CODECHAL_STATUS_ERROR;
}
if (m_standard == CODECHAL_HEVC)
{
// Print HuC_Status and HuC_Status2 registers
CODECHAL_DECODE_VERBOSEMESSAGE("Index = %d", i);
CODECHAL_DECODE_VERBOSEMESSAGE("HUC_STATUS register = 0x%x",
m_decodeStatusBuf.m_decodeStatus[i].m_hucErrorStatus >> 32);
CODECHAL_DECODE_VERBOSEMESSAGE("HUC_STATUS2 register = 0x%x",
m_decodeStatusBuf.m_decodeStatus[i].m_hucErrorStatus2 >> 32);
}
CODECHAL_DECODE_VERBOSEMESSAGE("Incrementing reports generated to %d.",
(reportsGenerated + 1));
reportsGenerated ++;
}
else
{
CODECHAL_DECODE_VERBOSEMESSAGE("status buffer %d is INCOMPLETE.", j);
codecStatus[j] = decodeStatusReport;
codecStatus[j].m_codecStatus = CODECHAL_STATUS_INCOMPLETE;
if(m_osInterface->bInlineCodecStatusUpdate)
{
// In Linux/Android, inline decode status reporting is enabled.
// If still received CODECHAL_STATUS_INCOMPLETE,
// it will be treat as GPU Hang. so need generate a report.
reportsGenerated ++;
}
}
}
}
m_decodeStatusBuf.m_firstIndex =
(m_decodeStatusBuf.m_firstIndex + reportsGenerated) % CODECHAL_DECODE_STATUS_NUM;
CODECHAL_DECODE_VERBOSEMESSAGE("m_firstIndex now becomes %d.", m_decodeStatusBuf.m_firstIndex);
return eStatus;
}
MOS_STATUS CodechalDecode::SendPrologWithFrameTracking(
PMOS_COMMAND_BUFFER cmdBuffer,
bool frameTrackingRequested)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_DECODE_FUNCTION_ENTER;
CODECHAL_DECODE_CHK_NULL_RETURN(cmdBuffer);
MOS_GPU_CONTEXT gpuContext = m_osInterface->pfnGetGpuContext(m_osInterface);
// Send Start Marker command
if (m_decodeParams.m_setMarkerEnabled)
{
CODECHAL_DECODE_CHK_STATUS_RETURN(SendMarkerCommand(cmdBuffer, MOS_RCS_ENGINE_USED(gpuContext)));
}
if (frameTrackingRequested)
{
// initialize command buffer attributes
cmdBuffer->Attributes.bTurboMode = m_hwInterface->m_turboMode;
cmdBuffer->Attributes.bMediaPreemptionEnabled = MOS_RCS_ENGINE_USED(gpuContext) ?
m_hwInterface->GetRenderInterface()->IsPreemptionEnabled() : 0;
cmdBuffer->Attributes.bEnableMediaFrameTracking = true;
cmdBuffer->Attributes.resMediaFrameTrackingSurface = &m_decodeStatusBuf.m_statusBuffer;
cmdBuffer->Attributes.dwMediaFrameTrackingTag = m_decodeStatusBuf.m_swStoreData;
// Set media frame tracking address offset(the offset from the decoder status buffer page, refer to CodecHalDecode_Initialize)
cmdBuffer->Attributes.dwMediaFrameTrackingAddrOffset = 0;
}
CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SendPrologCmd(m_miInterface, cmdBuffer, gpuContext));
MHW_GENERIC_PROLOG_PARAMS genericPrologParams;
MOS_ZeroMemory(&genericPrologParams, sizeof(genericPrologParams));
genericPrologParams.pOsInterface = m_osInterface;
genericPrologParams.pvMiInterface = m_miInterface;
genericPrologParams.bMmcEnabled = m_mmc->IsMmcEnabled();
CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_SendGenericPrologCmd(
cmdBuffer,
&genericPrologParams));
// Send predication command
if (m_decodeParams.m_predicationEnabled)
{
CODECHAL_DECODE_CHK_STATUS_RETURN(SendPredicationCommand(
cmdBuffer));
}
return eStatus;
}
MOS_STATUS CodechalDecode::SendPredicationCommand(
PMOS_COMMAND_BUFFER cmdBuffer)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_DECODE_FUNCTION_ENTER;
CODECHAL_DECODE_CHK_NULL_RETURN(cmdBuffer);
CODECHAL_DECODE_CHK_NULL_RETURN(m_miInterface);
MHW_MI_CONDITIONAL_BATCH_BUFFER_END_PARAMS condBBEndParams;
MOS_ZeroMemory(&condBBEndParams, sizeof(condBBEndParams));
// Skip current frame if presPredication is not equal to zero
if (m_decodeParams.m_predicationNotEqualZero)
{
auto mmioRegistersMfx = m_hwInterface->SelectVdboxAndGetMmioRegister(m_vdboxIndex, cmdBuffer);
MHW_MI_FLUSH_DW_PARAMS flushDwParams;
MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(cmdBuffer, &flushDwParams));
// load presPredication to general purpose register0
MHW_MI_STORE_REGISTER_MEM_PARAMS loadRegisterMemParams;
MOS_ZeroMemory(&loadRegisterMemParams, sizeof(loadRegisterMemParams));
loadRegisterMemParams.presStoreBuffer = m_decodeParams.m_presPredication;
loadRegisterMemParams.dwOffset = (uint32_t)m_decodeParams.m_predicationResOffset;
loadRegisterMemParams.dwRegister = mmioRegistersMfx->generalPurposeRegister0LoOffset;
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterMemCmd(
cmdBuffer,
&loadRegisterMemParams));
MHW_MI_LOAD_REGISTER_IMM_PARAMS loadRegisterImmParams;
MOS_ZeroMemory(&loadRegisterImmParams, sizeof(loadRegisterImmParams));
loadRegisterImmParams.dwData = 0;
loadRegisterImmParams.dwRegister = mmioRegistersMfx->generalPurposeRegister0HiOffset;
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(
cmdBuffer,
&loadRegisterImmParams));
// load 0 to general purpose register4
MOS_ZeroMemory(&loadRegisterImmParams, sizeof(loadRegisterImmParams));
loadRegisterImmParams.dwData = 0;
loadRegisterImmParams.dwRegister = mmioRegistersMfx->generalPurposeRegister4LoOffset;
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(
cmdBuffer,
&loadRegisterImmParams));
MOS_ZeroMemory(&loadRegisterImmParams, sizeof(loadRegisterImmParams));
loadRegisterImmParams.dwData = 0;
loadRegisterImmParams.dwRegister = mmioRegistersMfx->generalPurposeRegister4HiOffset;
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiLoadRegisterImmCmd(
cmdBuffer,
&loadRegisterImmParams));
//perform the add operation
MHW_MI_MATH_PARAMS miMathParams;
MHW_MI_ALU_PARAMS miAluParams[4];
MOS_ZeroMemory(&miMathParams, sizeof(miMathParams));
MOS_ZeroMemory(&miAluParams, sizeof(miAluParams));
// load srcA, reg0
miAluParams[0].AluOpcode = MHW_MI_ALU_LOAD;
miAluParams[0].Operand1 = MHW_MI_ALU_SRCA;
miAluParams[0].Operand2 = MHW_MI_ALU_GPREG0;
// load srcB, reg4
miAluParams[1].AluOpcode = MHW_MI_ALU_LOAD;
miAluParams[1].Operand1 = MHW_MI_ALU_SRCB;
miAluParams[1].Operand2 = MHW_MI_ALU_GPREG4;
// add srcA, srcB
miAluParams[2].AluOpcode = MHW_MI_ALU_ADD;
miAluParams[2].Operand1 = MHW_MI_ALU_SRCB;
miAluParams[2].Operand2 = MHW_MI_ALU_GPREG4;
// store reg0, ZF
miAluParams[3].AluOpcode = MHW_MI_ALU_STORE;
miAluParams[3].Operand1 = MHW_MI_ALU_GPREG0;
miAluParams[3].Operand2 = MHW_MI_ALU_ZF;
miMathParams.pAluPayload = miAluParams;
miMathParams.dwNumAluParams = 4; // four ALU commands needed for this substract opertaion. see following ALU commands.
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiMathCmd(
cmdBuffer,
&miMathParams));
// if zero, the zero flag will be 0xFFFFFFFF, else zero flag will be 0x0.
MHW_MI_STORE_REGISTER_MEM_PARAMS storeRegParams;
MOS_ZeroMemory(&storeRegParams, sizeof(storeRegParams));
storeRegParams.presStoreBuffer = &m_predicationBuffer;
storeRegParams.dwOffset = 0;
storeRegParams.dwRegister = mmioRegistersMfx->generalPurposeRegister0LoOffset;
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(
cmdBuffer,
&storeRegParams));
condBBEndParams.presSemaphoreBuffer = &m_predicationBuffer;
condBBEndParams.dwOffset = 0;
condBBEndParams.dwValue = 0;
condBBEndParams.bDisableCompareMask = true;
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiConditionalBatchBufferEndCmd(
cmdBuffer,
&condBBEndParams));
*m_decodeParams.m_tempPredicationBuffer = &m_predicationBuffer;
}
else
{
// Skip current frame if presPredication is equal to zero
condBBEndParams.presSemaphoreBuffer = m_decodeParams.m_presPredication;
condBBEndParams.dwOffset = (uint32_t)m_decodeParams.m_predicationResOffset;
condBBEndParams.bDisableCompareMask = true;
condBBEndParams.dwValue = 0;
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiConditionalBatchBufferEndCmd(
cmdBuffer,
&condBBEndParams));
}
return eStatus;
}
MOS_STATUS CodechalDecode::SendMarkerCommand(
PMOS_COMMAND_BUFFER cmdBuffer,
bool isRender)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_DECODE_FUNCTION_ENTER;
CODECHAL_DECODE_CHK_NULL_RETURN(cmdBuffer);
CODECHAL_DECODE_CHK_NULL_RETURN(m_miInterface);
if (isRender)
{
// Send pipe_control to get the timestamp
MHW_PIPE_CONTROL_PARAMS pipeControlParams;
MOS_ZeroMemory(&pipeControlParams, sizeof(pipeControlParams));
pipeControlParams.presDest = (PMOS_RESOURCE)m_decodeParams.m_presSetMarker;
pipeControlParams.dwResourceOffset = 0;
pipeControlParams.dwPostSyncOp = MHW_FLUSH_WRITE_TIMESTAMP_REG;
pipeControlParams.dwFlushMode = MHW_FLUSH_WRITE_CACHE;
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddPipeControl(cmdBuffer, NULL, &pipeControlParams));
}
else
{
// Send flush_dw to get the timestamp
MHW_MI_FLUSH_DW_PARAMS flushDwParams;
MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
flushDwParams.pOsResource = (PMOS_RESOURCE)m_decodeParams.m_presSetMarker;
flushDwParams.dwResourceOffset = 0;
flushDwParams.postSyncOperation = MHW_FLUSH_WRITE_TIMESTAMP_REG;
flushDwParams.bQWordEnable = 1;
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(cmdBuffer, &flushDwParams));
}
return eStatus;
}
MOS_STATUS CodechalDecode::SetCencBatchBuffer(
PMOS_COMMAND_BUFFER cmdBuffer)
{
CODECHAL_DECODE_CHK_NULL_RETURN(cmdBuffer);
MHW_BATCH_BUFFER batchBuffer;
MOS_ZeroMemory(&batchBuffer, sizeof(MHW_BATCH_BUFFER));
MOS_RESOURCE *resHeap = nullptr;
CODECHAL_DECODE_CHK_NULL_RETURN(resHeap = m_cencBuf->secondLvlBbBlock->GetResource());
batchBuffer.OsResource = *resHeap;
batchBuffer.dwOffset = m_cencBuf->secondLvlBbBlock->GetOffset();
batchBuffer.iSize = m_cencBuf->secondLvlBbBlock->GetSize();
batchBuffer.bSecondLevel = true;
#if (_DEBUG || _RELEASE_INTERNAL)
batchBuffer.iLastCurrent = batchBuffer.iSize;
#endif // (_DEBUG || _RELEASE_INTERNAL)
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(
cmdBuffer,
&batchBuffer));
CODECHAL_DEBUG_TOOL(
CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->Dump2ndLvlBatch(
&batchBuffer,
CODECHAL_NUM_MEDIA_STATES,
"_2ndLvlBatch"));)
// Update GlobalCmdBufId
MHW_MI_STORE_DATA_PARAMS miStoreDataParams;
MOS_ZeroMemory(&miStoreDataParams, sizeof(miStoreDataParams));
miStoreDataParams.pOsResource = m_cencBuf->resTracker;
miStoreDataParams.dwValue = m_cencBuf->trackerId;
CODECHAL_DECODE_VERBOSEMESSAGE("dwCmdBufId = %d", miStoreDataParams.dwValue);
CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(
cmdBuffer,
&miStoreDataParams));
return MOS_STATUS_SUCCESS;
}
#if USE_CODECHAL_DEBUG_TOOL
#ifdef _DECODE_PROCESSING_SUPPORTED
MOS_STATUS CodechalDecode::DumpProcessingParams(DecodeProcessingParams *decProcParams)
{
CODECHAL_DEBUG_FUNCTION_ENTER;
if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDecodeProcParams))
{
return MOS_STATUS_SUCCESS;
}
CODECHAL_DEBUG_CHK_NULL(decProcParams);
CODECHAL_DEBUG_CHK_NULL(decProcParams->m_inputSurface);
CODECHAL_DEBUG_CHK_NULL(decProcParams->m_outputSurface);
std::ostringstream oss;
oss.setf(std::ios::showbase | std::ios::uppercase);
oss << "Input Surface Resolution: "
<< +decProcParams->m_inputSurface->dwWidth << " x " << +decProcParams->m_inputSurface->dwHeight << std::endl;
oss << "Input Region Resolution: "
<< +decProcParams->m_inputSurfaceRegion.m_width << " x " << +decProcParams->m_inputSurfaceRegion.m_height << std::endl;
oss << "Input Region Offset: ("
<< +decProcParams->m_inputSurfaceRegion.m_x << "," << +decProcParams->m_inputSurfaceRegion.m_y << ")" << std::endl;
oss << "Input Surface Format: "
<< (decProcParams->m_inputSurface->Format == Format_NV12 ? "NV12" : "P010" )<< std::endl;
oss << "Output Surface Resolution: "
<< +decProcParams->m_outputSurface->dwWidth << " x " << +decProcParams->m_outputSurface->dwHeight << std::endl;
oss << "Output Region Resolution: "
<< +decProcParams->m_outputSurfaceRegion.m_width << " x " << +decProcParams->m_outputSurfaceRegion.m_height << std::endl;
oss << "Output Region Offset: ("
<< +decProcParams->m_outputSurfaceRegion.m_x << ", " << +decProcParams->m_outputSurfaceRegion.m_y << ")" << std::endl;
oss << "Output Surface Format: "
<< (decProcParams->m_outputSurface->Format == Format_NV12 ? "NV12" : "YUY2" )<< std::endl;
const char* filePath = m_debugInterface->CreateFileName(
"_DEC",
CodechalDbgBufferType::bufDecProcParams,
CodechalDbgExtType::txt);
std::ofstream ofs(filePath, std::ios::out);
ofs << oss.str();
ofs.close();
return MOS_STATUS_SUCCESS;
}
#endif
#endif