blob: 4207e1d6dc5baef158a4ceb20183b576e452db30 [file] [log] [blame]
/*
* Copyright (c) 2017-2018, 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_encode_hevc_base.cpp
//! \brief Defines base class for HEVC encoder.
//!
#include "codechal_encode_hevc_base.h"
#include "codechal_vdenc_hevc.h"
#include "codechal_encode_hevc.h"
#include "encode_hevc_header_packer.h"
#if USE_CODECHAL_DEBUG_TOOL
#include "codechal_debug.h"
#endif
const uint8_t CodechalEncodeHevcBase::TransformSkipCoeffsTable[4][2][2][2][2] =
{
{ { { { 42, 37 },{ 32, 40 } },{ { 40, 40 },{ 32, 45 } } },{ { { 29, 48 },{ 26, 53 } },{ { 26, 56 },{ 24, 62 } } } },
{ { { { 42, 40 },{ 32, 45 } },{ { 40, 46 },{ 32, 48 } } },{ { { 26, 53 },{ 24, 58 } },{ { 32, 53 },{ 26, 64 } } } },
{ { { { 38, 42 },{ 32, 51 } },{ { 43, 43 },{ 35, 46 } } },{ { { 26, 56 },{ 24, 64 } },{ { 35, 50 },{ 32, 57 } } } },
{ { { { 35, 46 },{ 32, 52 } },{ { 51, 42 },{ 38, 53 } } },{ { { 29, 56 },{ 29, 70 } },{ { 38, 47 },{ 37, 64 } } } },
};
const uint16_t CodechalEncodeHevcBase::TransformSkipLambdaTable[QP_NUM] =
{
149, 149, 149, 149, 149, 149, 149, 149,
149, 149, 149, 149, 149, 149, 149, 149,
149, 149, 149, 149, 149, 149, 149, 149,
149, 162, 174, 186, 199, 211, 224, 236,
249, 261, 273, 286, 298, 298, 298, 298,
298, 298, 298, 298, 298, 298, 298, 298,
298, 298, 298, 298
};
MOS_STATUS CodechalEncodeHevcBase::InitMmcState()
{
#ifdef _MMC_SUPPORTED
m_mmcState = MOS_New(CodechalMmcEncodeHevc, m_hwInterface, this);
CODECHAL_ENCODE_CHK_NULL_RETURN(m_mmcState);
#endif
return MOS_STATUS_SUCCESS;
}
MOS_STATUS CodechalEncodeHevcBase::Initialize(CodechalSetting * settings)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(settings);
#ifndef _FULL_OPEN_SOURCE
// for HEVC: the Ds+Copy kernel is by default used to do CSC and copy non-aligned surface
CODECHAL_ENCODE_CHK_NULL_RETURN(m_cscDsState);
m_cscDsState->EnableCopy();
m_cscDsState->EnableColor();
#endif
m_mfeEnabled = settings->isMfeEnabled;
CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::Initialize(settings));
CODECHAL_ENCODE_CHK_STATUS_RETURN(InitMmcState());
m_is10BitHevc = (settings->lumaChromaDepth & CODECHAL_LUMA_CHROMA_DEPTH_10_BITS) ? true : false;
m_chromaFormat = settings->chromaFormat;
m_bitDepth = (settings->lumaChromaDepth & CODECHAL_LUMA_CHROMA_DEPTH_8_BITS) ? 8 : ((settings->lumaChromaDepth & CODECHAL_LUMA_CHROMA_DEPTH_10_BITS) ? 10 : 12);
m_frameNum = 0;
const uint32_t picWidthInLCU = MOS_ROUNDUP_DIVIDE(m_frameWidth, CODECHAL_HEVC_MIN_LCU_SIZE); //assume smallest LCU to get max width
const uint32_t picHeightInLCU = MOS_ROUNDUP_DIVIDE(m_frameHeight, CODECHAL_HEVC_MIN_LCU_SIZE); //assume smallest LCU to get max height // MaxNumLcu is when LCU size is min lcu size(16)
const uint32_t maxNumLCUs = picWidthInLCU * picHeightInLCU;
m_mvOffset = MOS_ALIGN_CEIL((maxNumLCUs * (m_hcpInterface->GetHcpPakObjSize()) * sizeof(uint32_t)), CODECHAL_PAGE_SIZE);
// MaxNumCuRecords is when LCU size is max lcu size(64)
const uint32_t maxNumCuRecords = MOS_ROUNDUP_DIVIDE(m_frameWidth, MAX_LCU_SIZE) *
MOS_ROUNDUP_DIVIDE(m_frameHeight, MAX_LCU_SIZE) * 64;
m_mbCodeSize =
m_mvOffset + MOS_ALIGN_CEIL((maxNumCuRecords * m_hcpInterface->GetHevcEncCuRecordSize()), CODECHAL_PAGE_SIZE);
m_widthAlignedMaxLcu = MOS_ALIGN_CEIL(m_frameWidth, MAX_LCU_SIZE);
m_heightAlignedMaxLcu = MOS_ALIGN_CEIL(m_frameHeight, MAX_LCU_SIZE);
m_hevcBrcPakStatisticsSize = HEVC_BRC_PAK_STATISTCS_SIZE; // size for sturcture: CODECHAL_ENCODE_HEVC_PAK_STATS_BUFFER
m_sizeOfHcpPakFrameStats = 8 * CODECHAL_CACHELINE_SIZE;
// Initialize kernel State
CODECHAL_ENCODE_CHK_STATUS_RETURN(InitKernelState());
// Get max binding table count
m_maxBtCount = GetMaxBtCount();
// Picture Level Commands
CODECHAL_ENCODE_CHK_STATUS_RETURN(CalculatePictureStateCommandSize());
// Slice Level Commands
CODECHAL_ENCODE_CHK_STATUS_RETURN(
m_hwInterface->GetHxxPrimitiveCommandSize(
CODECHAL_ENCODE_MODE_HEVC,
&m_defaultSliceStatesSize,
&m_defaultSlicePatchListSize,
m_singleTaskPhaseSupported));
#if (_DEBUG || _RELEASE_INTERNAL)
MOS_USER_FEATURE_VALUE_DATA userFeatureData;
MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
MOS_UserFeature_ReadValue_ID(
nullptr,
__MEDIA_USER_FEATURE_VALUE_HEVC_ENCODE_IFRAME_RDOQ_ENABLE_ID,
&userFeatureData,
m_osInterface->pOsContext);
m_hevcIFrameRdoqEnabled = userFeatureData.i32Data ? true : false;
MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
MOS_UserFeature_ReadValue_ID(
nullptr,
__MEDIA_USER_FEATURE_VALUE_CODECHAL_RDOQ_INTRA_TU_OVERRIDE_ID,
&userFeatureData,
m_osInterface->pOsContext);
m_rdoqIntraTuOverride = (uint32_t)userFeatureData.u32Data;
MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
MOS_UserFeature_ReadValue_ID(
nullptr,
__MEDIA_USER_FEATURE_VALUE_CODECHAL_RDOQ_INTRA_TU_DISABLE_ID,
&userFeatureData,
m_osInterface->pOsContext);
m_rdoqIntraTuDisableOverride = (uint32_t)userFeatureData.u32Data;
MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
MOS_UserFeature_ReadValue_ID(
nullptr,
__MEDIA_USER_FEATURE_VALUE_CODECHAL_RDOQ_INTRA_TU_THRESHOLD_ID,
&userFeatureData,
m_osInterface->pOsContext);
m_rdoqIntraTuThresholdOverride = (uint32_t)userFeatureData.u32Data;
#endif
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::AllocatePakResources()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
const uint32_t minLcuSize = 16;
const uint32_t picWidthInMinLCU = MOS_ROUNDUP_DIVIDE(m_frameWidth, minLcuSize); //assume smallest LCU to get max width
const uint32_t picHeightInMinLCU = MOS_ROUNDUP_DIVIDE(m_frameHeight, minLcuSize); //assume smallest LCU to get max height
MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
allocParamsForBufferLinear.Format = Format_Buffer;
// Deblocking Filter Row Store Scratch data surface
const uint32_t formatDenom = 2;
uint32_t formatMultiFactor = m_chromaFormat == HCP_CHROMA_FORMAT_YUV444 ? 3 : 2;
formatMultiFactor *= m_is10BitHevc ? 2 : 1;
uint32_t size = ((m_frameWidth + 31) & 0xFFFFFFE0) >> 3;
size = MOS_ALIGN_CEIL(MOS_ROUNDUP_DIVIDE(size * formatMultiFactor, formatDenom), 4);
size *= CODECHAL_CACHELINE_SIZE;
allocParamsForBufferLinear.dwBytes = size;
allocParamsForBufferLinear.pBufName = "DeblockingScratchBuffer";
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBufferLinear,
&m_resDeblockingFilterRowStoreScratchBuffer);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate Deblocking Filter Row Store Scratch Buffer.");
return eStatus;
}
// Deblocking Filter Tile Row Store Scratch data surface
allocParamsForBufferLinear.dwBytes = size;
allocParamsForBufferLinear.pBufName = "DeblockingTileScratchBuffer";
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBufferLinear,
&m_resDeblockingFilterTileRowStoreScratchBuffer);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate Deblocking Filter Tile Row Store Scratch Buffer.");
return eStatus;
}
// Deblocking Filter Column Row Store Scratch data surface
size = ((m_frameHeight + picHeightInMinLCU * 6 + 31) & 0xFFFFFFE0) >> 3;
size = MOS_ALIGN_CEIL(MOS_ROUNDUP_DIVIDE(size * formatMultiFactor, formatDenom), 4);
size *= CODECHAL_CACHELINE_SIZE;
allocParamsForBufferLinear.dwBytes = size;
allocParamsForBufferLinear.pBufName = "DeblockingColumnScratchBuffer";
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBufferLinear,
&m_resDeblockingFilterColumnRowStoreScratchBuffer);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate Deblocking Filter Column Row Store Scratch Buffer.");
return eStatus;
}
// Metadata Line buffer
size = MOS_MAX(
MOS_ALIGN_CEIL((m_frameWidth + picWidthInMinLCU * 8 + 1023) >> 9, 2) * CODECHAL_CACHELINE_SIZE, // intra-slice
MOS_ALIGN_CEIL((((m_frameWidth + 15) >> 4) * 188 + picWidthInMinLCU * 9 + 1023) >> 9, 2) * CODECHAL_CACHELINE_SIZE // inter-slice
);
allocParamsForBufferLinear.dwBytes = size;
allocParamsForBufferLinear.pBufName = "MetadataLineBuffer";
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBufferLinear,
&m_resMetadataLineBuffer);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate Metadata Line Buffer.");
return eStatus;
}
// Metadata Tile Line buffer
size = MOS_MAX(
MOS_ALIGN_CEIL((m_frameWidth + picWidthInMinLCU * 8 + 1023) >> 9, 2) * CODECHAL_CACHELINE_SIZE, // intra-slice
MOS_ALIGN_CEIL((((m_frameWidth + 15) >> 4) * 172 + picWidthInMinLCU * 9 + 1023) >> 9, 2) * CODECHAL_CACHELINE_SIZE // inter-slice
);
allocParamsForBufferLinear.dwBytes = size;
allocParamsForBufferLinear.pBufName = "MetadataTileLineBuffer";
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBufferLinear,
&m_resMetadataTileLineBuffer);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate Metadata Tile Line Buffer.");
return eStatus;
}
// Metadata Tile Column buffer
size = MOS_MAX(
MOS_ALIGN_CEIL((m_frameHeight + picHeightInMinLCU * 8 + 1023) >> 9, 2) * CODECHAL_CACHELINE_SIZE, // intra-slice
MOS_ALIGN_CEIL((((m_frameHeight + 15) >> 4) * 172 + picHeightInMinLCU * 9 + 1023) >> 9, 2) * CODECHAL_CACHELINE_SIZE // inter-slice
);
allocParamsForBufferLinear.dwBytes = size;
allocParamsForBufferLinear.pBufName = "MetadataTileColumnBuffer";
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBufferLinear,
&m_resMetadataTileColumnBuffer);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate Metadata Tile Column Buffer.");
return eStatus;
}
MHW_VDBOX_HCP_BUFFER_SIZE_PARAMS hcpBufSizeParam;
MOS_ZeroMemory(&hcpBufSizeParam, sizeof(hcpBufSizeParam));
hcpBufSizeParam.ucMaxBitDepth = m_bitDepth;
hcpBufSizeParam.ucChromaFormat = m_chromaFormat;
hcpBufSizeParam.dwCtbLog2SizeY = 6; // assume Max LCU size
hcpBufSizeParam.dwPicWidth = MOS_ALIGN_CEIL(m_frameWidth, MAX_LCU_SIZE);
hcpBufSizeParam.dwPicHeight = MOS_ALIGN_CEIL(m_frameHeight, MAX_LCU_SIZE);
// SAO Line buffer
eStatus = (MOS_STATUS)m_hcpInterface->GetHevcBufferSize(
MHW_VDBOX_HCP_INTERNAL_BUFFER_SAO_LINE,
&hcpBufSizeParam);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to get the size for SAO Line Buffer.");
return eStatus;
}
allocParamsForBufferLinear.dwBytes = hcpBufSizeParam.dwBufferSize;
allocParamsForBufferLinear.pBufName = "SaoLineBuffer";
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBufferLinear,
&m_resSaoLineBuffer);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate SAO Line Buffer.");
return eStatus;
}
// SAO Tile Line buffer
eStatus = (MOS_STATUS)m_hcpInterface->GetHevcBufferSize(
MHW_VDBOX_HCP_INTERNAL_BUFFER_SAO_TILE_LINE,
&hcpBufSizeParam);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to get the size for SAO Tile Line Buffer.");
return eStatus;
}
allocParamsForBufferLinear.dwBytes = hcpBufSizeParam.dwBufferSize;
allocParamsForBufferLinear.pBufName = "SaoTileLineBuffer";
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBufferLinear,
&m_resSaoTileLineBuffer);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate SAO Tile Line Buffer.");
return eStatus;
}
// SAO Tile Column buffer
eStatus = (MOS_STATUS)m_hcpInterface->GetHevcBufferSize(
MHW_VDBOX_HCP_INTERNAL_BUFFER_SAO_TILE_COL,
&hcpBufSizeParam);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to get the size for SAO Tile Column Buffer.");
return eStatus;
}
allocParamsForBufferLinear.dwBytes = hcpBufSizeParam.dwBufferSize;
allocParamsForBufferLinear.pBufName = "SaoTileColumnBuffer";
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBufferLinear,
&m_resSaoTileColumnBuffer);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate SAO Tile Column Buffer.");
return eStatus;
}
// Lcu ILDB StreamOut buffer
size = 1000000;
allocParamsForBufferLinear.dwBytes = size;
allocParamsForBufferLinear.pBufName = "LcuILDBStreamOutBuffer";
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBufferLinear,
&m_resLcuIldbStreamOutBuffer);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate LCU ILDB StreamOut Buffer.");
return eStatus;
}
// Lcu Base Address buffer
// HEVC Encoder Mode: Slice size is written to this buffer when slice size conformance is enabled.
// 1 CL (= 16 DWs = 64 bytes) per slice * Maximum number of dynamic slice = 600
// Note that simulation is assigning much larger space for this.
allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(CODECHAL_HEVC_MAX_NUM_SLICES_LVL_6 * CODECHAL_CACHELINE_SIZE, CODECHAL_PAGE_SIZE);
allocParamsForBufferLinear.pBufName = "LcuBaseAddressBuffer";
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBufferLinear,
&m_resLcuBaseAddressBuffer);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate LCU Base Address Buffer.");
return eStatus;
}
uint32_t mvt_size = MOS_ALIGN_CEIL(((m_frameWidth + 63) >> 6)*((m_frameHeight + 15) >> 4), 2) * CODECHAL_CACHELINE_SIZE;
uint32_t mvtb_size = MOS_ALIGN_CEIL(((m_frameWidth + 31) >> 5)*((m_frameHeight + 31) >> 5), 2) * CODECHAL_CACHELINE_SIZE;
m_sizeOfMvTemporalBuffer = MOS_MAX(mvt_size, mvtb_size);
// SAO StreamOut buffer
size = MOS_ALIGN_CEIL(picWidthInMinLCU * picHeightInMinLCU * 16, CODECHAL_CACHELINE_SIZE); // 16 bytes per LCU
allocParamsForBufferLinear.dwBytes = size;
allocParamsForBufferLinear.pBufName = "SaoStreamOutBuffer";
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBufferLinear,
&m_resSaoStreamOutBuffer);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate SAO StreamOut Buffer.");
return eStatus;
}
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::AllocateResources()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::AllocateResources());
// Allocate Ref Lists
CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalAllocateDataList(
m_refList,
CODECHAL_NUM_UNCOMPRESSED_SURFACE_HEVC));
// Create the sync objects which will be used by each reference frame
for (uint32_t i = 0; i < CODECHAL_GET_ARRAY_LENGTH(m_refSync); i++)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource(m_osInterface, &m_refSync[i].resSyncObject));
m_refSync[i].bInUsed = false;
}
CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(AllocatePakResources(), "Failed to allocate PAK resources.");
if (m_encEnabled)
{
CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(AllocateEncResources(), "Failed to allocate ENC resources.");
CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(AllocateBrcResources(), "Failed to allocate BRC resources.");
}
CODECHAL_ENCODE_CHK_STATUS_RETURN(InitSurfaceInfoTable());
CreateMhwParams();
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::AllocateBuffer(
PCODECHAL_ENCODE_BUFFER buffer,
uint32_t size,
const char* name,
int32_t dwMemType)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(buffer);
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.dwMemType = dwMemType;
buffer->dwSize = size;
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParams,
&buffer->sResource);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate %s.", name);
return eStatus;
}
MOS_LOCK_PARAMS lockFlags;
MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
lockFlags.WriteOnly = 1;
uint8_t* data = (uint8_t*)m_osInterface->pfnLockResource(
m_osInterface,
&buffer->sResource,
&lockFlags);
CODECHAL_ENCODE_CHK_NULL_RETURN(data);
MOS_ZeroMemory(data, size);
m_osInterface->pfnUnlockResource(
m_osInterface,
&buffer->sResource);
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::AllocateBuffer2D(
PMOS_SURFACE surface,
uint32_t width,
uint32_t height,
const char* name,
MOS_TILE_TYPE tileType,
int32_t dwMemType)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(surface);
MOS_ZeroMemory(surface, sizeof(*surface));
surface->TileType = tileType;
surface->bArraySpacing = true;
surface->Format = Format_Buffer_2D;
surface->dwWidth = MOS_ALIGN_CEIL(width, 64);
surface->dwHeight = height;
surface->dwPitch = surface->dwWidth;
MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS));
allocParamsForBuffer2D.Type = MOS_GFXRES_2D;
allocParamsForBuffer2D.TileType = surface->TileType;
allocParamsForBuffer2D.Format = surface->Format;
allocParamsForBuffer2D.dwWidth = surface->dwWidth;
allocParamsForBuffer2D.dwHeight = surface->dwHeight;
allocParamsForBuffer2D.pBufName = name;
allocParamsForBuffer2D.dwMemType = dwMemType;
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBuffer2D,
&surface->OsResource);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate %s.", name);
return eStatus;
}
MOS_LOCK_PARAMS lockFlagsWriteOnly;
MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
lockFlagsWriteOnly.WriteOnly = true;
uint8_t* data = (uint8_t*)m_osInterface->pfnLockResource(
m_osInterface,
&(surface->OsResource),
&lockFlagsWriteOnly);
if (data == nullptr)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to Lock 2D Surface.");
eStatus = MOS_STATUS_UNKNOWN;
return eStatus;
}
MOS_ZeroMemory(data, surface->dwWidth * surface->dwHeight);
m_osInterface->pfnUnlockResource(m_osInterface, &(surface->OsResource));
CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(
m_osInterface,
surface));
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::AllocateSurface(
PMOS_SURFACE surface,
uint32_t width,
uint32_t height,
const char* name,
int32_t dwMemType)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_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_NV12;
allocParams.dwWidth = width;
allocParams.dwHeight = height;
allocParams.pBufName = name;
allocParams.dwMemType = dwMemType;
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParams,
&surface->OsResource);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate %s.", name);
return eStatus;
}
CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(
m_osInterface,
surface));
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::AllocateBatchBufferForPakSlices(
uint32_t numSlices,
uint8_t numPakPasses)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
MOS_ZeroMemory(
&m_batchBufferForPakSlices[m_currPakSliceIdx],
sizeof(MHW_BATCH_BUFFER));
// Get the slice size
uint32_t size = (numPakPasses + 1) * numSlices * m_sliceStatesSize;
m_batchBufferForPakSlices[m_currPakSliceIdx].bSecondLevel = true;
CODECHAL_ENCODE_CHK_STATUS_RETURN(Mhw_AllocateBb(
m_osInterface,
&m_batchBufferForPakSlices[m_currPakSliceIdx],
nullptr,
size));
MOS_LOCK_PARAMS lockFlags;
MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
lockFlags.WriteOnly = 1;
uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(
m_osInterface,
&m_batchBufferForPakSlices[m_currPakSliceIdx].OsResource,
&lockFlags);
if (data == nullptr)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to lock batch buffer for PAK slices.");
eStatus = MOS_STATUS_UNKNOWN;
return eStatus;
}
MOS_ZeroMemory(data, size);
m_osInterface->pfnUnlockResource(
m_osInterface,
&m_batchBufferForPakSlices[m_currPakSliceIdx].OsResource);
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::ReadSseStatistics(PMOS_COMMAND_BUFFER cmdBuffer)
{
CODECHAL_ENCODE_FUNCTION_ENTER;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
// encodeStatus is offset by 2 DWs in the resource
uint32_t sseOffsetinBytes = (m_encodeStatusBuf.wCurrIndex * m_encodeStatusBuf.dwReportSize) + sizeof(uint32_t) * 2 + m_encodeStatusBuf.dwSumSquareErrorOffset;
for (auto i = 0; i < 6; i++) // 64 bit SSE values for luma/ chroma channels need to be copied
{
MHW_MI_COPY_MEM_MEM_PARAMS miCpyMemMemParams;
MOS_ZeroMemory(&miCpyMemMemParams, sizeof(miCpyMemMemParams));
miCpyMemMemParams.presSrc = &m_resFrameStatStreamOutBuffer;
miCpyMemMemParams.dwSrcOffset = (HEVC_PAK_STATISTICS_SSE_OFFSET + i) * sizeof(uint32_t); // SSE luma offset is located at DW32 in Frame statistics, followed by chroma
miCpyMemMemParams.presDst = &m_encodeStatusBuf.resStatusBuffer;
miCpyMemMemParams.dwDstOffset = sseOffsetinBytes + i * sizeof(uint32_t);
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiCopyMemMemCmd(cmdBuffer, &miCpyMemMemParams));
}
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::CalculatePSNR(
EncodeStatus *encodeStatus,
EncodeStatusReport *encodeStatusReport)
{
CODECHAL_ENCODE_FUNCTION_ENTER;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_CHK_NULL_RETURN(encodeStatus);
CODECHAL_ENCODE_CHK_NULL_RETURN(encodeStatusReport);
uint32_t numLumaPixels = 0, numPixelsPerChromaChannel = 0;
numLumaPixels = m_frameHeight * m_frameWidth;
switch (m_hevcSeqParams->chroma_format_idc)
{
case HCP_CHROMA_FORMAT_MONOCHROME:
numPixelsPerChromaChannel = 0;
break;
case HCP_CHROMA_FORMAT_YUV420:
numPixelsPerChromaChannel = numLumaPixels / 4;
break;
case HCP_CHROMA_FORMAT_YUV422:
numPixelsPerChromaChannel = numLumaPixels / 2;
break;
case HCP_CHROMA_FORMAT_YUV444:
numPixelsPerChromaChannel = numLumaPixels;
break;
default:
numPixelsPerChromaChannel = numLumaPixels / 2;
break;
}
double squarePeakPixelValue = pow((1 << (m_hevcSeqParams->bit_depth_luma_minus8 + 8)) - 1, 2);
for (auto i = 0; i < 3; i++)
{
uint32_t numPixels = i ? numPixelsPerChromaChannel : numLumaPixels;
if (m_hevcSeqParams->bit_depth_luma_minus8 == 0)
{
//8bit pixel data is represented in 10bit format in HW. so SSE should right shift by 4.
encodeStatus->sumSquareError[i] >>= 4;
}
encodeStatusReport->PSNRx100[i] = (uint16_t) CodecHal_Clip3(0, 10000,
(uint16_t) (encodeStatus->sumSquareError[i] ? 1000 * log10(squarePeakPixelValue * numPixels / encodeStatus->sumSquareError[i]) : -1));
CODECHAL_ENCODE_VERBOSEMESSAGE("PSNRx100[%d]:%d.\n", i, encodeStatusReport->PSNRx100[i]);
}
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::ReleaseBatchBufferForPakSlices(uint32_t index)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
if (m_batchBufferForPakSlices[index].iSize)
{
Mhw_FreeBb(m_osInterface, &m_batchBufferForPakSlices[index], nullptr);
m_batchBufferForPakSlices[index].iSize = 0;
}
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::FreePakResources()
{
CODECHAL_ENCODE_FUNCTION_ENTER;
for (auto i = 0; i < CODECHAL_HEVC_NUM_PAK_SLICE_BATCH_BUFFERS; i++)
{
ReleaseBatchBufferForPakSlices(i);
}
m_osInterface->pfnFreeResource(m_osInterface, &m_resDeblockingFilterRowStoreScratchBuffer);
m_osInterface->pfnFreeResource(m_osInterface, &m_resDeblockingFilterTileRowStoreScratchBuffer);
m_osInterface->pfnFreeResource(m_osInterface, &m_resDeblockingFilterColumnRowStoreScratchBuffer);
m_osInterface->pfnFreeResource(m_osInterface, &m_resMetadataLineBuffer);
m_osInterface->pfnFreeResource(m_osInterface, &m_resMetadataTileLineBuffer);
m_osInterface->pfnFreeResource(m_osInterface, &m_resMetadataTileColumnBuffer);
m_osInterface->pfnFreeResource(m_osInterface, &m_resSaoLineBuffer);
m_osInterface->pfnFreeResource(m_osInterface, &m_resSaoTileLineBuffer);
m_osInterface->pfnFreeResource(m_osInterface, &m_resSaoTileColumnBuffer);
m_osInterface->pfnFreeResource(m_osInterface, &m_resLcuIldbStreamOutBuffer);
m_osInterface->pfnFreeResource(m_osInterface, &m_resLcuBaseAddressBuffer);
m_osInterface->pfnFreeResource(m_osInterface, &m_resSaoStreamOutBuffer);
return MOS_STATUS_SUCCESS;
}
void CodechalEncodeHevcBase::FreeResources()
{
CODECHAL_ENCODE_FUNCTION_ENTER;
CodechalEncoderState::FreeResources();
FreeEncResources();
FreeBrcResources();
FreePakResources();
// Release Ref Lists
CodecHalFreeDataList(m_refList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_HEVC);
for (uint32_t i = 0; i < CODECHAL_GET_ARRAY_LENGTH(m_refSync); i++)
{
m_osInterface->pfnDestroySyncResource(m_osInterface, &m_refSync[i].resSyncObject);
}
if (m_sliceStateParams)
{
MOS_Delete(m_sliceStateParams);
m_sliceStateParams = nullptr;
}
if (m_pipeModeSelectParams)
{
MOS_Delete(m_pipeModeSelectParams);
m_pipeModeSelectParams = nullptr;
}
if (m_pipeBufAddrParams)
{
MOS_Delete(m_pipeBufAddrParams);
m_pipeBufAddrParams = nullptr;
}
}
MOS_STATUS CodechalEncodeHevcBase::SetSequenceStructs()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
uint32_t frameWidth = (m_hevcSeqParams->wFrameWidthInMinCbMinus1 + 1) << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3);
uint32_t frameHeight = (m_hevcSeqParams->wFrameHeightInMinCbMinus1 + 1) << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3);
// check if there is a dynamic resolution change
if ((m_oriFrameHeight && (m_oriFrameHeight != frameHeight)) ||
(m_oriFrameWidth && (m_oriFrameWidth != frameWidth)))
{
if (frameHeight > m_createHeight || frameWidth > m_createWidth)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Resolution reset from lower resolution to higher resolution not supported if it is higher than the resolution of first frame.%d, %d %d, %d", m_createWidth, m_createHeight, frameWidth, frameHeight);
eStatus = MOS_STATUS_INVALID_PARAMETER;
return eStatus;
}
m_resolutionChanged = true;
m_brcInit = true;
}
else
{
m_resolutionChanged = false;
}
// setup internal parameters
m_oriFrameWidth = m_frameWidth = frameWidth;
m_oriFrameHeight = m_frameHeight = frameHeight;
m_picWidthInMb = (uint16_t)CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_oriFrameWidth);
m_picHeightInMb = (uint16_t)CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_oriFrameHeight);
if (m_resolutionChanged)
{
m_widthAlignedMaxLcu = MOS_ALIGN_CEIL(m_frameWidth, MAX_LCU_SIZE);
m_heightAlignedMaxLcu = MOS_ALIGN_CEIL(m_frameHeight, MAX_LCU_SIZE);
}
// Get row store cache params: as all the needed information is got here
if (m_hcpInterface->IsRowStoreCachingSupported())
{
MHW_VDBOX_ROWSTORE_PARAMS rowstoreParams = {};
rowstoreParams.Mode = m_mode;
rowstoreParams.dwPicWidth = m_frameWidth;
rowstoreParams.ucChromaFormat = m_chromaFormat;
rowstoreParams.ucBitDepthMinus8 = m_hevcSeqParams->bit_depth_luma_minus8;
rowstoreParams.ucLCUSize = 1 << (m_hevcSeqParams->log2_max_coding_block_size_minus3 + 3);
m_hwInterface->SetRowstoreCachingOffsets(&rowstoreParams);
}
m_brcEnabled = IsRateControlBrc(m_hevcSeqParams->RateControlMethod);
if (m_brcEnabled)
{
switch (m_hevcSeqParams->MBBRC)
{
case mbBrcInternal:
m_lcuBrcEnabled = (m_hevcSeqParams->TargetUsage == 1);
break;
case mbBrcDisabled:
m_lcuBrcEnabled = false;
break;
case mbBrcEnabled:
m_lcuBrcEnabled = true;
break;
}
if (m_hevcSeqParams->RateControlMethod == RATECONTROL_ICQ ||
m_hevcSeqParams->RateControlMethod == RATECONTROL_QVBR ||
m_hevcPicParams->NumROI)
{
// ICQ or ROI must result in LCU-based BRC to be enabled.
m_lcuBrcEnabled = true;
}
}
if (m_hevcSeqParams->RateControlMethod == RATECONTROL_VCM && m_lcuBrcEnabled)
{
m_lcuBrcEnabled = false; // when VCM is enabled, only frame-based BRC
}
if ((!m_vdencEnabled && m_hevcSeqParams->RateControlMethod == RATECONTROL_ICQ) || m_hevcSeqParams->RateControlMethod == RATECONTROL_QVBR)
{
if (m_hevcSeqParams->ICQQualityFactor < CODECHAL_ENCODE_HEVC_MIN_ICQ_QUALITYFACTOR ||
m_hevcSeqParams->ICQQualityFactor > CODECHAL_ENCODE_HEVC_MAX_ICQ_QUALITYFACTOR)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Invalid ICQ Quality Factor input (%d)\n", m_hevcSeqParams->ICQQualityFactor);
eStatus = MOS_STATUS_INVALID_PARAMETER;
return eStatus;
}
}
m_usAvbrAccuracy = CODECHAL_ENCODE_HEVC_DEFAULT_AVBR_ACCURACY;
m_usAvbrConvergence = CODECHAL_ENCODE_HEVC_DEFAULT_AVBR_CONVERGENCE;
// Calculate 4x, 16x, 32x dimensions as applicable
CODECHAL_ENCODE_CHK_STATUS_RETURN(CalcScaledDimensions());
// It is assumed to be frame-mode always
m_frameFieldHeight = m_frameHeight;
m_frameFieldHeightInMb = m_picHeightInMb;
m_downscaledFrameFieldHeightInMb16x = m_downscaledHeightInMb16x;
m_downscaledFrameFieldHeightInMb4x = m_downscaledHeightInMb4x;
m_downscaledFrameFieldHeightInMb32x = m_downscaledHeightInMb32x;
m_brcReset = m_hevcSeqParams->bResetBRC;
m_roiValueInDeltaQp = m_hevcSeqParams->ROIValueInDeltaQP;
uint32_t lcuInRow = MOS_ALIGN_CEIL(m_frameWidth, (1 << (m_hevcSeqParams->log2_max_coding_block_size_minus3 + 3))) >> (m_hevcSeqParams->log2_max_coding_block_size_minus3 + 3);
uint32_t lcu2MbRatio = (1 << (m_hevcSeqParams->log2_max_coding_block_size_minus3 + 3)) / CODECHAL_MACROBLOCK_WIDTH;
if (lcuInRow < 1 || lcu2MbRatio < 1)
{
eStatus = MOS_STATUS_INVALID_PARAMETER;
return eStatus;
}
if (m_brcReset &&
(!m_brcEnabled ||
m_hevcSeqParams->RateControlMethod == RATECONTROL_ICQ))
{
CODECHAL_ENCODE_ASSERTMESSAGE("BRC Reset cannot be trigerred in CQP/ICQ modes - invalid BRC parameters.");
m_brcReset = false;
}
if (m_hevcSeqParams->TargetUsage == 0x07 && !m_enable26WalkingPattern)
{
m_enable26WalkingPattern = true; // in the performance mode (TU=7), 26z walking pattern is not supported
}
if (!m_32xMeUserfeatureControl && m_32xMeSupported && m_hevcSeqParams->TargetUsage == 0x07)
{
m_32xMeSupported = false; // TU7 does not support ultra HME
}
m_encode4KSequence = ((m_frameWidth * m_frameHeight) >=
(ENCODE_HEVC_4K_PIC_WIDTH * ENCODE_HEVC_4K_PIC_HEIGHT))
? true
: false;
m_encode16KSequence = ((m_frameWidth * m_frameHeight) >=
(ENCODE_HEVC_16K_PIC_WIDTH * ENCODE_HEVC_16K_PIC_HEIGHT))
? true
: false;
// if GOP structure is I-frame only, we use 3 non-ref slots for tracked buffer
m_gopIsIdrFrameOnly = (m_hevcSeqParams->GopPicSize == 1);
// check output Chroma format
m_outputChromaFormat = m_hevcSeqParams->chroma_format_idc;
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::SetPictureStructs()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
{
m_refIdxMapping[i] = -1;
m_currUsedRefPic[i] = false;
}
// To obtain current "used" reference frames. The number of current used reference frames cannot be greater than 8
auto slcParams = m_hevcSliceParams;
for (uint32_t s = 0; s < m_numSlices; s++, slcParams++)
{
for (auto ll = 0; ll < 2; ll++)
{
uint32_t numRef = (ll == 0) ? slcParams->num_ref_idx_l0_active_minus1 :
slcParams->num_ref_idx_l1_active_minus1;
if (numRef > CODEC_MAX_NUM_REF_FRAME_HEVC)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Invalid number of ref frames for l0 %d or l1 %d", slcParams->num_ref_idx_l0_active_minus1, slcParams->num_ref_idx_l1_active_minus1);
eStatus = MOS_STATUS_INVALID_PARAMETER;
return eStatus;
}
for (uint32_t i = 0; i <= numRef; i++)
{
CODEC_PICTURE refPic = slcParams->RefPicList[ll][i];
if (!CodecHal_PictureIsInvalid(refPic) &&
!CodecHal_PictureIsInvalid(m_hevcPicParams->RefFrameList[refPic.FrameIdx]))
{
m_currUsedRefPic[refPic.FrameIdx] = true;
}
}
}
}
for (uint8_t i = 0, RefIdx = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
{
if (!m_currUsedRefPic[i])
{
continue;
}
uint8_t index = m_hevcPicParams->RefFrameList[i].FrameIdx;
bool duplicatedIdx = false;
for (unsigned char ii = 0; ii < i; ii++)
{
if (m_currUsedRefPic[i] && index == m_hevcPicParams->RefFrameList[ii].FrameIdx)
{
// We find the same FrameIdx in the ref_frame_list. Multiple reference frames are the same.
// In other words, RefFrameList[i] and RefFrameList[ii] have the same surface Id
duplicatedIdx = true;
m_refIdxMapping[i] = m_refIdxMapping[ii];
break;
}
}
if (duplicatedIdx)
{
continue;
}
if (RefIdx >= CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC)
{
// Total number of distingushing reference frames cannot be geater than 8.
CODECHAL_ENCODE_ASSERT(false);
eStatus = MOS_STATUS_INVALID_PARAMETER;
return eStatus;
}
// Map reference frame index [0-15] into a set of unique IDs within [0-7]
m_refIdxMapping[i] = RefIdx;
RefIdx++;
}
if (m_hevcPicParams->CodingType != I_TYPE && m_hevcPicParams->CollocatedRefPicIndex != 0xFF && m_hevcPicParams->CollocatedRefPicIndex < CODEC_MAX_NUM_REF_FRAME_HEVC)
{
uint8_t frameStoreId = (uint8_t)m_refIdxMapping[m_hevcPicParams->CollocatedRefPicIndex];
if (frameStoreId >= CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC || !m_currUsedRefPic[m_hevcPicParams->CollocatedRefPicIndex])
{
// CollocatedRefPicIndex is wrong in this case for the reference frame is not used be used
eStatus = MOS_STATUS_INVALID_PARAMETER;
return eStatus;
}
}
if (m_hevcPicParams->QpY > CODECHAL_ENCODE_HEVC_MAX_SLICE_QP)
{
return MOS_STATUS_INVALID_PARAMETER;
}
if (Mos_ResourceIsNull(&m_reconSurface.OsResource) &&
(!m_hevcPicParams->bUseRawPicForRef || m_codecFunction != CODECHAL_FUNCTION_ENC))
{
return MOS_STATUS_INVALID_PARAMETER;
}
if (m_hevcSeqParams->scaling_list_enable_flag && !m_hevcPicParams->scaling_list_data_present_flag)
{
CreateDefaultScalingList();
}
else if (!m_hevcSeqParams->scaling_list_enable_flag)
{
CreateFlatScalingList();
}
unsigned char prevRefIdx = m_currReconstructedPic.FrameIdx;
PCODEC_REF_LIST *refListFull = &m_refList[0];
// Sync initialize
if ((m_firstFrame) ||
(!m_brcEnabled && m_hevcPicParams->bUseRawPicForRef) ||
(!m_brcEnabled && (m_hevcPicParams->CodingType == I_TYPE)) ||
(!m_brcEnabled && !refListFull[prevRefIdx]->bUsedAsRef))
{
m_waitForPak = false;
}
else
{
m_waitForPak = true;
}
if (m_brcEnabled || m_hevcPicParams->bUsedAsRef)
{
m_signalEnc = true;
}
else
{
m_signalEnc = false;
}
m_currEncBbSet = MB_ENC_Frame_BB;
m_lastPicInSeq = m_hevcPicParams->bLastPicInSeq;
m_lastPicInStream = m_hevcPicParams->bLastPicInStream;
m_statusReportFeedbackNumber = m_hevcPicParams->StatusReportFeedbackNumber;
m_currOriginalPic = m_hevcPicParams->CurrOriginalPic;
m_currReconstructedPic = m_hevcPicParams->CurrReconstructedPic;
unsigned char currRefIdx = m_hevcPicParams->CurrReconstructedPic.FrameIdx;
refListFull[currRefIdx]->sRefReconBuffer = m_reconSurface;
refListFull[currRefIdx]->sRefRawBuffer = m_rawSurface;
refListFull[currRefIdx]->RefPic = m_hevcPicParams->CurrOriginalPic;
refListFull[currRefIdx]->bUsedAsRef = m_hevcPicParams->bUsedAsRef;
refListFull[currRefIdx]->resBitstreamBuffer = m_resBitstreamBuffer;
refListFull[currRefIdx]->bFormatConversionDone = false;
// P/B frames with empty ref lists are internally encoded as I frames,
// while picture header packing remains the original value
m_pictureCodingType = m_hevcPicParams->CodingType;
bool emptyRefFrmList = true;
for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
{
if (m_hevcPicParams->RefFrameList[i].PicFlags != PICTURE_INVALID)
{
emptyRefFrmList = false;
break;
}
}
if (emptyRefFrmList && m_pictureCodingType != I_TYPE)
{
// If there is no reference frame in the list, just mark the current picture as the I type
m_pictureCodingType = I_TYPE;
}
for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
{
m_picIdx[i].bValid = false;
if (m_hevcPicParams->RefFrameList[i].PicFlags != PICTURE_INVALID)
{
uint8_t index = m_hevcPicParams->RefFrameList[i].FrameIdx;
bool duplicatedIdx = false;
for (auto ii = 0; ii < i; ii++)
{
if (m_picIdx[ii].bValid && index == m_hevcPicParams->RefFrameList[ii].FrameIdx)
{
// We find the same FrameIdx in the ref_frame_list. Multiple reference frames are the same.
// In other words, RefFrameList[i] and RefFrameList[ii] have the same surface Id
duplicatedIdx = true;
break;
}
}
if (duplicatedIdx)
{
continue;
}
// this reference frame in unique. Save it into the full reference list with 127 items
refListFull[index]->RefPic.PicFlags =
CodecHal_CombinePictureFlags(refListFull[index]->RefPic, m_hevcPicParams->RefFrameList[i]);
refListFull[index]->iFieldOrderCnt[0] = m_hevcPicParams->RefFramePOCList[i];
refListFull[index]->iFieldOrderCnt[1] = m_hevcPicParams->RefFramePOCList[i];
refListFull[index]->sRefBuffer = m_hevcPicParams->bUseRawPicForRef ? refListFull[index]->sRefRawBuffer : refListFull[index]->sRefReconBuffer;
m_picIdx[i].bValid = true;
m_picIdx[i].ucPicIdx = index;
}
}
// Save the current RefList
uint8_t ii = 0;
for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
{
if (m_picIdx[i].bValid)
{
refListFull[currRefIdx]->RefList[ii] = m_hevcPicParams->RefFrameList[i];
ii++;
}
}
refListFull[currRefIdx]->ucNumRef = ii;
m_currRefList = refListFull[currRefIdx];
CodecEncodeHevcFeiPicParams *feiPicParams = (CodecEncodeHevcFeiPicParams *)m_encodeParams.pFeiPicParams;
if ((m_codecFunction == CODECHAL_FUNCTION_ENC_PAK) ||
((m_codecFunction == CODECHAL_FUNCTION_FEI_ENC_PAK) && (feiPicParams->bCTBCmdCuRecordEnable == false)) ||
(m_codecFunction == CODECHAL_FUNCTION_ENC_VDENC_PAK))
{
m_currMinus2MbCodeIndex = m_lastMbCodeIndex;
m_lastMbCodeIndex = m_currMbCodeIdx;
// the actual MbCode/MvData surface to be allocated later
m_trackedBuf->SetAllocationFlag(true);
}
else if (m_codecFunction == CODECHAL_FUNCTION_ENC)
{
CODECHAL_ENCODE_CHK_NULL_RETURN(m_encodeParams.presMbCodeSurface);
m_resMbCodeSurface = *m_encodeParams.presMbCodeSurface;
}
else if(((m_codecFunction == CODECHAL_FUNCTION_FEI_ENC_PAK) && feiPicParams->bCTBCmdCuRecordEnable) ||
(m_codecFunction == CODECHAL_FUNCTION_FEI_ENC) ||
(m_codecFunction == CODECHAL_FUNCTION_FEI_PAK))
{
if(Mos_ResourceIsNull(&feiPicParams->resCURecord) || Mos_ResourceIsNull(&feiPicParams->resCTBCmd))
{
return MOS_STATUS_INVALID_PARAMETER;
}
}
refListFull[currRefIdx]->iFieldOrderCnt[0] = m_hevcPicParams->CurrPicOrderCnt;
refListFull[currRefIdx]->iFieldOrderCnt[1] = m_hevcPicParams->CurrPicOrderCnt;
m_hmeEnabled = m_hmeSupported && m_pictureCodingType != I_TYPE;
m_b16XMeEnabled = m_16xMeSupported && m_pictureCodingType != I_TYPE;
m_b32XMeEnabled = m_32xMeSupported && m_pictureCodingType != I_TYPE;
CODECHAL_ENCODE_CHK_STATUS_RETURN(CalcLCUMaxCodingSize());
// Screen content flag will come in with PPS on Linux/Android, but in SPS on other platforms,
// we will use screen content flag in PPS for kernel programming, and update
// the PPS screen content flag based on the SPS screen content flag if enabled.
m_hevcPicParams->bScreenContent |= m_hevcSeqParams->bScreenContent;
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::CalcLCUMaxCodingSize()
{
CODECHAL_ENCODE_FUNCTION_ENTER;
uint16_t log2_max_coding_block_size = m_hevcSeqParams->log2_max_coding_block_size_minus3 + 3;
uint32_t rawCTUBits = (1 << (2 * log2_max_coding_block_size));
switch (m_hevcSeqParams->chroma_format_idc)
{
// 420
case 1:
rawCTUBits = rawCTUBits * 3 / 2;
break;
// 422
case 2:
rawCTUBits = rawCTUBits * 2;
break;
// 444
case 3:
rawCTUBits = rawCTUBits * 3;
break;
default:
break;
};
rawCTUBits = rawCTUBits * (m_hevcSeqParams->bit_depth_luma_minus8 + 8);
rawCTUBits = (5 * rawCTUBits / 3);
if (m_hevcPicParams->LcuMaxBitsizeAllowed == 0 || m_hevcPicParams->LcuMaxBitsizeAllowed > rawCTUBits)
{
m_hevcPicParams->LcuMaxBitsizeAllowed = rawCTUBits;
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS CodechalEncodeHevcBase::SetSliceStructs()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
if (m_numSlices > m_maxNumSlicesSupported)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Number of slice exceeds limit!");
return MOS_STATUS_INVALID_PARAMETER;
}
// first slice must come with slice_segment_address = 0
if (m_hevcSliceParams->slice_segment_address != 0)
{
CODECHAL_ENCODE_ASSERTMESSAGE("First slice segment_address != 0!");
return MOS_STATUS_INVALID_PARAMETER;
}
m_refList[m_currReconstructedPic.FrameIdx]->ucQPValue[0] = m_hevcPicParams->QpY + m_hevcSliceParams->slice_qp_delta;
m_lowDelay = true;
m_sameRefList = true;
m_arbitraryNumMbsInSlice = false;
uint32_t lcuInRow = MOS_ALIGN_CEIL(m_frameWidth, (1 << (m_hevcSeqParams->log2_max_coding_block_size_minus3 + 3))) >> (m_hevcSeqParams->log2_max_coding_block_size_minus3 + 3);
auto slcParams = m_hevcSliceParams;
for (uint32_t startLCU = 0, slcCount = 0; slcCount < m_numSlices; slcCount++, slcParams++)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(ValidateRefFrameData(slcParams));
if ((m_hevcPicParams->QpY + slcParams->slice_qp_delta) > CODECHAL_ENCODE_HEVC_MAX_SLICE_QP)
{
eStatus = MOS_STATUS_INVALID_PARAMETER;
return eStatus;
}
CODECHAL_ENCODE_CHK_STATUS_RETURN(ValidateLowDelayBFrame(slcParams));
CODECHAL_ENCODE_CHK_STATUS_RETURN(ValidateSameRefInL0L1(slcParams));
if (m_arbitraryNumMbsInSlice == false && (slcParams->NumLCUsInSlice % lcuInRow))
{
// Slice number must be multiple of LCU rows
m_arbitraryNumMbsInSlice = true;
}
if (!m_hevcPicParams->tiles_enabled_flag)
{
CODECHAL_ENCODE_ASSERT(slcParams->slice_segment_address == startLCU);
startLCU += slcParams->NumLCUsInSlice;
}
}
if (m_lowDelay && !m_sameRefList)
{
CODECHAL_ENCODE_NORMALMESSAGE("Attention: LDB frame but with different L0/L1 list !");
}
if (m_hevcSeqParams->RateControlMethod == RATECONTROL_VCM && m_pictureCodingType == B_TYPE && !m_lowDelay)
{
CODECHAL_ENCODE_ASSERTMESSAGE("VCM BRC mode does not support regular B-frames\n");
return MOS_STATUS_INVALID_PARAMETER;
}
CODECHAL_ENCODE_CHK_STATUS_RETURN(VerifySliceSAOState());
#if (_DEBUG || _RELEASE_INTERNAL)
if (!m_vdencEnabled)
{
m_forceSinglePakPass = false;
MOS_USER_FEATURE_VALUE_DATA userFeatureData;
MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
//read user feature key for pak pass number forcing.
MOS_UserFeature_ReadValue_ID(
nullptr,
__MEDIA_USER_FEATURE_VALUE_FORCE_PAK_PASS_NUM_ID,
&userFeatureData,
m_osInterface->pOsContext);
if (userFeatureData.u32Data > 0 && userFeatureData.u32Data <= m_numPasses)
{
m_numPasses = (uint8_t)userFeatureData.u32Data - 1;
if (m_numPasses == 0)
{
m_forceSinglePakPass = true;
CODECHAL_ENCODE_VERBOSEMESSAGE("Force to single PAK pass\n");
}
}
}
#endif
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::ValidateSameRefInL0L1(PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(slcParams);
if (m_sameRefList &&
slcParams->num_ref_idx_l0_active_minus1 >= slcParams->num_ref_idx_l1_active_minus1)
{
for (int refIdx = 0; refIdx < slcParams->num_ref_idx_l1_active_minus1 + 1; refIdx++)
{
CODEC_PICTURE refPicL0 = slcParams->RefPicList[0][refIdx];
CODEC_PICTURE refPicL1 = slcParams->RefPicList[1][refIdx];
if (!CodecHal_PictureIsInvalid(refPicL0) && !CodecHal_PictureIsInvalid(refPicL1) && refPicL0.FrameIdx != refPicL1.FrameIdx)
{
m_sameRefList = false;
break;
}
}
}
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::ValidateLowDelayBFrame(PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(slcParams);
// Examine if now it is in the low delay mode
if (slcParams->slice_type == CODECHAL_ENCODE_HEVC_B_SLICE && m_lowDelay)
{
// forward
for (int refIdx = 0; (refIdx < slcParams->num_ref_idx_l0_active_minus1 + 1) && m_lowDelay; refIdx++)
{
if (refIdx >= CODEC_MAX_NUM_REF_FRAME_HEVC)
{
break;
}
CODEC_PICTURE refPic = slcParams->RefPicList[0][refIdx];
if (!CodecHal_PictureIsInvalid(refPic) && m_hevcPicParams->RefFramePOCList[refPic.FrameIdx] > m_hevcPicParams->CurrPicOrderCnt)
{
m_lowDelay = false;
}
}
// backward
for (int refIdx = 0; (refIdx < slcParams->num_ref_idx_l1_active_minus1 + 1) && m_lowDelay; refIdx++)
{
if (refIdx >= CODEC_MAX_NUM_REF_FRAME_HEVC)
{
break;
}
CODEC_PICTURE refPic = slcParams->RefPicList[1][refIdx];
if (!CodecHal_PictureIsInvalid(refPic) && m_hevcPicParams->RefFramePOCList[refPic.FrameIdx] > m_hevcPicParams->CurrPicOrderCnt)
{
m_lowDelay = false;
}
}
}
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::VerifySliceSAOState()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
if (m_hevcSeqParams->SAO_enabled_flag)
{
auto slcParams = m_hevcSliceParams;
uint32_t slcSaoLumaCount = 0, slcSaoChromaCount = 0;
for (uint32_t slcCount = 0; slcCount < m_numSlices; slcCount++, slcParams++)
{
slcSaoLumaCount += slcParams->slice_sao_luma_flag;
slcSaoChromaCount += slcParams->slice_sao_chroma_flag;
}
// For HCP_SLICE_STATE command, slices must have the same SAO setting within a picture for encoder.
if (((slcSaoLumaCount > 0) && (slcSaoLumaCount != m_numSlices)) ||
((slcSaoChromaCount > 0) && (slcSaoChromaCount != m_numSlices)))
{
m_hevcSeqParams->SAO_enabled_flag = false;
CODECHAL_ENCODE_ASSERTMESSAGE("Invalid SAO parameters in slice. All slices must have the same SAO setting within a picture.");
}
}
m_uc2NdSaoPass = 0; // Assume there is no 2nd SAO pass
if (m_hevcSeqParams->SAO_enabled_flag && m_b2NdSaoPassNeeded)
{
m_numPasses = m_numPasses + 1; // one more pass for the 2nd SAO, i.e., BRC0, BRC1, ..., BRCn, and SAOn+1
m_uc2NdSaoPass = m_numPasses;
}
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::UpdateYUY2SurfaceInfo(
PMOS_SURFACE surface,
bool is10Bit)
{
CODECHAL_ENCODE_FUNCTION_ENTER;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_CHK_NULL_RETURN(surface);
if (Format_YUY2V == surface->Format ||
Format_Y216V == surface->Format)
{
// surface has been updated
return eStatus;
}
surface->Format = is10Bit ? Format_Y216V : Format_YUY2V;
surface->dwWidth = m_oriFrameWidth;
surface->dwHeight = m_oriFrameHeight;
surface->YPlaneOffset.iXOffset = 0;
surface->YPlaneOffset.iYOffset = 0;
surface->UPlaneOffset.iSurfaceOffset = surface->YPlaneOffset.iSurfaceOffset + surface->dwHeight * surface->dwPitch;
surface->UPlaneOffset.iXOffset = 0;
surface->UPlaneOffset.iYOffset = surface->dwHeight;
surface->VPlaneOffset.iSurfaceOffset = surface->UPlaneOffset.iSurfaceOffset;
surface->VPlaneOffset.iXOffset = 0;
surface->VPlaneOffset.iYOffset = surface->dwHeight;
return eStatus;
}
void CodechalEncodeHevcBase::CreateFlatScalingList()
{
CODECHAL_ENCODE_FUNCTION_ENTER;
for (auto i = 0; i < 6; i++)
{
memset(&(m_hevcIqMatrixParams->ucScalingLists0[i][0]),
0x10,
sizeof(m_hevcIqMatrixParams->ucScalingLists0[i]));
memset(&(m_hevcIqMatrixParams->ucScalingLists1[i][0]),
0x10,
sizeof(m_hevcIqMatrixParams->ucScalingLists1[i]));
memset(&(m_hevcIqMatrixParams->ucScalingLists2[i][0]),
0x10,
sizeof(m_hevcIqMatrixParams->ucScalingLists2[i]));
}
memset(&(m_hevcIqMatrixParams->ucScalingLists3[0][0]),
0x10,
sizeof(m_hevcIqMatrixParams->ucScalingLists3[0]));
memset(&(m_hevcIqMatrixParams->ucScalingLists3[1][0]),
0x10,
sizeof(m_hevcIqMatrixParams->ucScalingLists3[1]));
memset(&(m_hevcIqMatrixParams->ucScalingListDCCoefSizeID2[0]),
0x10,
sizeof(m_hevcIqMatrixParams->ucScalingListDCCoefSizeID2));
memset(&(m_hevcIqMatrixParams->ucScalingListDCCoefSizeID3[0]),
0x10,
sizeof(m_hevcIqMatrixParams->ucScalingListDCCoefSizeID3));
}
void CodechalEncodeHevcBase::CreateDefaultScalingList()
{
CODECHAL_ENCODE_FUNCTION_ENTER;
const uint8_t flatScalingList4x4[16] =
{
16,16,16,16,
16,16,16,16,
16,16,16,16,
16,16,16,16
};
const uint8_t defaultScalingList8x8[2][64] =
{
{
16,16,16,16,17,18,21,24,
16,16,16,16,17,19,22,25,
16,16,17,18,20,22,25,29,
16,16,18,21,24,27,31,36,
17,17,20,24,30,35,41,47,
18,19,22,27,35,44,54,65,
21,22,25,31,41,54,70,88,
24,25,29,36,47,65,88,115
},
{
16,16,16,16,17,18,20,24,
16,16,16,17,18,20,24,25,
16,16,17,18,20,24,25,28,
16,17,18,20,24,25,28,33,
17,18,20,24,25,28,33,41,
18,20,24,25,28,33,41,54,
20,24,25,28,33,41,54,71,
24,25,28,33,41,54,71,91
}
};
for (auto i = 0; i < 6; i++)
{
memcpy(&(m_hevcIqMatrixParams->ucScalingLists0[i][0]),
flatScalingList4x4,
sizeof(m_hevcIqMatrixParams->ucScalingLists0[i]));
}
for (auto i = 0; i < 3; i++)
{
memcpy(&(m_hevcIqMatrixParams->ucScalingLists1[i][0]),
defaultScalingList8x8[0],
sizeof(m_hevcIqMatrixParams->ucScalingLists1[i]));
memcpy(&(m_hevcIqMatrixParams->ucScalingLists1[3 + i][0]),
defaultScalingList8x8[1],
sizeof(m_hevcIqMatrixParams->ucScalingLists1[3 + i]));
memcpy(&(m_hevcIqMatrixParams->ucScalingLists2[i][0]),
defaultScalingList8x8[0],
sizeof(m_hevcIqMatrixParams->ucScalingLists2[i]));
memcpy(&(m_hevcIqMatrixParams->ucScalingLists2[3 + i][0]),
defaultScalingList8x8[1],
sizeof(m_hevcIqMatrixParams->ucScalingLists2[3 + i]));
}
memcpy(&(m_hevcIqMatrixParams->ucScalingLists3[0][0]),
defaultScalingList8x8[0],
sizeof(m_hevcIqMatrixParams->ucScalingLists3[0]));
memcpy(&(m_hevcIqMatrixParams->ucScalingLists3[1][0]),
defaultScalingList8x8[1],
sizeof(m_hevcIqMatrixParams->ucScalingLists3[1]));
memset(&(m_hevcIqMatrixParams->ucScalingListDCCoefSizeID2[0]),
0x10,
sizeof(m_hevcIqMatrixParams->ucScalingListDCCoefSizeID2));
memset(&(m_hevcIqMatrixParams->ucScalingListDCCoefSizeID3[0]),
0x10,
sizeof(m_hevcIqMatrixParams->ucScalingListDCCoefSizeID3));
}
MOS_STATUS CodechalEncodeHevcBase::VerifyCommandBufferSize()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
// resize CommandBuffer Size for every BRC pass
if (!m_singleTaskPhaseSupported)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(VerifySpaceAvailable());
}
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::GetCommandBuffer(PMOS_COMMAND_BUFFER cmdBuffer)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, cmdBuffer, 0));
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::ReturnCommandBuffer(PMOS_COMMAND_BUFFER cmdBuffer)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
m_osInterface->pfnReturnCommandBuffer(m_osInterface, cmdBuffer, 0);
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::SubmitCommandBuffer(
PMOS_COMMAND_BUFFER cmdBuffer,
bool nullRendering)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, cmdBuffer, nullRendering));
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::SendPrologWithFrameTracking(
PMOS_COMMAND_BUFFER cmdBuffer,
bool frameTrackingRequested,
MHW_MI_MMIOREGISTERS *mmioRegister)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::SendPrologWithFrameTracking(cmdBuffer, frameTrackingRequested, mmioRegister));
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::GetMaxMBPS(uint32_t levelIdc, uint32_t* maxMBPS, uint64_t* maxBytePerPic)
{
CODECHAL_ENCODE_FUNCTION_ENTER;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_CHK_NULL_RETURN(maxMBPS);
CODECHAL_ENCODE_CHK_NULL_RETURN(maxBytePerPic);
switch (levelIdc)
{
case 30:
*maxMBPS = 552960;
*maxBytePerPic = 36864; break;
case 60:
*maxMBPS = 3686400;
*maxBytePerPic = 122880; break;
case 63:
*maxMBPS = 7372800;
*maxBytePerPic = 245760; break;
case 90:
*maxMBPS = 16588800;
*maxBytePerPic = 552760; break;
case 93:
*maxMBPS = 33177600;
*maxBytePerPic = 983040; break;
case 120:
*maxMBPS = 66846720;
*maxBytePerPic = 2228224; break;
case 123:
*maxMBPS = 133693440;
*maxBytePerPic = 2228224; break;
case 150:
*maxMBPS = 267386880;
*maxBytePerPic = 8912896; break;
case 153:
*maxMBPS = 534773760;
*maxBytePerPic = 8912896; break;
case 156:
*maxMBPS = 1069547520;
*maxBytePerPic = 8912896; break;
case 180:
*maxMBPS = 1069547520;
*maxBytePerPic = 35651584; break;
case 183:
*maxMBPS = 2139095040;
*maxBytePerPic = 35651584; break;
case 186:
*maxMBPS = 4278190080;
*maxBytePerPic = 35651584; break;
default:
*maxMBPS = 16588800;
*maxBytePerPic = 552760; // CModel defaults to level 3.0 value if not found,
// we can do the same, just output that the issue exists and continue
CODECHAL_ENCODE_ASSERTMESSAGE("Unsupported LevelIDC setting for HEVC");
break;
}
return eStatus;
}
uint32_t CodechalEncodeHevcBase::GetProfileLevelMaxFrameSize()
{
CODECHAL_ENCODE_FUNCTION_ENTER;
uint8_t minCR = 2;
float_t formatFactor = 1.5;
float_t fminCrScale = 1.0;
uint32_t maxMBPS;
uint64_t maxBytePerPic;
int32_t levelIdc = m_hevcSeqParams->Level * 3;
if (levelIdc == 186 || levelIdc == 150)
{
minCR = 6;
}
else if (levelIdc >150)
{
minCR = 8;
}
else if (levelIdc >93)
{
minCR = 4;
}
if (m_hevcSeqParams->chroma_format_idc == 0)
{
if (m_hevcSeqParams->bit_depth_luma_minus8 == 0)
formatFactor = 1.0;
else if (m_hevcSeqParams->bit_depth_luma_minus8 == 8)
formatFactor = 2.0;
}
else if (m_hevcSeqParams->chroma_format_idc == 1)
{
if (m_hevcSeqParams->bit_depth_luma_minus8 == 2)
{
formatFactor = 1.875;
}
else if (m_hevcSeqParams->bit_depth_luma_minus8 == 4)
{
formatFactor = 2.25;
}
}
else if (m_hevcSeqParams->chroma_format_idc == 2)
{
fminCrScale = 0.5;
if (m_hevcSeqParams->bit_depth_luma_minus8 == 2)
{
formatFactor = 2.5;
}
else if (m_hevcSeqParams->bit_depth_luma_minus8 == 4)
{
formatFactor = 3.0;
}
}
else
{
fminCrScale = 0.5;
formatFactor = 3.0;
if (m_hevcSeqParams->bit_depth_luma_minus8 == 2)
{
formatFactor = 3.75;
}
else if (m_hevcSeqParams->bit_depth_luma_minus8 == 4)
{
formatFactor = 4.5;
}
}
fminCrScale *= minCR;
formatFactor /= fminCrScale;
GetMaxMBPS(levelIdc, &maxMBPS, &maxBytePerPic);
auto maxBytePerPicNot0 = (uint64_t)((((float_t)maxMBPS * (float_t)m_hevcSeqParams->FrameRate.Denominator) / (float_t)m_hevcSeqParams->FrameRate.Numerator) * formatFactor);
uint32_t profileLevelMaxFrame = 0;
uint32_t userMaxFrameSize = m_hevcSeqParams->UserMaxIFrameSize;
if ((m_hevcPicParams->CodingType != I_TYPE) && (m_hevcSeqParams->UserMaxPBFrameSize > 0))
{
userMaxFrameSize = m_hevcSeqParams->UserMaxPBFrameSize;
}
if (userMaxFrameSize != 0)
{
profileLevelMaxFrame = (uint32_t)MOS_MIN(userMaxFrameSize, maxBytePerPic);
profileLevelMaxFrame = (uint32_t)MOS_MIN(maxBytePerPicNot0, profileLevelMaxFrame);
}
else {
profileLevelMaxFrame = (uint32_t)MOS_MIN(maxBytePerPicNot0, maxBytePerPic);
}
profileLevelMaxFrame = (uint32_t)MOS_MIN((m_frameHeight * m_frameWidth), profileLevelMaxFrame);
return profileLevelMaxFrame;
}
void CodechalEncodeHevcBase::CalcTransformSkipParameters(
MHW_VDBOX_ENCODE_HEVC_TRANSFORM_SKIP_PARAMS& params)
{
CODECHAL_ENCODE_FUNCTION_ENTER;
if (!m_hevcPicParams->transform_skip_enabled_flag)
{
return;
}
params.Transformskip_enabled = true;
int sliceQP = CalSliceQp();
int qpIdx = 0;
if (sliceQP <= 22)
{
qpIdx = 0;
}
else if (sliceQP <= 27)
{
qpIdx = 1;
}
else if (sliceQP <= 32)
{
qpIdx = 2;
}
else
{
qpIdx = 3;
}
params.Transformskip_lambda = TransformSkipLambdaTable[sliceQP];
if (m_hevcPicParams->CodingType == I_TYPE)
{
params.Transformskip_Numzerocoeffs_Factor0 = TransformSkipCoeffsTable[qpIdx][0][0][0][0];
params.Transformskip_Numzerocoeffs_Factor1 = TransformSkipCoeffsTable[qpIdx][0][0][1][0];
params.Transformskip_Numnonzerocoeffs_Factor0 = TransformSkipCoeffsTable[qpIdx][0][0][0][1] + 32;
params.Transformskip_Numnonzerocoeffs_Factor1 = TransformSkipCoeffsTable[qpIdx][0][0][1][1] + 32;
}
else
{
params.Transformskip_Numzerocoeffs_Factor0 = TransformSkipCoeffsTable[qpIdx][1][0][0][0];
params.Transformskip_Numzerocoeffs_Factor1 = TransformSkipCoeffsTable[qpIdx][1][0][1][0];
params.Transformskip_Numnonzerocoeffs_Factor0 = TransformSkipCoeffsTable[qpIdx][1][0][0][1] + 32;
params.Transformskip_Numnonzerocoeffs_Factor1 = TransformSkipCoeffsTable[qpIdx][1][0][1][1] + 32;
}
}
MOS_STATUS CodechalEncodeHevcBase::SetSemaphoreMem(
PMOS_RESOURCE semaphoreMem,
PMOS_COMMAND_BUFFER cmdBuffer,
uint32_t value)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(semaphoreMem);
CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
MHW_MI_STORE_DATA_PARAMS storeDataParams;
MOS_ZeroMemory(&storeDataParams, sizeof(storeDataParams));
storeDataParams.pOsResource = semaphoreMem;
storeDataParams.dwResourceOffset = 0;
storeDataParams.dwValue = value;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(
cmdBuffer,
&storeDataParams));
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::SendHWWaitCommand(
PMOS_RESOURCE semaphoreMem,
PMOS_COMMAND_BUFFER cmdBuffer,
uint32_t semValue)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(semaphoreMem);
CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
MHW_MI_SEMAPHORE_WAIT_PARAMS miSemaphoreWaitParams;
MOS_ZeroMemory(&miSemaphoreWaitParams, sizeof(miSemaphoreWaitParams));
miSemaphoreWaitParams.presSemaphoreMem = semaphoreMem;
miSemaphoreWaitParams.bPollingWaitMode = true;
miSemaphoreWaitParams.dwSemaphoreData = semValue;
miSemaphoreWaitParams.CompareOperation = MHW_MI_SAD_EQUAL_SDD;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiSemaphoreWaitCmd(cmdBuffer, &miSemaphoreWaitParams));
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::SendMIAtomicCmd(
PMOS_RESOURCE semaMem,
uint32_t immData,
MHW_COMMON_MI_ATOMIC_OPCODE opCode,
PMOS_COMMAND_BUFFER cmdBuffer
)
{
MHW_MI_ATOMIC_PARAMS atomicParams;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
MOS_ZeroMemory((&atomicParams), sizeof(atomicParams));
atomicParams.pOsResource = semaMem;
atomicParams.dwDataSize = sizeof(uint32_t);
atomicParams.Operation = opCode;
atomicParams.bInlineData = true;
atomicParams.dwOperand1Data[0] = immData;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiAtomicCmd(cmdBuffer, &atomicParams));
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::WaitForVDBOX(PMOS_COMMAND_BUFFER cmdBuffer)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
if (!m_firstFrame &&
!Mos_ResourceIsNull(&m_refSync[m_lastMbCodeIndex].resSemaphoreMem.sResource))
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(
SendHWWaitCommand(
&m_refSync[m_lastMbCodeIndex].resSemaphoreMem.sResource,
cmdBuffer,
1));
}
//keep these codes here, in case later we need support parallel frame PAK (need more than one set of internal buffers used by PAK HW).
#if 0
if (m_pictureCodingType == I_TYPE)
{
return eStatus;
}
bool refHasBeenWaited[CODEC_NUM_TRACKED_BUFFERS] = { false };
// check all reference frames. If one of them has not be waited, then it needs to be wait and ensure it has been encoded completely.
PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams = pHevcSliceParams;
for (uint32_t s = 0; s < m_numSlices; s++, slcParams++)
{
for (auto ll = 0; ll < 2; ll++)
{
uint32_t numRef = (ll == 0) ? slcParams->num_ref_idx_l0_active_minus1 :
slcParams->num_ref_idx_l1_active_minus1;
for (uint32_t i = 0; i <= numRef; i++)
{
CODEC_PICTURE refPic = slcParams->RefPicList[ll][i];
if (!CodecHal_PictureIsInvalid(refPic) &&
!CodecHal_PictureIsInvalid(pHevcPicParams->RefFrameList[refPic.FrameIdx]))
{
uint32_t idx = pHevcPicParams->RefFrameList[refPic.FrameIdx].FrameIdx;
uint8_t ucMbCodeIdx = pRefList[idx]->ucMbCodeIdx;
if (ucMbCodeIdx >= CODEC_NUM_TRACKED_BUFFERS)
{
// MB code index is wrong
eStatus = MOS_STATUS_INVALID_PARAMETER;
return eStatus;
}
if (refHasBeenWaited[ucMbCodeIdx] || Mos_ResourceIsNull(&RefSync[ucMbCodeIdx].resSemaphoreMem.sResource))
{
continue;
}
// Use HW wait command
CODECHAL_ENCODE_CHK_STATUS_RETURN(
SendHWWaitCommand(
&RefSync[ucMbCodeIdx].resSemaphoreMem.sResource,
cmdBuffer, 1));
refHasBeenWaited[ucMbCodeIdx] = true;
}
}
}
}
#endif
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::ReadBrcPakStatistics(
PMOS_COMMAND_BUFFER cmdBuffer,
EncodeReadBrcPakStatsParams* params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
CODECHAL_ENCODE_CHK_NULL_RETURN(params);
CODECHAL_ENCODE_CHK_NULL_RETURN(params->presBrcPakStatisticBuffer);
CODECHAL_ENCODE_CHK_NULL_RETURN(params->presStatusBuffer);
if (m_vdboxIndex > m_mfxInterface->GetMaxVdboxIndex()) \
{
CODECHAL_ENCODE_ASSERTMESSAGE("ERROR - vdbox index exceed the maximum");
eStatus = MOS_STATUS_INVALID_PARAMETER;
return eStatus;
}
auto mmioRegisters = m_hcpInterface->GetMmioRegisters(m_vdboxIndex);
MHW_MI_STORE_REGISTER_MEM_PARAMS miStoreRegMemParams;
MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
miStoreRegMemParams.presStoreBuffer = params->presBrcPakStatisticBuffer;
miStoreRegMemParams.dwOffset = CODECHAL_OFFSETOF(CODECHAL_ENCODE_HEVC_PAK_STATS_BUFFER, HCP_BITSTREAM_BYTECOUNT_FRAME);
miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncBitstreamBytecountFrameRegOffset;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
miStoreRegMemParams.presStoreBuffer = params->presBrcPakStatisticBuffer;
miStoreRegMemParams.dwOffset = CODECHAL_OFFSETOF(CODECHAL_ENCODE_HEVC_PAK_STATS_BUFFER, HCP_BITSTREAM_BYTECOUNT_FRAME_NOHEADER);
miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncBitstreamBytecountFrameNoHeaderRegOffset;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
miStoreRegMemParams.presStoreBuffer = params->presBrcPakStatisticBuffer;
miStoreRegMemParams.dwOffset = CODECHAL_OFFSETOF(CODECHAL_ENCODE_HEVC_PAK_STATS_BUFFER, HCP_IMAGE_STATUS_CONTROL);
miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncImageStatusCtrlRegOffset;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
MHW_MI_STORE_DATA_PARAMS storeDataParams;
storeDataParams.pOsResource = params->presStatusBuffer;
storeDataParams.dwResourceOffset = params->dwStatusBufNumPassesOffset;
storeDataParams.dwValue = params->ucPass;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(cmdBuffer, &storeDataParams));
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::ReadHcpStatus(PMOS_COMMAND_BUFFER cmdBuffer)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
EncodeStatusBuffer *encodeStatusBuf = &m_encodeStatusBuf;
uint32_t baseOffset =
(encodeStatusBuf->wCurrIndex * encodeStatusBuf->dwReportSize) +
sizeof(uint32_t) * 2; // pEncodeStatus is offset by 2 DWs in the resource
MHW_MI_FLUSH_DW_PARAMS flushDwParams;
MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(cmdBuffer, &flushDwParams));
auto mmioRegisters = m_hcpInterface->GetMmioRegisters(m_vdboxIndex);
MHW_MI_STORE_REGISTER_MEM_PARAMS miStoreRegMemParams;
MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
miStoreRegMemParams.presStoreBuffer = &encodeStatusBuf->resStatusBuffer;
miStoreRegMemParams.dwOffset = baseOffset + encodeStatusBuf->dwBSByteCountOffset;
miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncBitstreamBytecountFrameRegOffset;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
miStoreRegMemParams.presStoreBuffer = &encodeStatusBuf->resStatusBuffer;
miStoreRegMemParams.dwOffset = baseOffset + encodeStatusBuf->dwBSSEBitCountOffset;
miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncBitstreamSeBitcountFrameRegOffset;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
miStoreRegMemParams.presStoreBuffer = &encodeStatusBuf->resStatusBuffer;
miStoreRegMemParams.dwOffset = baseOffset + encodeStatusBuf->dwQpStatusCountOffset;
miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncQpStatusCountRegOffset;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::ReadImageStatus(PMOS_COMMAND_BUFFER cmdBuffer)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
EncodeStatusBuffer *encodeStatusBuf = &m_encodeStatusBuf;
uint32_t baseOffset =
(encodeStatusBuf->wCurrIndex * encodeStatusBuf->dwReportSize) +
sizeof(uint32_t) * 2; // pEncodeStatus is offset by 2 DWs in the resource
auto mmioRegisters = m_hcpInterface->GetMmioRegisters(m_vdboxIndex);
MHW_MI_STORE_REGISTER_MEM_PARAMS miStoreRegMemParams;
MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
miStoreRegMemParams.presStoreBuffer = &encodeStatusBuf->resStatusBuffer;
miStoreRegMemParams.dwOffset = baseOffset + encodeStatusBuf->dwImageStatusMaskOffset;
miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncImageStatusMaskRegOffset;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
miStoreRegMemParams.presStoreBuffer = &encodeStatusBuf->resStatusBuffer;
miStoreRegMemParams.dwOffset = baseOffset + encodeStatusBuf->dwImageStatusCtrlOffset;
miStoreRegMemParams.dwRegister = mmioRegisters->hcpEncImageStatusCtrlRegOffset;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));
MHW_MI_FLUSH_DW_PARAMS flushDwParams;
MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(cmdBuffer, &flushDwParams));
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::UserFeatureKeyReport()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::UserFeatureKeyReport())
CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_HEVC_ENCODE_MODE_ID, m_codecFunction, m_osInterface->pOsContext);
CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_HEVC_ENCODE_ME_ENABLE_ID, m_hmeSupported, m_osInterface->pOsContext);
CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_HEVC_ENCODE_16xME_ENABLE_ID, m_16xMeSupported, m_osInterface->pOsContext);
CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_HEVC_ENCODE_32xME_ENABLE_ID, m_32xMeSupported, m_osInterface->pOsContext);
CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_HEVC_ENCODE_26Z_ENABLE_ID, (!m_enable26WalkingPattern), m_osInterface->pOsContext);
CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_ENCODE_RATECONTROL_METHOD_ID, m_hevcSeqParams->RateControlMethod, m_osInterface->pOsContext);
#if (_DEBUG || _RELEASE_INTERNAL)
CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_SIM_IN_USE_ID, m_osInterface->bSimIsActive, m_osInterface->pOsContext);
CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_HEVC_ENCODE_RDOQ_ENABLE_ID, m_hevcRdoqEnabled, m_osInterface->pOsContext);
#endif
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::GetStatusReport(
EncodeStatus *encodeStatus,
EncodeStatusReport *encodeStatusReport)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(encodeStatus);
CODECHAL_ENCODE_CHK_NULL_RETURN(encodeStatusReport);
// The last pass of BRC may have a zero value of hcpCumulativeFrameDeltaQp
if (encodeStatus->ImageStatusCtrl.hcpTotalPass && encodeStatus->ImageStatusCtrl.hcpCumulativeFrameDeltaQp == 0)
{
encodeStatus->ImageStatusCtrl.hcpCumulativeFrameDeltaQp = encodeStatus->ImageStatusCtrlOfLastBRCPass.hcpCumulativeFrameDeltaQp;
}
encodeStatus->ImageStatusCtrlOfLastBRCPass.hcpCumulativeFrameDeltaQp = 0;
encodeStatusReport->CodecStatus = CODECHAL_STATUS_SUCCESSFUL;
encodeStatusReport->bitstreamSize = encodeStatus->dwMFCBitstreamByteCountPerFrame + encodeStatus->dwHeaderBytesInserted;
encodeStatusReport->PanicMode = encodeStatus->ImageStatusCtrl.Panic;
encodeStatusReport->AverageQp = 0;
encodeStatusReport->QpY = 0;
encodeStatusReport->SuggestedQpYDelta = encodeStatus->ImageStatusCtrl.hcpCumulativeFrameDeltaQp;
encodeStatusReport->NumberPasses = (unsigned char)encodeStatus->ImageStatusCtrl.hcpTotalPass + 1; //initial pass is considered to be 0,hence +1 to report;
CODECHAL_ENCODE_VERBOSEMESSAGE("Single Pipe Mode Exectued PAK Pass number: %d\n", encodeStatusReport->NumberPasses);
if (m_frameWidth != 0 && m_frameHeight != 0)
{
// Based on HW team:
// The CumulativeQp from the PAK accumulated at TU level and normalized to TU4x4
// qp(for TU 8x8) = qp*4
// qp(for TU 16x16) = qp *16
// qp(for TU 32x32) = qp*64
// all these qp are accumulated for entire frame.
// the HW will ceil the CumulativeQp number to max (24 bit)
encodeStatusReport->QpY = encodeStatusReport->AverageQp =
(uint8_t)(((uint32_t)encodeStatus->QpStatusCount.hcpCumulativeQP)
/ ((MOS_ALIGN_CEIL(m_frameWidth, (1 << 2)) >> 2) *
(MOS_ALIGN_CEIL(m_frameHeight, (1 << 2)) >> 2)));
}
if (!Mos_ResourceIsNull(&m_resFrameStatStreamOutBuffer))
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(CalculatePSNR(encodeStatus, encodeStatusReport));
}
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::InitializePicture(const EncoderParams& params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
m_hevcSeqParams = (PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS)(params.pSeqParams);
m_hevcPicParams = (PCODEC_HEVC_ENCODE_PICTURE_PARAMS)(params.pPicParams);
m_hevcSliceParams = (PCODEC_HEVC_ENCODE_SLICE_PARAMS)params.pSliceParams;
m_hevcFeiPicParams = (CodecEncodeHevcFeiPicParams *)params.pFeiPicParams;
m_hevcIqMatrixParams = (PCODECHAL_HEVC_IQ_MATRIX_PARAMS)params.pIQMatrixBuffer;
m_nalUnitParams = params.ppNALUnitParams;
CODECHAL_ENCODE_CHK_NULL_RETURN(m_hevcSeqParams);
CODECHAL_ENCODE_CHK_NULL_RETURN(m_hevcPicParams);
CODECHAL_ENCODE_CHK_NULL_RETURN(m_hevcSliceParams);
CODECHAL_ENCODE_CHK_NULL_RETURN(m_hevcIqMatrixParams);
CODECHAL_ENCODE_CHK_NULL_RETURN(m_nalUnitParams);
CODECHAL_ENCODE_CHK_STATUS_RETURN(PlatformCapabilityCheck());
if (CodecHalIsFeiEncode(m_codecFunction))
{
CODECHAL_ENCODE_CHK_NULL_RETURN(m_hevcFeiPicParams);
m_hevcSeqParams->TargetUsage = 0x04;
}
if (m_newSeq)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(SetSequenceStructs());
if (m_hevcSeqParams->log2_min_coding_block_size_minus3)
{
m_cscDsState->SetHcpReconAlignment(1 << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3));
}
}
if (const_cast<EncoderParams *>(&params)->bAcceleratorHeaderPackingCaps)
{
HevcHeaderPacker Packer;
Packer.SliceHeaderPacker(const_cast<EncoderParams *>(&params));
}
CODECHAL_ENCODE_CHK_STATUS_RETURN(SetPictureStructs());
CODECHAL_ENCODE_CHK_STATUS_RETURN(SetSliceStructs());
// Scaling occurs when either HME or BRC is enabled
m_scalingEnabled = m_hmeSupported || m_brcEnabled;
m_useRawForRef = m_hevcPicParams->bUseRawPicForRef;
if (m_hevcPicParams->SkipFrameFlag == FRAME_SKIP_NORMAL)
{
m_skipFrameFlag = m_hevcPicParams->SkipFrameFlag;
m_numSkipFrames = m_hevcPicParams->NumSkipFrames;
m_sizeSkipFrames = m_hevcPicParams->SizeSkipFrames;
}
m_pictureStatesSize = m_defaultPictureStatesSize;
m_picturePatchListSize = m_defaultPicturePatchListSize;
m_sliceStatesSize = m_defaultSliceStatesSize;
m_slicePatchListSize = m_defaultSlicePatchListSize;
// Mb Qp data
m_mbQpDataEnabled = params.bMbQpDataEnabled;
if (m_mbQpDataEnabled)
{
m_mbQpDataSurface = *(params.psMbQpDataSurface);
}
CODECHAL_DEBUG_TOOL(
m_debugInterface->m_currPic = m_hevcPicParams->CurrOriginalPic;
m_debugInterface->m_bufferDumpFrameNum = m_storeData;
m_debugInterface->m_frameType = m_pictureCodingType;
if (m_newSeq) {
CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpSeqParams(
m_hevcSeqParams));
}
CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpPicParams(
m_hevcPicParams));
if (CodecHalIsFeiEncode(m_codecFunction)) {
CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpFeiPicParams(
m_hevcFeiPicParams));
}
for (uint32_t i = 0; i < m_numSlices; i++) {
CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpSliceParams(
&m_hevcSliceParams[i],
m_hevcPicParams));
})
CODECHAL_ENCODE_CHK_STATUS_RETURN(SetStatusReportParams(
m_refList[m_currReconstructedPic.FrameIdx]));
m_bitstreamUpperBound = m_encodeParams.dwBitstreamSize;
return eStatus;
}
void CodechalEncodeHevcBase::SetHcpPipeModeSelectParams(MHW_VDBOX_PIPE_MODE_SELECT_PARAMS& pipeModeSelectParams)
{
pipeModeSelectParams = {};
pipeModeSelectParams.Mode = m_mode;
pipeModeSelectParams.bStreamOutEnabled = m_vdencEnabled;
pipeModeSelectParams.bVdencEnabled = m_vdencEnabled;
pipeModeSelectParams.bRdoqEnable = m_hevcRdoqEnabled ? (m_pictureCodingType == I_TYPE ? m_hevcIFrameRdoqEnabled : 1) : 0;
pipeModeSelectParams.bAdvancedRateControlEnable = m_vdencBrcEnabled;
if (m_hevcSeqParams->SAO_enabled_flag)
{
// uses pipe mode select command to tell if this is the first or second pass of SAO
pipeModeSelectParams.bSaoFirstPass = !IsLastPass();
if (m_singleTaskPhaseSupportedInPak &&
m_b2NdSaoPassNeeded &&
m_brcEnabled)
{
if (GetCurrentPass() == m_uc2NdSaoPass - 1) // the last BRC pass. This separates BRC passes and the 2nd pass SAO into different DMA buffer submissions
{
m_lastTaskInPhase = true;
}
else if (GetCurrentPass() == m_uc2NdSaoPass) // the 2nd SAO pass
{
m_firstTaskInPhase = true;
m_lastTaskInPhase = true;
}
}
}
}
void CodechalEncodeHevcBase::SetHcpSrcSurfaceParams(MHW_VDBOX_SURFACE_PARAMS& srcSurfaceParams)
{
MOS_ZeroMemory(&srcSurfaceParams, sizeof(srcSurfaceParams));
srcSurfaceParams.Mode = m_mode;
srcSurfaceParams.psSurface = m_rawSurfaceToPak;
srcSurfaceParams.ucSurfaceStateId = CODECHAL_HCP_SRC_SURFACE_ID;
srcSurfaceParams.ucBitDepthLumaMinus8 = m_hevcSeqParams->bit_depth_luma_minus8;
srcSurfaceParams.ucBitDepthChromaMinus8 = m_hevcSeqParams->bit_depth_chroma_minus8;
srcSurfaceParams.bDisplayFormatSwizzle = m_hevcPicParams->bDisplayFormatSwizzle;
srcSurfaceParams.ChromaType = m_outputChromaFormat;
srcSurfaceParams.bSrc8Pak10Mode = false; //No usage for 8->10 bit encode
srcSurfaceParams.dwActualHeight = ((m_hevcSeqParams->wFrameHeightInMinCbMinus1 + 1) << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3));
#ifdef _MMC_SUPPORTED
m_mmcState->SetSurfaceState(&srcSurfaceParams);
#endif
}
void CodechalEncodeHevcBase::SetHcpReconSurfaceParams(MHW_VDBOX_SURFACE_PARAMS& reconSurfaceParams)
{
MOS_ZeroMemory(&reconSurfaceParams, sizeof(reconSurfaceParams));
reconSurfaceParams.Mode = m_mode;
reconSurfaceParams.psSurface = &m_reconSurface;
reconSurfaceParams.ucSurfaceStateId = CODECHAL_HCP_DECODED_SURFACE_ID;
reconSurfaceParams.ucBitDepthLumaMinus8 = m_hevcSeqParams->bit_depth_luma_minus8;
reconSurfaceParams.ucBitDepthChromaMinus8 = m_hevcSeqParams->bit_depth_chroma_minus8;
reconSurfaceParams.ChromaType = m_outputChromaFormat;
reconSurfaceParams.dwActualHeight = ((m_hevcSeqParams->wFrameHeightInMinCbMinus1 + 1) << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3));
reconSurfaceParams.dwReconSurfHeight = m_rawSurfaceToPak->dwHeight;
#ifdef _MMC_SUPPORTED
m_mmcState->SetSurfaceState(&reconSurfaceParams);
#endif
}
void CodechalEncodeHevcBase::SetHcpPipeBufAddrParams(MHW_VDBOX_PIPE_BUF_ADDR_PARAMS& pipeBufAddrParams)
{
CODECHAL_ENCODE_FUNCTION_ENTER;
pipeBufAddrParams = {};
pipeBufAddrParams.Mode = m_mode;
pipeBufAddrParams.psPreDeblockSurface = &m_reconSurface;
pipeBufAddrParams.psPostDeblockSurface = &m_reconSurface;
pipeBufAddrParams.psRawSurface = m_rawSurfaceToPak;
pipeBufAddrParams.presStreamOutBuffer = m_vdencEnabled ? &m_resStreamOutBuffer[0] : nullptr;
pipeBufAddrParams.presMfdDeblockingFilterRowStoreScratchBuffer = &m_resDeblockingFilterRowStoreScratchBuffer;
pipeBufAddrParams.presDeblockingFilterTileRowStoreScratchBuffer = &m_resDeblockingFilterTileRowStoreScratchBuffer;
pipeBufAddrParams.presDeblockingFilterColumnRowStoreScratchBuffer = &m_resDeblockingFilterColumnRowStoreScratchBuffer;
pipeBufAddrParams.presMetadataLineBuffer = &m_resMetadataLineBuffer;
pipeBufAddrParams.presMetadataTileLineBuffer = &m_resMetadataTileLineBuffer;
pipeBufAddrParams.presMetadataTileColumnBuffer = &m_resMetadataTileColumnBuffer;
pipeBufAddrParams.presSaoLineBuffer = &m_resSaoLineBuffer;
pipeBufAddrParams.presSaoTileLineBuffer = &m_resSaoTileLineBuffer;
pipeBufAddrParams.presSaoTileColumnBuffer = &m_resSaoTileColumnBuffer;
pipeBufAddrParams.presCurMvTempBuffer = m_trackedBuf->GetMvTemporalBuffer(CODEC_CURR_TRACKED_BUFFER);
pipeBufAddrParams.presLcuBaseAddressBuffer = &m_resLcuBaseAddressBuffer;
pipeBufAddrParams.dwLcuStreamOutOffset = 0;
pipeBufAddrParams.presLcuILDBStreamOutBuffer = &m_resLcuIldbStreamOutBuffer;
pipeBufAddrParams.presSaoStreamOutBuffer = &m_resSaoStreamOutBuffer;
pipeBufAddrParams.presFrameStatStreamOutBuffer = &m_resFrameStatStreamOutBuffer;
pipeBufAddrParams.dwFrameStatStreamOutOffset = 0;
pipeBufAddrParams.presSseSrcPixelRowStoreBuffer = &m_resSseSrcPixelRowStoreBuffer;
pipeBufAddrParams.presPakCuLevelStreamoutBuffer =
Mos_ResourceIsNull(&m_resPakcuLevelStreamoutData.sResource) ? nullptr : &m_resPakcuLevelStreamoutData.sResource;
pipeBufAddrParams.bRawIs10Bit = m_is10BitHevc;
//add for B frame support
if (m_pictureCodingType != I_TYPE)
{
for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
{
if (!m_picIdx[i].bValid || !m_currUsedRefPic[i])
{
continue;
}
uint8_t idx = m_picIdx[i].ucPicIdx;
CodecHalGetResourceInfo(m_osInterface, &(m_refList[idx]->sRefReconBuffer));
uint8_t frameStoreId = (uint8_t)m_refIdxMapping[i];
pipeBufAddrParams.presReferences[frameStoreId] = &(m_refList[idx]->sRefReconBuffer.OsResource);
uint8_t refMbCodeIdx = m_refList[idx]->ucScalingIdx;
pipeBufAddrParams.presColMvTempBuffer[frameStoreId] = m_trackedBuf->GetMvTemporalBuffer(refMbCodeIdx);
}
}
}
void CodechalEncodeHevcBase::SetHcpIndObjBaseAddrParams(MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS& indObjBaseAddrParams)
{
MOS_ZeroMemory(&indObjBaseAddrParams, sizeof(indObjBaseAddrParams));
indObjBaseAddrParams.Mode = CODECHAL_ENCODE_MODE_HEVC;
indObjBaseAddrParams.presMvObjectBuffer = &m_resMbCodeSurface;
indObjBaseAddrParams.dwMvObjectOffset = m_mvOffset;
indObjBaseAddrParams.dwMvObjectSize = m_mbCodeSize - m_mvOffset;
indObjBaseAddrParams.presPakBaseObjectBuffer = &m_resBitstreamBuffer;
indObjBaseAddrParams.dwPakBaseObjectSize =m_bitstreamUpperBound;
indObjBaseAddrParams.presPakTileSizeStasBuffer = nullptr;
indObjBaseAddrParams.dwPakTileSizeStasBufferSize = 0;
indObjBaseAddrParams.dwPakTileSizeRecordOffset = 0;
}
void CodechalEncodeHevcBase::SetHcpQmStateParams(MHW_VDBOX_QM_PARAMS& fqmParams, MHW_VDBOX_QM_PARAMS& qmParams)
{
MOS_ZeroMemory(&fqmParams, sizeof(fqmParams));
fqmParams.Standard = CODECHAL_HEVC;
fqmParams.pHevcIqMatrix = (PMHW_VDBOX_HEVC_QM_PARAMS)m_hevcIqMatrixParams;
MOS_ZeroMemory(&qmParams, sizeof(qmParams));
qmParams.Standard = CODECHAL_HEVC;
qmParams.pHevcIqMatrix = (PMHW_VDBOX_HEVC_QM_PARAMS)m_hevcIqMatrixParams;
}
void CodechalEncodeHevcBase::SetHcpPicStateParams(MHW_VDBOX_HEVC_PIC_STATE& picStateParams)
{
CODECHAL_ENCODE_FUNCTION_ENTER;
picStateParams = {};
picStateParams.pHevcEncSeqParams = m_hevcSeqParams;
picStateParams.pHevcEncPicParams = m_hevcPicParams;
picStateParams.bSAOEnable = m_hevcSeqParams->SAO_enabled_flag ? (m_hevcSliceParams->slice_sao_luma_flag || m_hevcSliceParams->slice_sao_chroma_flag) : 0;
picStateParams.bUseVDEnc = m_vdencEnabled;
picStateParams.bNotFirstPass = m_vdencEnabled && !IsFirstPass() ;
picStateParams.bHevcRdoqEnabled = m_hevcRdoqEnabled ? (m_pictureCodingType == I_TYPE ? m_hevcIFrameRdoqEnabled : 1) : 0;
picStateParams.bRDOQIntraTUDisable = m_hevcRdoqEnabled && (1 != m_hevcSeqParams->TargetUsage);
picStateParams.wRDOQIntraTUThreshold = (uint16_t)m_rdoqIntraTuThreshold;
picStateParams.bTransformSkipEnable = m_hevcPicParams->transform_skip_enabled_flag;
#if (_DEBUG || _RELEASE_INTERNAL)
if (m_rdoqIntraTuOverride)
{
int32_t RDOQIntraTUThreshold = 0;
if (m_rdoqIntraTuThresholdOverride >= 100)
{
RDOQIntraTUThreshold = 65535;
}
else if (m_rdoqIntraTuThresholdOverride > 0)
{
uint32_t frameWidth = (m_hevcSeqParams->wFrameWidthInMinCbMinus1 + 1) << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3);
uint32_t frameHeight = (m_hevcSeqParams->wFrameHeightInMinCbMinus1 + 1) << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3);
int32_t frameSize = frameWidth * frameHeight;
RDOQIntraTUThreshold = (((frameSize * m_rdoqIntraTuThreshold) / 100) >> 8);
uint16_t numPipe = m_numVdbox;
if ((m_hevcPicParams->num_tile_columns_minus1 + 1) > m_numVdbox)
{
numPipe = 1;
}
if ((m_hevcPicParams->tiles_enabled_flag) && (numPipe > 1))
{
RDOQIntraTUThreshold /= numPipe;
}
if (RDOQIntraTUThreshold > 65535)
{
RDOQIntraTUThreshold = 65535;
}
}
picStateParams.bRDOQIntraTUDisable = m_rdoqIntraTuDisableOverride;
picStateParams.wRDOQIntraTUThreshold = (uint16_t)RDOQIntraTUThreshold;
}
#endif
picStateParams.currPass = m_currPass;
if (CodecHalIsFeiEncode(m_codecFunction) && m_hevcFeiPicParams && m_hevcFeiPicParams->dwMaxFrameSize)
{
picStateParams.deltaQp = m_hevcFeiPicParams->pDeltaQp;
picStateParams.maxFrameSize = m_hevcFeiPicParams->dwMaxFrameSize;
}
}
MOS_STATUS CodechalEncodeHevcBase::SetBatchBufferForPakSlices()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
m_useBatchBufferForPakSlices = m_singleTaskPhaseSupported && m_singleTaskPhaseSupportedInPak;
m_batchBufferForPakSlicesStartOffset = 0;
if (m_useBatchBufferForPakSlices)
{
if (IsFirstPass())
{
// The same buffer is used for all slices for all passes
uint32_t batchBufferForPakSlicesSize =
(m_numPasses + 1) * m_numSlices * m_sliceStatesSize;
CODECHAL_ENCODE_ASSERT(batchBufferForPakSlicesSize);
if (batchBufferForPakSlicesSize >
(uint32_t)m_batchBufferForPakSlices[m_currPakSliceIdx].iSize)
{
if (m_batchBufferForPakSlices[m_currPakSliceIdx].iSize)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(ReleaseBatchBufferForPakSlices(m_currPakSliceIdx));
}
CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBatchBufferForPakSlices(
m_numSlices,
m_numPasses));
}
}
CODECHAL_ENCODE_CHK_STATUS_RETURN(Mhw_LockBb(
m_osInterface,
&m_batchBufferForPakSlices[m_currPakSliceIdx]));
m_batchBufferForPakSlicesStartOffset = IsFirstPass() ? 0 : (uint32_t)m_batchBufferForPakSlices[m_currPakSliceIdx].iCurrent;
}
return eStatus;
}
void CodechalEncodeHevcBase::CreateMhwParams()
{
m_sliceStateParams = MOS_New(MHW_VDBOX_HEVC_SLICE_STATE);
m_pipeModeSelectParams = MOS_New(MHW_VDBOX_PIPE_MODE_SELECT_PARAMS);
m_pipeBufAddrParams = MOS_New(MHW_VDBOX_PIPE_BUF_ADDR_PARAMS);
}
void CodechalEncodeHevcBase::SetHcpSliceStateCommonParams(MHW_VDBOX_HEVC_SLICE_STATE& sliceStateParams)
{
CODECHAL_ENCODE_FUNCTION_ENTER;
sliceStateParams = {};
sliceStateParams.presDataBuffer = &m_resMbCodeSurface;
sliceStateParams.pHevcPicIdx = &(m_picIdx[0]);
sliceStateParams.pEncodeHevcSeqParams = m_hevcSeqParams;
sliceStateParams.pEncodeHevcPicParams = m_hevcPicParams;
sliceStateParams.pBsBuffer = &m_bsBuffer;
sliceStateParams.ppNalUnitParams = m_nalUnitParams;
sliceStateParams.bBrcEnabled = m_brcEnabled;
sliceStateParams.dwHeaderBytesInserted = 0;
sliceStateParams.dwHeaderDummyBytes = 0;
sliceStateParams.pRefIdxMapping = m_refIdxMapping;
sliceStateParams.bIsLowDelay = m_lowDelay;
sliceStateParams.RoundingIntra = m_roundingIntra;
sliceStateParams.RoundingInter = m_roundingInter;
}
void CodechalEncodeHevcBase::SetHcpSliceStateParams(
MHW_VDBOX_HEVC_SLICE_STATE& sliceStateParams,
PCODEC_ENCODER_SLCDATA slcData,
uint32_t currSlcIdx)
{
CODECHAL_ENCODE_FUNCTION_ENTER;
sliceStateParams.pEncodeHevcSliceParams = &m_hevcSliceParams[currSlcIdx];
sliceStateParams.dwDataBufferOffset = slcData[currSlcIdx].CmdOffset;
sliceStateParams.dwOffset = slcData[currSlcIdx].SliceOffset;
sliceStateParams.dwLength = slcData[currSlcIdx].BitSize;
sliceStateParams.uiSkipEmulationCheckCount = slcData[currSlcIdx].SkipEmulationByteCount;
sliceStateParams.dwSliceIndex = currSlcIdx;
sliceStateParams.bLastSlice = (currSlcIdx == m_numSlices - 1);
sliceStateParams.bFirstPass = IsFirstPass();
sliceStateParams.bLastPass = IsLastPass();
sliceStateParams.bInsertBeforeSliceHeaders = (currSlcIdx == 0);
sliceStateParams.bSaoLumaFlag = (m_hevcSeqParams->SAO_enabled_flag) ? m_hevcSliceParams[currSlcIdx].slice_sao_luma_flag : 0;
sliceStateParams.bSaoChromaFlag = (m_hevcSeqParams->SAO_enabled_flag) ? m_hevcSliceParams[currSlcIdx].slice_sao_chroma_flag : 0;
sliceStateParams.DeblockingFilterDisable = m_hevcSliceParams[currSlcIdx].slice_deblocking_filter_disable_flag;
sliceStateParams.TcOffsetDiv2 = m_hevcSliceParams[currSlcIdx].tc_offset_div2;
sliceStateParams.BetaOffsetDiv2 = m_hevcSliceParams[currSlcIdx].beta_offset_div2;
if (m_useBatchBufferForPakSlices)
{
sliceStateParams.pBatchBufferForPakSlices =
&m_batchBufferForPakSlices[m_currPakSliceIdx];
sliceStateParams.bSingleTaskPhaseSupported = true;
sliceStateParams.dwBatchBufferForPakSlicesStartOffset = m_batchBufferForPakSlicesStartOffset;
}
if (m_hevcPicParams->transform_skip_enabled_flag)
{
CalcTransformSkipParameters(sliceStateParams.EncodeHevcTransformSkipParams);
}
}
MOS_STATUS CodechalEncodeHevcBase::AddHcpRefIdxCmd(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_BATCH_BUFFER batchBuffer,
PMHW_VDBOX_HEVC_SLICE_STATE params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(params);
CODECHAL_ENCODE_CHK_NULL_RETURN(params->pEncodeHevcSliceParams);
CODECHAL_ENCODE_CHK_NULL_RETURN(params->pEncodeHevcPicParams);
if (cmdBuffer == nullptr && batchBuffer == nullptr)
{
CODECHAL_ENCODE_ASSERTMESSAGE("There was no valid buffer to add the HW command to.");
return MOS_STATUS_NULL_POINTER;
}
PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams = params->pEncodeHevcPicParams;
PCODEC_HEVC_ENCODE_SLICE_PARAMS hevcSlcParams = params->pEncodeHevcSliceParams;
if (hevcSlcParams->slice_type != CODECHAL_ENCODE_HEVC_I_SLICE)
{
MHW_VDBOX_HEVC_REF_IDX_PARAMS refIdxParams;
refIdxParams.CurrPic = hevcPicParams->CurrReconstructedPic;
refIdxParams.isEncode = true;
refIdxParams.ucList = LIST_0;
refIdxParams.ucNumRefForList = hevcSlcParams->num_ref_idx_l0_active_minus1 + 1;
eStatus = MOS_SecureMemcpy(&refIdxParams.RefPicList, sizeof(refIdxParams.RefPicList),
&hevcSlcParams->RefPicList, sizeof(hevcSlcParams->RefPicList));
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
return eStatus;
}
refIdxParams.hevcRefList = (void**)m_refList;
refIdxParams.poc_curr_pic = hevcPicParams->CurrPicOrderCnt;
for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
{
refIdxParams.poc_list[i] = hevcPicParams->RefFramePOCList[i];
}
refIdxParams.pRefIdxMapping = params->pRefIdxMapping;
refIdxParams.RefFieldPicFlag = 0; // there is no interlaced support in encoder
refIdxParams.RefBottomFieldFlag = 0; // there is no interlaced support in encoder
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpRefIdxStateCmd(cmdBuffer, batchBuffer, &refIdxParams));
if (hevcSlcParams->slice_type == CODECHAL_ENCODE_HEVC_B_SLICE)
{
refIdxParams.ucList = LIST_1;
refIdxParams.ucNumRefForList = hevcSlcParams->num_ref_idx_l1_active_minus1 + 1;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpRefIdxStateCmd(cmdBuffer, batchBuffer, &refIdxParams));
}
}
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::AddHcpPakInsertNALUs(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_BATCH_BUFFER batchBuffer,
PMHW_VDBOX_HEVC_SLICE_STATE params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(params);
CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBsBuffer);
CODECHAL_ENCODE_CHK_NULL_RETURN(params->ppNalUnitParams);
if (cmdBuffer == nullptr && batchBuffer == nullptr)
{
CODECHAL_ENCODE_ASSERTMESSAGE("There was no valid buffer to add the HW command to.");
return MOS_STATUS_NULL_POINTER;
}
//insert AU, SPS, PSP headers before first slice header
if (params->bInsertBeforeSliceHeaders)
{
uint32_t maxBytesInPakInsertObjCmd = ((2 << 11) - 1) * 4; // 12 bits for Length field in PAK_INSERT_OBJ cmd
for (auto i = 0; i < HEVC_MAX_NAL_UNIT_TYPE; i++)
{
uint32_t nalunitPosiSize = params->ppNalUnitParams[i]->uiSize;
uint32_t nalunitPosiOffset = params->ppNalUnitParams[i]->uiOffset;
while (nalunitPosiSize > 0)
{
uint32_t bitSize = MOS_MIN(maxBytesInPakInsertObjCmd * 8, nalunitPosiSize * 8);
uint32_t offSet = nalunitPosiOffset;
MHW_VDBOX_PAK_INSERT_PARAMS pakInsertObjectParams;
MOS_ZeroMemory(&pakInsertObjectParams, sizeof(pakInsertObjectParams));
pakInsertObjectParams.bEmulationByteBitsInsert = params->ppNalUnitParams[i]->bInsertEmulationBytes;
pakInsertObjectParams.uiSkipEmulationCheckCount = params->ppNalUnitParams[i]->uiSkipEmulationCheckCount;
pakInsertObjectParams.pBsBuffer = params->pBsBuffer;
pakInsertObjectParams.dwBitSize = bitSize;
pakInsertObjectParams.dwOffset = offSet;
pakInsertObjectParams.pBatchBufferForPakSlices = batchBuffer;
pakInsertObjectParams.bVdencInUse = params->bVdencInUse;
if (nalunitPosiSize > maxBytesInPakInsertObjCmd)
{
nalunitPosiSize -= maxBytesInPakInsertObjCmd;
nalunitPosiOffset += maxBytesInPakInsertObjCmd;
}
else
{
nalunitPosiSize = 0;
}
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpPakInsertObject(cmdBuffer, &pakInsertObjectParams));
}
}
}
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::AddHcpPakInsertSliceHeader(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_BATCH_BUFFER batchBuffer,
PMHW_VDBOX_HEVC_SLICE_STATE params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(params);
CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBsBuffer);
if (cmdBuffer == nullptr && batchBuffer == nullptr)
{
CODECHAL_ENCODE_ASSERTMESSAGE("There was no valid buffer to add the HW command to.");
return MOS_STATUS_NULL_POINTER;
}
// Insert slice header
MHW_VDBOX_PAK_INSERT_PARAMS pakInsertObjectParams;
MOS_ZeroMemory(&pakInsertObjectParams, sizeof(pakInsertObjectParams));
pakInsertObjectParams.bLastHeader = true;
pakInsertObjectParams.bEmulationByteBitsInsert = true;
pakInsertObjectParams.pBatchBufferForPakSlices = batchBuffer;
// App does the slice header packing, set the skip count passed by the app
pakInsertObjectParams.uiSkipEmulationCheckCount = params->uiSkipEmulationCheckCount;
pakInsertObjectParams.pBsBuffer = params->pBsBuffer;
pakInsertObjectParams.dwBitSize = params->dwLength;
pakInsertObjectParams.dwOffset = params->dwOffset;
pakInsertObjectParams.bVdencInUse = params->bVdencInUse;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpPakInsertObject(
cmdBuffer,
&pakInsertObjectParams));
return eStatus;
}
CodechalEncodeHevcBase::CodechalEncodeHevcBase(
CodechalHwInterface* hwInterface,
CodechalDebugInterface* debugInterface,
PCODECHAL_STANDARD_INFO standardInfo)
:CodechalEncoderState(hwInterface, debugInterface, standardInfo)
{
// initialze class members
MOS_ZeroMemory(&m_resDeblockingFilterRowStoreScratchBuffer, sizeof(m_resDeblockingFilterRowStoreScratchBuffer));
MOS_ZeroMemory(&m_resDeblockingFilterTileRowStoreScratchBuffer, sizeof(m_resDeblockingFilterTileRowStoreScratchBuffer));
MOS_ZeroMemory(&m_resDeblockingFilterColumnRowStoreScratchBuffer, sizeof(m_resDeblockingFilterColumnRowStoreScratchBuffer));
MOS_ZeroMemory(&m_resMetadataLineBuffer, sizeof(m_resMetadataLineBuffer));
MOS_ZeroMemory(&m_resMetadataTileLineBuffer, sizeof(m_resMetadataTileLineBuffer));
MOS_ZeroMemory(&m_resMetadataTileColumnBuffer, sizeof(m_resMetadataTileColumnBuffer));
MOS_ZeroMemory(&m_resSaoLineBuffer, sizeof(m_resSaoLineBuffer));
MOS_ZeroMemory(&m_resSaoTileLineBuffer, sizeof(m_resSaoTileLineBuffer));
MOS_ZeroMemory(&m_resSaoTileColumnBuffer, sizeof(m_resSaoTileColumnBuffer));
MOS_ZeroMemory(&m_resLcuBaseAddressBuffer, sizeof(m_resLcuBaseAddressBuffer));
MOS_ZeroMemory(&m_resLcuIldbStreamOutBuffer, sizeof(m_resLcuIldbStreamOutBuffer));
MOS_ZeroMemory(&m_resSaoStreamOutBuffer, sizeof(m_resSaoStreamOutBuffer));
MOS_ZeroMemory(&m_resFrameStatStreamOutBuffer, sizeof(m_resFrameStatStreamOutBuffer));
MOS_ZeroMemory(&m_resSseSrcPixelRowStoreBuffer, sizeof(m_resSseSrcPixelRowStoreBuffer));
MOS_ZeroMemory(m_batchBufferForPakSlices, sizeof(m_batchBufferForPakSlices));
MOS_ZeroMemory(m_refSync, sizeof(m_refSync));
MOS_ZeroMemory(m_refIdxMapping, sizeof(m_refIdxMapping));
MOS_ZeroMemory(m_currUsedRefPic, sizeof(m_currUsedRefPic));
;
MOS_ZeroMemory(m_picIdx, sizeof(m_picIdx));
MOS_ZeroMemory(m_refList, sizeof(m_refList));
MOS_ZeroMemory(&m_s4XMeMvDataBuffer, sizeof(m_s4XMeMvDataBuffer));
MOS_ZeroMemory(&m_s16XMeMvDataBuffer, sizeof(m_s16XMeMvDataBuffer));
MOS_ZeroMemory(&m_s32XMeMvDataBuffer, sizeof(m_s32XMeMvDataBuffer));
MOS_ZeroMemory(&m_s4XMeDistortionBuffer, sizeof(m_s4XMeDistortionBuffer));
MOS_ZeroMemory(&m_mbQpDataSurface, sizeof(m_mbQpDataSurface));
MOS_ZeroMemory(&m_resPakcuLevelStreamoutData, sizeof(m_resPakcuLevelStreamoutData));
m_fieldScalingOutputInterleaved = false;
m_interlacedFieldDisabled = true;
m_firstField = true; // Each frame is treated as the first field
m_userFeatureKeyReport = true;
m_useCmScalingKernel = true;
m_codecGetStatusReportDefined = true; // Codec specific GetStatusReport is implemented.
m_vdboxOneDefaultUsed = true;
}
MOS_STATUS CodechalEncodeHevcBase::CalculatePictureStateCommandSize()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
MHW_VDBOX_STATE_CMDSIZE_PARAMS stateCmdSizeParams;
CODECHAL_ENCODE_CHK_STATUS_RETURN(
m_hwInterface->GetHxxStateCommandSize(
CODECHAL_ENCODE_MODE_HEVC,
&m_defaultPictureStatesSize,
&m_defaultPicturePatchListSize,
&stateCmdSizeParams));
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::AddHcpPipeBufAddrCmd(
PMOS_COMMAND_BUFFER cmdBuffer)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
*m_pipeBufAddrParams = {};
SetHcpPipeBufAddrParams(*m_pipeBufAddrParams);
#ifdef _MMC_SUPPORTED
m_mmcState->SetPipeBufAddr(m_pipeBufAddrParams);
#endif
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpPipeBufAddrCmd(cmdBuffer, m_pipeBufAddrParams));
return eStatus;
}
short CodechalEncodeHevcBase::ComputeTemporalDifferent(CODEC_PICTURE refPic)
{
short diff_poc = 0;
if (!CodecHal_PictureIsInvalid(refPic))
{
diff_poc = m_hevcPicParams->CurrPicOrderCnt - m_hevcPicParams->RefFramePOCList[refPic.FrameIdx];
if (diff_poc < -16)
{
CODECHAL_ENCODE_ASSERTMESSAGE("POC out of range, it will be clipped.");
diff_poc = -16;
}
else
if (diff_poc > 16)
{
CODECHAL_ENCODE_ASSERTMESSAGE("POC out of range, it will be clipped.");
diff_poc = 16;
}
}
return diff_poc;
}
MOS_STATUS CodechalEncodeHevcBase::InitSurfaceCodecParams1D(
PCODECHAL_SURFACE_CODEC_PARAMS surfaceCodecParams,
PMOS_RESOURCE buffer,
uint32_t size,
uint32_t offset,
uint32_t cacheabilityControl,
uint32_t bindingTableOffset,
bool isWritable)
{
if (surfaceCodecParams == nullptr)
{
return MOS_STATUS_NULL_POINTER;
}
MOS_ZeroMemory(surfaceCodecParams, sizeof(*surfaceCodecParams));
surfaceCodecParams->presBuffer = buffer;
surfaceCodecParams->dwSize = size;
surfaceCodecParams->dwOffset = offset;
surfaceCodecParams->dwCacheabilityControl = cacheabilityControl;
surfaceCodecParams->dwBindingTableOffset = bindingTableOffset;
surfaceCodecParams->bIsWritable =
surfaceCodecParams->bRenderTarget = isWritable;
return MOS_STATUS_SUCCESS;
}
MOS_STATUS CodechalEncodeHevcBase::InitSurfaceCodecParams2D(
PCODECHAL_SURFACE_CODEC_PARAMS surfaceCodecParams,
PMOS_SURFACE surface,
uint32_t cacheabilityControl,
uint32_t bindingTableOffset,
uint32_t verticalLineStride,
bool isWritable)
{
if (surfaceCodecParams == nullptr)
{
return MOS_STATUS_NULL_POINTER;
}
MOS_ZeroMemory(surfaceCodecParams, sizeof(*surfaceCodecParams));
surfaceCodecParams->bIs2DSurface = true;
surfaceCodecParams->bMediaBlockRW = true; // Use media block RW for DP 2D surface access
surfaceCodecParams->psSurface = surface;
surfaceCodecParams->dwCacheabilityControl = cacheabilityControl;
surfaceCodecParams->dwBindingTableOffset = bindingTableOffset;
surfaceCodecParams->dwVerticalLineStride = verticalLineStride;
surfaceCodecParams->bIsWritable =
surfaceCodecParams->bRenderTarget = isWritable;
return MOS_STATUS_SUCCESS;
}
MOS_STATUS CodechalEncodeHevcBase::AllocateResources4xME(
HmeParams *param)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(param);
if (!m_encEnabled || !m_hmeSupported)
{
return eStatus;
}
MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS));
allocParamsForBuffer2D.Type = MOS_GFXRES_2D;
allocParamsForBuffer2D.TileType = MOS_TILE_LINEAR;
allocParamsForBuffer2D.Format = Format_Buffer_2D;
MOS_ZeroMemory(param->ps4xMeMvDataBuffer, sizeof(MOS_SURFACE));
param->ps4xMeMvDataBuffer->TileType = MOS_TILE_LINEAR;
param->ps4xMeMvDataBuffer->bArraySpacing = true;
param->ps4xMeMvDataBuffer->Format = Format_Buffer_2D;
param->ps4xMeMvDataBuffer->dwWidth = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 32), 64); // MediaBlockRW requires pitch multiple of 64 bytes when linear.
param->ps4xMeMvDataBuffer->dwHeight = (m_downscaledHeightInMb4x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER);
param->ps4xMeMvDataBuffer->dwPitch = param->ps4xMeMvDataBuffer->dwWidth;
allocParamsForBuffer2D.dwWidth = param->ps4xMeMvDataBuffer->dwWidth;
allocParamsForBuffer2D.dwHeight = param->ps4xMeMvDataBuffer->dwHeight;
allocParamsForBuffer2D.pBufName = "4xME MV Data Buffer";
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBuffer2D,
&param->ps4xMeMvDataBuffer->OsResource);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate 4xME MV Data Buffer.");
return eStatus;
}
CleanUpResource(&param->ps4xMeMvDataBuffer->OsResource, &allocParamsForBuffer2D);
if (param->b4xMeDistortionBufferSupported)
{
uint32_t ajustedHeight =
m_downscaledHeightInMb4x * CODECHAL_MACROBLOCK_HEIGHT * SCALE_FACTOR_4x;
uint32_t downscaledFieldHeightInMB4x =
CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(((ajustedHeight + 1) >> 1) / 4);
MOS_ZeroMemory(param->ps4xMeDistortionBuffer, sizeof(MOS_SURFACE));
param->ps4xMeDistortionBuffer->TileType = MOS_TILE_LINEAR;
param->ps4xMeDistortionBuffer->bArraySpacing = true;
param->ps4xMeDistortionBuffer->Format = Format_Buffer_2D;
param->ps4xMeDistortionBuffer->dwWidth = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 8), 64);
param->ps4xMeDistortionBuffer->dwHeight = 2 * MOS_ALIGN_CEIL((downscaledFieldHeightInMB4x * 4 * 10), 8);
param->ps4xMeDistortionBuffer->dwPitch = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 8), 64);
allocParamsForBuffer2D.dwWidth = param->ps4xMeDistortionBuffer->dwWidth;
allocParamsForBuffer2D.dwHeight = param->ps4xMeDistortionBuffer->dwHeight;
allocParamsForBuffer2D.pBufName = "4xME Distortion Buffer";
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBuffer2D,
&param->ps4xMeDistortionBuffer->OsResource);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate 4xME Distortion Buffer.");
return eStatus;
}
CleanUpResource(&param->ps4xMeDistortionBuffer->OsResource, &allocParamsForBuffer2D);
}
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::AllocateResources16xME(
HmeParams *param)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(param);
if (!m_encEnabled || !m_hmeSupported)
{
return eStatus;
}
MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS));
allocParamsForBuffer2D.Type = MOS_GFXRES_2D;
allocParamsForBuffer2D.TileType = MOS_TILE_LINEAR;
allocParamsForBuffer2D.Format = Format_Buffer_2D;
if (m_16xMeSupported)
{
MOS_ZeroMemory(param->ps16xMeMvDataBuffer, sizeof(MOS_SURFACE));
param->ps16xMeMvDataBuffer->TileType = MOS_TILE_LINEAR;
param->ps16xMeMvDataBuffer->bArraySpacing = true;
param->ps16xMeMvDataBuffer->Format = Format_Buffer_2D;
param->ps16xMeMvDataBuffer->dwWidth = MOS_ALIGN_CEIL((m_downscaledWidthInMb16x * 32), 64); // MediaBlockRW requires pitch multiple of 64 bytes when linear
param->ps16xMeMvDataBuffer->dwHeight = (m_downscaledHeightInMb16x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER);
param->ps16xMeMvDataBuffer->dwPitch = param->ps16xMeMvDataBuffer->dwWidth;
allocParamsForBuffer2D.dwWidth = param->ps16xMeMvDataBuffer->dwWidth;
allocParamsForBuffer2D.dwHeight = param->ps16xMeMvDataBuffer->dwHeight;
allocParamsForBuffer2D.pBufName = "16xME MV Data Buffer";
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBuffer2D,
&param->ps16xMeMvDataBuffer->OsResource);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate 16xME MV Data Buffer.");
return eStatus;
}
CleanUpResource(&param->ps16xMeMvDataBuffer->OsResource, &allocParamsForBuffer2D);
}
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::AllocateResources32xME(
HmeParams *param)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(param);
if (!m_encEnabled || !m_hmeSupported)
{
return eStatus;
}
MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS));
allocParamsForBuffer2D.Type = MOS_GFXRES_2D;
allocParamsForBuffer2D.TileType = MOS_TILE_LINEAR;
allocParamsForBuffer2D.Format = Format_Buffer_2D;
if (m_32xMeSupported)
{
MOS_ZeroMemory(param->ps32xMeMvDataBuffer, sizeof(MOS_SURFACE));
param->ps32xMeMvDataBuffer->TileType = MOS_TILE_LINEAR;
param->ps32xMeMvDataBuffer->bArraySpacing = true;
param->ps32xMeMvDataBuffer->Format = Format_Buffer_2D;
param->ps32xMeMvDataBuffer->dwWidth = MOS_ALIGN_CEIL((m_downscaledWidthInMb32x * 32), 64); // MediaBlockRW requires pitch multiple of 64 bytes when linear
param->ps32xMeMvDataBuffer->dwHeight = (m_downscaledHeightInMb32x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER);
param->ps32xMeMvDataBuffer->dwPitch = param->ps32xMeMvDataBuffer->dwWidth;
allocParamsForBuffer2D.dwWidth = param->ps32xMeMvDataBuffer->dwWidth;
allocParamsForBuffer2D.dwHeight = param->ps32xMeMvDataBuffer->dwHeight;
allocParamsForBuffer2D.pBufName = "32xME MV Data Buffer";
eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
m_osInterface,
&allocParamsForBuffer2D,
&param->ps32xMeMvDataBuffer->OsResource);
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("%s: Failed to allocate 32xME MV Data Buffer\n", __FUNCTION__);
return eStatus;
}
CleanUpResource(&param->ps32xMeMvDataBuffer->OsResource, &allocParamsForBuffer2D);
}
return eStatus;
}
MOS_STATUS CodechalEncodeHevcBase::DestroyMEResources(
HmeParams *param)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(param);
if (nullptr != param->ps16xMeMvDataBuffer)
{
m_osInterface->pfnFreeResource(
m_osInterface,
&param->ps16xMeMvDataBuffer->OsResource);
}
if (nullptr != param->ps32xMeMvDataBuffer)
{
m_osInterface->pfnFreeResource(
m_osInterface,
&param->ps32xMeMvDataBuffer->OsResource);
}
if (nullptr != param->ps4xMeDistortionBuffer)
{
m_osInterface->pfnFreeResource(
m_osInterface,
&param->ps4xMeDistortionBuffer->OsResource);
}
if (nullptr != param->ps4xMeMvDataBuffer)
{
m_osInterface->pfnFreeResource(
m_osInterface,
&param->ps4xMeMvDataBuffer->OsResource);
}
if (nullptr != param->presMvAndDistortionSumSurface)
{
m_osInterface->pfnFreeResource(
m_osInterface,
param->presMvAndDistortionSumSurface);
}
return eStatus;
}
void CodechalEncodeHevcBase::MotionEstimationDisableCheck()
{
CODECHAL_ENCODE_FUNCTION_ENTER;
if (m_downscaledWidth4x < m_minScaledDimension || m_downscaledWidthInMb4x < m_minScaledDimensionInMb ||
m_downscaledHeight4x < m_minScaledDimension || m_downscaledHeightInMb4x < m_minScaledDimensionInMb)
{
if (m_downscaledWidth4x < m_minScaledDimension || m_downscaledWidthInMb4x < m_minScaledDimensionInMb)
{
m_downscaledWidth4x = m_minScaledDimension;
m_downscaledWidthInMb4x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_downscaledWidth4x);
}
if (m_downscaledHeight4x < m_minScaledDimension || m_downscaledHeightInMb4x < m_minScaledDimensionInMb)
{
m_downscaledHeight4x = m_minScaledDimension;
m_downscaledHeightInMb4x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_downscaledHeight4x);
}
}
if (m_downscaledWidth16x < m_minScaledDimension || m_downscaledWidthInMb16x < m_minScaledDimensionInMb ||
m_downscaledHeight16x < m_minScaledDimension || m_downscaledHeightInMb16x < m_minScaledDimensionInMb)
{
if (m_downscaledWidth16x < m_minScaledDimension || m_downscaledWidthInMb16x < m_minScaledDimensionInMb)
{
m_downscaledWidth16x = m_minScaledDimension;
m_downscaledWidthInMb16x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_downscaledWidth16x);
}
if (m_downscaledHeight16x < m_minScaledDimension || m_downscaledHeightInMb16x < m_minScaledDimensionInMb)
{
m_downscaledHeight16x = m_minScaledDimension;
m_downscaledHeightInMb16x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_downscaledHeight16x);
}
}
if (m_downscaledWidth32x < m_minScaledDimension || m_downscaledWidthInMb32x < m_minScaledDimensionInMb)
{
m_downscaledWidth32x = m_minScaledDimension;
m_downscaledWidthInMb32x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_downscaledWidth32x);
}
if (m_downscaledHeight32x < m_minScaledDimension || m_downscaledHeightInMb32x < m_minScaledDimensionInMb)
{
m_downscaledHeight32x = m_minScaledDimension;
m_downscaledHeightInMb32x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_downscaledHeight32x);
}
}
MOS_STATUS CodechalEncodeHevcBase::ExecuteKernelFunctions()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_STATUS_RETURN(EncodeKernelFunctions());
return eStatus;
}
uint32_t CodecHalHevcEncode_GetBitstreamBufferSize(
uint32_t frameWidth,
uint32_t frameHeight,
uint8_t chromaFormat,
bool is10Bits)
{
// 4:2:0 uncompression buffer size
frameHeight = (frameHeight * 3) / (is10Bits ? 1 : 2);
if (chromaFormat == HCP_CHROMA_FORMAT_YUV422)
{
frameWidth = (frameWidth * 8) / 6; //4:2:2 v.s 4:2:0
}
else if (chromaFormat == HCP_CHROMA_FORMAT_YUV444)
{
frameWidth = (frameWidth * 12) / 6; //4:4:4 v.s 4:2:0
}
return frameWidth * frameHeight;
}
#if USE_CODECHAL_DEBUG_TOOL
MOS_STATUS CodechalEncodeHevcBase::DumpSeqParams(
PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS seqParams)
{
CODECHAL_DEBUG_FUNCTION_ENTER;
if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSeqParams))
{
return MOS_STATUS_SUCCESS;
}
CODECHAL_DEBUG_CHK_NULL(seqParams);
std::ostringstream oss;
oss.setf(std::ios::showbase | std::ios::uppercase);
oss << "# DDI Parameters:" << std::endl;
oss << "wFrameWidthInMinCbMinus1 = " << +seqParams->wFrameWidthInMinCbMinus1 << std::endl;
oss << "wFrameHeightInMinCbMinus1 = " << +seqParams->wFrameHeightInMinCbMinus1 << std::endl;
oss << "general_profile_idc = " << +seqParams->general_profile_idc << std::endl;
oss << "Level = " << +seqParams->Level << std::endl;
oss << "general_tier_flag = " << +seqParams->general_tier_flag << std::endl;
oss << "GopPicSize = " << +seqParams->GopPicSize << std::endl;
oss << "GopRefDist = " << +seqParams->GopRefDist << std::endl;
oss << "GopOptFlag = " << +seqParams->GopOptFlag << std::endl;
oss << "TargetUsage = " << +seqParams->TargetUsage << std::endl;
oss << "RateControlMethod = " << +seqParams->RateControlMethod << std::endl;
oss << "TargetBitRate = " << +seqParams->TargetBitRate << std::endl;
oss << "MaxBitRate = " << +seqParams->MaxBitRate << std::endl;
oss << "MinBitRate = " << +seqParams->MinBitRate << std::endl;
oss << "FramesRate.Numerator = " << +seqParams->FrameRate.Numerator << std::endl;
oss << "FramesRate.Denominator = " << +seqParams->FrameRate.Denominator << std::endl;
oss << "InitVBVBufferFullnessInBit = " << +seqParams->InitVBVBufferFullnessInBit << std::endl;
oss << "VBVBufferSizeInBit = " << +seqParams->VBVBufferSizeInBit << std::endl;
oss << "bResetBRC = " << +seqParams->bResetBRC << std::endl;
oss << "GlobalSearch = " << +seqParams->GlobalSearch << std::endl;
oss << "LocalSearch = " << +seqParams->LocalSearch << std::endl;
oss << "EarlySkip = " << +seqParams->EarlySkip << std::endl;
oss << "MBBRC = " << +seqParams->MBBRC << std::endl;
oss << "ParallelBRC = " << +seqParams->ParallelBRC << std::endl;
oss << "SliceSizeControl = " << +seqParams->SliceSizeControl << std::endl;
oss << "SourceFormat = " << +seqParams->SourceFormat << std::endl;
oss << "SourceBitDepth = " << +seqParams->SourceBitDepth << std::endl;
oss << "QpAdjustment = " << +seqParams->QpAdjustment << std::endl;
oss << "ROIValueInDeltaQP = " << +seqParams->ROIValueInDeltaQP << std::endl;
oss << "BlockQPforNonRectROI = " << +seqParams->BlockQPforNonRectROI << std::endl;
oss << "EnableTileBasedEncode = " << +seqParams->EnableTileBasedEncode << std::endl;
oss << "bAutoMaxPBFrameSizeForSceneChange = " << +seqParams->bAutoMaxPBFrameSizeForSceneChange << std::endl;
oss << "EnableStreamingBufferLLC = " << +seqParams->EnableStreamingBufferLLC << std::endl;
oss << "EnableStreamingBufferDDR = " << +seqParams->EnableStreamingBufferDDR << std::endl;
oss << "LowDelayMode = " << +seqParams->LowDelayMode << std::endl;
oss << "DisableHRDConformance = " << +seqParams->DisableHRDConformance << std::endl;
oss << "HierarchicalFlag = " << +seqParams->HierarchicalFlag << std::endl;
oss << "UserMaxIFrameSize = " << +seqParams->UserMaxIFrameSize << std::endl;
oss << "UserMaxPBFrameSize = " << +seqParams->UserMaxPBFrameSize << std::endl;
oss << "ICQQualityFactor = " << +seqParams->ICQQualityFactor << std::endl;
oss << "NumB = " << +seqParams->NumOfBInGop[0] << std::endl;
oss << "NumB1 = " << +seqParams->NumOfBInGop[1] << std::endl;
oss << "NumB2 = " << +seqParams->NumOfBInGop[2] << std::endl;
oss << "UserMaxIFrameSize = " << +seqParams->UserMaxIFrameSize << std::endl;
oss << "UserMaxPBFrameSize = " << +seqParams->UserMaxPBFrameSize << std::endl;
oss << "ICQQualityFactor = " << +seqParams->ICQQualityFactor << std::endl;
oss << "scaling_list_enable_flag = " << +seqParams->scaling_list_enable_flag << std::endl;
oss << "sps_temporal_mvp_enable_flag = " << +seqParams->sps_temporal_mvp_enable_flag << std::endl;
oss << "strong_intra_smoothing_enable_flag = " << +seqParams->strong_intra_smoothing_enable_flag << std::endl;
oss << "amp_enabled_flag = " << +seqParams->amp_enabled_flag << std::endl;
oss << "SAO_enabled_flag = " << +seqParams->SAO_enabled_flag << std::endl;
oss << "pcm_enabled_flag = " << +seqParams->pcm_enabled_flag << std::endl;
oss << "pcm_loop_filter_disable_flag = " << +seqParams->pcm_loop_filter_disable_flag << std::endl;
oss << "chroma_format_idc = " << +seqParams->chroma_format_idc << std::endl;
oss << "separate_colour_plane_flag = " << +seqParams->separate_colour_plane_flag << std::endl;
oss << "palette_mode_enabled_flag = " << +seqParams->palette_mode_enabled_flag << std::endl;
oss << "RGBEncodingEnable = " << +seqParams->RGBEncodingEnable << std::endl;
oss << "PrimaryChannelForRGBEncoding = " << +seqParams->PrimaryChannelForRGBEncoding << std::endl;
oss << "SecondaryChannelForRGBEncoding = " << +seqParams->SecondaryChannelForRGBEncoding << std::endl;
oss << "log2_max_coding_block_size_minus3 = " << +seqParams->log2_max_coding_block_size_minus3 << std::endl;
oss << "log2_min_coding_block_size_minus3 = " << +seqParams->log2_min_coding_block_size_minus3 << std::endl;
oss << "log2_max_transform_block_size_minus2 = " << +seqParams->log2_max_transform_block_size_minus2 << std::endl;
oss << "log2_min_transform_block_size_minus2 = " << +seqParams->log2_min_transform_block_size_minus2 << std::endl;
oss << "max_transform_hierarchy_depth_intra = " << +seqParams->max_transform_hierarchy_depth_intra << std::endl;
oss << "max_transform_hierarchy_depth_inter = " << +seqParams->max_transform_hierarchy_depth_inter << std::endl;
oss << "log2_min_PCM_cb_size_minus3 = " << +seqParams->log2_min_PCM_cb_size_minus3 << std::endl;
oss << "log2_max_PCM_cb_size_minus3 = " << +seqParams->log2_max_PCM_cb_size_minus3 << std::endl;
oss << "bit_depth_luma_minus8 = " << +seqParams->bit_depth_luma_minus8 << std::endl;
oss << "bit_depth_chroma_minus8 = " << +seqParams->bit_depth_chroma_minus8 << std::endl;
oss << "pcm_sample_bit_depth_luma_minus1 = " << +seqParams->pcm_sample_bit_depth_luma_minus1 << std::endl;
oss << "pcm_sample_bit_depth_chroma_minus1 = " << +seqParams->pcm_sample_bit_depth_chroma_minus1 << std::endl;
oss << "Video Surveillance Mode = " << +seqParams->bVideoSurveillance << std::endl;
oss << "Frame Size Tolerance = " << +seqParams->FrameSizeTolerance << std::endl;
oss << "Look Ahead Depth = " << +seqParams->LookaheadDepth << std::endl;
const char *fileName = m_debugInterface->CreateFileName(
"_DDIEnc",
CodechalDbgBufferType::bufSeqParams,
CodechalDbgExtType::txt);
std::ofstream ofs(fileName, std::ios::out);
ofs << oss.str();
ofs.close();
if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDriverUltDump))
{
if (!m_debugInterface->m_ddiFileName.empty())
{
std::ofstream ofs(m_debugInterface->m_ddiFileName, std::ios::app);
ofs << "SeqParamFile"
<< " = \"" << m_debugInterface->m_fileName << "\"" << std::endl;
ofs.close();
}
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS CodechalEncodeHevcBase::DumpPicParams(
PCODEC_HEVC_ENCODE_PICTURE_PARAMS picParams)
{
CODECHAL_DEBUG_FUNCTION_ENTER;
if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrPicParams))
{
return MOS_STATUS_SUCCESS;
}
CODECHAL_DEBUG_CHK_NULL(picParams);
std::ostringstream oss;
oss.setf(std::ios::showbase | std::ios::uppercase);
oss << "# DDI Parameters:" << std::endl;
oss << "CurrOriginalPic = " << +picParams->CurrOriginalPic.FrameIdx << std::endl;
oss << "CurrReconstructedPic = " << +picParams->CurrReconstructedPic.FrameIdx << std::endl;
oss << "CollocatedRefPicIndex = " << +picParams->CollocatedRefPicIndex << std::endl;
for (uint16_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; ++i)
{
oss << "RefFrameList[" << +i << "] = " << +picParams->RefFrameList[i].FrameIdx << std::endl;
}
oss << "CurrPicOrderCnt = " << +picParams->CurrPicOrderCnt << std::endl;
for (uint16_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; ++i)
{
oss << "RefFramePOCList[" << +i << "] = " << +picParams->RefFramePOCList[i] << std::endl;
}
oss << "CodingType = " << +picParams->CodingType << std::endl;
oss << "HierarchLevelPlus1 = " << +picParams->HierarchLevelPlus1 << std::endl;
oss << "NumSlices = " << +picParams->NumSlices << std::endl;
oss << "tiles_enabled_flag = " << +picParams->tiles_enabled_flag << std::endl;
if (picParams->tiles_enabled_flag)
{
oss << "num_tile_columns = " << +picParams->num_tile_columns_minus1 + 1 << std::endl;
for (uint32_t i = 0; i <= picParams->num_tile_columns_minus1; i++)
{
oss << "tile_column_width[" << +i << "] = " << +picParams->tile_column_width[i] << std::endl;
}
oss << "num_tile_rows = " << +picParams->num_tile_rows_minus1 + 1 << std::endl;
for (uint32_t i = 0; i <= picParams->num_tile_rows_minus1; i++)
{
oss << "tile_row_height[" << +i << "] = " << +picParams->tile_row_height[i] << std::endl;
}
}
oss << "entropy_coding_sync_enabled_flag = " << +picParams->entropy_coding_sync_enabled_flag << std::endl;
oss << "sign_data_hiding_flag = " << +picParams->sign_data_hiding_flag << std::endl;
oss << "constrained_intra_pred_flag = " << +picParams->constrained_intra_pred_flag << std::endl;
oss << "transform_skip_enabled_flag = " << +picParams->transform_skip_enabled_flag << std::endl;
oss << "transquant_bypass_enabled_flag = " << +picParams->transquant_bypass_enabled_flag << std::endl;
oss << "cu_qp_delta_enabled_flag = " << +picParams->cu_qp_delta_enabled_flag << std::endl;
oss << "weighted_pred_flag = " << +picParams->weighted_pred_flag << std::endl;
oss << "weighted_bipred_flag = " << +picParams->weighted_bipred_flag << std::endl;
oss << "bEnableGPUWeightedPrediction = " << +picParams->bEnableGPUWeightedPrediction << std::endl;
oss << "loop_filter_across_slices_flag = " << +picParams->loop_filter_across_slices_flag << std::endl;
oss << "loop_filter_across_tiles_flag = " << +picParams->loop_filter_across_tiles_flag << std::endl;
oss << "scaling_list_data_present_flag = " << +picParams->scaling_list_data_present_flag << std::endl;
oss << "dependent_slice_segments_enabled_flag = " << +picParams->dependent_slice_segments_enabled_flag << std::endl;
oss << "bLastPicInSeq = " << +picParams->bLastPicInSeq << std::endl;
oss << "bLastPicInStream = " << +picParams->bLastPicInStream << std::endl;
oss << "bUseRawPicForRef = " << +picParams->bUseRawPicForRef << std::endl;
oss << "bEmulationByteInsertion = " << +picParams->bEmulationByteInsertion << std::endl;
oss << "bEnableRollingIntraRefresh = " << +picParams->bEnableRollingIntraRefresh << std::endl;
oss << "BRCPrecision = " << +picParams->BRCPrecision << std::endl;
oss << "bScreenContent = " << +picParams->bScreenContent << std::endl;
oss << "QpY = " << +picParams->QpY << std::endl;
oss << "diff_cu_qp_delta_depth = " << +picParams->diff_cu_qp_delta_depth << std::endl;
oss << "pps_cb_qp_offset = " << +picParams->pps_cb_qp_offset << std::endl;
oss << "pps_cr_qp_offset = " << +picParams->pps_cr_qp_offset << std::endl;
oss << "num_tile_columns_minus1 = " << +picParams->num_tile_columns_minus1 << std::endl;
oss << "num_tile_rows_minus1 = " << +picParams->num_tile_rows_minus1 << std::endl;
oss << "log2_parallel_merge_level_minus2 = " << +picParams->log2_parallel_merge_level_minus2 << std::endl;
oss << "num_ref_idx_l0_default_active_minus1 = " << +picParams->num_ref_idx_l0_default_active_minus1 << std::endl;
oss << "num_ref_idx_l1_default_active_minus1 = " << +picParams->num_ref_idx_l1_default_active_minus1 << std::endl;
oss << "LcuMaxBitsizeAllowed = " << +picParams->LcuMaxBitsizeAllowed << std::endl;
oss << "IntraInsertionLocation = " << +picParams->IntraInsertionLocation << std::endl;
oss << "IntraInsertionSize = " << +picParams->IntraInsertionSize << std::endl;
oss << "QpDeltaForInsertedIntra = " << +picParams->QpDeltaForInsertedIntra << std::endl;
oss << "StatusReportFeedbackNumber = " << +picParams->StatusReportFeedbackNumber << std::endl;
oss << "slice_pic_parameter_set_id = " << +picParams->slice_pic_parameter_set_id << std::endl;
oss << "nal_unit_type = " << +picParams->nal_unit_type << std::endl;
oss << "MaxSliceSizeInBytes = " << +picParams->MaxSliceSizeInBytes << std::endl;
oss << "NumROI = " << +picParams->NumROI << std::endl;
for (uint8_t i = 0; i < 16; ++i)
{
oss << "ROI[" << +i << "] = ";
oss << picParams->ROI[i].Top << " ";
oss << picParams->ROI[i].Bottom << " ";
oss << picParams->ROI[i].Left << " ";
oss << picParams->ROI[i].Right << " ";
oss << picParams->ROI[i].PriorityLevelOrDQp << std::endl;
}
oss << "MaxDeltaQp = " << +picParams->MaxDeltaQp << std::endl;
oss << "MinDeltaQp = " << +picParams->MinDeltaQp << std::endl;
oss << "NumDirtyRects = " << +picParams->NumDirtyRects << std::endl;
if ((picParams->NumDirtyRects > 0) && picParams->pDirtyRect)
{
for (uint16_t i = 0; i < picParams->NumDirtyRects; i++)
{
oss << "pDirtyRect[" << +i << "].Bottom = " << +picParams->pDirtyRect[i].Bottom << std::endl;
oss << "pDirtyRect[" << +i << "].Top = " << +picParams->pDirtyRect[i].Top << std::endl;
oss << "pDirtyRect[" << +i << "].Left = " << +picParams->pDirtyRect[i].Left << std::endl;
oss << "pDirtyRect[" << +i << "].Right = " << +picParams->pDirtyRect[i].Right << std::endl;
}
}
oss << "TargetFrameSize = " << +picParams->TargetFrameSize << std::endl;
const char *fileName = m_debugInterface->CreateFileName(
"_DDIEnc",
CodechalDbgBufferType::bufPicParams,
CodechalDbgExtType::txt);
std::ofstream ofs(fileName, std::ios::out);
ofs << oss.str();
ofs.close();
if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDriverUltDump))
{
if (!m_debugInterface->m_ddiFileName.empty())
{
std::ofstream ofs(m_debugInterface->m_ddiFileName, std::ios::app);
ofs << "PicNum"
<< " = \"" << m_debugInterface->m_bufferDumpFrameNum << "\"" << std::endl;
ofs << "PicParamFile"
<< " = \"" << m_debugInterface->m_fileName << "\"" << std::endl;
ofs.close();
}
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS CodechalEncodeHevcBase::DumpFeiPicParams(
CodecEncodeHevcFeiPicParams *feiPicParams)
{
CODECHAL_DEBUG_FUNCTION_ENTER;
if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrFeiPicParams))
{
return MOS_STATUS_SUCCESS;
}
CODECHAL_DEBUG_CHK_NULL(feiPicParams);
std::ostringstream oss;
oss.setf(std::ios::showbase | std::ios::uppercase);
oss << "# DDI Parameters:" << std::endl;
oss << "NumMVPredictorsL0 = " << +feiPicParams->NumMVPredictorsL0 << std::endl;
oss << "NumMVPredictorsL1 = " << +feiPicParams->NumMVPredictorsL1 << std::endl;
oss << "bCTBCmdCuRecordEnable = " << +feiPicParams->bCTBCmdCuRecordEnable << std::endl;
oss << "bDistortionEnable = " << +feiPicParams->bDistortionEnable << std::endl;
oss << "SearchPath = " << +feiPicParams->SearchPath << std::endl;
oss << "LenSP = " << +feiPicParams->LenSP << std::endl;
oss << "MultiPredL0 = " << +feiPicParams->MultiPredL0 << std::endl;
oss << "MultiPredL1 = " << +feiPicParams->MultiPredL1 << std::endl;
oss << "SubPelMode = " << +feiPicParams->SubPelMode << std::endl;
oss << "AdaptiveSearch = " << +feiPicParams->AdaptiveSearch << std::endl;
oss << "MVPredictorInput = " << +feiPicParams->MVPredictorInput << std::endl;
oss << "bPerBlockQP = " << +feiPicParams->bPerBlockQP << std::endl;
oss << "bPerCTBInput = " << +feiPicParams->bPerCTBInput << std::endl;
oss << "bColocatedCTBDistortion = " << +feiPicParams->bColocatedCTBDistortion << std::endl;
oss << "bForceLCUSplit = " << +feiPicParams->bForceLCUSplit << std::endl;
oss << "bEnableCU64Check = " << +feiPicParams->bEnableCU64Check << std::endl;
oss << "bEnableCU64AmpCheck = " << +feiPicParams->bEnableCU64AmpCheck << std::endl;
oss << "bCU64SkipCheckOnly = " << +feiPicParams->bCU64SkipCheckOnly << std::endl;
oss << "RefWidth = " << +feiPicParams->RefWidth << std::endl;
oss << "RefHeight = " << +feiPicParams->RefHeight << std::endl;
oss << "SearchWindow = " << +feiPicParams->SearchWindow << std::endl;
oss << "MaxNumIMESearchCenter = " << +feiPicParams->MaxNumIMESearchCenter << std::endl;
oss << "NumConcurrentEncFramePartition = " << +feiPicParams->NumConcurrentEncFramePartition << std::endl;
const char *fileName = m_debugInterface->CreateFileName(
"_DDIEnc",
CodechalDbgBufferType::bufFeiPicParams,
CodechalDbgExtType::txt);
std::ofstream ofs(fileName, std::ios::out);
ofs << oss.str();
ofs.close();
if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDriverUltDump))
{
if (!m_debugInterface->m_ddiFileName.empty())
{
std::ofstream ofs(m_debugInterface->m_ddiFileName, std::ios::app);
ofs << "PicNum"
<< " = \"" << m_debugInterface->m_bufferDumpFrameNum << "\"" << std::endl;
ofs << "FeiPicParamFile"
<< " = \"" << m_debugInterface->m_fileName << "\"" << std::endl;
ofs.close();
}
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS CodechalEncodeHevcBase::DumpSliceParams(
PCODEC_HEVC_ENCODE_SLICE_PARAMS sliceParams,
PCODEC_HEVC_ENCODE_PICTURE_PARAMS picParams)
{
CODECHAL_DEBUG_FUNCTION_ENTER;
if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSlcParams))
{
return MOS_STATUS_SUCCESS;
}
CODECHAL_DEBUG_CHK_NULL(sliceParams);
m_debugInterface->m_sliceId = sliceParams->slice_id; // set here for constructing debug file name
std::ostringstream oss;
oss.setf(std::ios::showbase | std::ios::uppercase);
oss << "# DDI Parameters:" << std::endl;
oss << "slice_segment_address = " << +sliceParams->slice_segment_address << std::endl;
oss << "NumLCUsInSlice = " << +sliceParams->NumLCUsInSlice << std::endl;
// RefPicList (2 x CODEC_MAX_NUM_REF_FRAME_HEVC)
for (uint8_t i = 0; i < 2; ++i)
{
for (uint8_t j = 0; j < CODEC_MAX_NUM_REF_FRAME_HEVC; ++j)
{
oss << "RefPicList[" << +i << "][" << +j << "] = " << +sliceParams->RefPicList[i][j].PicEntry << std::endl;
}
}
oss << "num_ref_idx_l0_active_minus1 = " << +sliceParams->num_ref_idx_l0_active_minus1 << std::endl;
oss << "num_ref_idx_l1_active_minus1 = " << +sliceParams->num_ref_idx_l1_active_minus1 << std::endl;
oss << "bLastSliceOfPic = " << +sliceParams->bLastSliceOfPic << std::endl;
oss << "dependent_slice_segment_flag = " << +sliceParams->dependent_slice_segment_flag << std::endl;
oss << "slice_temporal_mvp_enable_flag = " << +sliceParams->slice_temporal_mvp_enable_flag << std::endl;
oss << "slice_type = " << +sliceParams->slice_type << std::endl;
oss << "slice_sao_luma_flag = " << +sliceParams->slice_sao_luma_flag << std::endl;
oss << "slice_sao_chroma_flag = " << +sliceParams->slice_sao_chroma_flag << std::endl;
oss << "mvd_l1_zero_flag = " << +sliceParams->mvd_l1_zero_flag << std::endl;
oss << "cabac_init_flag = " << +sliceParams->cabac_init_flag << std::endl;
oss << "slice_deblocking_filter_disable_flag = " << +sliceParams->slice_deblocking_filter_disable_flag << std::endl;
oss << "collocated_from_l0_flag = " << +sliceParams->collocated_from_l0_flag << std::endl;
oss << "slice_qp_delta = " << +sliceParams->slice_qp_delta << std::endl;
oss << "slice_cb_qp_offset = " << +sliceParams->slice_cb_qp_offset << std::endl;
oss << "slice_cr_qp_offset = " << +sliceParams->slice_cr_qp_offset << std::endl;
oss << "beta_offset_div2 = " << +sliceParams->beta_offset_div2 << std::endl;
oss << "tc_offset_div2 = " << +sliceParams->tc_offset_div2 << std::endl;
oss << "luma_log2_weight_denom = " << +sliceParams->luma_log2_weight_denom << std::endl;
oss << "delta_chroma_log2_weight_denom = " << +sliceParams->delta_chroma_log2_weight_denom << std::endl;
for (uint8_t i = 0; i < 2; ++i)
{
for (uint8_t j = 0; j < CODEC_MAX_NUM_REF_FRAME_HEVC; ++j)
{
oss << "luma_offset[" << +i << "][" << +j << "] = " << +sliceParams->luma_offset[i][j] << std::endl;
oss << "delta_luma_weight[" << +i << "][" << +j << "] = " << +sliceParams->delta_luma_weight[i][j] << std::endl;
}
}
for (uint8_t i = 0; i < 2; ++i)
{
for (uint8_t j = 0; j < CODEC_MAX_NUM_REF_FRAME_HEVC; ++j)
{
for (uint8_t k = 0; k < 2; ++k)
{
oss << "chroma_offset[" << +i << "][" << +j << "][" << +k << "] = " << +sliceParams->chroma_offset[i][j][k] << std::endl;
oss << "delta_chroma_weight[" << +i << "][" << +j << "][" << +k << "] = " << +sliceParams->delta_chroma_weight[i][j][k] << std::endl;
}
}
}
oss << "PredWeightTableBitOffset = " << +sliceParams->PredWeightTableBitOffset << std::endl;
oss << "PredWeightTableBitLength = " << +sliceParams->PredWeightTableBitLength << std::endl;
oss << "MaxNumMergeCand = " << +sliceParams->MaxNumMergeCand << std::endl;
oss << "slice_id = " << +sliceParams->slice_id << std::endl;
oss << "SliceHeaderByteOffset = " << +sliceParams->SliceHeaderByteOffset << std::endl;
oss << "BitLengthSliceHeaderStartingPortion = " << +sliceParams->BitLengthSliceHeaderStartingPortion << std::endl;
oss << "SliceSAOFlagBitOffset = " << +sliceParams->SliceSAOFlagBitOffset << std::endl;
const char *fileName = m_debugInterface->CreateFileName(
"_DDIEnc",
CodechalDbgBufferType::bufSlcParams,
CodechalDbgExtType::txt);
std::ofstream ofs(fileName, std::ios::out);
ofs << oss.str();
ofs.close();
if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDriverUltDump))
{
if (!m_debugInterface->m_ddiFileName.empty())
{
std::ofstream ofs(m_debugInterface->m_ddiFileName, std::ios::app);
ofs << "SlcParamFile"
<< " = \"" << m_debugInterface->m_fileName << "\"" << std::endl;
ofs.close();
}
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS CodechalEncodeHevcBase::DumpMbEncPakOutput(PCODEC_REF_LIST currRefList, CodechalDebugInterface* debugInterface)
{
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(currRefList);
CODECHAL_ENCODE_CHK_NULL_RETURN(debugInterface);
CODECHAL_ENCODE_CHK_STATUS_RETURN(debugInterface->DumpBuffer(
&currRefList->resRefMbCodeBuffer,
CodechalDbgAttr::attrOutput,
"PakObj",
m_mvOffset,
0,
CODECHAL_MEDIA_STATE_ENC_NORMAL));
CODECHAL_ENCODE_CHK_STATUS_RETURN(debugInterface->DumpBuffer(
&currRefList->resRefMbCodeBuffer,
CodechalDbgAttr::attrOutput,
"CuRecord",
m_mbCodeSize - m_mvOffset,
m_mvOffset,
CODECHAL_MEDIA_STATE_ENC_NORMAL));
return MOS_STATUS_SUCCESS;
}
MOS_STATUS CodechalEncodeHevcBase::DumpFrameStatsBuffer(CodechalDebugInterface* debugInterface)
{
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(debugInterface);
CODECHAL_ENCODE_CHK_STATUS_RETURN(debugInterface->DumpBuffer(
&m_resFrameStatStreamOutBuffer,
CodechalDbgAttr::attrFrameState,
"FrameStatus",
m_sizeOfHcpPakFrameStats,
0,
CODECHAL_NUM_MEDIA_STATES));
return MOS_STATUS_SUCCESS;
}
MOS_STATUS CodechalEncodeHevcBase::CreateHevcPar()
{
CODECHAL_DEBUG_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(m_debugInterface);
if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDumpEncodePar))
{
CODECHAL_ENCODE_CHK_NULL_RETURN(m_hevcPar = MOS_New(EncodeHevcPar));
MOS_ZeroMemory(m_hevcPar, sizeof(EncodeHevcPar));
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS CodechalEncodeHevcBase::DestroyHevcPar()
{
CODECHAL_DEBUG_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpSeqParFile());
MOS_Delete(m_hevcPar);
return MOS_STATUS_SUCCESS;
}
MOS_STATUS CodechalEncodeHevcBase::PopulateConstParam()
{
CODECHAL_DEBUG_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(m_debugInterface);
if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDumpEncodePar))
{
return MOS_STATUS_SUCCESS;
}
m_encodeParState->m_isConstDumped = true; //Not use this for now, force ture so it can return directly.
if (m_encodeParState->m_isConstDumped)
{
return MOS_STATUS_SUCCESS;
}
std::ostringstream oss;
oss.setf(std::ios::showbase | std::ios::uppercase);
oss << "StartFrameNum = 0" << std::endl;
oss << "SliceStartLCU = 0" << std::endl;
oss << "LowDelay = 1" << std::endl;
oss << "EnableBAsRefs = 1" << std::endl;
oss << "HMECoarseRefPic = 0" << std::endl;
oss << "RefListModforWeightPred = 0" << std::endl;
oss << "EnableStatistics = 0xf00" << std::endl;
oss << "OutputQualityType = 3" << std::endl;
oss << "StaticFrameZMVPercent = 80" << std::endl;
oss << "HMEStreamInRefCost = 50" << std::endl;
m_encodeParState->m_isConstDumped = true;
const char *fileName = m_debugInterface->CreateFileName(
"EncodeSequence",
"EncodePar",
CodechalDbgExtType::par);
std::ofstream ofs(fileName, std::ios::app);
ofs << oss.str();
ofs.close();
return MOS_STATUS_SUCCESS;
}
MOS_STATUS CodechalEncodeHevcBase::PopulateDdiParam(
PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams,
PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams,
PCODEC_HEVC_ENCODE_SLICE_PARAMS hevcSlcParams)
{
if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDumpEncodePar))
{
return MOS_STATUS_SUCCESS;
}
if (hevcSlcParams->slice_type == CODECHAL_ENCODE_HEVC_I_SLICE)
{
m_hevcPar->ISliceQP = hevcPicParams->QpY + hevcSlcParams->slice_qp_delta;
m_hevcPar->StartFrameNum = 0;
m_hevcPar->ProfileIDC = hevcSeqParams->general_profile_idc;
m_hevcPar->LevelIDC = hevcSeqParams->Level;
m_hevcPar->NumP = 0;
m_hevcPar->NumB = hevcSeqParams->GopPicSize - 1;
m_hevcPar->NumSlices = hevcPicParams->NumSlices;
m_hevcPar->SliceStartLCU = 0;
m_hevcPar->Log2MaxCUSize = hevcSeqParams->log2_max_coding_block_size_minus3 + 3;
m_hevcPar->Log2MinCUSize = hevcSeqParams->log2_min_coding_block_size_minus3 + 3;
m_hevcPar->Log2MaxTUSize = hevcSeqParams->log2_max_transform_block_size_minus2 + 2;
m_hevcPar->Log2MinTUSize = hevcSeqParams->log2_min_transform_block_size_minus2 + 2;
uint32_t inputChromaFormatIDC = 0;
switch (m_rawSurface.Format)
{
case (Format_NV12):
case (Format_P010):
inputChromaFormatIDC = 1;
break;
case (Format_YUY2):
case (Format_Y210):
inputChromaFormatIDC = 2;
break;
case (Format_Y410):
case (Format_AYUV):
inputChromaFormatIDC = 3;
break;
default:
inputChromaFormatIDC = 0;
break;
}
m_hevcPar->InputChromaFormatIDC = inputChromaFormatIDC;
m_hevcPar->ChromaFormatIDC = hevcSeqParams->chroma_format_idc;
m_hevcPar->InputBitDepthLuma = hevcSeqParams->SourceBitDepth ? 10 : 8;
m_hevcPar->InputBitDepthChroma = hevcSeqParams->SourceBitDepth ? 10 : 8;
m_hevcPar->OutputBitDepthLuma = hevcSeqParams->bit_depth_luma_minus8 + 8;
m_hevcPar->OutputBitDepthChroma = hevcSeqParams->bit_depth_chroma_minus8 + 8;
m_hevcPar->InternalBitDepthLuma = hevcSeqParams->bit_depth_luma_minus8 + 8;
m_hevcPar->InternalBitDepthChroma = hevcSeqParams->bit_depth_chroma_minus8 + 8;
m_hevcPar->Log2TUMaxDepthInter = hevcSeqParams->max_transform_hierarchy_depth_inter;
m_hevcPar->Log2TUMaxDepthIntra = hevcSeqParams->max_transform_hierarchy_depth_intra;
m_hevcPar->Log2ParallelMergeLevel = hevcPicParams->log2_parallel_merge_level_minus2 + 2;
m_hevcPar->TransquantBypassEnableFlag = hevcPicParams->transquant_bypass_enabled_flag;
m_hevcPar->TransformSkipEnabledFlag = hevcPicParams->transform_skip_enabled_flag;
m_hevcPar->TSDecisionEnabledFlag = hevcPicParams->transform_skip_enabled_flag;
m_hevcPar->TemporalMvpEnableFlag = hevcSeqParams->sps_temporal_mvp_enable_flag;
m_hevcPar->CollocatedFromL0Flag = hevcSlcParams->collocated_from_l0_flag;
m_hevcPar->CollocatedRefIdx = hevcPicParams->CollocatedRefPicIndex;
m_hevcPar->MvdL1ZeroFlag = hevcSlcParams->mvd_l1_zero_flag;
m_hevcPar->AmpEnabledFlag = hevcSeqParams->amp_enabled_flag;
m_hevcPar->CuQpDeltaEnabledFlag = hevcPicParams->cu_qp_delta_enabled_flag;
m_hevcPar->DiffCuQpDeltaDepth = hevcPicParams->diff_cu_qp_delta_depth;
m_hevcPar->ChromaCbQpOffset = hevcPicParams->pps_cb_qp_offset;
m_hevcPar->ChromaCrQpOffset = hevcPicParams->pps_cr_qp_offset;
m_hevcPar->DeblockingTc = hevcSlcParams->tc_offset_div2;
m_hevcPar->DeblockingIDC = hevcSlcParams->slice_deblocking_filter_disable_flag;
m_hevcPar->LoopFilterAcrossSlicesEnabledFlag = hevcPicParams->loop_filter_across_slices_flag;
m_hevcPar->SignDataHidingFlag = hevcPicParams->sign_data_hiding_flag;
m_hevcPar->CabacInitFlag = hevcSlcParams->cabac_init_flag;
m_hevcPar->ConstrainedIntraPred = hevcPicParams->constrained_intra_pred_flag;
m_hevcPar->LowDelay = 1;
m_hevcPar->EnableBAsRefs = 1;
m_hevcPar->BitRate = hevcSeqParams->TargetBitRate * 1000;
m_hevcPar->MaxBitRate = hevcSeqParams->MaxBitRate * 1000;
m_hevcPar->VbvSzInBit = hevcSeqParams->VBVBufferSizeInBit;
m_hevcPar->InitVbvFullnessInBit = hevcSeqParams->InitVBVBufferFullnessInBit;
m_hevcPar->CuRC = hevcSeqParams->MBBRC;
m_hevcPar->EnableMultipass = 1;
m_hevcPar->MaxNumPakPassesI = m_numPasses + 1;
m_hevcPar->MaxNumPakPassesPB = m_numPasses + 1;
m_hevcPar->UserMaxIFrame = hevcSeqParams->UserMaxIFrameSize;
m_hevcPar->UserMaxPBFrame = hevcSeqParams->UserMaxPBFrameSize;
m_hevcPar->FrameRateM = hevcSeqParams->FrameRate.Numerator;
m_hevcPar->FrameRateD = hevcSeqParams->FrameRate.Denominator;
m_hevcPar->IntraRefreshEnable = hevcPicParams->bEnableRollingIntraRefresh ? 1 : 0;
m_hevcPar->IntraRefreshMode = hevcPicParams->bEnableRollingIntraRefresh == 2 ? 1 : 0;
m_hevcPar->IntraRefreshSizeIn32x32 = hevcPicParams->IntraInsertionSize;
m_hevcPar->IntraRefreshDeltaQP = hevcPicParams->QpDeltaForInsertedIntra;
m_hevcPar->HMECoarseRefPic = 0;
//Weighted Prediction
m_hevcPar->FadeDetectionEnable = hevcPicParams->bEnableGPUWeightedPrediction;
m_hevcPar->WeightedPred = hevcPicParams->weighted_pred_flag;
m_hevcPar->WeightedBiPred = hevcPicParams->weighted_bipred_flag;
m_hevcPar->Log2LumaDenom = hevcSlcParams->luma_log2_weight_denom;
m_hevcPar->Log2ChromaDenom = hevcSlcParams->delta_chroma_log2_weight_denom;
m_hevcPar->RefListModforWeightPred = hevcPicParams->bEnableGPUWeightedPrediction;
m_hevcPar->OutputQualityType = 3;
m_hevcPar->SliceSizeCtrl = hevcSeqParams->SliceSizeControl;
m_hevcPar->SliceSizeThreshold = hevcPicParams->MaxSliceSizeInBytes; //?
m_hevcPar->MaxSliceSize = hevcPicParams->MaxSliceSizeInBytes;
m_hevcPar->VDEncMode = m_hevcSeqParams->TargetUsage == 7 ? 0 : 1;
//TU related
m_hevcPar->DisableIntraLuma4x4Tu = m_hevcSeqParams->TargetUsage == 7 ? 1 : 0;
m_hevcPar->HMERef1Disable = m_hevcSeqParams->TargetUsage == 7 ? 1 : 0;
m_hevcPar->NumBetaPreditors = m_hevcSeqParams->TargetUsage == 7 ? 2 : 4;
m_hevcPar->MaxNumImePredictor = m_hevcSeqParams->TargetUsage == 7 ? 4 : 8;
m_hevcPar->NumMergeCandidateCu8x8 = m_hevcSeqParams->TargetUsage == 7 ? 0 : 1;
m_hevcPar->NumMergeCandidateCu16x16 = 2;
m_hevcPar->NumMergeCandidateCu32x32 = m_hevcSeqParams->TargetUsage == 7 ? 2 : 3;
m_hevcPar->NumMergeCandidateCu64x64 = m_hevcSeqParams->TargetUsage == 7 ? 2 : 4;
m_hevcPar->MaxRefIdxL0 = MOS_MAX(m_hevcPar->MaxRefIdxL0, hevcSlcParams->num_ref_idx_l0_active_minus1);
m_hevcPar->MaxRefIdxL1 = MOS_MAX(m_hevcPar->MaxRefIdxL1, hevcSlcParams->num_ref_idx_l1_active_minus1);
uint8_t brcMethod = 0;
uint8_t brcType = 0;
if (CodecHalIsRateControlBrc(hevcSeqParams->RateControlMethod, CODECHAL_HEVC))
{
brcMethod = 2;
switch (hevcSeqParams->RateControlMethod)
{
case RATECONTROL_ICQ:
brcMethod = m_vdencEnabled ? 2 : 3;
brcType = 0;
break;
case RATECONTROL_QVBR:
brcMethod = m_vdencEnabled ? 2 : 4;
brcType = 2;
break;
case RATECONTROL_CBR:
brcType = 1;
break;
case RATECONTROL_VBR:
brcType = 2;
break;
case RATECONTROL_VCM:
brcType = m_vdencEnabled ? 4 : 3;
break;
default:
brcMethod = 0;
brcType = 0;
break;
}
if (hevcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_EXTREMELY_LOW)
{
// low delay mode
brcType = 8;
}
}
m_hevcPar->CRFQualityFactor = hevcSeqParams->ICQQualityFactor;
m_hevcPar->BRCMethod = brcMethod;
m_hevcPar->BRCType = brcType;
m_hevcPar->SAOEnabledFlag = hevcSlcParams->slice_sao_luma_flag | hevcSlcParams->slice_sao_chroma_flag;
m_hevcPar->IntraFrameRDOQEnabledFlag = m_hevcRdoqEnabled;
m_hevcPar->InterFrameRDOQEnabledFlag = m_hevcRdoqEnabled;
m_hevcPar->StreamInEn = m_vdencStreamInEnabled;
m_hevcPar->StreamInMvPredictorRef = m_hevcSeqParams->TargetUsage == 1 ? 7 : 0;
m_hevcPar->StaticFrameZMVPercent = 80;
m_hevcPar->HMEStreamInRefCost = 50;
m_hevcPar->IntraPeriod = hevcSeqParams->GopPicSize;
m_hevcPar->BGOPSize = 0;
}
else if (hevcSlcParams->slice_type == CODECHAL_ENCODE_HEVC_P_SLICE)
{
m_hevcPar->StreamInEn = m_vdencStreamInEnabled;
m_hevcPar->PSliceQP = hevcPicParams->QpY + hevcSlcParams->slice_qp_delta;
m_hevcPar->MaxRefIdxL0 = MOS_MAX(m_hevcPar->MaxRefIdxL0, static_cast<uint32_t>(hevcSlcParams->num_ref_idx_l0_active_minus1 + 1));
m_hevcPar->MaxRefIdxL1 = MOS_MAX(m_hevcPar->MaxRefIdxL1, static_cast<uint32_t>(hevcSlcParams->num_ref_idx_l1_active_minus1 + 1));
}
else if (hevcSlcParams->slice_type == CODECHAL_ENCODE_HEVC_B_SLICE)
{
m_hevcPar->StreamInEn = m_vdencStreamInEnabled;
m_hevcPar->BSliceQP = hevcPicParams->QpY + hevcSlcParams->slice_qp_delta;
m_hevcPar->MaxRefIdxL0 = MOS_MAX(m_hevcPar->MaxRefIdxL0, static_cast<uint32_t>(hevcSlcParams->num_ref_idx_l0_active_minus1 + 1));
m_hevcPar->MaxRefIdxL1 = MOS_MAX(m_hevcPar->MaxRefIdxL1, static_cast<uint32_t>(hevcSlcParams->num_ref_idx_l1_active_minus1 + 1));
}
return MOS_STATUS_SUCCESS;
}
#endif