blob: 33f3be597087ae58afeaa8a54be2920d405fa842 [file] [log] [blame]
/*
* Copyright (c) 2017, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
//!
//! \file codechal_encode_hevc_g9_skl.cpp
//! \brief HEVC dual-pipe encoder for GEN9 SKL.
//!
#include "codechal_encode_hevc_g9_skl.h"
#include "igcodeckrn_g9.h"
//! HEVC encoder kernel header structure for G9 SKL
struct CODECHAL_ENC_HEVC_KERNEL_HEADER_G9_SKL
{
int nKernelCount; //!< Total number of kernels
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_I_2xDownSampling_Kernel; //!< 2x down sampling kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_I_32x32_PU_ModeDecision_Kernel; //!< Intra 32x32 PU mode decision kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_I_16x16_PU_SADComputation_Kernel; //!< Intra 16x16 PU SAD computation kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_I_16x16_PU_ModeDecision_Kernel; //!< Intra 16x16 PU mode decision kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_I_8x8_PU_Kernel; //!< Intra 8x8 PU mode decision kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_I_8x8_PU_FMode_Kernel; //!< Intra 8x8 PU final mode decision kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_PB_32x32_PU_IntraCheck; //!< P/B 32x32 PU intra mode check kernel
CODECHAL_KERNEL_HEADER HEVC_LCUEnc_PB_MB; //!< P/B MbEnc Kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_I_DS4HME; //!< 4x Scaling kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_P_HME; //!< P frame HME kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_B_HME; //!< B frame HME kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_I_COARSE; //!< Intra coarse kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_BRC_Init; //!< BRC init kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_BRC_Reset; //!< BRC reset kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_BRC_Update; //!< BRC update kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_BRC_LCU_Update; //!< BRC LCU update kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_PB_Pak; //!< P/B frame PAK kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_PB_Adv; //!< P/B frame Adv kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_BRC_Blockcopy; //!< BRC blockcopy kerenel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_DS_Combined; //!< Down scale and format conversion kernel
CODECHAL_KERNEL_HEADER HEVC_LCUEnc_P_MB; //!< P frame MbEnc kernel
CODECHAL_KERNEL_HEADER Hevc_LCUEnc_P_Adv; //!< P frame Adv kernel
};
//! \brief typedef of struct CODECHAL_ENC_HEVC_KERNEL_HEADER_G9_SKL
using PCODECHAL_ENC_HEVC_KERNEL_HEADER_G9_SKL = struct CODECHAL_ENC_HEVC_KERNEL_HEADER_G9_SKL*;
MOS_STATUS CodechalEncHevcStateG9Skl::GetKernelHeaderAndSize(
void *binary,
EncOperation operation,
uint32_t krnStateIdx,
void *krnHeader,
uint32_t *krnSize)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
CODECHAL_ENCODE_CHK_NULL_RETURN(binary);
CODECHAL_ENCODE_CHK_NULL_RETURN(krnHeader);
CODECHAL_ENCODE_CHK_NULL_RETURN(krnSize);
PCODECHAL_ENC_HEVC_KERNEL_HEADER_G9_SKL kernelHeaderTable = (PCODECHAL_ENC_HEVC_KERNEL_HEADER_G9_SKL)binary;
PCODECHAL_KERNEL_HEADER currKrnHeader = nullptr;
if (operation == ENC_SCALING4X)
{
currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_I_DS4HME;
}
else if (operation == ENC_ME)
{
// SKL supports P frame. P HME index CODECHAL_ENCODE_ME_IDX_P is 0 and B HME index CODECHAL_ENCODE_ME_IDX_B is 1
if (krnStateIdx == 0)
{
currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_P_HME;
}
else
{
currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_B_HME;
}
}
else if (operation == ENC_BRC)
{
switch (krnStateIdx)
{
case CODECHAL_HEVC_BRC_COARSE_INTRA:
currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_I_COARSE;
break;
case CODECHAL_HEVC_BRC_INIT:
currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_BRC_Init;
break;
case CODECHAL_HEVC_BRC_RESET:
currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_BRC_Reset;
break;
case CODECHAL_HEVC_BRC_FRAME_UPDATE:
currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_BRC_Update;
break;
case CODECHAL_HEVC_BRC_LCU_UPDATE:
currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_BRC_LCU_Update;
break;
default:
CODECHAL_ENCODE_ASSERTMESSAGE("Unsupported BRC mode requested");
eStatus = MOS_STATUS_INVALID_PARAMETER;
return eStatus;
}
}
else if (operation == ENC_MBENC)
{
switch (krnStateIdx)
{
case CODECHAL_HEVC_MBENC_2xSCALING:
case CODECHAL_HEVC_MBENC_32x32MD:
case CODECHAL_HEVC_MBENC_16x16SAD:
case CODECHAL_HEVC_MBENC_16x16MD:
case CODECHAL_HEVC_MBENC_8x8PU:
case CODECHAL_HEVC_MBENC_8x8FMODE:
case CODECHAL_HEVC_MBENC_32x32INTRACHECK:
case CODECHAL_HEVC_MBENC_BENC:
currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_I_2xDownSampling_Kernel;
currKrnHeader += krnStateIdx;
break;
case CODECHAL_HEVC_MBENC_BPAK:
currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_PB_Pak;
break;
case CODECHAL_HEVC_MBENC_ADV:
currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_PB_Adv;
break;
case CODECHAL_HEVC_MBENC_DS_COMBINED:
// Ignore this kernel on SKL.
*krnSize = 0;
return eStatus;
case CODECHAL_HEVC_MBENC_PENC:
currKrnHeader = &kernelHeaderTable->HEVC_LCUEnc_P_MB;
break;
case CODECHAL_HEVC_MBENC_ADV_P:
currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_P_Adv;
break;
default:
CODECHAL_ENCODE_ASSERTMESSAGE("Unsupported ENC mode requested");
eStatus = MOS_STATUS_INVALID_PARAMETER;
return eStatus;
}
}
else
{
CODECHAL_ENCODE_ASSERTMESSAGE("Unsupported ENC mode requested");
eStatus = MOS_STATUS_INVALID_PARAMETER;
return eStatus;
}
*((PCODECHAL_KERNEL_HEADER)krnHeader) = *currKrnHeader;
PCODECHAL_KERNEL_HEADER nextKrnHeader = (currKrnHeader + 1);
PCODECHAL_KERNEL_HEADER invalidEntry = (PCODECHAL_KERNEL_HEADER)(((uint8_t*)binary) + sizeof(*kernelHeaderTable));
uint32_t nextKrnOffset = *krnSize;
if (nextKrnHeader < invalidEntry)
{
nextKrnOffset = nextKrnHeader->KernelStartPointer << MHW_KERNEL_OFFSET_SHIFT;
}
*krnSize = nextKrnOffset - (currKrnHeader->KernelStartPointer << MHW_KERNEL_OFFSET_SHIFT);
return eStatus;
}
void CodechalEncHevcStateG9Skl::UpdateSSDSliceCount()
{
CodechalEncodeHevcBase::UpdateSSDSliceCount();
uint32_t sliceCount;
if (m_frameHeight * m_frameWidth >= 3840 * 2160 && m_targetUsage <= 4)
{
sliceCount = 0;
}
else
{
sliceCount = 2;
}
if (m_osInterface->pfnSetSliceCount)
{
m_osInterface->pfnSetSliceCount(m_osInterface, &sliceCount);
}
}
MOS_STATUS CodechalEncHevcStateG9Skl::Initialize(CodechalSetting * settings)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
CODECHAL_ENCODE_FUNCTION_ENTER;
// common initilization
CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncHevcStateG9::Initialize(settings));
m_cscDsState->EnableMmc();
return eStatus;
}
CodechalEncHevcStateG9Skl::CodechalEncHevcStateG9Skl(
CodechalHwInterface* hwInterface,
CodechalDebugInterface* debugInterface,
PCODECHAL_STANDARD_INFO standardInfo)
:CodechalEncHevcStateG9(hwInterface, debugInterface, standardInfo)
{
m_kernelBase = (uint8_t *)IGCODECKRN_G9;
pfnGetKernelHeaderAndSize = GetKernelHeaderAndSize;
m_noMeKernelForPFrame = false;
MOS_STATUS eStatus = InitMhw();
if (eStatus != MOS_STATUS_SUCCESS)
{
CODECHAL_ENCODE_ASSERTMESSAGE("HEVC encoder MHW initialization failed.");
}
}