blob: 18c45f2acef6fbfab8eed8fd24525230d0c43666 [file] [log] [blame]
/*
* Copyright (c) 2017-2019, 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_brc_g12.cpp
//! \brief HEVC dual-pipe encoder brc kernels for GEN12.
//!
#include "codechal_encode_hevc_mbenc_g12.h"
#include "codechal_encode_hevc_brc_g12.h"
#include "codechal_encode_hevc_g12.h"
#include "mhw_vdbox_hcp_g12_X.h"
#include "Gen12_HEVC_B_LCU32.h"
#include "Gen12_HEVC_B_LCU64.h"
#include "cm_wrapper.h"
#include "Gen12_HEVC_BRC_INIT.h"
#include "Gen12_HEVC_BRC_RESET.h"
#include "Gen12_HEVC_BRC_UPDATE.h"
#include "Gen12_HEVC_BRC_LCUQP.h"
#include "codechal_debug.h"
#if USE_PROPRIETARY_CODE
#include "cm_device_rt.h"
#endif
#if MOS_MEDIASOLO_SUPPORTED
#include "mos_os_solo.h"
#endif // (_DEBUG || _RELEASE_INTERNAL)
MOS_STATUS CodecHalHevcBrcG12::AllocateBrcResources()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
return MOS_STATUS_SUCCESS;
}
MOS_STATUS CodecHalHevcBrcG12::FreeBrcResources()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
// Destroy the container for BRC buffers
if (m_histBufferBrc)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroySurface(m_histBufferBrc));
m_histBufferBrc = nullptr;
}
if (m_PAKStatsBufferBrc)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroySurface(m_PAKStatsBufferBrc));
m_PAKStatsBufferBrc = nullptr;
}
if (m_PICStateInBufferBrc)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroySurface(m_PICStateInBufferBrc));
m_PICStateInBufferBrc = nullptr;
}
if (m_PICStateOutBufferBrc)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroySurface(m_PICStateOutBufferBrc));
m_PICStateOutBufferBrc = nullptr;
}
if (m_CombinedEncBufferBrc)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroySurface(m_CombinedEncBufferBrc));
m_CombinedEncBufferBrc = nullptr;
}
if (m_PixelMBStatsBufferBrc)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroySurface(m_PixelMBStatsBufferBrc));
m_PixelMBStatsBufferBrc = nullptr;
}
if (m_ConstDataBufferBRC)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroySurface(m_ConstDataBufferBRC));
m_ConstDataBufferBRC = nullptr;
}
if (m_BrcMbQp)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroySurface(m_BrcMbQp));
m_BrcMbQp = nullptr;
}
if (m_BrcROISurf)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroySurface(m_BrcROISurf));
m_BrcROISurf = nullptr;
}
if (m_cmKrnBrcInit)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroyKernel(m_cmKrnBrcInit));
m_cmKrnBrcInit = nullptr;
}
if (m_cmProgramBrcInit)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroyProgram(m_cmProgramBrcInit));
m_cmProgramBrcInit = nullptr;
}
if (m_cmKrnBrcReset)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroyKernel(m_cmKrnBrcReset));
m_cmKrnBrcReset = nullptr;
}
if (m_cmProgramBrcReset)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroyProgram(m_cmProgramBrcReset));
m_cmProgramBrcReset = nullptr;
}
if (m_cmKrnBrcUpdate)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroyKernel(m_cmKrnBrcUpdate));
m_cmKrnBrcUpdate = nullptr;
}
if (m_cmProgramBrcUpdate)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroyProgram(m_cmProgramBrcUpdate));
m_cmProgramBrcUpdate = nullptr;
}
if (m_cmKrnBrcLCUQP)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroyKernel(m_cmKrnBrcLCUQP));
m_cmKrnBrcLCUQP = nullptr;
}
if (m_cmProgramBrcLCUQP)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroyProgram(m_cmProgramBrcLCUQP));
m_cmProgramBrcLCUQP = nullptr;
}
if (m_threadSpaceBrcInitReset)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroyThreadSpace(m_threadSpaceBrcInitReset));
m_threadSpaceBrcInitReset = nullptr;
}
if (m_threadSpaceBrcUpdate)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroyThreadSpace(m_threadSpaceBrcUpdate));
m_threadSpaceBrcUpdate = nullptr;
}
if (m_threadSpaceBrcLCUQP)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroyThreadSpace(m_threadSpaceBrcLCUQP));
m_threadSpaceBrcLCUQP = nullptr;
}
return eStatus;
}
MOS_STATUS CodecHalHevcBrcG12::InitBrcKernelState()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->LoadProgram((void *)HEVC_BRC_INIT_GENX,
HEVC_BRC_INIT_GENX_SIZE,
m_cmProgramBrcInit,
"-nojitter"));
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->CreateKernel(m_cmProgramBrcInit,
"HEVC_brc_init",
m_cmKrnBrcInit));
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->LoadProgram((void *)HEVC_BRC_RESET_GENX,
HEVC_BRC_RESET_GENX_SIZE,
m_cmProgramBrcReset,
"-nojitter"));
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->CreateKernel(m_cmProgramBrcReset,
"HEVC_brc_reset",
m_cmKrnBrcReset));
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->LoadProgram((void *)HEVC_BRC_UPDATE_GENX,
HEVC_BRC_UPDATE_GENX_SIZE,
m_cmProgramBrcUpdate,
"-nojitter"));
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->CreateKernel(m_cmProgramBrcUpdate,
"HEVC_brc_update",
m_cmKrnBrcUpdate));
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->LoadProgram((void *)HEVC_BRC_LCUQP_GENX,
HEVC_BRC_LCUQP_GENX_SIZE,
m_cmProgramBrcLCUQP,
"-nojitter"));
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->CreateKernel(m_cmProgramBrcLCUQP,
"HEVC_brc_lcuqp",
m_cmKrnBrcLCUQP));
return eStatus;
}
MOS_STATUS CodecHalHevcBrcG12::SetupKernelArgsBrcInit()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
//Setup surfaces
int idx = 0;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrc->SetKernelArg(idx++, sizeof(encoderBrc->curbe), &encoderBrc->curbe));
SurfaceIndex *pIndex0 = nullptr;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_histBufferBrc->GetIndex(pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrc->SetKernelArg(idx++, sizeof(SurfaceIndex), pIndex0));
//Setup Distortion 2D surface
CmSurface2D *brcDistortion = (encoderBrc->m_pictureCodingType == I_TYPE) ? encoderBrc->m_brcBuffers.brcIntraDistortionSurface
: encoderBrc->m_brcBuffers.meBrcDistortionSurface;
CODECHAL_ENCODE_CHK_STATUS_RETURN(brcDistortion->GetIndex(pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrc->SetKernelArg(idx++, sizeof(SurfaceIndex), pIndex0));
return eStatus;
}
MOS_STATUS CodecHalHevcBrcG12::SetupThreadSpace(CmKernel *cmKernel, CmThreadSpace *& threadSpace)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_CHK_STATUS_RETURN(cmKernel->SetThreadCount(1));
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->CreateThreadSpace(1, 1, threadSpace));
CODECHAL_ENCODE_CHK_STATUS_RETURN(cmKernel->AssociateThreadSpace(threadSpace));
return eStatus;
}
MOS_STATUS CodecHalHevcBrcG12::SetupBrcLcuqpThreadSpace(CmKernel *cmKernel, CmThreadSpace *& threadSpace)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
uint32_t xThread = (encoderBrc->m_downscaledWidthInMb4x * SCALE_FACTOR_4x + 15) >> 4;
uint32_t yThread = (encoderBrc->m_downscaledHeightInMb4x * SCALE_FACTOR_4x + 7) >> 3;
CODECHAL_ENCODE_CHK_STATUS_RETURN(cmKernel->SetThreadCount(xThread * yThread));
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->CreateThreadSpace(xThread, yThread, threadSpace));
CODECHAL_ENCODE_CHK_STATUS_RETURN(cmKernel->AssociateThreadSpace(threadSpace));
return eStatus;
}
MOS_STATUS CodecHalHevcBrcG12::InitCurbeDataBrcInit()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
return eStatus;
}
MOS_STATUS CodecHalHevcBrcG12::SetupSurfacesBrcInit()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
if (!m_histBufferBrc)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->CreateBuffer(
&encoderBrc->m_brcBuffers.resBrcHistoryBuffer, //m_brcHistoryBufferSize,
m_histBufferBrc));
}
return eStatus;
}
MOS_STATUS CodecHalHevcBrcG12::EncodeBrcInitResetKernel()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
// Setup curbe for BrcInitReset kernel
if (encoderBrc->m_brcInit)
{
m_cmKrnBrc = m_cmKrnBrcInit;
}
else
{
m_cmKrnBrc = m_cmKrnBrcReset;
}
/* Only one CM kernel is used to switch between brcInit and brcReset, same rule for threadSpace.
Destroy old one and create a new threadSpace when only brcReset is triggered. */
if (encoderBrc->m_brcReset && m_threadSpaceBrcInitReset)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroyThreadSpace(m_threadSpaceBrcInitReset));
m_threadSpaceBrcInitReset = nullptr;
}
if (!m_threadSpaceBrcInitReset)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(SetupThreadSpace(m_cmKrnBrc, m_threadSpaceBrcInitReset));
}
CODECHAL_ENCODE_CHK_STATUS_RETURN(BrcInitResetCurbe());
CODECHAL_ENCODE_CHK_STATUS_RETURN(SetupSurfacesBrcInit());
CODECHAL_ENCODE_CHK_STATUS_RETURN(SetupKernelArgsBrcInit());
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmTask->AddKernel(m_cmKrnBrc));
if (!encoderBrc->m_singleTaskPhaseSupported || encoderBrc->m_lastTaskInPhase)
{
CmEvent * event = CM_NO_EVENT;
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmQueue->EnqueueFast(encoderBrc->m_cmTask, event));
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmTask->Reset());
encoderBrc->m_lastTaskInPhase = false;
}
else
{
encoderBrc->m_cmTask->AddSync();
}
encoderBrc->m_brcInit = encoderBrc->m_brcReset = false;
// End FW
return eStatus;
}
MOS_STATUS CodecHalHevcBrcG12::BrcInitResetCurbe()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
// Initialize the CURBE data
encoderBrc->curbe = encoderBrc->m_brcInitResetCurbeInit;
uint32_t profileLevelMaxFrame = encoderBrc->GetProfileLevelMaxFrameSize();
if (encoderBrc->m_hevcSeqParams->RateControlMethod == RATECONTROL_CBR ||
encoderBrc->m_hevcSeqParams->RateControlMethod == RATECONTROL_VBR ||
encoderBrc->m_hevcSeqParams->RateControlMethod == RATECONTROL_AVBR)
{
if (encoderBrc->m_hevcSeqParams->InitVBVBufferFullnessInBit == 0)
{
CODECHAL_ENCODE_ASSERTMESSAGE("Initial VBV Buffer Fullness is zero\n");
return MOS_STATUS_INVALID_PARAMETER;
}
if (encoderBrc->m_hevcSeqParams->VBVBufferSizeInBit == 0)
{
CODECHAL_ENCODE_ASSERTMESSAGE("VBV buffer size in bits is zero\n");
return MOS_STATUS_INVALID_PARAMETER;
}
}
encoderBrc->curbe.DW0_ProfileLevelMaxFrame = profileLevelMaxFrame;
encoderBrc->curbe.DW1_InitBufFull = encoderBrc->m_hevcSeqParams->InitVBVBufferFullnessInBit;
encoderBrc->curbe.DW2_BufSize = encoderBrc->m_hevcSeqParams->VBVBufferSizeInBit;
encoderBrc->curbe.DW3_TargetBitRate = encoderBrc->m_hevcSeqParams->TargetBitRate * CODECHAL_ENCODE_BRC_KBPS; //DDI in Kbits
encoderBrc->curbe.DW4_MaximumBitRate = encoderBrc->m_hevcSeqParams->MaxBitRate * CODECHAL_ENCODE_BRC_KBPS;
encoderBrc->curbe.DW5_MinimumBitRate = 0;
encoderBrc->curbe.DW6_FrameRateM = encoderBrc->m_hevcSeqParams->FrameRate.Numerator;
encoderBrc->curbe.DW7_FrameRateD = encoderBrc->m_hevcSeqParams->FrameRate.Denominator;
encoderBrc->curbe.DW8_BRCFlag = encoderBrc->BRCINIT_IGNORE_PICTURE_HEADER_SIZE; // always ignore the picture header size set in BRC Update curbe;
if (encoderBrc->m_hevcPicParams->NumROI)
{
encoderBrc->curbe.DW8_BRCFlag |= encoderBrc->BRCINIT_DISABLE_MBBRC; // BRC ROI need disable MBBRC logic in LcuBrc Kernel
}
else
{
encoderBrc->curbe.DW8_BRCFlag |= (encoderBrc->m_lcuBrcEnabled) ? 0 : encoderBrc->BRCINIT_DISABLE_MBBRC;
}
encoderBrc->curbe.DW8_BRCFlag |= (encoderBrc->m_brcEnabled && encoderBrc->m_numPipe > 1) ? encoderBrc->BRCINIT_USEHUCBRC : 0;
encoderBrc->curbe.DW8_BRCFlag |= (encoderBrc->m_enableFramePanicMode) ? encoderBrc->BRCINIT_PANIC_MODE_ISENABLED : 0;
// For non-ICQ, ACQP Buffer always set to 1
encoderBrc->curbe.DW25_ACQPBuffer = 1;
encoderBrc->curbe.DW25_SlidingWindowSize = encoderBrc->m_slidingWindowSize;
if (encoderBrc->m_hevcSeqParams->RateControlMethod == RATECONTROL_CBR)
{
encoderBrc->curbe.DW4_MaximumBitRate = encoderBrc->curbe.DW3_TargetBitRate;
encoderBrc->curbe.DW8_BRCFlag |= encoderBrc->BRCINIT_ISCBR;
}
else if (encoderBrc->m_hevcSeqParams->RateControlMethod == RATECONTROL_VBR)
{
if (encoderBrc->curbe.DW4_MaximumBitRate < encoderBrc->curbe.DW3_TargetBitRate)
{
encoderBrc->curbe.DW4_MaximumBitRate = 2 * encoderBrc->curbe.DW3_TargetBitRate;
}
encoderBrc->curbe.DW8_BRCFlag |= encoderBrc->BRCINIT_ISVBR;
}
else if (encoderBrc->m_hevcSeqParams->RateControlMethod == RATECONTROL_AVBR)
{
encoderBrc->curbe.DW8_BRCFlag |= encoderBrc->BRCINIT_ISAVBR;
// For AVBR, max bitrate = target bitrate,
encoderBrc->curbe.DW3_TargetBitRate = encoderBrc->m_hevcSeqParams->TargetBitRate * CODECHAL_ENCODE_BRC_KBPS; //DDI in Kbits
encoderBrc->curbe.DW4_MaximumBitRate = encoderBrc->m_hevcSeqParams->TargetBitRate * CODECHAL_ENCODE_BRC_KBPS;
}
else if (encoderBrc->m_hevcSeqParams->RateControlMethod == RATECONTROL_ICQ)
{
encoderBrc->curbe.DW8_BRCFlag |= encoderBrc->BRCINIT_ISICQ;
encoderBrc->curbe.DW25_ACQPBuffer = encoderBrc->m_hevcSeqParams->ICQQualityFactor;
}
else if (encoderBrc->m_hevcSeqParams->RateControlMethod == RATECONTROL_VCM)
{
encoderBrc->curbe.DW4_MaximumBitRate = encoderBrc->curbe.DW3_TargetBitRate;
encoderBrc->curbe.DW8_BRCFlag |= encoderBrc->BRCINIT_ISVCM;
}
else if (encoderBrc->m_hevcSeqParams->RateControlMethod == RATECONTROL_CQP)
{
encoderBrc->curbe.DW8_BRCFlag = encoderBrc->BRCINIT_ISCQP;
}
else if (encoderBrc->m_hevcSeqParams->RateControlMethod == RATECONTROL_QVBR)
{
if (encoderBrc->curbe.DW4_MaximumBitRate < encoderBrc->curbe.DW3_TargetBitRate)
{
encoderBrc->curbe.DW4_MaximumBitRate = encoderBrc->curbe.DW3_TargetBitRate; // Use max bit rate for HRD compliance
}
encoderBrc->curbe.DW8_BRCFlag = encoderBrc->curbe.DW8_BRCFlag | encoderBrc->BRCINIT_ISQVBR | encoderBrc->BRCINIT_ISVBR; // We need to make sure that VBR is used for QP determination.
// use ICQQualityFactor to determine the larger Qp for each MB
encoderBrc->curbe.DW25_ACQPBuffer = encoderBrc->m_hevcSeqParams->ICQQualityFactor;
}
encoderBrc->curbe.DW9_FrameWidth = encoderBrc->m_oriFrameWidth;
encoderBrc->curbe.DW10_FrameHeight = encoderBrc->m_oriFrameHeight;
encoderBrc->curbe.DW10_AVBRAccuracy = encoderBrc->m_usAvbrAccuracy;
encoderBrc->curbe.DW11_AVBRConvergence = encoderBrc->m_usAvbrConvergence;
encoderBrc->curbe.DW12_NumberSlice = encoderBrc->m_numSlices;
/**********************************************************************
In case of non-HB/BPyramid Structure
BRC_Param_A = GopP
BRC_Param_B = GopB
In case of HB/BPyramid GOP Structure
BRC_Param_A, BRC_Param_B, BRC_Param_C, BRC_Param_D are
BRC Parameters set as follows as per CModel equation
***********************************************************************/
// BPyramid GOP
const auto GopPicSize = encoderBrc->m_hevcSeqParams->GopPicSize;
const auto GopRefDist = encoderBrc->m_hevcSeqParams->GopRefDist;
encoderBrc->m_HierchGopBRCEnabled = false;
if(encoderBrc->m_hevcSeqParams->HierarchicalFlag && GopRefDist > 1 && GopRefDist <= 8 )
{
uint32_t numB[9] = {0, 0, 1, 1, 1, 1, 1, 1, 1};
uint32_t numB1[9] = {0, 0, 0, 1, 2, 2, 2, 2, 2};
uint32_t numB2[9] = {0, 0, 0, 0, 0, 1, 2, 3, 4};
uint32_t numOfPyramid = (GopPicSize - 1) / GopRefDist;
uint32_t remOfPyramid = (GopPicSize - 1) % GopRefDist;
encoderBrc->curbe.DW8_BRCGopP = numOfPyramid * numB[GopRefDist] + numB[remOfPyramid + 1];
encoderBrc->curbe.DW9_BRCGopB = numOfPyramid * numB[GopRefDist] + numB[remOfPyramid];
encoderBrc->curbe.DW13_BRCGopB1 = numOfPyramid * numB1[GopRefDist] + numB1[remOfPyramid];
encoderBrc->curbe.DW14_BRCGopB2 = numOfPyramid * numB2[GopRefDist] + numB2[remOfPyramid];
encoderBrc->m_HierchGopBRCEnabled = true;
// B1 Level GOP
if (GopRefDist <= 4 || encoderBrc->curbe.DW14_BRCGopB2 == 0)
{
encoderBrc->curbe.DW14_MaxBRCLevel = 3;
}
// B2 Level GOP
else
{
encoderBrc->curbe.DW14_MaxBRCLevel = 4;
}
}
// For Regular GOP - No BPyramid
else
{
encoderBrc->curbe.DW14_MaxBRCLevel = 1;
encoderBrc->curbe.DW8_BRCGopP = (GopRefDist) ? MOS_ROUNDUP_DIVIDE(GopPicSize - 1, GopRefDist) : 0;
encoderBrc->curbe.DW9_BRCGopB = GopPicSize - 1 - encoderBrc->curbe.DW8_BRCGopP;
}
// Set dynamic thresholds
double inputBitsPerFrame = (double)((double)encoderBrc->curbe.DW4_MaximumBitRate * (double)encoderBrc->curbe.DW7_FrameRateD);
inputBitsPerFrame = (double)(inputBitsPerFrame / encoderBrc->curbe.DW6_FrameRateM);
if (encoderBrc->curbe.DW2_BufSize < (uint32_t)inputBitsPerFrame * 4)
{
encoderBrc->curbe.DW2_BufSize = (uint32_t)inputBitsPerFrame * 4;
}
if (encoderBrc->curbe.DW1_InitBufFull == 0)
{
encoderBrc->curbe.DW1_InitBufFull = 7 * encoderBrc->curbe.DW2_BufSize / 8;
}
if (encoderBrc->curbe.DW1_InitBufFull < (uint32_t)(inputBitsPerFrame * 2))
{
encoderBrc->curbe.DW1_InitBufFull = (uint32_t)(inputBitsPerFrame * 2);
}
if (encoderBrc->curbe.DW1_InitBufFull > encoderBrc->curbe.DW2_BufSize)
{
encoderBrc->curbe.DW1_InitBufFull = encoderBrc->curbe.DW2_BufSize;
}
if (encoderBrc->m_hevcSeqParams->RateControlMethod == RATECONTROL_AVBR)
{
// For AVBR, Buffer size = 2*Bitrate, InitVBV = 0.75 * BufferSize
encoderBrc->curbe.DW2_BufSize = 2 * encoderBrc->m_hevcSeqParams->TargetBitRate * CODECHAL_ENCODE_BRC_KBPS;
encoderBrc->curbe.DW1_InitBufFull = (uint32_t)(0.75 * encoderBrc->curbe.DW2_BufSize);
}
if (encoderBrc->m_hevcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_EXTREMELY_LOW)
{
encoderBrc->curbe.DW15_LongTermInterval = 0; // no LTR for low delay brc
}
else
{
encoderBrc->curbe.DW15_LongTermInterval = (encoderBrc->m_enableBrcLTR && encoderBrc->m_ltrInterval) ?
encoderBrc->m_ltrInterval : encoderBrc->m_enableBrcLTR ? HEVC_BRC_LONG_TERM_REFRENCE_FLAG : 0;
}
double bpsRatio = ( (double) inputBitsPerFrame / (( (double) encoderBrc->curbe.DW2_BufSize) / 30));
bpsRatio = (bpsRatio < 0.1) ? 0.1 : (bpsRatio > 3.5) ? 3.5 : bpsRatio;
encoderBrc->curbe.DW19_DeviationThreshold0_PBframe = (uint32_t)(-50 * pow(0.90, bpsRatio));
encoderBrc->curbe.DW19_DeviationThreshold1_PBframe = (uint32_t)(-50 * pow(0.66, bpsRatio));
encoderBrc->curbe.DW19_DeviationThreshold2_PBframe = (uint32_t)(-50 * pow(0.46, bpsRatio));
encoderBrc->curbe.DW19_DeviationThreshold3_PBframe = (uint32_t)(-50 * pow(0.3, bpsRatio));
encoderBrc->curbe.DW20_DeviationThreshold4_PBframe = (uint32_t)(50 * pow(0.3, bpsRatio));
encoderBrc->curbe.DW20_DeviationThreshold5_PBframe = (uint32_t)(50 * pow(0.46, bpsRatio));
encoderBrc->curbe.DW20_DeviationThreshold6_PBframe = (uint32_t)(50 * pow(0.7, bpsRatio));
encoderBrc->curbe.DW20_DeviationThreshold7_PBframe = (uint32_t)(50 * pow(0.9, bpsRatio));
encoderBrc->curbe.DW21_DeviationThreshold0_VBRcontrol = (uint32_t)(-50 * pow(0.9, bpsRatio));
encoderBrc->curbe.DW21_DeviationThreshold1_VBRcontrol = (uint32_t)(-50 * pow(0.7, bpsRatio));
encoderBrc->curbe.DW21_DeviationThreshold2_VBRcontrol = (uint32_t)(-50 * pow(0.5, bpsRatio));
encoderBrc->curbe.DW21_DeviationThreshold3_VBRcontrol = (uint32_t)(-50 * pow(0.3, bpsRatio));
encoderBrc->curbe.DW22_DeviationThreshold4_VBRcontrol = (uint32_t)(100 * pow(0.4, bpsRatio));
encoderBrc->curbe.DW22_DeviationThreshold5_VBRcontrol = (uint32_t)(100 * pow(0.5, bpsRatio));
encoderBrc->curbe.DW22_DeviationThreshold6_VBRcontrol = (uint32_t)(100 * pow(0.75, bpsRatio));
encoderBrc->curbe.DW22_DeviationThreshold7_VBRcontrol = (uint32_t)(100 * pow(0.9, bpsRatio));
encoderBrc->curbe.DW23_DeviationThreshold0_Iframe = (uint32_t)(-50 * pow(0.8, bpsRatio));
encoderBrc->curbe.DW23_DeviationThreshold1_Iframe = (uint32_t)(-50 * pow(0.6, bpsRatio));
encoderBrc->curbe.DW23_DeviationThreshold2_Iframe = (uint32_t)(-50 * pow(0.34, bpsRatio));
encoderBrc->curbe.DW23_DeviationThreshold3_Iframe = (uint32_t)(-50 * pow(0.2, bpsRatio));
encoderBrc->curbe.DW24_DeviationThreshold4_Iframe = (uint32_t)(50 * pow(0.2, bpsRatio));
encoderBrc->curbe.DW24_DeviationThreshold5_Iframe = (uint32_t)(50 * pow(0.4, bpsRatio));
encoderBrc->curbe.DW24_DeviationThreshold6_Iframe = (uint32_t)(50 * pow(0.66, bpsRatio));
encoderBrc->curbe.DW24_DeviationThreshold7_Iframe = (uint32_t)(50 * pow(0.9, bpsRatio));
if (encoderBrc->m_hevcSeqParams->HierarchicalFlag && !encoderBrc->m_hevcSeqParams->LowDelayMode &&
(encoderBrc->m_hevcSeqParams->GopRefDist == 4 || encoderBrc->m_hevcSeqParams->GopRefDist == 8))
{
encoderBrc->curbe.DW26_RandomAccess = true;
}
else
{
encoderBrc->curbe.DW26_RandomAccess = false;
}
if (encoderBrc->m_brcInit)
{
encoderBrc->m_dBrcInitCurrentTargetBufFullInBits = encoderBrc->curbe.DW1_InitBufFull;
}
encoderBrc->m_brcInitResetBufSizeInBits = encoderBrc->curbe.DW2_BufSize;
encoderBrc->m_dBrcInitResetInputBitsPerFrame = inputBitsPerFrame;
return eStatus;
}
MOS_STATUS CodecHalHevcBrcG12::BrcUpdateCurbe()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
// Initialize the CURBE data
encoderBrc->curbeBrcUpdate = encoderBrc->m_brcUpdateCurbeInit;
encoderBrc->curbeBrcUpdate.DW5_TargetSize_Flag = 0;
if (encoderBrc->m_dBrcInitCurrentTargetBufFullInBits > (double)encoderBrc->m_brcInitResetBufSizeInBits)
{
encoderBrc->m_dBrcInitCurrentTargetBufFullInBits -= (double)encoderBrc->m_brcInitResetBufSizeInBits;
encoderBrc->curbeBrcUpdate.DW5_TargetSize_Flag = 1;
}
if (encoderBrc->m_numSkipFrames)
{
// pass num/size of skipped frames to update BRC
encoderBrc->curbeBrcUpdate.DW6_NumSkippedFrames = encoderBrc->m_numSkipFrames;
encoderBrc->curbeBrcUpdate.DW15_SizeOfSkippedFrames = encoderBrc->m_sizeSkipFrames;
// account for skipped frame in calculating CurrentTargetBufFullInBits
encoderBrc->m_dBrcInitCurrentTargetBufFullInBits += encoderBrc->m_dBrcInitResetInputBitsPerFrame * encoderBrc->m_numSkipFrames;
}
encoderBrc->curbeBrcUpdate.DW0_TargetSize = (uint32_t)(encoderBrc->m_dBrcInitCurrentTargetBufFullInBits);
encoderBrc->curbeBrcUpdate.DW1_FrameNumber = encoderBrc->m_storeData - 1; // Check if we can remove this (set to 0)
uint32_t picHdrSize = encoderBrc->GetPicHdrSize();
encoderBrc->curbeBrcUpdate.DW2_PictureHeaderSize = picHdrSize;
encoderBrc->curbeBrcUpdate.DW5_CurrFrameBrcLevel = encoderBrc->m_currFrameBrcLevel;
encoderBrc->curbeBrcUpdate.DW5_MaxNumPAKs = m_brcNumPakPasses;
if (encoderBrc->m_hevcSeqParams->RateControlMethod == RATECONTROL_CQP)
{
encoderBrc->curbeBrcUpdate.DW6_CqpValue = encoderBrc->m_hevcPicParams->QpY + encoderBrc->m_hevcSliceParams->slice_qp_delta;
}
encoderBrc->curbeBrcUpdate.DW6_SlidingWindowEnable = (encoderBrc->m_hevcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_LOW);
if (encoderBrc->m_hevcPicParams->NumROI)
{
encoderBrc->curbeBrcUpdate.DW6_ROIEnable = encoderBrc->m_brcEnabled ? false : true;
encoderBrc->curbeBrcUpdate.DW6_BRCROIEnable = encoderBrc->m_brcEnabled ? true : false;
encoderBrc->curbeBrcUpdate.DW6_RoiRatio = encoderBrc->CalculateROIRatio();
}
if (encoderBrc->m_minMaxQpControlEnabled)
{
if (encoderBrc->m_hevcPicParams->CodingType == I_TYPE)
{
encoderBrc->curbeBrcUpdate.DW7_FrameMaxQP = encoderBrc->m_maxQpForI;
encoderBrc->curbeBrcUpdate.DW7_FrameMinQP = encoderBrc->m_minQpForI;
}
else if (encoderBrc->m_hevcPicParams->CodingType == P_TYPE)
{
encoderBrc->curbeBrcUpdate.DW7_FrameMaxQP = encoderBrc->m_maxQpForP;
encoderBrc->curbeBrcUpdate.DW7_FrameMinQP = encoderBrc->m_minQpForP;
}
else if (encoderBrc->m_hevcPicParams->CodingType == B_TYPE)
{
encoderBrc->curbeBrcUpdate.DW7_FrameMaxQP = encoderBrc->m_maxQpForB;
encoderBrc->curbeBrcUpdate.DW7_FrameMinQP = encoderBrc->m_minQpForB;
}
}
//for low delay brc
encoderBrc->curbeBrcUpdate.DW6_LowDelayEnable = (encoderBrc->m_hevcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_EXTREMELY_LOW);
encoderBrc->curbeBrcUpdate.DW16_UserMaxFrameSize = encoderBrc->GetProfileLevelMaxFrameSize();
encoderBrc->curbeBrcUpdate.DW14_ParallelMode = encoderBrc->m_hevcSeqParams->ParallelBRC;
if (encoderBrc->m_hevcSeqParams->RateControlMethod == RATECONTROL_AVBR)
{
encoderBrc->curbeBrcUpdate.DW3_StartGAdjFrame0 = (uint32_t)((10 * encoderBrc->m_usAvbrConvergence) / (double)150);
encoderBrc->curbeBrcUpdate.DW3_StartGAdjFrame1 = (uint32_t)((50 * encoderBrc->m_usAvbrConvergence) / (double)150);
encoderBrc->curbeBrcUpdate.DW4_StartGAdjFrame2 = (uint32_t)((100 * encoderBrc->m_usAvbrConvergence) / (double)150);
encoderBrc->curbeBrcUpdate.DW4_StartGAdjFrame3 = (uint32_t)((150 * encoderBrc->m_usAvbrConvergence) / (double)150);
encoderBrc->curbeBrcUpdate.DW11_gRateRatioThreshold0 =
(uint32_t)((100 - (encoderBrc->m_usAvbrAccuracy / (double)30)*(100 - 40)));
encoderBrc->curbeBrcUpdate.DW11_gRateRatioThreshold1 =
(uint32_t)((100 - (encoderBrc->m_usAvbrAccuracy / (double)30)*(100 - 75)));
encoderBrc->curbeBrcUpdate.DW12_gRateRatioThreshold2 = (uint32_t)((100 - (encoderBrc->m_usAvbrAccuracy / (double)30)*(100 - 97)));
encoderBrc->curbeBrcUpdate.DW12_gRateRatioThreshold3 = (uint32_t)((100 + (encoderBrc->m_usAvbrAccuracy / (double)30)*(103 - 100)));
encoderBrc->curbeBrcUpdate.DW12_gRateRatioThreshold4 = (uint32_t)((100 + (encoderBrc->m_usAvbrAccuracy / (double)30)*(125 - 100)));
encoderBrc->curbeBrcUpdate.DW12_gRateRatioThreshold5 = (uint32_t)((100 + (encoderBrc->m_usAvbrAccuracy / (double)30)*(160 - 100)));
}
if (encoderBrc->m_hevcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_EXTREMELY_LOW)
{
encoderBrc->curbeBrcUpdate.DW17_LongTerm_Current = 0; // no LTR for low delay brc
}
else
{
encoderBrc->m_isFrameLTR = (CodecHal_PictureIsLongTermRef(encoderBrc->m_currReconstructedPic));
encoderBrc->curbeBrcUpdate.DW17_LongTerm_Current = (encoderBrc->m_enableBrcLTR && encoderBrc->m_isFrameLTR) ? 1 : 0;
}
return eStatus;
}
MOS_STATUS CodecHalHevcBrcG12::EncodeBrcFrameUpdateKernel()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
PerfTagSetting perfTag;
perfTag.Value = 0;
perfTag.Mode = (uint16_t)encoderBrc->m_mode & CODECHAL_ENCODE_MODE_BIT_MASK;
perfTag.CallType = CODECHAL_ENCODE_PERFTAG_CALL_BRC_UPDATE;
perfTag.PictureCodingType = encoderBrc->m_pictureCodingType;
encoderBrc->GetOsInterface()->pfnSetPerfTag(encoderBrc->GetOsInterface(), perfTag.Value);
encoderBrc->GetOsInterface()->pfnIncPerfBufferID(encoderBrc->GetOsInterface());
if (!m_threadSpaceBrcUpdate)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(SetupThreadSpace(m_cmKrnBrcUpdate, m_threadSpaceBrcUpdate));
}
CODECHAL_ENCODE_CHK_STATUS_RETURN(BrcUpdateCurbe());
CODECHAL_ENCODE_CHK_STATUS_RETURN(SetupSurfacesBrcUpdate());
CODECHAL_ENCODE_CHK_STATUS_RETURN(SetupKernelArgsBrcUpdate());
CODECHAL_DEBUG_TOOL(
CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpBrcInputBuffers()));
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmTask->AddKernel(m_cmKrnBrcUpdate));
if (!encoderBrc->m_singleTaskPhaseSupported || encoderBrc->m_lastTaskInPhase)
{
CmEvent * event = CM_NO_EVENT;
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmQueue->EnqueueFast(encoderBrc->m_cmTask, event));
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmTask->Reset());
encoderBrc->m_lastTaskInPhase = false;
}
else
{
encoderBrc->m_cmTask->AddSync();
}
return eStatus;
}
MOS_STATUS CodecHalHevcBrcG12::SetupSurfacesBrcUpdate()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
// Fill HCP_IMG_STATE so that BRC kernel can use it to generate the write buffer for PAK
PMOS_RESOURCE brcHcpStateReadBuffer = &encoderBrc->m_brcBuffers.resBrcImageStatesReadBuffer[encoderBrc->m_currRecycledBufIdx];
MHW_VDBOX_HEVC_PIC_STATE_G12 mhwHevcPicState;
mhwHevcPicState.pHevcEncSeqParams = encoderBrc->m_hevcSeqParams;
mhwHevcPicState.pHevcEncPicParams = encoderBrc->m_hevcPicParams;
mhwHevcPicState.brcNumPakPasses = m_brcNumPakPasses;
mhwHevcPicState.rhodomainRCEnable = encoderBrc->m_brcEnabled && (encoderBrc->m_numPipe > 1);
mhwHevcPicState.bSAOEnable = encoderBrc->m_hevcSeqParams->SAO_enabled_flag ? (encoderBrc->m_hevcSliceParams->slice_sao_luma_flag || encoderBrc->m_hevcSliceParams->slice_sao_chroma_flag) : 0;
mhwHevcPicState.bTransformSkipEnable = encoderBrc->m_hevcPicParams->transform_skip_enabled_flag;
mhwHevcPicState.bHevcRdoqEnabled = encoderBrc->m_hevcRdoqEnabled;
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_hcpInterface->AddHcpHevcPicBrcBuffer(brcHcpStateReadBuffer, &mhwHevcPicState));
PMOS_SURFACE brcConstantData = &encoderBrc->m_brcBuffers.sBrcConstantDataBuffer[encoderBrc->m_currRecycledBufIdx];
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->SetupBrcConstantTable(brcConstantData));
if (!m_histBufferBrc)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->CreateBuffer(
&encoderBrc->m_brcBuffers.resBrcHistoryBuffer, //m_brcHistoryBufferSize,
m_histBufferBrc));
}
// BRC Prev PAK statistics output buffer
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->UpdateBuffer(
&encoderBrc->m_brcBuffers.resBrcPakStatisticBuffer[encoderBrc->m_brcBuffers.uiCurrBrcPakStasIdxForRead],
m_PAKStatsBufferBrc));
// BRC HCP_PIC_STATE read
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->UpdateBuffer(
brcHcpStateReadBuffer,
m_PICStateInBufferBrc));
// BRC HCP_PIC_STATE write
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->UpdateBuffer(
&encoderBrc->m_brcBuffers.resBrcImageStatesWriteBuffer[encoderBrc->m_currRecycledBufIdx],
m_PICStateOutBufferBrc));
// BRC Data Surface
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->UpdateSurface2D(
&brcConstantData->OsResource,
m_ConstDataBufferBRC));
// Pixel MB Statistics surface
if (!m_PixelMBStatsBufferBrc)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->CreateBuffer(
&encoderBrc->m_resMbStatsBuffer,
m_PixelMBStatsBufferBrc));
}
// Combined ENC-parameter buffer
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->UpdateBuffer(
&encoderBrc->m_brcInputForEncKernelBuffer->sResource,
m_CombinedEncBufferBrc));
return eStatus;
}
MOS_STATUS CodecHalHevcBrcG12::SetupKernelArgsBrcUpdate()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
int idx = 0;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrcUpdate->SetKernelArg(idx++, sizeof(encoderBrc->m_brcUpdateCurbeInit), &encoderBrc->curbeBrcUpdate));
SurfaceIndex *pIndex0 = nullptr;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_histBufferBrc->GetIndex(pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrcUpdate->SetKernelArg(idx++, sizeof(SurfaceIndex), pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_PAKStatsBufferBrc->GetIndex(pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrcUpdate->SetKernelArg(idx++, sizeof(SurfaceIndex), pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_PICStateInBufferBrc->GetIndex(pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrcUpdate->SetKernelArg(idx++, sizeof(SurfaceIndex), pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_PICStateOutBufferBrc->GetIndex(pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrcUpdate->SetKernelArg(idx++, sizeof(SurfaceIndex), pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_CombinedEncBufferBrc->GetIndex(pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrcUpdate->SetKernelArg(idx++, sizeof(SurfaceIndex), pIndex0));
//Setup Distortion 2D surface
CmSurface2D *brcDistortion = (encoderBrc->m_pictureCodingType == I_TYPE) ? encoderBrc->m_brcBuffers.brcIntraDistortionSurface
: encoderBrc->m_brcBuffers.meBrcDistortionSurface;
CODECHAL_ENCODE_CHK_STATUS_RETURN(brcDistortion->GetIndex(pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrcUpdate->SetKernelArg(idx++, sizeof(SurfaceIndex), pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_ConstDataBufferBRC->GetIndex(pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrcUpdate->SetKernelArg(idx++, sizeof(SurfaceIndex), pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_PixelMBStatsBufferBrc->GetIndex(pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrcUpdate->SetKernelArg(idx++, sizeof(SurfaceIndex), pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_brcBuffers.mvAndDistortionSumSurface->GetIndex(pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrcUpdate->SetKernelArg(idx++, sizeof(SurfaceIndex), pIndex0));
return eStatus;
}
MOS_STATUS CodecHalHevcBrcG12::EncodeBrcLcuUpdateKernel()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
PerfTagSetting perfTag;
perfTag.Value = 0;
perfTag.Mode = (uint16_t)encoderBrc->m_mode & CODECHAL_ENCODE_MODE_BIT_MASK;
perfTag.CallType = CODECHAL_ENCODE_PERFTAG_CALL_BRC_UPDATE_LCU;
perfTag.PictureCodingType = encoderBrc->m_pictureCodingType;
encoderBrc->GetOsInterface()->pfnSetPerfTag(encoderBrc->GetOsInterface(), perfTag.Value);
encoderBrc->GetOsInterface()->pfnIncPerfBufferID(encoderBrc->GetOsInterface());
CODECHAL_ENCODE_CHK_STATUS_RETURN(BrcUpdateCurbe());
CODECHAL_ENCODE_CHK_STATUS_RETURN(SetupSurfacesBrcLcuQp());
if (encoderBrc->m_hevcPicParams->NumROI)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->SetupROISurface());
}
CODECHAL_ENCODE_CHK_STATUS_RETURN(SetupKernelArgsBrcLcuQp());
if (encoderBrc->m_resolutionChanged && m_threadSpaceBrcLCUQP)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->DestroyThreadSpace(m_threadSpaceBrcLCUQP));
m_threadSpaceBrcLCUQP = nullptr;
}
if (!m_threadSpaceBrcLCUQP)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(SetupBrcLcuqpThreadSpace(m_cmKrnBrcLCUQP, m_threadSpaceBrcLCUQP));
}
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmTask->AddKernel(m_cmKrnBrcLCUQP));
if (!encoderBrc->m_singleTaskPhaseSupported || encoderBrc->m_lastTaskInPhase)
{
CmEvent * event = CM_NO_EVENT;
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmQueue->EnqueueFast(encoderBrc->m_cmTask, event));
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmTask->Reset());
encoderBrc->m_lastTaskInPhase = false;
}
else
{
encoderBrc->m_cmTask->AddSync();
}
return eStatus;
}
MOS_STATUS CodecHalHevcBrcG12::SetupSurfacesBrcLcuQp()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
if (!m_histBufferBrc)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->CreateBuffer(
&encoderBrc->m_brcBuffers.resBrcHistoryBuffer,
m_histBufferBrc));
}
// Pixel MB Statistics surface
if (!m_PixelMBStatsBufferBrc)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->CreateBuffer(
&encoderBrc->m_resMbStatsBuffer,
m_PixelMBStatsBufferBrc));
}
if (!m_BrcMbQp) {
// BRC Data Surface
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->CreateSurface2D(
&encoderBrc->m_brcBuffers.sBrcMbQpBuffer.OsResource,
m_BrcMbQp));
}
if (!m_BrcROISurf)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->m_cmDev->CreateSurface2D(
&encoderBrc->m_brcBuffers.sBrcRoiSurface.OsResource,
m_BrcROISurf));
}
return eStatus;
}
MOS_STATUS CodecHalHevcBrcG12::SetupKernelArgsBrcLcuQp()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
int idx = 0;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrcLCUQP->SetKernelArg(idx++, sizeof(encoderBrc->m_brcUpdateCurbeInit), &encoderBrc->curbeBrcUpdate));
SurfaceIndex *pIndex0 = nullptr;
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_histBufferBrc->GetIndex(pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrcLCUQP->SetKernelArg(idx++, sizeof(SurfaceIndex), pIndex0));
//Setup Distortion 2D surface
CmSurface2D *brcDistortion = (encoderBrc->m_pictureCodingType == I_TYPE) ? encoderBrc->m_brcBuffers.brcIntraDistortionSurface
: encoderBrc->m_brcBuffers.meBrcDistortionSurface;
CODECHAL_ENCODE_CHK_STATUS_RETURN(brcDistortion->GetIndex(pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrcLCUQP->SetKernelArg(idx++, sizeof(SurfaceIndex), pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_PixelMBStatsBufferBrc->GetIndex(pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrcLCUQP->SetKernelArg(idx++, sizeof(SurfaceIndex), pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_BrcMbQp->GetIndex(pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrcLCUQP->SetKernelArg(idx++, sizeof(SurfaceIndex), pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_BrcROISurf->GetIndex(pIndex0));
CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cmKrnBrcLCUQP->SetKernelArg(idx++, sizeof(SurfaceIndex), pIndex0));
return eStatus;
}
#if USE_CODECHAL_DEBUG_TOOL
MOS_STATUS CodecHalHevcBrcG12::DumpBrcInputBuffers()
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->GetDebugInterface()->DumpBuffer(
&encoderBrc->m_mvAndDistortionSumSurface.sResource,
CodechalDbgAttr::attrInput,
"MvDistSum",
encoderBrc->m_mvAndDistortionSumSurface.dwSize,
0,
CODECHAL_MEDIA_STATE_BRC_UPDATE));
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->GetDebugInterface()->DumpBuffer(
&encoderBrc->m_brcBuffers.resBrcImageStatesReadBuffer[encoderBrc->m_currRecycledBufIdx],
CodechalDbgAttr::attrInput,
"ImgStateRead",
BRC_IMG_STATE_SIZE_PER_PASS * encoderBrc->GetHwInterface()->GetMfxInterface()->GetBrcNumPakPasses(),
0,
CODECHAL_MEDIA_STATE_BRC_UPDATE));
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->GetDebugInterface()->DumpSurface(
&encoderBrc->m_brcBuffers.sBrcConstantDataBuffer[encoderBrc->m_currRecycledBufIdx],
CodechalDbgAttr::attrInput,
"ConstData",
CODECHAL_MEDIA_STATE_BRC_UPDATE));
// PAK statistics buffer is only dumped for BrcUpdate kernel input
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->GetDebugInterface()->DumpBuffer(
&encoderBrc->m_brcBuffers.resBrcPakStatisticBuffer[encoderBrc->m_brcBuffers.uiCurrBrcPakStasIdxForRead],
CodechalDbgAttr::attrInput,
"PakStats",
HEVC_BRC_PAK_STATISTCS_SIZE,
0,
CODECHAL_MEDIA_STATE_BRC_UPDATE));
// HEVC maintains a ptr to its own distortion surface, as it may be a couple different surfaces
if (encoderBrc->m_brcDistortion)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(
encoderBrc->GetDebugInterface()->DumpBuffer(
&encoderBrc->m_brcDistortion->OsResource,
CodechalDbgAttr::attrInput,
"BrcDist_BeforeFrameBrc",
encoderBrc->m_brcBuffers.sMeBrcDistortionBuffer.dwPitch * encoderBrc->m_brcBuffers.sMeBrcDistortionBuffer.dwHeight,
encoderBrc->m_brcBuffers.dwMeBrcDistortionBottomFieldOffset,
CODECHAL_MEDIA_STATE_BRC_UPDATE));
}
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->GetDebugInterface()->DumpBuffer(&encoderBrc->m_brcBuffers.resBrcHistoryBuffer,
CodechalDbgAttr::attrInput,
"HistoryRead_beforeFramBRC",
encoderBrc->m_brcHistoryBufferSize,
0,
CODECHAL_MEDIA_STATE_BRC_UPDATE));
if (encoderBrc->m_brcBuffers.pMbEncKernelStateInUse)
{
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->GetDebugInterface()->DumpCurbe(
CODECHAL_MEDIA_STATE_BRC_UPDATE,
encoderBrc->m_brcBuffers.pMbEncKernelStateInUse));
}
CODECHAL_ENCODE_CHK_STATUS_RETURN(encoderBrc->GetDebugInterface()->DumpBuffer(&encoderBrc->m_resMbStatsBuffer,
CodechalDbgAttr::attrInput,
"MBStatsSurf",
encoderBrc->GetHwInterface()->m_avcMbStatBufferSize,
0,
CODECHAL_MEDIA_STATE_BRC_UPDATE));
return eStatus;
}
#endif