blob: 512c7aa0e3fc2f0a02b95e9d5de0d2265c603b37 [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 media_ddi_encode_fei_avc.cpp
//! \brief Implements class for DDI media avc fei encode
//!
#include "media_libva.h"
#include "media_libva_encoder.h"
#include "media_libva_util.h"
#include "hwinfo_linux.h"
#include "media_ddi_encode_base.h"
#include "media_ddi_encode_fei_avc.h"
#include "media_ddi_encode_const.h"
#include "media_ddi_factory.h"
static const uint8_t feiMaxPassesNum = 4;
extern template class MediaDdiFactoryNoArg<DdiEncodeBase>;
static bool isEncodeAvcFeiRegistered =
MediaDdiFactoryNoArg<DdiEncodeBase>::RegisterCodec<DdiEncodeAvcFei>(ENCODE_ID_AVCFEI);
DdiEncodeAvcFei::~DdiEncodeAvcFei()
{
if (nullptr == m_encodeCtx)
{
return;
}
MOS_FreeMemory(m_encodeCtx->pFeiPicParams);
m_encodeCtx->pFeiPicParams = nullptr;
MOS_FreeMemory(m_encodeCtx->pPreEncParams);
m_encodeCtx->pPreEncParams = nullptr;
MOS_FreeMemory(iqMatrixParams);
iqMatrixParams = nullptr;
MOS_FreeMemory(iqWeightScaleLists);
iqWeightScaleLists = nullptr;
}
VAStatus DdiEncodeAvcFei::ContextInitialize(CodechalSetting * codecHalSettings)
{
VAStatus status = DdiEncodeAvc::ContextInitialize(codecHalSettings);
if (VA_STATUS_SUCCESS != status)
{
return status;
}
codecHalSettings->codecFunction = m_encodeCtx->codecFunction;
m_encodeCtx->pFeiPicParams = (void *)MOS_AllocAndZeroMemory(CODEC_AVC_MAX_PPS_NUM * sizeof(CodecEncodeAvcFeiPicParams));
DDI_CHK_NULL(m_encodeCtx->pFeiPicParams, "nullptr m_encodeCtx->pFeiPicParams", VA_STATUS_ERROR_ALLOCATION_FAILED);
m_encodeCtx->pPreEncParams = (void *)MOS_AllocAndZeroMemory(CODEC_AVC_MAX_PPS_NUM * sizeof(FeiPreEncParams));
DDI_CHK_NULL(m_encodeCtx->pPreEncParams, "nullptr m_encodeCtx->pPreEncParams", VA_STATUS_ERROR_ALLOCATION_FAILED);
iqMatrixParams = (PCODEC_AVC_IQ_MATRIX_PARAMS)MOS_AllocAndZeroMemory(sizeof(CODEC_AVC_IQ_MATRIX_PARAMS));
DDI_CHK_NULL(iqMatrixParams, "nullptr iqMatrixParams", VA_STATUS_ERROR_ALLOCATION_FAILED);
iqWeightScaleLists = (PCODEC_AVC_ENCODE_IQ_WEIGTHSCALE_LISTS)MOS_AllocAndZeroMemory(sizeof(CODEC_AVC_ENCODE_IQ_WEIGTHSCALE_LISTS));
DDI_CHK_NULL(iqWeightScaleLists, "nullptr iqWeightScaleLists", VA_STATUS_ERROR_ALLOCATION_FAILED);
return VA_STATUS_SUCCESS;
}
VAStatus DdiEncodeAvcFei::EncodeInCodecHal(uint32_t numSlices)
{
uint8_t ppsIdx, spsIdx;
PCODEC_AVC_ENCODE_PIC_PARAMS picParams;
DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_NULL(m_encodeCtx->pCodecHal, "nullptr m_encodeCtx->pCodecHal", VA_STATUS_ERROR_INVALID_CONTEXT);
DDI_CHK_NULL(m_encodeCtx->pMediaCtx, "nullptr m_encodeCtx->pMediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
CodecEncodeAvcFeiPicParams *feiPicParams = (CodecEncodeAvcFeiPicParams *)(m_encodeCtx->pFeiPicParams);
FeiPreEncParams *preEncParams = (FeiPreEncParams*)(m_encodeCtx->pPreEncParams);
DDI_CODEC_RENDER_TARGET_TABLE *rtTbl = &(m_encodeCtx->RTtbl);
MOS_STATUS status;
EncoderParams *encodeParams = &m_encodeCtx->EncodeParams;
MOS_ZeroMemory(encodeParams, sizeof(EncoderParams));
if ((feiPicParams != nullptr) && CodecHalIsFeiEncode(m_encodeCtx->codecFunction))
{
encodeParams->ExecCodecFunction = m_encodeCtx->codecFunction;
}
else if (m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_PRE_ENC)
{
encodeParams->ExecCodecFunction = m_encodeCtx->codecFunction;
}
else
{
encodeParams->ExecCodecFunction = CODECHAL_FUNCTION_ENC_PAK;
}
// Raw Surface
PMOS_SURFACE rawSurface = &encodeParams->rawSurface;
rawSurface->Format = Format_NV12;
rawSurface->dwOffset = 0;
DdiMedia_MediaSurfaceToMosResource(rtTbl->pCurrentRT, &(rawSurface->OsResource));
if (m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_PRE_ENC)
{
if (rtTbl->pRT[preEncParams->CurrOriginalPicture.FrameIdx] != rtTbl->pCurrentRT)
{
DDI_ASSERTMESSAGE("PREENC CurrOriginalPicture.FrameIdx != pCurrentRT");
}
rawSurface->dwWidth = rawSurface->OsResource.iWidth;
rawSurface->dwHeight = rawSurface->OsResource.iHeight;
rawSurface->dwPitch = rawSurface->OsResource.iPitch;
rawSurface->TileType = rawSurface->OsResource.TileType;
rawSurface->TileModeGMM = rawSurface->OsResource.TileModeGMM;
rawSurface->bGMMTileEnabled = rawSurface->OsResource.bGMMTileEnabled;
preEncParams->psCurrOriginalSurface = rawSurface;
encodeParams->pPreEncParams = m_encodeCtx->pPreEncParams;
DDI_CHK_RET(ClearRefList(&m_encodeCtx->RTtbl, false), "ClearRefList failed!");
}
else
{
// Recon Surface
PMOS_SURFACE reconSurface = &encodeParams->reconSurface;
reconSurface->Format = Format_NV12;
reconSurface->dwOffset = 0;
DdiMedia_MediaSurfaceToMosResource(rtTbl->pCurrentReconTarget, &(reconSurface->OsResource));
// Bitstream surface
PMOS_RESOURCE bitstreamSurface = &encodeParams->resBitstreamBuffer;
*bitstreamSurface = m_encodeCtx->resBitstreamBuffer; // in render picture
bitstreamSurface->Format = Format_Buffer;
encodeParams->psRawSurface = &encodeParams->rawSurface;
encodeParams->psReconSurface = &encodeParams->reconSurface;
encodeParams->presBitstreamBuffer = &encodeParams->resBitstreamBuffer;
PMOS_SURFACE mbQpSurface = &encodeParams->mbQpSurface;
if (m_encodeCtx->bMBQpEnable)
{
mbQpSurface->Format = Format_Buffer_2D;
mbQpSurface->dwOffset = 0;
mbQpSurface->OsResource = m_encodeCtx->resMBQpBuffer;
encodeParams->psMbQpDataSurface = &encodeParams->mbQpSurface;
encodeParams->bMbQpDataEnabled = true;
}
PMOS_SURFACE disableSkipMapSurface = &encodeParams->disableSkipMapSurface;
encodeParams->bMbDisableSkipMapEnabled = m_encodeCtx->bMbDisableSkipMapEnabled;
if (encodeParams->bMbDisableSkipMapEnabled)
{
disableSkipMapSurface->Format = Format_Buffer;
disableSkipMapSurface->dwOffset = 0;
disableSkipMapSurface->OsResource = m_encodeCtx->resPerMBSkipMapBuffer;
encodeParams->psMbDisableSkipMapSurface = &encodeParams->disableSkipMapSurface;
}
// correct some params
if (CODECHAL_ENCODE_MODE_AVC == m_encodeCtx->wModeType)
{
PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams;
CODECHAL_ENCODE_AVC_VUI_PARAMS *vuiParam;
vuiParam = (CODECHAL_ENCODE_AVC_VUI_PARAMS *)m_encodeCtx->pVuiParams;
seqParams = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
if (VA_RC_CQP == m_encodeCtx->uiRCMethod)
{
vuiParam->bit_rate_value_minus1[0] = 0;
vuiParam->cpb_size_value_minus1[0] = 0;
seqParams->TargetBitRate = 0;
seqParams->MaxBitRate = 0;
seqParams->MinBitRate = 0;
seqParams->InitVBVBufferFullnessInBit = 0;
seqParams->VBVBufferSizeInBit = 0;
}
encodeParams->uiSlcStructCaps = CODECHAL_SLICE_STRUCT_ARBITRARYMBSLICE;
}
ppsIdx = ((PCODEC_AVC_ENCODE_SLICE_PARAMS)(m_encodeCtx->pSliceParams))->pic_parameter_set_id;
picParams = (PCODEC_AVC_ENCODE_PIC_PARAMS)m_encodeCtx->pPicParams + ppsIdx;
spsIdx = picParams->seq_parameter_set_id;
encodeParams->pSeqParams = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)m_encodeCtx->pSeqParams + spsIdx;
encodeParams->pPicParams = picParams;
encodeParams->pVuiParams = m_encodeCtx->pVuiParams;
encodeParams->pSliceParams = m_encodeCtx->pSliceParams;
encodeParams->pAVCQCParams = m_qcParams;
encodeParams->pAVCRoundingParams = m_roundingParams;
// Sequence data
encodeParams->bNewSeq = m_encodeCtx->bNewSeq;
// VUI
encodeParams->bNewVuiData = m_encodeCtx->bNewVuiData;
// Slice level data
encodeParams->dwNumSlices = numSlices;
// IQmatrix params
encodeParams->bNewQmatrixData = m_encodeCtx->bNewQmatrixData;
encodeParams->bPicQuant = m_encodeCtx->bPicQuant;
encodeParams->ppNALUnitParams = m_encodeCtx->ppNALUnitParams;
encodeParams->pSeiData = m_encodeCtx->pSEIFromApp;
encodeParams->pSeiParamBuffer = m_encodeCtx->pSEIFromApp->pSEIBuffer;
encodeParams->dwSEIDataOffset = 0;
status = MOS_SecureMemcpy(&iqMatrixParams->ScalingList4x4,
6 * 16 * sizeof(uint8_t),
&m_scalingLists4x4,
6 * 16 * sizeof(uint8_t));
if (MOS_STATUS_SUCCESS != status)
{
DDI_ASSERTMESSAGE("DDI:Failed to copy scaling list 4x4!");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
status = MOS_SecureMemcpy(&iqMatrixParams->ScalingList8x8,
2 * 64 * sizeof(uint8_t),
&m_scalingLists8x8,
2 * 64 * sizeof(uint8_t));
if (MOS_STATUS_SUCCESS != status)
{
DDI_ASSERTMESSAGE("DDI:Failed to copy scaling list 8x8!");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
encodeParams->pIQMatrixBuffer = iqMatrixParams;
status = MOS_SecureMemcpy(&iqWeightScaleLists->WeightScale4x4,
(CODEC_AVC_WEIGHT_SCALE_4x4 * sizeof(uint32_t)),
&m_weightScale4x4,
(CODEC_AVC_WEIGHT_SCALE_4x4 * sizeof(uint32_t)));
if (MOS_STATUS_SUCCESS != status)
{
DDI_ASSERTMESSAGE("DDI:Failed to copy weight scale list 4x4!");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
status = MOS_SecureMemcpy(&iqWeightScaleLists->WeightScale8x8,
(CODEC_AVC_WEIGHT_SCALE_8x8 * sizeof(uint32_t)),
&m_weightScale8x8,
(CODEC_AVC_WEIGHT_SCALE_8x8 * sizeof(uint32_t)));
if (MOS_STATUS_SUCCESS != status)
{
DDI_ASSERTMESSAGE("DDI:Failed to copy weight scale list 8x8!");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
encodeParams->pIQWeightScaleLists = iqWeightScaleLists;
// whether driver need to pack slice header
if (true == m_encodeCtx->bHavePackedSliceHdr)
{
encodeParams->bAcceleratorHeaderPackingCaps = false;
}
else
{
encodeParams->bAcceleratorHeaderPackingCaps = true;
}
encodeParams->pBSBuffer = m_encodeCtx->pbsBuffer;
encodeParams->pSlcHeaderData = (void *)m_encodeCtx->pSliceHeaderData;
encodeParams->pFeiPicParams = (CodecEncodeAvcFeiPicParams *)(m_encodeCtx->pFeiPicParams);
//clear registered recon/ref surface flags
DDI_CHK_RET(ClearRefList(&m_encodeCtx->RTtbl, true), "ClearRefList failed!");
}
CodechalEncoderState *encoder = dynamic_cast<CodechalEncoderState *>(m_encodeCtx->pCodecHal);
DDI_CHK_NULL(encoder, "nullptr Codechal encode", VA_STATUS_ERROR_INVALID_PARAMETER);
if (!encoder->m_mfeEnabled)
{
status = m_encodeCtx->pCodecHal->Execute(encodeParams);
if (MOS_STATUS_SUCCESS != status)
{
DDI_ASSERTMESSAGE("DDI:Failed in Codechal!");
return VA_STATUS_ERROR_ENCODING_ERROR;
}
}
return VA_STATUS_SUCCESS;
}
VAStatus DdiEncodeAvcFei::ResetAtFrameLevel()
{
DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_NULL(m_encodeCtx->pFeiPicParams, "nullptr m_encodeCtx->pFeiPicParams", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_NULL(m_encodeCtx->pPreEncParams, "nullptr m_encodeCtx->pPreEncParams", VA_STATUS_ERROR_INVALID_PARAMETER);
// Assume there is only one SPS parameter
PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
seqParams->bInitBRC = 0x0;
seqParams->bResetBRC = 0x0;
CodecEncodeAvcFeiPicParams *feiPicParams = (CodecEncodeAvcFeiPicParams *)(m_encodeCtx->pFeiPicParams);
FeiPreEncParams *preEncParams = (FeiPreEncParams*)(m_encodeCtx->pPreEncParams);
m_encodeCtx->dwNumSlices = 0x0;
m_encodeCtx->indexNALUnit = 0x0;
m_encodeCtx->uiSliceHeaderCnt = 0x0;
// reset bsbuffer every frame
m_encodeCtx->pbsBuffer->pCurrent = m_encodeCtx->pbsBuffer->pBase;
m_encodeCtx->pbsBuffer->SliceOffset = 0x0;
m_encodeCtx->pbsBuffer->BitOffset = 0x0;
m_encodeCtx->pbsBuffer->BitSize = 0x0;
// clear the packed header information
if (nullptr != m_encodeCtx->ppNALUnitParams)
{
MOS_ZeroMemory(m_encodeCtx->ppNALUnitParams[0], sizeof(CODECHAL_NAL_UNIT_PARAMS) * CODECHAL_ENCODE_AVC_MAX_NAL_TYPE);
}
m_encodeCtx->bHavePackedSliceHdr = false;
m_encodeCtx->bLastPackedHdrIsSlice = false;
m_encodeCtx->bMbDisableSkipMapEnabled = false;
m_encodeCtx->bMBQpEnable = false;
if (nullptr != m_roundingParams)
{
MOS_ZeroMemory(m_roundingParams, sizeof(CODECHAL_ENCODE_AVC_ROUNDING_PARAMS));
}
if (CodecHalIsFeiEncode(m_encodeCtx->codecFunction) && m_encodeCtx->codecFunction != CODECHAL_FUNCTION_FEI_PRE_ENC)
{
m_encodeCtx->codecFunction = CODECHAL_FUNCTION_FEI_ENC_PAK;
feiPicParams->NumMVPredictorsL0 = 0; // number of MV Predictors L0 provided, max is 4
feiPicParams->NumMVPredictorsL1 = 0; // number of MV Predictors L1 provided, max is 2
feiPicParams->SearchPath = 0; // search path, default is 0, 0 and 2 mean full search, 1 means diamond search
feiPicParams->LenSP = 57; // max number of SUs per reference which is evaluated by the predetermined SUs, range is [1, 63]
feiPicParams->SubMBPartMask = 0x77; // the bit-mask for disabling sub-partition, bit 0 16x16, bit 1 16x8, bit 2 8x16 ... default value is 1110111b
feiPicParams->IntraPartMask = 0; // luma intra partition mask bits, bit 0 16x16, bit 1 8x8, bit 2 4x4
feiPicParams->MultiPredL0 = false; // true neighbor MV will be used as predictori for L0, false will not.
feiPicParams->MultiPredL1 = false; // true neighbor MV will be used as predictori for L0, false will not.
feiPicParams->SubPelMode = 3; // half/quater pixels mode, 00b integer mode search, 01b half mode search, 11b quater mode search
feiPicParams->InterSAD = 2;
feiPicParams->IntraSAD = 2;
feiPicParams->DistortionType = 0; // output distortion type, 0 raw distortion without cost, 1 distortion with cost
feiPicParams->RepartitionCheckEnable = false; // true, enables the additional calls on Fraction & Bidirectional Refinement
feiPicParams->AdaptiveSearch = true; // whether adaptive searching is enabled for IME
feiPicParams->MVPredictorEnable = false; // if enable MV Predictor input
feiPicParams->bMBQp = false; // if enable MB per QP input
feiPicParams->bPerMBInput = false; // if enable per MB control/special input
feiPicParams->bMBSizeCtrl = false; // if enable MB size control when enabled per MB special input
feiPicParams->RefWidth = 48;
feiPicParams->RefHeight = 40;
feiPicParams->SearchWindow = 0;
feiPicParams->DistortionEnable = false;
feiPicParams->MbCodeMvEnable = false;
}
if (m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_PRE_ENC)
{
preEncParams->dwNumPastReferences = 1; // Number of past reference frame
preEncParams->dwNumFutureReferences = 0; // Number of future reference frame
MOS_ZeroMemory(&(preEncParams->CurrOriginalPicture), sizeof(CODEC_PICTURE));
MOS_ZeroMemory(&(preEncParams->PastRefPicture), sizeof(CODEC_PICTURE));
MOS_ZeroMemory(&(preEncParams->FutureRefPicture), sizeof(CODEC_PICTURE));
preEncParams->dwFrameQp = 25; // Frame level QP
preEncParams->dwLenSP = 57; // max number of SUs per reference which is evaluated by the predetermined SUs, range is [1, 63]
preEncParams->dwSearchPath = 0; // search path, default is 0, 0 and 2 mean full search, 1 means diamond search
preEncParams->dwSubMBPartMask = 0x77; // the bit-mask for disabling sub-partition, bit 0 16x16, bit 1 16x8, bit 2 8x16 ... default value is 1110111b
preEncParams->dwIntraPartMask = 0;
preEncParams->dwSubPelMode = 3; // half/quater pixels mode, 00b integer mode search, 01b half mode search, 11b quater mode search
preEncParams->dwInterSAD = 2;
preEncParams->dwIntraSAD = 2;
preEncParams->bAdaptiveSearch = 1; // whether adaptive searching is enabled for IME
preEncParams->dwMVPredictorCtrl = 0; // MV predictor control, 0, disable, 1, enabled for past reference, 2, enabled for future reference, 3 enabled for both
preEncParams->bMBQp = false; // if enable MB per QP input
preEncParams->bFTEnable = false; // if use provided QP (frame level QP and per MB QP) and obtained MV to judge the number of non zero coefficients
preEncParams->dwRefWidth = 48;
preEncParams->dwRefHeight = 40;
preEncParams->dwSearchWindow = 0; // defines predefined search windows, 0, disable
// 1, Tiny 4 SUs 24x24 windows
// 2, small 9 SUs 28x28 windows
// 3, diamond 16 SUs 48x40 windows
// 4, large diamon 32SUs 48x40 windows
// 5, exhaustive 48SUs 48x40 windows
preEncParams->bDisableMVOutput = false; // if disable MV output buffer
preEncParams->bDisableStatisticsOutput = false; // if disable Statisticts output buffer
preEncParams->bEnable8x8Statistics = false; // if enable, generate block8x8 average and variance output
}
return VA_STATUS_SUCCESS;
}
VAStatus DdiEncodeAvcFei::RenderPicture(
VADriverContextP ctx,
VAContextID context,
VABufferID *buffers,
int32_t numBuffers)
{
DDI_FUNCTION_ENTER();
DDI_CHK_NULL(ctx, "nullptr context in vpgEncodeRenderPicture!", VA_STATUS_ERROR_INVALID_CONTEXT);
PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
// assume the VAContextID is encoder ID
DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
uint32_t numSlices = 0;
VAStatus vaStatus = VA_STATUS_SUCCESS;
DDI_MEDIA_BUFFER *buf;
void *data;
uint32_t dataSize;
for (int32_t i = 0; i < numBuffers; i++)
{
buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, buffers[i]);
DDI_CHK_NULL(buf, "Invalid buffer.", VA_STATUS_ERROR_INVALID_BUFFER);
if (buf->uiType == VAEncMacroblockDisableSkipMapBufferType)
{
DdiMedia_MediaBufferToMosResource(buf, &(m_encodeCtx->resPerMBSkipMapBuffer));
m_encodeCtx->bMbDisableSkipMapEnabled = true;
continue;
}
dataSize = buf->iSize;
// can use internal function instead of DdiMedia_MapBuffer here?
DdiMedia_MapBuffer(ctx, buffers[i], &data);
DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_BUFFER);
switch (buf->uiType)
{
case VAIQMatrixBufferType:
case VAQMatrixBufferType:
DDI_CHK_STATUS(Qmatrix(data), VA_STATUS_ERROR_INVALID_BUFFER);
break;
case VAEncSequenceParameterBufferType:
DDI_CHK_STATUS(ParseSeqParams(data), VA_STATUS_ERROR_INVALID_BUFFER);
m_encodeCtx->bNewSeq = true;
break;
case VAEncPictureParameterBufferType:
DDI_CHK_STATUS(ParsePicParams(mediaCtx, data), VA_STATUS_ERROR_INVALID_BUFFER);
// it should use pFeiPicParams->function, but it may be still not set here yet
if (m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC)
break;
DDI_CHK_STATUS(
AddToStatusReportQueue((void *)m_encodeCtx->resBitstreamBuffer.bo),
VA_STATUS_ERROR_INVALID_BUFFER);
break;
case VAEncSliceParameterBufferType:
numSlices = buf->uiNumElements;
DDI_CHK_STATUS(ParseSlcParams(mediaCtx, data, numSlices), VA_STATUS_ERROR_INVALID_BUFFER);
break;
case VAEncPackedHeaderParameterBufferType:
DDI_CHK_STATUS(ParsePackedHeaderParams(data), VA_STATUS_ERROR_INVALID_BUFFER);
break;
case VAEncPackedHeaderDataBufferType:
vaStatus = ParsePackedHeaderData(data);
break;
case VAEncMiscParameterBufferType:
DDI_CHK_STATUS(ParseMiscParams(data), VA_STATUS_ERROR_INVALID_BUFFER);
break;
case VAEncQPBufferType:
DdiMedia_MediaBufferToMosResource(buf, &m_encodeCtx->resMBQpBuffer);
m_encodeCtx->bMBQpEnable = true;
break;
case VAStatsStatisticsParameterBufferType:
DDI_CHK_STATUS(ParseStatsParams(mediaCtx, data), VA_STATUS_ERROR_INVALID_BUFFER);
break;
case VAEncFEIMBControlBufferType:
case VAEncFEIMVPredictorBufferType:
case VAEncFEIMVBufferType:
case VAEncFEIMBCodeBufferType:
case VAEncFEIDistortionBufferType:
case VAStatsMVPredictorBufferType:
case VAStatsStatisticsBufferType:
case VAStatsStatisticsBottomFieldBufferType:
case VAStatsMVBufferType:
{
// handled in VAEncMiscParameterBufferType/VAEncMiscParameterTypeFEIFrameControlIntel case by vaBufferID
break;
}
default:
DDI_ASSERTMESSAGE("not supported buffer type in vpgEncodeRenderPicture.");
// vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
break;
}
DdiMedia_UnmapBuffer(ctx, buffers[i]);
}
DDI_FUNCTION_EXIT(vaStatus);
return vaStatus;
}
VAStatus DdiEncodeAvcFei::ParseMiscParamFeiPic(void *data)
{
DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
CodecEncodeAvcFeiPicParams *feiPicParams = (CodecEncodeAvcFeiPicParams *)(m_encodeCtx->pFeiPicParams);
DDI_CHK_NULL(feiPicParams, "nullptr feiPicParams", VA_STATUS_ERROR_INVALID_PARAMETER);
VAEncMiscParameterFEIFrameControlH264 *vaEncMiscParamFeiPic = (VAEncMiscParameterFEIFrameControlH264*)data;
m_encodeCtx->codecFunction = CODECHAL_FUNCTION_INVALID;
if (vaEncMiscParamFeiPic->function & VA_FEI_FUNCTION_ENC_PAK)
m_encodeCtx->codecFunction = CODECHAL_FUNCTION_FEI_ENC_PAK;
if (vaEncMiscParamFeiPic->function == VA_FEI_FUNCTION_ENC)
m_encodeCtx->codecFunction = CODECHAL_FUNCTION_FEI_ENC;
if (vaEncMiscParamFeiPic->function == VA_FEI_FUNCTION_PAK)
m_encodeCtx->codecFunction = CODECHAL_FUNCTION_FEI_PAK;
feiPicParams->NumMVPredictorsL0 = vaEncMiscParamFeiPic->num_mv_predictors_l0;
feiPicParams->NumMVPredictorsL1 = vaEncMiscParamFeiPic->num_mv_predictors_l1;
feiPicParams->SearchPath = vaEncMiscParamFeiPic->search_path;
feiPicParams->LenSP = vaEncMiscParamFeiPic->len_sp;
feiPicParams->SubMBPartMask = vaEncMiscParamFeiPic->sub_mb_part_mask;
feiPicParams->IntraPartMask = vaEncMiscParamFeiPic->intra_part_mask;
feiPicParams->MultiPredL0 = vaEncMiscParamFeiPic->multi_pred_l0;
feiPicParams->MultiPredL1 = vaEncMiscParamFeiPic->multi_pred_l1;
feiPicParams->SubPelMode = vaEncMiscParamFeiPic->sub_pel_mode;
feiPicParams->InterSAD = vaEncMiscParamFeiPic->inter_sad;
feiPicParams->IntraSAD = vaEncMiscParamFeiPic->intra_sad;
feiPicParams->DistortionType = vaEncMiscParamFeiPic->distortion_type;
feiPicParams->RepartitionCheckEnable = vaEncMiscParamFeiPic->repartition_check_enable;
feiPicParams->AdaptiveSearch = vaEncMiscParamFeiPic->adaptive_search;
feiPicParams->MVPredictorEnable = vaEncMiscParamFeiPic->mv_predictor_enable;
feiPicParams->bMBQp = vaEncMiscParamFeiPic->mb_qp;
feiPicParams->bPerMBInput = vaEncMiscParamFeiPic->mb_input;
feiPicParams->bMBSizeCtrl = vaEncMiscParamFeiPic->mb_size_ctrl;
feiPicParams->RefWidth = vaEncMiscParamFeiPic->ref_width;
feiPicParams->RefHeight = vaEncMiscParamFeiPic->ref_height;
feiPicParams->SearchWindow = vaEncMiscParamFeiPic->search_window;
DDI_MEDIA_BUFFER *mediaBuffer;
VAStatus status = VA_STATUS_SUCCESS;
if (feiPicParams->bPerMBInput)
{
mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->mb_ctrl);
DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resMBCtrl));
}
if (feiPicParams->MVPredictorEnable == 1)
{
mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->mv_predictor);
DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resMVPredictor));
}
else if ((feiPicParams->NumMVPredictorsL0 != 0) || (feiPicParams->NumMVPredictorsL1 != 0))
{
DDI_ASSERTMESSAGE("feiPicParams->NumMVPredictorsL0 and NumMVPredictorsL1 should be set to 0 when feiPicParams->MVPredictorEnable is false!");
status = VA_STATUS_ERROR_INVALID_PARAMETER;
}
if (feiPicParams->bMBQp)
{
mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->qp);
DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resMBQp));
}
feiPicParams->MbCodeMvEnable = false;
if (vaEncMiscParamFeiPic->mv_data != VA_INVALID_ID)
{
feiPicParams->MbCodeMvEnable = true;
mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->mv_data);
DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resMVData));
if (m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC)
{
RemoveFromEncStatusReportQueue(mediaBuffer, FEI_ENC_BUFFER_TYPE_MVDATA);
if (VA_STATUS_SUCCESS != AddToEncStatusReportQueue((void *)(feiPicParams->resMVData.bo), FEI_ENC_BUFFER_TYPE_MVDATA))
{
DDI_ASSERTMESSAGE("feiPicParams->resMVData is invalid for FEI ENC only");
status = VA_STATUS_ERROR_INVALID_PARAMETER;
}
}
}
if (vaEncMiscParamFeiPic->mb_code_data != VA_INVALID_ID)
{
if (feiPicParams->MbCodeMvEnable == false)
{
DDI_ASSERTMESSAGE("MV data and MB Code should be enabled or disabled together!");
status = MOS_STATUS_INVALID_PARAMETER;
}
mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->mb_code_data);
DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resMBCode));
if (m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC)
{
RemoveFromEncStatusReportQueue(mediaBuffer, FEI_ENC_BUFFER_TYPE_MBCODE);
if (MOS_STATUS_SUCCESS != AddToEncStatusReportQueue((void *)(feiPicParams->resMBCode.bo), FEI_ENC_BUFFER_TYPE_MBCODE))
{
DDI_ASSERTMESSAGE("feiPicParams->resMBCode is invalid for FEI ENC only");
status = VA_STATUS_ERROR_INVALID_PARAMETER;
}
}
}
if (vaEncMiscParamFeiPic->distortion != VA_INVALID_ID)
{
feiPicParams->DistortionEnable = true;
mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->distortion);
DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resDistortion));
if (m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC)
{
RemoveFromEncStatusReportQueue(mediaBuffer, FEI_ENC_BUFFER_TYPE_DISTORTION);
if (MOS_STATUS_SUCCESS != AddToEncStatusReportQueue((void *)(feiPicParams->resDistortion.bo), FEI_ENC_BUFFER_TYPE_DISTORTION))
{
DDI_ASSERTMESSAGE("feiPicParams->resDistortion is invalid for FEI ENC only");
status = VA_STATUS_ERROR_INVALID_PARAMETER;
}
}
}
if (m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC)
{
AddToEncStatusReportQueueUpdatePos();
}
//add for mutlple pass pak
feiPicParams->dwMaxFrameSize = vaEncMiscParamFeiPic->max_frame_size;
if (feiPicParams->dwMaxFrameSize)
{
feiPicParams->dwNumPasses = vaEncMiscParamFeiPic->num_passes;
if ((feiPicParams->dwNumPasses == 0) || (feiPicParams->dwNumPasses > feiMaxPassesNum))
{
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
if (feiPicParams->pDeltaQp != nullptr)
{
MOS_FreeMemory(feiPicParams->pDeltaQp);
}
feiPicParams->pDeltaQp = (uint8_t *)MOS_AllocAndZeroMemory(sizeof(uint8_t) * feiPicParams->dwNumPasses);
if (!feiPicParams->pDeltaQp)
{
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
if (MOS_STATUS_SUCCESS != MOS_SecureMemcpy(feiPicParams->pDeltaQp, feiPicParams->dwNumPasses, vaEncMiscParamFeiPic->delta_qp, feiPicParams->dwNumPasses))
{
status = VA_STATUS_ERROR_INVALID_PARAMETER;
}
}
return status;
}
VAStatus DdiEncodeAvcFei::AddToEncStatusReportQueue(
void *encBuf,
DDI_ENCODE_FEI_ENC_BUFFER_TYPE typeIdx)
{
DDI_CHK_NULL(encBuf, "nullptr encBuf", VA_STATUS_ERROR_INVALID_PARAMETER);
CodecEncodeAvcFeiPicParams *feiPicParams = (CodecEncodeAvcFeiPicParams *)(m_encodeCtx->pFeiPicParams);
DDI_CHK_NULL(feiPicParams, "nullptr feiPicParams", VA_STATUS_ERROR_INVALID_PARAMETER);
if (m_encodeCtx->codecFunction != CODECHAL_FUNCTION_FEI_ENC)
{
DDI_ASSERTMESSAGE("ENC output buffers status checking is not allowed for non-FEI_ENC case! .");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
if ((typeIdx < 0) || (typeIdx >= FEI_ENC_BUFFER_TYPE_MAX))
{
DDI_ASSERTMESSAGE("ENC output buffers status checking, gets invalid buffer type index! .");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
int32_t idx = m_encodeCtx->statusReportBuf.ulHeadPosition;
m_encodeCtx->statusReportBuf.encInfos[idx].pEncBuf[typeIdx] = encBuf;
m_encodeCtx->statusReportBuf.encInfos[idx].uiStatus = 0;
m_encodeCtx->statusReportBuf.encInfos[idx].uiBuffers++;
return VA_STATUS_SUCCESS;
}
VAStatus DdiEncodeAvcFei::AddToEncStatusReportQueueUpdatePos()
{
CodecEncodeAvcFeiPicParams *feiPicParams = (CodecEncodeAvcFeiPicParams *)(m_encodeCtx->pFeiPicParams);
DDI_CHK_NULL(feiPicParams, "nullptr feiPicParams", VA_STATUS_ERROR_INVALID_PARAMETER);
if (m_encodeCtx->codecFunction != CODECHAL_FUNCTION_FEI_ENC)
{
DDI_ASSERTMESSAGE("ENC output buffers status checking is not allowed for non-FEI_ENC case! .");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
int32_t i = m_encodeCtx->statusReportBuf.ulHeadPosition;
if ((m_encodeCtx->statusReportBuf.encInfos[i].uiBuffers == (feiPicParams->MbCodeMvEnable * 2 + feiPicParams->DistortionEnable)) &&
m_encodeCtx->statusReportBuf.encInfos[i].uiBuffers != 0)
{
m_encodeCtx->statusReportBuf.ulHeadPosition = (m_encodeCtx->statusReportBuf.ulHeadPosition + 1) % DDI_ENCODE_MAX_STATUS_REPORT_BUFFER;
}
return VA_STATUS_SUCCESS;
}
VAStatus DdiEncodeAvcFei::AddToPreEncStatusReportQueue(
void *preEncBuf,
DDI_ENCODE_PRE_ENC_BUFFER_TYPE typeIdx)
{
DDI_CHK_NULL(preEncBuf, "nullptr preEncBuf", VA_STATUS_ERROR_INVALID_PARAMETER);
if (m_encodeCtx->codecFunction != CODECHAL_FUNCTION_FEI_PRE_ENC)
{
DDI_ASSERTMESSAGE("PRE ENC output buffers status checking is not allowed for non-PRE_ENC case! .");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
if ((typeIdx < 0) || (typeIdx >= PRE_ENC_BUFFER_TYPE_MAX))
{
DDI_ASSERTMESSAGE("PRE ENC output buffers status checking, gets invalid buffer type index! .");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
int32_t i = m_encodeCtx->statusReportBuf.ulHeadPosition;
m_encodeCtx->statusReportBuf.preencInfos[i].pPreEncBuf[typeIdx] = preEncBuf;
m_encodeCtx->statusReportBuf.preencInfos[i].uiStatus = 0;
m_encodeCtx->statusReportBuf.preencInfos[i].uiBuffers++;
return VA_STATUS_SUCCESS;
}
VAStatus DdiEncodeAvcFei::AddToPreEncStatusReportQueueUpdatePos()
{
FeiPreEncParams *preEncParams = (FeiPreEncParams*)(m_encodeCtx->pPreEncParams);
DDI_CHK_NULL(preEncParams, "nullptr preEncParams", VA_STATUS_ERROR_INVALID_PARAMETER);
if (m_encodeCtx->codecFunction != CODECHAL_FUNCTION_FEI_PRE_ENC)
{
DDI_ASSERTMESSAGE("PRE ENC output buffers status checking is not allowed for non-PRE_ENC case! .");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
uint32_t numBuffers = (!preEncParams->bInterlaced) ? (2 - preEncParams->bDisableMVOutput - preEncParams->bDisableStatisticsOutput)
: (3 - preEncParams->bDisableMVOutput - 2 * preEncParams->bDisableStatisticsOutput);
int32_t i = m_encodeCtx->statusReportBuf.ulHeadPosition;
if ((m_encodeCtx->statusReportBuf.preencInfos[i].uiBuffers == numBuffers) &&
m_encodeCtx->statusReportBuf.preencInfos[i].uiBuffers != 0)
{
m_encodeCtx->statusReportBuf.ulHeadPosition = (m_encodeCtx->statusReportBuf.ulHeadPosition + 1) % DDI_ENCODE_MAX_STATUS_REPORT_BUFFER;
}
return VA_STATUS_SUCCESS;
}
VAStatus DdiEncodeAvcFei::ParseMiscParams(void *ptr)
{
DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
VAEncMiscParameterBuffer *miscParamBuf = (VAEncMiscParameterBuffer *)ptr;
DDI_CHK_NULL(miscParamBuf->data, "nullptr miscParamBuf->data", VA_STATUS_ERROR_INVALID_PARAMETER);
VAStatus status = MOS_STATUS_SUCCESS;
switch ((int32_t)(miscParamBuf->type))
{
case VAEncMiscParameterTypeHRD:
status = ParseMiscParamHRD((void *)miscParamBuf->data);
break;
case VAEncMiscParameterTypeFrameRate:
status = ParseMiscParamFR((void *)miscParamBuf->data);
break;
case VAEncMiscParameterTypeRateControl:
status = ParseMiscParamRC((void *)miscParamBuf->data);
break;
case VAEncMiscParameterTypeEncQuality:
status = ParseMiscParamEncQuality((void *)miscParamBuf->data);
break;
case VAEncMiscParameterTypeQuantization:
status = ParseMiscParamQuantization((void *)miscParamBuf->data);
break;
case VAEncMiscParameterTypeRIR:
status = ParseMiscParameterRIR((void *)miscParamBuf->data);
break;
case VAEncMiscParameterTypeSkipFrame:
status = ParseMiscParamSkipFrame((void *)miscParamBuf->data);
break;
case VAEncMiscParameterTypeMaxFrameSize:
status = ParseMiscParamMaxFrameSize((void *)miscParamBuf->data);
break;
case VAEncMiscParameterTypeQualityLevel:
status = ParseMiscParamQualityLevel((void *)miscParamBuf->data);
break;
case VAEncMiscParameterTypeMaxSliceSize:
status = ParseMiscParamMaxSliceSize((void *)miscParamBuf->data);
break;
case VAEncMiscParameterTypeROI:
status = ParseMiscParamROI((void *)miscParamBuf->data);
break;
case VAEncMiscParameterTypeFEIFrameControl:
status = ParseMiscParamFeiPic((void *)miscParamBuf->data);
break;
case VAEncMiscParameterTypeDirtyRect:
status = ParseMiscParamDirtyROI((void *)miscParamBuf->data);
break;
case VAEncMiscParameterTypeCustomRoundingControl:
status = ParseMiscParamRounding((void *)miscParamBuf->data);
break;
case VAEncMiscParameterTypeSubMbPartPel:
status = ParseMiscParamSubMbPartPel((void *)miscParamBuf->data);
break;
default:
DDI_ASSERTMESSAGE("unsupported misc parameter type.");
status = VA_STATUS_ERROR_INVALID_PARAMETER;
break;
}
return status;
}
VAStatus DdiEncodeAvcFei::ParseStatsParams(PDDI_MEDIA_CONTEXT mediaCtx, void *ptr)
{
if ((nullptr == ptr) || (nullptr == m_encodeCtx))
{
DDI_ASSERTMESSAGE("invalidate input parameters");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
VAStatsStatisticsParameterH264 *statsParams = (VAStatsStatisticsParameterH264 *)ptr;
FeiPreEncParams *preEncParams = (FeiPreEncParams*)(m_encodeCtx->pPreEncParams);
DDI_CODEC_RENDER_TARGET_TABLE *rtTbl = &(m_encodeCtx->RTtbl);
preEncParams->dwNumPastReferences = statsParams->stats_params.num_past_references;
preEncParams->dwNumFutureReferences = statsParams->stats_params.num_future_references;
preEncParams->dwFrameQp = statsParams->frame_qp;
preEncParams->dwLenSP = statsParams->len_sp;
preEncParams->dwSearchPath = statsParams->search_path;
preEncParams->dwSubMBPartMask = statsParams->sub_mb_part_mask;
preEncParams->dwIntraPartMask = statsParams->intra_part_mask;
preEncParams->dwSubPelMode = statsParams->sub_pel_mode;
preEncParams->dwInterSAD = statsParams->inter_sad;
preEncParams->dwIntraSAD = statsParams->intra_sad;
preEncParams->bAdaptiveSearch = statsParams->adaptive_search;
preEncParams->dwMVPredictorCtrl = statsParams->mv_predictor_ctrl;
preEncParams->bMBQp = statsParams->mb_qp;
preEncParams->bFTEnable = statsParams->ft_enable;
preEncParams->dwRefWidth = statsParams->ref_width;
preEncParams->dwRefHeight = statsParams->ref_height;
preEncParams->dwSearchWindow = statsParams->search_window;
preEncParams->bDisableMVOutput = statsParams->disable_mv_output;
preEncParams->bDisableStatisticsOutput = statsParams->disable_statistics_output;
preEncParams->bEnable8x8Statistics = statsParams->enable_8x8_statistics;
preEncParams->bInputUpdated = false;
preEncParams->bCurPicUpdated = false;
preEncParams->bPastRefUpdated = false;
preEncParams->bFutureRefUpdated = false;
preEncParams->bPastRefStatsNeeded = false;
preEncParams->bFutureRefStatsNeeded = false;
if (statsParams->stats_params.input.picture_id == VA_INVALID_ID)
{
DDI_ASSERTMESSAGE("invalidate input parameters, current picture id is invalidate");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
if ((statsParams->stats_params.input.flags & VA_PICTURE_STATS_CONTENT_UPDATED) != 0)
{
preEncParams->bCurPicUpdated = true;
}
CODEC_PICTURE_FLAG picFlags = ((statsParams->stats_params.input.flags & 0xF) == VA_PICTURE_STATS_PROGRESSIVE) ? PICTURE_FRAME : (((statsParams->stats_params.input.flags & 0xF) == VA_PICTURE_STATS_TOP_FIELD) ? PICTURE_TOP_FIELD : (((statsParams->stats_params.input.flags & 0xF) == VA_PICTURE_STATS_BOTTOM_FIELD) ? PICTURE_BOTTOM_FIELD : PICTURE_INVALID));
preEncParams->bInterlaced = (picFlags == PICTURE_TOP_FIELD || picFlags == PICTURE_BOTTOM_FIELD);
DDI_MEDIA_SURFACE *currentSurface = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, statsParams->stats_params.input.picture_id);
if (nullptr == currentSurface)
{
DDI_ASSERTMESSAGE("invalidate current ref surface");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
DDI_CHK_RET(RegisterRTSurfaces(&m_encodeCtx->RTtbl, currentSurface), "RegisterRTSurfaces failed!");
preEncParams->CurrOriginalPicture.FrameIdx = (uint8_t)GetRenderTargetID(rtTbl, currentSurface);
preEncParams->CurrOriginalPicture.PicFlags = picFlags;
DDI_MEDIA_BUFFER *mediaBuffer;
if ((preEncParams->dwNumPastReferences == 1) && (statsParams->stats_params.past_references[0].picture_id != VA_INVALID_ID))
{
if ((statsParams->stats_params.past_references->flags & VA_PICTURE_STATS_CONTENT_UPDATED) != 0)
{
preEncParams->bPastRefUpdated = true;
}
DDI_MEDIA_SURFACE *pastRefSurface = (DDI_MEDIA_SURFACE *)DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, statsParams->stats_params.past_references->picture_id);
if (nullptr == pastRefSurface)
{
DDI_ASSERTMESSAGE("invalidate Future ref surface");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
DDI_CHK_RET(RegisterRTSurfaces(&m_encodeCtx->RTtbl, pastRefSurface), "RegisterRTSurfaces failed!");
preEncParams->PastRefPicture.FrameIdx = (uint8_t)GetRenderTargetID(rtTbl, pastRefSurface);
picFlags = ((statsParams->stats_params.past_references->flags & 0xF) == VA_PICTURE_STATS_PROGRESSIVE) ? PICTURE_FRAME : (((statsParams->stats_params.past_references->flags & 0xF) == VA_PICTURE_STATS_TOP_FIELD) ? PICTURE_TOP_FIELD : (((statsParams->stats_params.past_references->flags & 0xF) == VA_PICTURE_STATS_BOTTOM_FIELD) ? PICTURE_BOTTOM_FIELD : PICTURE_INVALID));
preEncParams->PastRefPicture.PicFlags = picFlags;
DdiMedia_MediaSurfaceToMosResource(pastRefSurface, &(preEncParams->sPastRefSurface.OsResource));
preEncParams->sPastRefSurface.dwWidth = preEncParams->sPastRefSurface.OsResource.iWidth;
preEncParams->sPastRefSurface.dwHeight = preEncParams->sPastRefSurface.OsResource.iHeight;
preEncParams->sPastRefSurface.dwPitch = preEncParams->sPastRefSurface.OsResource.iPitch;
preEncParams->sPastRefSurface.TileType = preEncParams->sPastRefSurface.OsResource.TileType;
preEncParams->sPastRefSurface.TileModeGMM = preEncParams->sPastRefSurface.OsResource.TileModeGMM;
preEncParams->sPastRefSurface.bGMMTileEnabled = preEncParams->sPastRefSurface.OsResource.bGMMTileEnabled;
preEncParams->bPastRefStatsNeeded = false;
if (statsParams->stats_params.past_ref_stat_buf)
{
if (!preEncParams->bDisableStatisticsOutput)
{
mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, *(statsParams->stats_params.past_ref_stat_buf));
if (nullptr == mediaBuffer)
{
DDI_ASSERTMESSAGE("invalidate statistics output media buffer for Past ref");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->sPastRefStatsBuffer));
if (picFlags == PICTURE_TOP_FIELD || picFlags == PICTURE_BOTTOM_FIELD)
{
mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, *(statsParams->stats_params.past_ref_stat_buf + 1));
if (nullptr == mediaBuffer)
{
DDI_ASSERTMESSAGE("invalidate statistics output media buffer for Past bottom field ref");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->sPastRefStatsBotFieldBuffer));
}
preEncParams->bPastRefStatsNeeded = true;
}
else
preEncParams->bPastRefStatsNeeded = false;
}
}
else
{
preEncParams->PastRefPicture.FrameIdx = (uint8_t)DDI_CODEC_INVALID_FRAME_INDEX;
preEncParams->PastRefPicture.PicFlags = PICTURE_INVALID;
}
if ((preEncParams->dwNumFutureReferences == 1) && (statsParams->stats_params.future_references[0].picture_id != VA_INVALID_ID))
{
if ((statsParams->stats_params.future_references->flags & VA_PICTURE_STATS_CONTENT_UPDATED) != 0)
{
preEncParams->bFutureRefUpdated = true;
}
DDI_MEDIA_SURFACE *futureRefSurface = (DDI_MEDIA_SURFACE *)DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, statsParams->stats_params.future_references->picture_id);
if (nullptr == futureRefSurface)
{
DDI_ASSERTMESSAGE("invalidate Future ref surface");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
DDI_CHK_RET(RegisterRTSurfaces(&m_encodeCtx->RTtbl, futureRefSurface), "RegisterRTSurfaces failed!");
preEncParams->FutureRefPicture.FrameIdx = (uint8_t)GetRenderTargetID(rtTbl, futureRefSurface);
picFlags = ((statsParams->stats_params.future_references->flags & 0xF) == VA_PICTURE_STATS_PROGRESSIVE) ? PICTURE_FRAME : (((statsParams->stats_params.future_references->flags & 0xF) == VA_PICTURE_STATS_TOP_FIELD) ? PICTURE_TOP_FIELD : (((statsParams->stats_params.future_references->flags & 0xF) == VA_PICTURE_STATS_BOTTOM_FIELD) ? PICTURE_BOTTOM_FIELD : PICTURE_INVALID));
preEncParams->FutureRefPicture.PicFlags = picFlags;
DdiMedia_MediaSurfaceToMosResource(futureRefSurface, &(preEncParams->sFutureRefSurface.OsResource));
preEncParams->sFutureRefSurface.dwWidth = preEncParams->sFutureRefSurface.OsResource.iWidth;
preEncParams->sFutureRefSurface.dwHeight = preEncParams->sFutureRefSurface.OsResource.iHeight;
preEncParams->sFutureRefSurface.dwPitch = preEncParams->sFutureRefSurface.OsResource.iPitch;
preEncParams->sFutureRefSurface.TileType = preEncParams->sFutureRefSurface.OsResource.TileType;
preEncParams->bFutureRefStatsNeeded = false;
if (!preEncParams->bDisableStatisticsOutput)
{
if (statsParams->stats_params.future_ref_stat_buf)
{
mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, *(statsParams->stats_params.future_ref_stat_buf));
if (nullptr == mediaBuffer)
{
DDI_ASSERTMESSAGE("invalidate statistics output media buffer for Future ref");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->sFutureRefStatsBuffer));
if (picFlags == PICTURE_TOP_FIELD || picFlags == PICTURE_BOTTOM_FIELD)
{
mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, *(statsParams->stats_params.future_ref_stat_buf + 1));
if (nullptr == mediaBuffer)
{
DDI_ASSERTMESSAGE("invalidate statistics output media buffer for Future ref");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->sFutureRefStatsBotFieldBuffer));
}
preEncParams->bFutureRefStatsNeeded = true;
}
else
preEncParams->bFutureRefStatsNeeded = false;
}
}
else
{
preEncParams->FutureRefPicture.FrameIdx = (uint8_t)DDI_CODEC_INVALID_FRAME_INDEX;
preEncParams->FutureRefPicture.PicFlags = PICTURE_INVALID;
}
if (preEncParams->dwMVPredictorCtrl)
{
mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, statsParams->stats_params.mv_predictor);
if (nullptr == mediaBuffer)
{
DDI_ASSERTMESSAGE("invalidate mv_predictor media buffer");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->resMvPredBuffer));
}
if (preEncParams->bMBQp)
{
mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, statsParams->stats_params.qp);
if (nullptr == mediaBuffer)
{
DDI_ASSERTMESSAGE("invalidate qp media buffer");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->resMbQpBuffer));
}
uint32_t i = 0;
if (!preEncParams->bDisableMVOutput)
{
mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, statsParams->stats_params.outputs[i++]);
if (nullptr == mediaBuffer)
{
DDI_ASSERTMESSAGE("invalidate mv output media buffer");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->resMvBuffer));
RemoveFromPreEncStatusReportQueue(mediaBuffer, PRE_ENC_BUFFER_TYPE_MVDATA);
if (VA_STATUS_SUCCESS != AddToPreEncStatusReportQueue((void *)(preEncParams->resMvBuffer.bo), PRE_ENC_BUFFER_TYPE_MVDATA))
{
DDI_ASSERTMESSAGE("preEncParams->resMvBuffer is invalid for PREENC only");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
}
if (!preEncParams->bDisableStatisticsOutput)
{
mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, statsParams->stats_params.outputs[i++]);
if (nullptr == mediaBuffer)
{
DDI_ASSERTMESSAGE("invalidate statistics output media buffer");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->resStatsBuffer));
RemoveFromPreEncStatusReportQueue(mediaBuffer, PRE_ENC_BUFFER_TYPE_STATS);
if (VA_STATUS_SUCCESS != AddToPreEncStatusReportQueue((void *)(preEncParams->resStatsBuffer.bo), PRE_ENC_BUFFER_TYPE_STATS))
{
DDI_ASSERTMESSAGE("preEncParams->resStatsBuffer is invalid for PREENC only");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
if (preEncParams->bInterlaced)
{
mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, statsParams->stats_params.outputs[i++]);
if (nullptr == mediaBuffer)
{
DDI_ASSERTMESSAGE("invalidate statistics output media bottom field buffer, must provide bottom field statistics buffer for both top and bottom field PreENC");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->resStatsBotFieldBuffer));
RemoveFromPreEncStatusReportQueue(mediaBuffer, PRE_ENC_BUFFER_TYPE_STATS_BOT);
if (VA_STATUS_SUCCESS != AddToPreEncStatusReportQueue((void *)(preEncParams->resStatsBotFieldBuffer.bo), PRE_ENC_BUFFER_TYPE_STATS_BOT))
{
DDI_ASSERTMESSAGE("preEncParams->resStatsBotFieldBuffer is invalid for PREENC only");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}
}
}
AddToPreEncStatusReportQueueUpdatePos();
return VA_STATUS_SUCCESS;
}