blob: f5f59372fdfba9e650a5e634af82eb052beb05b2 [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 mhw_vdbox_mfx_generic.h
//! \brief MHW interface for constructing MFX commands for the Vdbox engine
//! \details Impelements shared Vdbox MFX command construction functions across all platforms as templates
//!
#ifndef _MHW_VDBOX_MFX_GENERIC_H_
#define _MHW_VDBOX_MFX_GENERIC_H_
#include "mhw_vdbox_mfx_interface.h"
//! MHW Vdbox Mfx generic interface
/*!
This class defines the shared Mfx command construction functions across all platforms as templates
*/
template <class TMfxCmds, class TMiCmds>
class MhwVdboxMfxInterfaceGeneric : public MhwVdboxMfxInterface
{
protected:
//!
//! \brief Constructor
//!
MhwVdboxMfxInterfaceGeneric(
PMOS_INTERFACE osInterface,
MhwMiInterface *miInterface,
MhwCpInterface *cpInterface,
bool decodeInUse) :
MhwVdboxMfxInterface(osInterface, miInterface, cpInterface, decodeInUse)
{
MHW_FUNCTION_ENTER;
}
//!
//! \brief Destructor
//!
virtual ~MhwVdboxMfxInterfaceGeneric() {}
MOS_STATUS AddMfdAvcPicidCmd(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_VDBOX_PIC_ID_PARAMS params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(cmdBuffer);
MHW_MI_CHK_NULL(params);
MHW_MI_CHK_NULL(params->pAvcPicIdx);
typename TMfxCmds::MFD_AVC_PICID_STATE_CMD cmd;
cmd.DW1.PictureidRemappingDisable = 1;
if (params->bPicIdRemappingInUse)
{
uint32_t j = 0;
cmd.DW1.PictureidRemappingDisable = 0;
for (auto i = 0; i < (CODEC_MAX_NUM_REF_FRAME / 2); i++)
{
cmd.Pictureidlist1616Bits[i] = avcPicidDefault;
if (params->pAvcPicIdx[j++].bValid)
{
cmd.Pictureidlist1616Bits[i] = (cmd.Pictureidlist1616Bits[i] & 0xffff0000) | params->pAvcPicIdx[j - 1].ucPicIdx;
}
if (params->pAvcPicIdx[j++].bValid)
{
cmd.Pictureidlist1616Bits[i] = (cmd.Pictureidlist1616Bits[i] & 0x0000ffff) | (params->pAvcPicIdx[j - 1].ucPicIdx << 16);
}
}
}
else
{
for (auto i = 0; i < (CODEC_MAX_NUM_REF_FRAME / 2); i++)
{
cmd.Pictureidlist1616Bits[i] = avcPicidDisabled;
}
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
MOS_STATUS AddMfxQmCmd(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_VDBOX_QM_PARAMS params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(cmdBuffer);
MHW_MI_CHK_NULL(params);
typename TMfxCmds::MFX_QM_STATE_CMD cmd;
uint8_t* qMatrix = (uint8_t*)cmd.ForwardQuantizerMatrix;
if (params->Standard == CODECHAL_AVC)
{
MHW_MI_CHK_NULL(params->pAvcIqMatrix);
for (auto i = 0; i < 16; i++)
{
cmd.ForwardQuantizerMatrix[i] = 0;
}
cmd.DW1.Obj0.Avc = avcQmIntra4x4;
for (auto i = 0; i < 3; i++)
{
for (auto ii = 0; ii < 16; ii++)
{
qMatrix[i * 16 + ii] = params->pAvcIqMatrix->List4x4[i][ii];
}
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
cmd.DW1.Obj0.Avc = avcQmInter4x4;
for (auto i = 3; i < 6; i++)
{
for (auto ii = 0; ii < 16; ii++)
{
qMatrix[(i - 3) * 16 + ii] = params->pAvcIqMatrix->List4x4[i][ii];
}
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
cmd.DW1.Obj0.Avc = avcQmIntra8x8;
for (auto ii = 0; ii < 64; ii++)
{
qMatrix[ii] = params->pAvcIqMatrix->List8x8[0][ii];
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
cmd.DW1.Obj0.Avc = avcQmInter8x8;
for (auto ii = 0; ii < 64; ii++)
{
qMatrix[ii] = params->pAvcIqMatrix->List8x8[1][ii];
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
}
else if (params->Standard == CODECHAL_MPEG2)
{
MHW_MI_CHK_NULL(params->pMpeg2IqMatrix);
if (params->Mode == CODECHAL_ENCODE_MODE_MPEG2)
{
cmd.DW1.Obj0.Avc = mpeg2QmIntra;
if (params->pMpeg2IqMatrix->m_loadIntraQuantiserMatrix)
{
for (auto i = 0; i < 64; i++)
{
qMatrix[i] = (uint8_t)(params->pMpeg2IqMatrix->m_intraQuantiserMatrix[m_mpeg2QuantMatrixScan[i]]);
}
}
else
{
for (auto i = 0; i < 64; i++)
{
qMatrix[i] = (uint8_t)(m_mpeg2DefaultIntraQuantizerMatrix[i]);
}
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
cmd.DW1.Obj0.Avc = mpeg2QmNonIntra;
if (params->pMpeg2IqMatrix->m_loadNonIntraQuantiserMatrix)
{
for (auto i = 0; i < 64; i++)
{
qMatrix[i] = (uint8_t)(params->pMpeg2IqMatrix->m_nonIntraQuantiserMatrix[m_mpeg2QuantMatrixScan[i]]);
}
}
else
{
for (auto i = 0; i < 64; i++)
{
qMatrix[i] = (uint8_t)(m_mpeg2DefaultNonIntraQuantizerMatrix[i]);
}
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
}
else
{
cmd.DW1.Obj0.Avc = mpeg2QmIntra;
if (params->pMpeg2IqMatrix->m_loadIntraQuantiserMatrix)
{
uint8_t *src = params->pMpeg2IqMatrix->m_intraQuantiserMatrix;
for (auto i = 0; i < 64; i++)
{
qMatrix[i] = (uint8_t)(src[m_mpeg2QuantMatrixScan[i]]);
}
}
else
{
for (auto i = 0; i < 64; i++)
{
qMatrix[i] = (uint8_t)(m_mpeg2DefaultIntraQuantizerMatrix[i]);
}
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
cmd.DW1.Obj0.Avc = mpeg2QmNonIntra;
if (params->pMpeg2IqMatrix->m_loadNonIntraQuantiserMatrix)
{
uint8_t *src = params->pMpeg2IqMatrix->m_nonIntraQuantiserMatrix;
for (auto i = 0; i < 64; i++)
{
qMatrix[i] = (uint8_t)(src[m_mpeg2QuantMatrixScan[i]]);
}
}
else
{
for (auto i = 0; i < 64; i++)
{
qMatrix[i] = (uint8_t)(m_mpeg2DefaultNonIntraQuantizerMatrix[i]);
}
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
}
}
else if (params->Standard == CODECHAL_JPEG)
{
MHW_MI_CHK_NULL(params->pJpegQuantMatrix);
cmd.DW1.Obj0.Avc = params->pJpegQuantMatrix->m_jpegQMTableType[params->JpegQMTableSelector];
if (params->bJpegQMRotation)
{
for (auto i = 0; i < 8; i++)
{
for (auto ii = 0; ii < 8; ii++)
{
qMatrix[i + 8 * ii] = params->pJpegQuantMatrix->m_quantMatrix[params->JpegQMTableSelector][i * 8 + ii];
}
}
}
else
{
for (auto i = 0; i < 64; i++)
{
qMatrix[i] = params->pJpegQuantMatrix->m_quantMatrix[params->JpegQMTableSelector][i];
}
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
}
else
{
eStatus = MOS_STATUS_INVALID_PARAMETER;
}
return eStatus;
}
MOS_STATUS AddMfxFqmCmd(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_VDBOX_QM_PARAMS params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(cmdBuffer);
MHW_MI_CHK_NULL(params);
typename TMfxCmds::MFX_FQM_STATE_CMD cmd;
if (params->Standard == CODECHAL_AVC)
{
MHW_MI_CHK_NULL(params->pAvcIqMatrix);
PMHW_VDBOX_AVC_QM_PARAMS iqMatrix = params->pAvcIqMatrix;
uint16_t *fqMatrix = (uint16_t*)cmd.ForwardQuantizerMatrix;
for (auto i = 0; i < 32; i++)
{
cmd.ForwardQuantizerMatrix[i] = 0;
}
cmd.DW1.Obj0.Avc = avcQmIntra4x4;
for (auto i = 0; i < 3; i++)
{
for (auto ii = 0; ii < 16; ii++)
{
fqMatrix[i * 16 + ii] =
GetReciprocalScalingValue(iqMatrix->List4x4[i][m_columnScan4x4[ii]]);
}
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
cmd.DW1.Obj0.Avc = avcQmInter4x4;
for (auto i = 0; i < 3; i++)
{
for (auto ii = 0; ii < 16; ii++)
{
fqMatrix[i * 16 + ii] =
GetReciprocalScalingValue(iqMatrix->List4x4[i + 3][m_columnScan4x4[ii]]);
}
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
cmd.DW1.Obj0.Avc = avcQmIntra8x8;
for (auto i = 0; i < 64; i++)
{
fqMatrix[i] = GetReciprocalScalingValue(iqMatrix->List8x8[0][m_columnScan8x8[i]]);
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
cmd.DW1.Obj0.Avc = avcQmInter8x8;
for (auto i = 0; i < 64; i++)
{
fqMatrix[i] = GetReciprocalScalingValue(iqMatrix->List8x8[1][m_columnScan8x8[i]]);
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
}
else if (params->Standard == CODECHAL_MPEG2)
{
uint16_t *fqMatrix = (uint16_t*)cmd.ForwardQuantizerMatrix;
cmd.DW1.Obj0.Avc = mpeg2QmIntra;
if (params->pMpeg2IqMatrix->m_loadIntraQuantiserMatrix)
{
for (auto i = 0; i < 64; i++)
{
fqMatrix[i] = GetReciprocalScalingValue(
(uint8_t)(params->pMpeg2IqMatrix->m_intraQuantiserMatrix[m_mpeg2QuantMatrixScan[m_columnScan8x8[i]]]));
}
}
else
{
for (auto i = 0; i < 64; i++)
{
fqMatrix[i] = GetReciprocalScalingValue(
(uint8_t)m_mpeg2DefaultIntraQuantizerMatrix[m_columnScan8x8[i]]);
}
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
cmd.DW1.Obj0.Avc = mpeg2QmNonIntra;
if (params->pMpeg2IqMatrix->m_loadNonIntraQuantiserMatrix)
{
for (auto i = 0; i < 64; i++)
{
fqMatrix[i] = GetReciprocalScalingValue(
(uint8_t)(params->pMpeg2IqMatrix->m_nonIntraQuantiserMatrix[m_mpeg2QuantMatrixScan[m_columnScan8x8[i]]]));
}
}
else
{
for (auto i = 0; i < 64; i++)
{
fqMatrix[i] = GetReciprocalScalingValue(
(uint8_t)m_mpeg2DefaultNonIntraQuantizerMatrix[m_columnScan8x8[i]]);
}
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
}
return eStatus;
}
MOS_STATUS AddMfxAvcRefIdx(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_BATCH_BUFFER batchBuffer,
PMHW_VDBOX_AVC_REF_IDX_PARAMS params)
{
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(params);
if (cmdBuffer == nullptr && batchBuffer == nullptr)
{
MHW_ASSERTMESSAGE("No valid buffer to add the command to!");
return MOS_STATUS_INVALID_PARAMETER;
}
typename TMfxCmds::MFX_AVC_REF_IDX_STATE_CMD cmd;
// Need to add an empty MFX_AVC_REF_IDX_STATE_CMD for dummy reference on I-Frame
if (!params->bDummyReference)
{
auto uiList = params->uiList;
cmd.DW1.RefpiclistSelect = uiList;
CODEC_REF_LIST **avcRefList = (CODEC_REF_LIST **)params->avcRefList;
AvcRefListWrite *cmdAvcRefListWrite = (AvcRefListWrite *)&(cmd.ReferenceListEntry);
uint8_t picIDOneOnOneMapping = 0;
if (params->bVdencInUse && uiList == LIST_1)
{
picIDOneOnOneMapping += params->uiNumRefForList[LIST_0] << 1;
}
for (uint32_t i = 0; i < params->uiNumRefForList[uiList]; i++)
{
uint8_t idx = params->RefPicList[uiList][i].FrameIdx;
if (!params->bIntelEntrypointInUse)
{
if (idx >= CODEC_MAX_NUM_REF_FRAME)
{
MHW_ASSERT(false); // Idx must be within 0 to 15
idx = 0;
}
idx = params->pAvcPicIdx[idx].ucPicIdx;
}
uint8_t picID = params->bPicIdRemappingInUse ?
params->RefPicList[uiList][i].FrameIdx : avcRefList[idx]->ucFrameId;
// When one on one ref idx mapping is enabled, program picID count from 0, 2 ...
if (params->oneOnOneMapping)
{
picID = picIDOneOnOneMapping;
picIDOneOnOneMapping += 2;
}
cmdAvcRefListWrite->UC[i].frameStoreID = picID;
cmdAvcRefListWrite->UC[i].bottomField =
CodecHal_PictureIsBottomField(params->RefPicList[uiList][i]);
cmdAvcRefListWrite->UC[i].fieldPicFlag =
CodecHal_PictureIsField(params->RefPicList[uiList][i]);
cmdAvcRefListWrite->UC[i].longTermFlag =
CodecHal_PictureIsLongTermRef(avcRefList[idx]->RefPic);
cmdAvcRefListWrite->UC[i].nonExisting = 0;
}
for (auto i = params->uiNumRefForList[uiList]; i < 32; i++)
{
cmdAvcRefListWrite->UC[i].value = 0x80;
}
}
MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));
return MOS_STATUS_SUCCESS;
}
MOS_STATUS AddMfxDecodeAvcWeightOffset(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_BATCH_BUFFER batchBuffer,
PMHW_VDBOX_AVC_WEIGHTOFFSET_PARAMS params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(params);
if (cmdBuffer == nullptr && batchBuffer == nullptr)
{
MHW_ASSERTMESSAGE("No valid buffer to add the command to!");
return MOS_STATUS_INVALID_PARAMETER;
}
typename TMfxCmds::MFX_AVC_WEIGHTOFFSET_STATE_CMD cmd;
cmd.DW1.WeightAndOffsetSelect = params->uiList;
//The correct explicit calculation (like in Cantiga)
for (auto i = 0; i < CODEC_MAX_NUM_REF_FIELD; i++)
{
cmd.Weightoffset[3 * i] = params->Weights[params->uiList][i][0][0] & 0xFFFF; // Y weight
cmd.Weightoffset[3 * i] |= (params->Weights[params->uiList][i][0][1] & 0xFFFF) << 16; // Y offset
cmd.Weightoffset[3 * i + 1] = params->Weights[params->uiList][i][1][0] & 0xFFFF; // Cb weight
cmd.Weightoffset[3 * i + 1] |= (params->Weights[params->uiList][i][1][1] & 0xFFFF) << 16; // Cb offset
cmd.Weightoffset[3 * i + 2] = params->Weights[params->uiList][i][2][0] & 0xFFFF; // Cr weight
cmd.Weightoffset[3 * i + 2] |= (params->Weights[params->uiList][i][2][1] & 0xFFFF) << 16; // Cr offset
}
MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
MOS_STATUS AddMfxEncodeAvcWeightOffset(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_BATCH_BUFFER batchBuffer,
PMHW_VDBOX_AVC_WEIGHTOFFSET_PARAMS params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(params);
if (cmdBuffer == nullptr && batchBuffer == nullptr)
{
MHW_ASSERTMESSAGE("No valid buffer to add the command to!");
return MOS_STATUS_INVALID_PARAMETER;
}
typename TMfxCmds::MFX_AVC_WEIGHTOFFSET_STATE_CMD cmd;
cmd.DW1.WeightAndOffsetSelect = params->uiList;
for (uint32_t i = 0; i < params->uiNumRefForList; i++)
{
if (params->uiLumaWeightFlag & (1 << i))
{
cmd.Weightoffset[3 * i] = params->Weights[params->uiList][i][0][0] & 0xFFFF; // Y weight
cmd.Weightoffset[3 * i] |= (params->Weights[params->uiList][i][0][1] & 0xFFFF) << 16; // Y offset
}
else
{
cmd.Weightoffset[3 * i] = 1 << (params->uiLumaLogWeightDenom); // Y weight
cmd.Weightoffset[3 * i] = cmd.Weightoffset[3 * i] | (0 << 16); // Y offset
}
if (params->uiChromaWeightFlag & (1 << i))
{
cmd.Weightoffset[3 * i + 1] = params->Weights[params->uiList][i][1][0] & 0xFFFF; // Cb weight
cmd.Weightoffset[3 * i + 1] |= (params->Weights[params->uiList][i][1][1] & 0xFFFF) << 16; // Cb offset
cmd.Weightoffset[3 * i + 2] = params->Weights[params->uiList][i][2][0] & 0xFFFF; // Cr weight
cmd.Weightoffset[3 * i + 2] |= (params->Weights[params->uiList][i][2][1] & 0xFFFF) << 16; // Cr offset
}
else
{
cmd.Weightoffset[3 * i + 1] = 1 << (params->uiChromaLogWeightDenom); // Cb weight
cmd.Weightoffset[3 * i + 1] = cmd.Weightoffset[3 * i + 1] | (0 << 16); // Cb offset
cmd.Weightoffset[3 * i + 2] = 1 << (params->uiChromaLogWeightDenom); // Cr weight
cmd.Weightoffset[3 * i + 2] = cmd.Weightoffset[3 * i + 2] | (0 << 16); // Cr offset
}
}
MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
MOS_STATUS AddMfxDecodeAvcSlice(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_BATCH_BUFFER batchBuffer,
PMHW_VDBOX_AVC_SLICE_STATE avcSliceState)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(avcSliceState);
MHW_MI_CHK_NULL(avcSliceState->pAvcPicParams);
MHW_MI_CHK_NULL(avcSliceState->pAvcSliceParams);
if (cmdBuffer == nullptr && batchBuffer == nullptr)
{
MHW_ASSERTMESSAGE("No valid buffer to add the command to!");
return MOS_STATUS_INVALID_PARAMETER;
}
auto picParams = avcSliceState->pAvcPicParams;
uint32_t mbaffMultiplier = 1;
if (picParams->seq_fields.mb_adaptive_frame_field_flag &&
!picParams->pic_fields.field_pic_flag)
{
mbaffMultiplier++;
}
uint16_t frameFieldHeightInMb = 0;
CodecHal_GetFrameFieldHeightInMb(
picParams->CurrPic,
picParams->pic_height_in_mbs_minus1 + 1,
frameFieldHeightInMb);
auto sliceParams = avcSliceState->pAvcSliceParams;
typename TMfxCmds::MFX_AVC_SLICE_STATE_CMD cmd;
// Set MFX_AVC_SLICE_STATE_CMD
cmd.DW1.SliceType = m_AvcBsdSliceType[sliceParams->slice_type];
cmd.DW2.Log2WeightDenomChroma = sliceParams->chroma_log2_weight_denom;
cmd.DW2.Log2WeightDenomLuma = sliceParams->luma_log2_weight_denom;
cmd.DW3.WeightedPredictionIndicator = 0;
cmd.DW3.DisableDeblockingFilterIndicator = avcSliceState->ucDisableDeblockingFilterIdc;
cmd.DW3.CabacInitIdc10 = sliceParams->cabac_init_idc;
cmd.DW3.SliceQuantizationParameter = 26 + picParams->pic_init_qp_minus26 + sliceParams->slice_qp_delta;
cmd.DW3.SliceBetaOffsetDiv2 = avcSliceState->ucSliceBetaOffsetDiv2;
cmd.DW3.SliceAlphaC0OffsetDiv2 = avcSliceState->ucSliceAlphaC0OffsetDiv2;
auto widthInMb = picParams->pic_width_in_mbs_minus1 + 1;
if (avcSliceState->bPhantomSlice)
{
cmd.DW4.SliceStartMbNum = widthInMb * frameFieldHeightInMb;
cmd.DW4.SliceVerticalPosition = frameFieldHeightInMb;
cmd.DW4.SliceHorizontalPosition = widthInMb;
}
else
{
cmd.DW4.SliceStartMbNum = sliceParams->first_mb_in_slice * mbaffMultiplier;
cmd.DW4.SliceVerticalPosition = (sliceParams->first_mb_in_slice / widthInMb) * mbaffMultiplier;
cmd.DW4.SliceHorizontalPosition = sliceParams->first_mb_in_slice % widthInMb;
}
if (avcSliceState->bLastSlice)
{
cmd.DW5.NextSliceVerticalPosition = frameFieldHeightInMb;
cmd.DW5.NextSliceHorizontalPosition = 0;
}
else
{
cmd.DW5.NextSliceVerticalPosition = (sliceParams->first_mb_in_next_slice / widthInMb) * mbaffMultiplier;
cmd.DW5.NextSliceHorizontalPosition = sliceParams->first_mb_in_next_slice % widthInMb;
}
cmd.DW6.IsLastSlice = avcSliceState->bLastSlice;
cmd.DW9.Roundintra = 5;
cmd.DW9.Roundintraenable = 1;
cmd.DW9.Roundinter = 2;
if (IsAvcPSlice(sliceParams->slice_type))
{
cmd.DW2.NumberOfReferencePicturesInInterPredictionList0 = sliceParams->num_ref_idx_l0_active_minus1 + 1;
cmd.DW3.WeightedPredictionIndicator = picParams->pic_fields.weighted_pred_flag;
}
else if (IsAvcBSlice(sliceParams->slice_type))
{
cmd.DW2.NumberOfReferencePicturesInInterPredictionList1 = sliceParams->num_ref_idx_l1_active_minus1 + 1;
cmd.DW2.NumberOfReferencePicturesInInterPredictionList0 = sliceParams->num_ref_idx_l0_active_minus1 + 1;
cmd.DW3.WeightedPredictionIndicator = picParams->pic_fields.weighted_bipred_idc;
cmd.DW3.DirectPredictionType = sliceParams->direct_spatial_mv_pred_flag;
// Set MFX_AVC_WEIGHTOFFSET_STATE_CMD_G6
if (picParams->pic_fields.weighted_bipred_idc != 1)
{
// luma/chroma_log2_weight_denoms need to be set to default value in the case of implicit mode
cmd.DW2.Log2WeightDenomChroma = m_log2WeightDenomDefault;
cmd.DW2.Log2WeightDenomLuma = m_log2WeightDenomDefault;
}
}
MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
MOS_STATUS AddMfxEncodeAvcSlice(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_BATCH_BUFFER batchBuffer,
PMHW_VDBOX_AVC_SLICE_STATE avcSliceState)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(avcSliceState);
MHW_MI_CHK_NULL(avcSliceState->pEncodeAvcSeqParams);
MHW_MI_CHK_NULL(avcSliceState->pEncodeAvcPicParams);
MHW_MI_CHK_NULL(avcSliceState->pEncodeAvcSliceParams);
if (cmdBuffer == nullptr && batchBuffer == nullptr)
{
MHW_ASSERTMESSAGE("No valid buffer to add the command to!");
return MOS_STATUS_INVALID_PARAMETER;
}
auto seqParams = avcSliceState->pEncodeAvcSeqParams;
auto sliceParams = avcSliceState->pEncodeAvcSliceParams;
auto picParams = avcSliceState->pEncodeAvcPicParams;
uint16_t widthInMb = seqParams->pic_width_in_mbs_minus1 + 1;
uint16_t frameFieldHeightInMb = avcSliceState->wFrameFieldHeightInMB;
bool mbaffFrameFlag = seqParams->mb_adaptive_frame_field_flag ? true : false;
uint32_t startMbNum = sliceParams->first_mb_in_slice * (1 + mbaffFrameFlag);
typename TMfxCmds::MFX_AVC_SLICE_STATE_CMD cmd;
//DW1
cmd.DW1.SliceType = Slice_Type[sliceParams->slice_type];
//DW2
cmd.DW2.Log2WeightDenomLuma = sliceParams->luma_log2_weight_denom;
cmd.DW2.Log2WeightDenomChroma = sliceParams->chroma_log2_weight_denom;
cmd.DW2.NumberOfReferencePicturesInInterPredictionList0 = 0;
cmd.DW2.NumberOfReferencePicturesInInterPredictionList1 = 0;
//DW3
cmd.DW3.SliceAlphaC0OffsetDiv2 = sliceParams->slice_alpha_c0_offset_div2;
cmd.DW3.SliceBetaOffsetDiv2 = sliceParams->slice_beta_offset_div2;
cmd.DW3.SliceQuantizationParameter = 26 + picParams->pic_init_qp_minus26 + sliceParams->slice_qp_delta;
cmd.DW3.CabacInitIdc10 = sliceParams->cabac_init_idc;
cmd.DW3.DisableDeblockingFilterIndicator = sliceParams->disable_deblocking_filter_idc;
cmd.DW3.DirectPredictionType =
IsAvcBSlice(sliceParams->slice_type) ? sliceParams->direct_spatial_mv_pred_flag : 0;
cmd.DW3.WeightedPredictionIndicator = DEFAULT_WEIGHTED_INTER_PRED_MODE;
//DW4
cmd.DW4.SliceHorizontalPosition = startMbNum % widthInMb;
cmd.DW4.SliceVerticalPosition = startMbNum / widthInMb;
//DW5
cmd.DW5.NextSliceHorizontalPosition = (startMbNum + sliceParams->NumMbsForSlice) % widthInMb;
cmd.DW5.NextSliceVerticalPosition = (startMbNum + sliceParams->NumMbsForSlice) / widthInMb;
//DW6
cmd.DW6.StreamId10 = 0;
cmd.DW6.SliceId30 = sliceParams->slice_id;
cmd.DW6.Cabaczerowordinsertionenable = 1;
cmd.DW6.Emulationbytesliceinsertenable = 1;
cmd.DW6.IsLastSlice =
(startMbNum + sliceParams->NumMbsForSlice) >= (uint32_t)(widthInMb * frameFieldHeightInMb);
// Driver only programs 1st slice state, VDENC will detect the last slice
if (avcSliceState->bVdencInUse)
{
cmd.DW6.TailInsertionPresentInBitstream = avcSliceState->bVdencNoTailInsertion ?
0 : (picParams->bLastPicInSeq || picParams->bLastPicInStream);
}
else
{
cmd.DW6.TailInsertionPresentInBitstream = (picParams->bLastPicInSeq || picParams->bLastPicInStream) && cmd.DW6.IsLastSlice;
}
cmd.DW6.SlicedataInsertionPresentInBitstream = 1;
cmd.DW6.HeaderInsertionPresentInBitstream = 1;
cmd.DW6.MbTypeSkipConversionDisable = 0;
cmd.DW6.MbTypeDirectConversionDisable = 0;
cmd.DW6.RateControlCounterEnable = (avcSliceState->bBrcEnabled && (!avcSliceState->bFirstPass));
if (cmd.DW6.RateControlCounterEnable == true)
{
// These fields are valid only when RateControlCounterEnable = 1
cmd.DW6.RcPanicType = 1; // CBP Panic
cmd.DW6.RcPanicEnable =
(avcSliceState->bRCPanicEnable &&
(seqParams->RateControlMethod != RATECONTROL_AVBR) &&
(seqParams->RateControlMethod != RATECONTROL_IWD_VBR) &&
(seqParams->RateControlMethod != RATECONTROL_ICQ) &&
(seqParams->RateControlMethod != RATECONTROL_VCM) &&
(seqParams->RateControlMethod != RATECONTROL_CQP) &&
avcSliceState->bLastPass); // Enable only in the last pass
cmd.DW6.RcStableTolerance = 0;
cmd.DW6.RcTriggleMode = 2; // Loose Rate Control
cmd.DW6.Resetratecontrolcounter = !startMbNum;
}
cmd.DW9.Roundinter = 2;
if (IsAvcPSlice(sliceParams->slice_type))
{
cmd.DW2.NumberOfReferencePicturesInInterPredictionList0 = sliceParams->num_ref_idx_l0_active_minus1_from_DDI + 1;
cmd.DW3.WeightedPredictionIndicator = picParams->weighted_pred_flag;
cmd.DW9.Roundinterenable = avcSliceState->bRoundingInterEnable;
cmd.DW9.Roundinter = avcSliceState->dwRoundingValue;
}
else if (IsAvcBSlice(sliceParams->slice_type))
{
cmd.DW2.NumberOfReferencePicturesInInterPredictionList1 = sliceParams->num_ref_idx_l1_active_minus1_from_DDI + 1;
cmd.DW2.NumberOfReferencePicturesInInterPredictionList0 = sliceParams->num_ref_idx_l0_active_minus1_from_DDI + 1;
cmd.DW3.WeightedPredictionIndicator = picParams->weighted_bipred_idc;
if (picParams->weighted_bipred_idc == IMPLICIT_WEIGHTED_INTER_PRED_MODE)
{
if (avcSliceState->bVdencInUse)
{
cmd.DW2.Log2WeightDenomLuma = 0;
cmd.DW2.Log2WeightDenomChroma = 0;
}
else
{
// SNB requirement
cmd.DW2.Log2WeightDenomLuma = 5;
cmd.DW2.Log2WeightDenomChroma = 5;
}
}
cmd.DW9.Roundinterenable = avcSliceState->bRoundingInterEnable;
cmd.DW9.Roundinter = avcSliceState->dwRoundingValue;
}
cmd.DW9.Roundintra = avcSliceState->dwRoundingIntraValue;
cmd.DW9.Roundintraenable = 1;
MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
MOS_STATUS AddMfdAvcDpbCmd(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_VDBOX_AVC_DPB_PARAMS params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(cmdBuffer);
MHW_MI_CHK_NULL(params);
MHW_MI_CHK_NULL(params->pAvcPicParams);
auto avcPicParams = params->pAvcPicParams;
auto currFrameIdx = avcPicParams->CurrPic.FrameIdx;
auto currAvcRefList = params->ppAvcRefList[currFrameIdx];
int16_t refFrameOrder[CODEC_MAX_NUM_REF_FRAME] = { 0 };
uint32_t usedForRef = 0;
uint16_t nonExistingFrameFlags = 0;
uint16_t longTermFrame = 0;
for (uint8_t i = 0; i < currAvcRefList->ucNumRef; i++)
{
auto picIdx = currAvcRefList->RefList[i].FrameIdx;
auto refAvcRefList = params->ppAvcRefList[picIdx];
bool longTermFrameFlag = (currAvcRefList->RefList[i].PicFlags == PICTURE_LONG_TERM_REFERENCE);
uint8_t frameID = params->bPicIdRemappingInUse ? i : refAvcRefList->ucFrameId;
int16_t frameNum = refAvcRefList->sFrameNumber;
refFrameOrder[frameID] = frameNum;
usedForRef |= (((currAvcRefList->uiUsedForReferenceFlags >> (i * 2)) & 3) << (frameID * 2));
nonExistingFrameFlags |= (((currAvcRefList->usNonExistingFrameFlags >> i) & 1) << frameID);
longTermFrame |= (((uint16_t)longTermFrameFlag) << frameID);
}
typename TMfxCmds::MFD_AVC_DPB_STATE_CMD cmd;
cmd.DW1.NonExistingframeFlag161Bit = nonExistingFrameFlags;
cmd.DW1.LongtermframeFlag161Bit = longTermFrame;
cmd.DW2.Value = usedForRef;
for (auto i = 0, j = 0; i < 8; i++, j++)
{
cmd.Ltstframenumlist1616Bits[i] = (refFrameOrder[j++] & 0xFFFF); //FirstEntry
cmd.Ltstframenumlist1616Bits[i] = cmd.Ltstframenumlist1616Bits[i] | ((refFrameOrder[j] & 0xFFFF) << 16); //SecondEntry
}
auto mvcExtPicParams = params->pMvcExtPicParams;
if (mvcExtPicParams)
{
for (auto i = 0, j = 0; i < (CODEC_MAX_NUM_REF_FRAME / 2); i++, j++)
{
cmd.Viewidlist1616Bits[i] = mvcExtPicParams->ViewIDList[j++];
cmd.Viewidlist1616Bits[i] = cmd.Viewidlist1616Bits[i] | (mvcExtPicParams->ViewIDList[j] << 16);
}
for (auto i = 0, j = 0; i < (CODEC_MAX_NUM_REF_FRAME / 4); i++, j++)
{
cmd.Vieworderlistl0168Bits[i] = GetViewOrder(params, j++, LIST_0); //FirstEntry
cmd.Vieworderlistl0168Bits[i] = cmd.Vieworderlistl0168Bits[i] | (GetViewOrder(params, j++, LIST_0) << 8); //SecondEntry
cmd.Vieworderlistl0168Bits[i] = cmd.Vieworderlistl0168Bits[i] | (GetViewOrder(params, j++, LIST_0) << 16); //ThirdEntry
cmd.Vieworderlistl0168Bits[i] = cmd.Vieworderlistl0168Bits[i] | (GetViewOrder(params, j, LIST_0) << 24); //FourthEntry
}
for (auto i = 0, j = 0; i < (CODEC_MAX_NUM_REF_FRAME / 4); i++, j++)
{
cmd.Vieworderlistl1168Bits[i] = GetViewOrder(params, j++, LIST_1); //FirstEntry
cmd.Vieworderlistl1168Bits[i] = cmd.Vieworderlistl1168Bits[i] | (GetViewOrder(params, j++, LIST_1) << 8); //SecondEntry
cmd.Vieworderlistl1168Bits[i] = cmd.Vieworderlistl1168Bits[i] | (GetViewOrder(params, j++, LIST_1) << 16); //ThirdEntry
cmd.Vieworderlistl1168Bits[i] = cmd.Vieworderlistl1168Bits[i] | (GetViewOrder(params, j, LIST_1) << 24); //FourthEntry
}
}
else
{
for (auto i = 0, j = 0; i < (CODEC_MAX_NUM_REF_FRAME / 2); i++, j++)
{
cmd.Viewidlist1616Bits[i] = 0;
}
for (auto i = 0, j = 0; i < (CODEC_MAX_NUM_REF_FRAME / 4); i++, j++)
{
cmd.Vieworderlistl0168Bits[i] = 0; //FirstEntry
}
for (auto i = 0, j = 0; i < (CODEC_MAX_NUM_REF_FRAME / 4); i++, j++)
{
cmd.Vieworderlistl1168Bits[i] = 0; //FirstEntry
}
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
MOS_STATUS AddMfxAvcImgBrcBuffer(
PMOS_RESOURCE brcImgBuffer,
PMHW_VDBOX_AVC_IMG_PARAMS params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(brcImgBuffer);
MHW_MI_CHK_NULL(params);
MOS_LOCK_PARAMS lockFlags;
MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
lockFlags.WriteOnly = 1;
uint8_t *data = (uint8_t*)m_osInterface->pfnLockResource(m_osInterface, brcImgBuffer, &lockFlags);
MHW_MI_CHK_NULL(data);
MOS_COMMAND_BUFFER constructedCmdBuf;
constructedCmdBuf.pCmdBase = (uint32_t *)data;
constructedCmdBuf.pCmdPtr = (uint32_t *)data;
constructedCmdBuf.iOffset = 0;
constructedCmdBuf.iRemaining = BRC_IMG_STATE_SIZE_PER_PASS * m_numBrcPakPasses;
MHW_MI_CHK_STATUS(AddMfxAvcImgCmd(&constructedCmdBuf, nullptr, params));
typename TMfxCmds::MFX_AVC_IMG_STATE_CMD cmd = *(typename TMfxCmds::MFX_AVC_IMG_STATE_CMD *)data;
for (uint32_t i = 0; i < m_numBrcPakPasses; i++)
{
if (i == 0)
{
cmd.DW4.Mbstatenabled =
cmd.DW5.Nonfirstpassflag = false;
}
else
{
cmd.DW4.Mbstatenabled = true;
cmd.DW5.IntraIntermbipcmflagForceipcmcontrolmask = true;
cmd.DW5.Nonfirstpassflag = true;
}
/* Setting the MbRateCtrlFlag to 0 so that the accumulative delta QP for consecutive passes is applied on top of
the macroblock QP values in inline data. This is changed because the streamout QP behavior is causing a mismatch
between the HW output and prototype output.*/
cmd.DW5.MbratectrlflagMbLevelRateControlEnablingFlag = false;
*(typename TMfxCmds::MFX_AVC_IMG_STATE_CMD *)data = cmd;
/* add batch buffer end insertion flag */
uint32_t* insertion = (uint32_t*)(data + (TMfxCmds::MFX_AVC_IMG_STATE_CMD::byteSize));
*insertion = 0x05000000;
data += BRC_IMG_STATE_SIZE_PER_PASS;
}
return eStatus;
}
MOS_STATUS AddMfxDecodeMpeg2PicCmd(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_VDBOX_MPEG2_PIC_STATE params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(cmdBuffer);
MHW_MI_CHK_NULL(params);
MHW_MI_CHK_NULL(params->pMpeg2PicParams);
typename TMfxCmds::MFX_MPEG2_PIC_STATE_CMD cmd;
auto picParams = params->pMpeg2PicParams;
cmd.DW1.ScanOrder = picParams->W0.m_scanOrder;
cmd.DW1.IntraVlcFormat = picParams->W0.m_intraVlcFormat;
cmd.DW1.QuantizerScaleType = picParams->W0.m_quantizerScaleType;
cmd.DW1.ConcealmentMotionVectorFlag = picParams->W0.m_concealmentMVFlag;
cmd.DW1.FramePredictionFrameDct = picParams->W0.m_frameDctPrediction;
cmd.DW1.TffTopFieldFirst = (CodecHal_PictureIsFrame(picParams->m_currPic)) ?
picParams->W0.m_topFieldFirst : picParams->m_topFieldFirst;
cmd.DW1.PictureStructure = (CodecHal_PictureIsFrame(picParams->m_currPic)) ?
mpeg2Vc1Frame : (CodecHal_PictureIsTopField(picParams->m_currPic)) ?
mpeg2Vc1TopField : mpeg2Vc1BottomField;
cmd.DW1.IntraDcPrecision = picParams->W0.m_intraDCPrecision;
cmd.DW1.FCode00 = picParams->W1.m_fcode00;
cmd.DW1.FCode01 = picParams->W1.m_fcode01;
cmd.DW1.FCode10 = picParams->W1.m_fcode10;
cmd.DW1.FCode11 = picParams->W1.m_fcode11;
cmd.DW2.PictureCodingType = picParams->m_pictureCodingType;
if (params->Mode == CODECHAL_DECODE_MODE_MPEG2VLD)
{
cmd.DW2.ISliceConcealmentMode = params->dwMPEG2ISliceConcealmentMode;
cmd.DW2.PBSliceConcealmentMode = params->dwMPEG2PBSliceConcealmentMode;
cmd.DW2.PBSlicePredictedBidirMotionTypeOverrideBiDirectionMvTypeOverride = params->dwMPEG2PBSlicePredBiDirMVTypeOverride;
cmd.DW2.PBSlicePredictedMotionVectorOverrideFinalMvValueOverride = params->dwMPEG2PBSlicePredMVOverride;
cmd.DW3.SliceConcealmentDisableBit = 1;
}
uint16_t widthInMbs =
(picParams->m_horizontalSize + CODECHAL_MACROBLOCK_WIDTH - 1) /
CODECHAL_MACROBLOCK_WIDTH;
uint16_t heightInMbs =
(picParams->m_verticalSize + CODECHAL_MACROBLOCK_HEIGHT - 1) /
CODECHAL_MACROBLOCK_HEIGHT;
cmd.DW3.Framewidthinmbsminus170PictureWidthInMacroblocks = widthInMbs - 1;
cmd.DW3.Frameheightinmbsminus170PictureHeightInMacroblocks = (CodecHal_PictureIsField(picParams->m_currPic)) ?
((heightInMbs * 2) - 1) : heightInMbs - 1;
if (params->bDeblockingEnabled)
{
cmd.DW3.Reserved120 = 9;
}
cmd.DW4.Roundintradc = 3;
cmd.DW4.Roundinterdc = 1;
cmd.DW4.Roundintraac = 5;
cmd.DW4.Roundinterac = 1;
cmd.DW6.Intrambmaxsize = 0xfff;
cmd.DW6.Intermbmaxsize = 0xfff;
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
MOS_STATUS AddMfxEncodeMpeg2PicCmd(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_VDBOX_MPEG2_PIC_STATE params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(cmdBuffer);
MHW_MI_CHK_NULL(params);
MHW_MI_CHK_NULL(params->pEncodeMpeg2PicParams);
typename TMfxCmds::MFX_MPEG2_PIC_STATE_CMD cmd;
auto picParams = params->pEncodeMpeg2PicParams;
cmd.DW1.ScanOrder = picParams->m_alternateScan;
cmd.DW1.IntraVlcFormat = picParams->m_intraVlcFormat;
cmd.DW1.QuantizerScaleType = picParams->m_qscaleType;
cmd.DW1.ConcealmentMotionVectorFlag = picParams->m_concealmentMotionVectors;
cmd.DW1.FramePredictionFrameDct = picParams->m_framePredFrameDCT;
cmd.DW1.TffTopFieldFirst = !picParams->m_interleavedFieldBFF;
cmd.DW1.PictureStructure = (CodecHal_PictureIsFrame(picParams->m_currOriginalPic)) ?
mpeg2Vc1Frame : (CodecHal_PictureIsTopField(picParams->m_currOriginalPic)) ?
mpeg2Vc1TopField : mpeg2Vc1BottomField;
cmd.DW1.IntraDcPrecision = picParams->m_intraDCprecision;
if (picParams->m_pictureCodingType == I_TYPE)
{
cmd.DW1.FCode00 = 0xf;
cmd.DW1.FCode01 = 0xf;
}
else
{
cmd.DW1.FCode00 = picParams->m_fcode00;
cmd.DW1.FCode01 = picParams->m_fcode01;
}
cmd.DW1.FCode10 = picParams->m_fcode10;
cmd.DW1.FCode11 = picParams->m_fcode11;
cmd.DW2.PictureCodingType = picParams->m_pictureCodingType;
cmd.DW2.LoadslicepointerflagLoadbitstreampointerperslice = 0; // Do not reload bitstream pointer for each slice
cmd.DW3.Framewidthinmbsminus170PictureWidthInMacroblocks = params->wPicWidthInMb - 1;
cmd.DW3.Frameheightinmbsminus170PictureHeightInMacroblocks = params->wPicHeightInMb - 1;
cmd.DW4.Roundintradc = 3;
cmd.DW4.Roundinterdc = 1;
cmd.DW4.Roundintraac = 5;
cmd.DW4.Roundinterac = 1;
cmd.DW4.Mbstatenabled = 0;
cmd.DW5.Mbratecontrolmask = 0;
cmd.DW5.Framesizecontrolmask = 0; // Disable first for PAK pass, used when MacroblockStatEnable is 1
cmd.DW6.Intrambmaxsize = 0xfff;
cmd.DW6.Intermbmaxsize = 0xfff;
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
MOS_STATUS AddMfdMpeg2BsdObject(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_BATCH_BUFFER batchBuffer,
PMHW_VDBOX_MPEG2_SLICE_STATE params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(params);
MHW_MI_CHK_NULL(params->pMpeg2SliceParams);
if (cmdBuffer == nullptr && batchBuffer == nullptr)
{
MHW_ASSERTMESSAGE("No valid buffer to add the command to!");
return MOS_STATUS_INVALID_PARAMETER;
}
typename TMfxCmds::MFD_MPEG2_BSD_OBJECT_CMD cmd;
auto sliceParams = params->pMpeg2SliceParams;
uint32_t endMb = params->dwSliceStartMbOffset + sliceParams->m_numMbsForSlice;
uint32_t slcLocation = (uint32_t)(sliceParams->m_sliceDataOffset + params->dwOffset);
cmd.DW1.IndirectBsdDataLength = params->dwLength;
cmd.DW2.IndirectDataStartAddress = slcLocation;
cmd.DW3.FirstMacroblockBitOffset = (sliceParams->m_macroblockOffset & 0x0007);
cmd.DW3.IsLastMb = cmd.DW3.LastPicSlice = params->bLastSlice;
cmd.DW3.Reserved100 =
((endMb / params->wPicWidthInMb) != sliceParams->m_sliceVerticalPosition) ? 1 : 0;
cmd.DW3.MacroblockCount = sliceParams->m_numMbsForSlice;
cmd.DW3.SliceHorizontalPosition = sliceParams->m_sliceHorizontalPosition;
cmd.DW3.SliceVerticalPosition = sliceParams->m_sliceVerticalPosition;
cmd.DW4.QuantizerScaleCode = sliceParams->m_quantiserScaleCode;
if (cmd.DW3.IsLastMb)
{
cmd.DW4.NextSliceHorizontalPosition = 0;
cmd.DW4.NextSliceVerticalPosition = params->wPicHeightInMb;
}
else
{
cmd.DW4.NextSliceHorizontalPosition = endMb % params->wPicWidthInMb;
cmd.DW4.NextSliceVerticalPosition = endMb / params->wPicWidthInMb;
}
uint32_t offset = ((sliceParams->m_macroblockOffset & 0x0000fff8) >> 3); // #of bytes of header data in bitstream buffer (before video data)
MHW_CP_SLICE_INFO_PARAMS sliceInfoParam;
sliceInfoParam.presDataBuffer = params->presDataBuffer;
sliceInfoParam.dwDataStartOffset[0] = sliceParams->m_sliceDataOffset + offset;
MHW_MI_CHK_STATUS(m_cpInterface->SetMfxProtectionState(
m_decodeInUse,
cmdBuffer,
batchBuffer,
&sliceInfoParam));
MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
//!
//! \struct MFD_MPEG2_IT_OBJECT_CMD
//! \brief MFD MPEG2 it object command
//!
struct MFD_MPEG2_IT_OBJECT_CMD
{
typename TMfxCmds::MFD_IT_OBJECT_CMD m_header;
typename TMfxCmds::MFD_IT_OBJECT_MPEG2_INLINE_DATA_CMD m_inlineData;
};
MOS_STATUS AddMfdMpeg2ITObject(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_BATCH_BUFFER batchBuffer,
PMHW_VDBOX_MPEG2_MB_STATE params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(params);
if (cmdBuffer == nullptr && batchBuffer == nullptr)
{
MHW_ASSERTMESSAGE("No valid buffer to add the command to!");
return MOS_STATUS_INVALID_PARAMETER;
}
MFD_MPEG2_IT_OBJECT_CMD cmd;
cmd.m_inlineData.DW0.MacroblockIntraType = mpeg2Vc1MacroblockIntra;
typename TMfxCmds::MFD_IT_OBJECT_MPEG2_INLINE_DATA_CMD *inlineDataMpeg2 = &(cmd.m_inlineData);
typename TMfxCmds::MFD_IT_OBJECT_CMD *cmdMfdItObject = &(cmd.m_header);
//------------------------------------
// Shared indirect data
//------------------------------------
cmdMfdItObject->DW0.DwordLength += TMfxCmds::MFD_IT_OBJECT_MPEG2_INLINE_DATA_CMD::dwSize;
cmdMfdItObject->DW3.IndirectItCoeffDataLength = (params->dwDCTLength) << 2;
cmdMfdItObject->DW4.IndirectItCoeffDataStartAddressOffset = params->dwITCoffDataAddrOffset;
//------------------------------------
// Shared inline data
//------------------------------------
auto mbParams = params->pMBParams;
inlineDataMpeg2->DW0.DctType = mbParams->MBType.m_fieldResidual;
inlineDataMpeg2->DW0.CodedBlockPattern = mbParams->m_codedBlockPattern;
inlineDataMpeg2->DW1.Horzorigin = mbParams->m_mbAddr % params->wPicWidthInMb;
inlineDataMpeg2->DW1.Vertorigin = mbParams->m_mbAddr / params->wPicWidthInMb;
inlineDataMpeg2->DW0.Lastmbinrow = (inlineDataMpeg2->DW1.Horzorigin == (params->wPicWidthInMb - 1));
if (params->wPicCodingType != I_TYPE)
{
inlineDataMpeg2->DW0.MacroblockIntraType = mbParams->MBType.m_intraMb;
inlineDataMpeg2->DW0.MacroblockMotionForward = mbParams->MBType.m_motionFwd;
inlineDataMpeg2->DW0.MacroblockMotionBackward = mbParams->MBType.m_motionBwd;
inlineDataMpeg2->DW0.MotionType = mbParams->MBType.m_motionType;
inlineDataMpeg2->DW0.MotionVerticalFieldSelect = mbParams->MBType.m_mvertFieldSel;
// Next, copy in the motion vectors
if (mbParams->MBType.m_intraMb == 0)
{
uint32_t *point = (uint32_t*)(params->sPackedMVs0);
inlineDataMpeg2->DW2.Value = *point++;
inlineDataMpeg2->DW3.Value = *point++;
point = (uint32_t*)(params->sPackedMVs1);
inlineDataMpeg2->DW4.Value = *point++;
inlineDataMpeg2->DW5.Value = *point++;
}
}
MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
MOS_STATUS AddMfcMpeg2SliceGroupCmd(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_VDBOX_MPEG2_SLICE_STATE mpeg2SliceState)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(cmdBuffer);
MHW_MI_CHK_NULL(mpeg2SliceState);
MHW_MI_CHK_NULL(mpeg2SliceState->pEncodeMpeg2PicParams);
MHW_MI_CHK_NULL(mpeg2SliceState->pEncodeMpeg2SliceParams);
MHW_MI_CHK_NULL(mpeg2SliceState->pSlcData);
auto sliceParams = mpeg2SliceState->pEncodeMpeg2SliceParams;
auto picParams = mpeg2SliceState->pEncodeMpeg2PicParams;
auto seqParams = mpeg2SliceState->pEncodeMpeg2SeqParams;
auto slcData = mpeg2SliceState->pSlcData;
typename TMfxCmds::MFC_MPEG2_SLICEGROUP_STATE_CMD cmd;
cmd.DW1.Streamid10EncoderOnly = 0;
cmd.DW1.Sliceid30EncoderOnly = 0;
cmd.DW1.Intrasliceflag = 1;
cmd.DW1.Intraslice = sliceParams->m_intraSlice;
cmd.DW1.Firstslicehdrdisabled = 0;
cmd.DW1.TailpresentflagTailInsertionPresentInBitstreamEncoderOnly =
(picParams->m_lastPicInStream && (slcData->SliceGroup & SLICE_GROUP_LAST));
cmd.DW1.SlicedataPresentflagSlicedataInsertionPresentInBitstreamEncoderOnly = 1;
cmd.DW1.HeaderpresentflagHeaderInsertionPresentInBitstreamEncoderOnly = 1;
cmd.DW1.BitstreamoutputflagCompressedBitstreamOutputDisableFlagEncoderOnly = 0;
cmd.DW1.Islastslicegrp = (slcData->SliceGroup & SLICE_GROUP_LAST) ? 1 : 0;
cmd.DW1.SkipconvdisabledMbTypeSkipConversionDisableEncoderOnly = sliceParams->m_intraSlice; // Disable for I slice
cmd.DW1.MbratectrlflagRatecontrolcounterenableEncoderOnly = (mpeg2SliceState->bBrcEnabled && (!mpeg2SliceState->bFirstPass));
cmd.DW1.MbratectrlresetResetratecontrolcounterEncoderOnly = 1;
cmd.DW1.RatectrlpanictypeRcPanicTypeEncoderOnly = 1; // CBP type
cmd.DW1.MbratectrlmodeRcTriggleModeEncoderOnly = 2; // Loose Rate Control Mode
cmd.DW1.RatectrlpanicflagRcPanicEnableEncoderOnly =
(mpeg2SliceState->bRCPanicEnable &&
(seqParams->m_rateControlMethod != RATECONTROL_AVBR) &&
(seqParams->m_rateControlMethod != RATECONTROL_IWD_VBR) &&
(seqParams->m_rateControlMethod != RATECONTROL_ICQ) &&
(seqParams->m_rateControlMethod != RATECONTROL_VCM) &&
(seqParams->m_rateControlMethod != RATECONTROL_CQP) &&
mpeg2SliceState->bLastPass); // Enable only in the last pass
cmd.DW2.FirstmbxcntAlsoCurrstarthorzpos = sliceParams->m_firstMbX;
cmd.DW2.FirstmbycntAlsoCurrstartvertpos = sliceParams->m_firstMbY;
cmd.DW2.NextsgmbxcntAlsoNextstarthorzpos = slcData->NextSgMbXCnt;
cmd.DW2.NextsgmbycntAlsoNextstartvertpos = slcData->NextSgMbYCnt;
cmd.DW3.Slicegroupqp = sliceParams->m_quantiserScaleCode;
cmd.DW3.Slicegroupskip = 0; // MBZ for MPEG2
// H/W should use this start addr only for the first slice, since LoadSlicePointerFlag = 0 in PIC_STATE
cmd.DW4.BitstreamoffsetIndirectPakBseDataStartAddressWrite = 0;
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
MOS_STATUS AddMfcMpeg2PakInsertBrcBuffer(
PMOS_RESOURCE brcPicHeaderInputBuffer,
PMHW_VDBOX_PAK_INSERT_PARAMS params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(brcPicHeaderInputBuffer);
MHW_MI_CHK_NULL(params);
MHW_MI_CHK_NULL(params->pBsBuffer);
typename TMfxCmds::MFX_PAK_INSERT_OBJECT_CMD cmd;
uint32_t byteSize = (params->pBsBuffer->BitSize + 7) >> 3;
uint32_t dataBitsInLastDw = params->pBsBuffer->BitSize % 32;
if (dataBitsInLastDw == 0)
{
dataBitsInLastDw = 32;
}
uint32_t dwordsUsed = TMfxCmds::MFX_PAK_INSERT_OBJECT_CMD::dwSize + ((byteSize + 3) >> 2);
cmd.DW0.DwordLength = OP_LENGTH(dwordsUsed);
cmd.DW1.BitstreamstartresetResetbitstreamstartingpos = 0;
cmd.DW1.EndofsliceflagLastdstdatainsertcommandflag = 0;
cmd.DW1.LastheaderflagLastsrcheaderdatainsertcommandflag = 1;
cmd.DW1.EmulationflagEmulationbytebitsinsertenable = 0;
cmd.DW1.SkipemulbytecntSkipEmulationByteCount = 0;
cmd.DW1.DatabitsinlastdwSrcdataendingbitinclusion50 = dataBitsInLastDw;
cmd.DW1.DatabyteoffsetSrcdatastartingbyteoffset10 = 0;
MOS_LOCK_PARAMS lockFlags;
MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
lockFlags.WriteOnly = 1;
uint8_t* data = (uint8_t*)m_osInterface->pfnLockResource(
m_osInterface,
brcPicHeaderInputBuffer,
&lockFlags);
MHW_MI_CHK_NULL(data);
eStatus = MOS_SecureMemcpy(data, TMfxCmds::MFX_PAK_INSERT_OBJECT_CMD::byteSize, &cmd, TMfxCmds::MFX_PAK_INSERT_OBJECT_CMD::byteSize);
if (eStatus != MOS_STATUS_SUCCESS)
{
MHW_ASSERTMESSAGE("Failed to copy memory.");
return eStatus;
}
// Use the exact data byte size to make sure that we don't overrun the bit buffer.
eStatus = MOS_SecureMemcpy(data + TMfxCmds::MFX_PAK_INSERT_OBJECT_CMD::byteSize, byteSize, params->pBsBuffer->pBase, byteSize);
if (eStatus != MOS_STATUS_SUCCESS)
{
MHW_ASSERTMESSAGE("Failed to copy memory.");
return eStatus;
}
// Need to make sure that the batch buffer end command begins on a dword boundary. So use
// a dword aligned data size in the offset calculation instead of the straight byte size.
// Note: The variable dwDwordsUsed already contains the size of the INSERT command.
typename TMiCmds::MI_BATCH_BUFFER_END_CMD cmdMiBatchBufferEnd;
eStatus = MOS_SecureMemcpy(data + sizeof(uint32_t)*dwordsUsed,
sizeof(cmdMiBatchBufferEnd),
&cmdMiBatchBufferEnd,
cmdMiBatchBufferEnd.byteSize);
if (eStatus != MOS_STATUS_SUCCESS)
{
MHW_ASSERTMESSAGE("Failed to copy memory.");
return eStatus;
}
MHW_MI_CHK_STATUS(m_osInterface->pfnUnlockResource(m_osInterface, brcPicHeaderInputBuffer));
*(params->pdwMpeg2PicHeaderTotalBufferSize) = sizeof(uint32_t)* dwordsUsed +
cmdMiBatchBufferEnd.byteSize;
*(params->pdwMpeg2PicHeaderDataStartOffset) = TMfxCmds::MFX_PAK_INSERT_OBJECT_CMD::byteSize;
return eStatus;
}
MOS_STATUS AddMfxMpeg2PicBrcBuffer(
PMOS_RESOURCE brcImgBuffer,
PMHW_VDBOX_MPEG2_PIC_STATE params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(brcImgBuffer);
MHW_MI_CHK_NULL(params);
MOS_LOCK_PARAMS lockFlags;
MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
lockFlags.WriteOnly = 1;
uint8_t *data = (uint8_t*)m_osInterface->pfnLockResource(m_osInterface, brcImgBuffer, &lockFlags);
MHW_MI_CHK_NULL(data);
MOS_COMMAND_BUFFER constructedCmdBuf;
constructedCmdBuf.pCmdBase = (uint32_t *)data;
constructedCmdBuf.pCmdPtr = (uint32_t *)data;
constructedCmdBuf.iOffset = 0;
constructedCmdBuf.iRemaining = BRC_IMG_STATE_SIZE_PER_PASS * m_numBrcPakPasses;
MHW_MI_CHK_STATUS(AddMfxMpeg2PicCmd(&constructedCmdBuf, params));
typename TMfxCmds::MFX_MPEG2_PIC_STATE_CMD cmd = *(typename TMfxCmds::MFX_MPEG2_PIC_STATE_CMD *)data;
for (uint32_t i = 0; i < m_numBrcPakPasses; i++)
{
cmd.DW5.Framebitratemaxreportmask = 1;
cmd.DW5.Framebitrateminreportmask = 1;
if (i == 0)
{
cmd.DW4.Mbstatenabled = 0; // Disable for first PAK pass
cmd.DW5.Mbratecontrolmask = 0;
cmd.DW5.Framesizecontrolmask = 0; // Disable first for PAK pass
}
else
{
cmd.DW4.Mbstatenabled = 1; // Disable for first PAK pass
cmd.DW5.Mbratecontrolmask = 1;
cmd.DW5.Framesizecontrolmask = 1;
}
cmd.DW8.Value = m_mpeg2SliceDeltaQPMax[i];
cmd.DW9.Value = m_mpeg2InitSliceDeltaQPMin[i];
cmd.DW10.Value = m_mpeg2FrameBitrateMinMax[i];
cmd.DW11.Value = m_mpeg2FrameBitrateMinMaxDelta[i];
*(typename TMfxCmds::MFX_MPEG2_PIC_STATE_CMD *)data = cmd;
data += BRC_IMG_STATE_SIZE_PER_PASS;
}
return eStatus;
}
MOS_STATUS AddMfxVc1PredPipeCmd(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_VDBOX_VC1_PRED_PIPE_PARAMS params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(cmdBuffer);
MHW_MI_CHK_NULL(params);
MHW_MI_CHK_NULL(params->pVc1PicParams);
auto vc1PicParams = params->pVc1PicParams;
auto destParams = params->ppVc1RefList[vc1PicParams->CurrPic.FrameIdx];
auto fwdRefParams = params->ppVc1RefList[vc1PicParams->ForwardRefIdx];
auto bwdRefParams = params->ppVc1RefList[vc1PicParams->BackwardRefIdx];
bool isPPicture = IsVc1PPicture(
vc1PicParams->CurrPic,
vc1PicParams->picture_fields.is_first_field,
vc1PicParams->picture_fields.picture_type);
bool isBPicture = IsVc1BPicture(
vc1PicParams->CurrPic,
vc1PicParams->picture_fields.is_first_field,
vc1PicParams->picture_fields.picture_type);
bool isSecondField = !vc1PicParams->picture_fields.is_first_field;
RefBoundaryReplicationMode refBoundaryReplicationMode;
refBoundaryReplicationMode.BY0.value = 0;
if (isPPicture || isBPicture)
{
if (fwdRefParams->dwRefSurfaceFlags & CODECHAL_VC1_PROGRESSIVE)
{
if (!vc1PicParams->picture_fields.is_first_field)
{
if (vc1PicParams->picture_fields.top_field_first)
{
refBoundaryReplicationMode.BY0.ref0 = vc1InterlacedBoundary;
refBoundaryReplicationMode.BY0.ref2 = vc1ProgressiveBoundary;
}
else
{
refBoundaryReplicationMode.BY0.ref2 = vc1InterlacedBoundary;
refBoundaryReplicationMode.BY0.ref0 = vc1ProgressiveBoundary;
}
}
else
{
refBoundaryReplicationMode.BY0.ref0 = vc1ProgressiveBoundary;
refBoundaryReplicationMode.BY0.ref2 = vc1ProgressiveBoundary;
}
}
else
{
refBoundaryReplicationMode.BY0.ref0 = refBoundaryReplicationMode.BY0.ref2 = vc1InterlacedBoundary;
}
}
if (isBPicture)
{
if (bwdRefParams->dwRefSurfaceFlags & CODECHAL_VC1_PROGRESSIVE)
{
refBoundaryReplicationMode.BY0.ref1 = refBoundaryReplicationMode.BY0.ref3 = vc1ProgressiveBoundary;
}
else
{
refBoundaryReplicationMode.BY0.ref1 = refBoundaryReplicationMode.BY0.ref3 = vc1InterlacedBoundary;
}
}
typename TMfxCmds::MFX_VC1_PRED_PIPE_STATE_CMD cmd;
cmd.DW1.ReferenceFrameBoundaryReplicationMode = refBoundaryReplicationMode.BY0.value;
uint32_t fwdDoubleIcEnable = 0, fwdSingleIcEnable = 0;
uint32_t bwdDoubleIcEnable = 0, bwdSingleIcEnable = 0;
uint8_t icField = 0;
// Interlaced Frame & Frame
if (!CodecHal_PictureIsField(vc1PicParams->CurrPic))
{
if (isPPicture)
{
if (vc1PicParams->picture_fields.intensity_compensation)
{
if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP))
{
fwdDoubleIcEnable = TOP_FIELD;
cmd.DW3.Lumscale1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
cmd.DW3.Lumshift1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
// IC values for the bottom out of bound pixels (replicated lines of the last
// line of top field)
cmd.DW3.Lumscale2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
cmd.DW3.Lumshift2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
MOS_BIT_ON(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP_2);
icField++;
}
else if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP))
{
fwdDoubleIcEnable = BOTTOM_FIELD;
// IC values for the top out of bound pixels (replicated lines of the first
// line of bottom field)
cmd.DW3.Lumscale1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
cmd.DW3.Lumshift1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
cmd.DW3.Lumscale2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
cmd.DW3.Lumshift2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
MOS_BIT_ON(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP_2);
icField++;
}
uint16_t lumaScale = vc1PicParams->luma_scale;
uint16_t lumaShift = vc1PicParams->luma_shift;
MOS_BIT_ON(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_FRAME_COMP);
fwdSingleIcEnable = TOP_FIELD | BOTTOM_FIELD;
cmd.DW2.Lumscale1SingleFwd = lumaScale;
cmd.DW2.Lumshift1SingleFwd = lumaShift;
cmd.DW2.Lumscale2SingleFwd = lumaScale;
cmd.DW2.Lumshift2SingleFwd = lumaShift;
// Set double backward values for top and bottom out of bound pixels
bwdDoubleIcEnable = TOP_FIELD | BOTTOM_FIELD;
cmd.DW5.Lumscale1DoubleBwd = lumaScale;
cmd.DW5.Lumshift1DoubleBwd = lumaShift;
cmd.DW5.Lumscale2DoubleBwd = lumaScale;
cmd.DW5.Lumshift2DoubleBwd = lumaShift;
// Save IC
fwdRefParams->Vc1IcValues[icField].wICCScale1 =
fwdRefParams->Vc1IcValues[icField].wICCScale2 = lumaScale;
fwdRefParams->Vc1IcValues[icField].wICCShiftL1 =
fwdRefParams->Vc1IcValues[icField].wICCShiftL2 = lumaShift;
}
else
{
// special case for interlaced field references when no IC is indicated
if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP))
{
cmd.DW2.Lumscale1SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
cmd.DW2.Lumshift1SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
fwdSingleIcEnable = TOP_FIELD;
icField++;
}
if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP))
{
cmd.DW2.Lumscale2SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
cmd.DW2.Lumshift2SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
fwdSingleIcEnable |= BOTTOM_FIELD;
icField++;
}
}
}
else if (isBPicture)
{
// Forward reference IC
if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP_2))
{
fwdDoubleIcEnable = TOP_FIELD;
cmd.DW3.Lumscale1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
cmd.DW3.Lumshift1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
// IC values for the bottom out of bound pixels (replicated lines of the last
// line of top field)
cmd.DW3.Lumscale2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
cmd.DW3.Lumshift2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
}
if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP_2))
{
fwdDoubleIcEnable |= BOTTOM_FIELD;
// IC values for the top out of bound pixels (replicated lines of the first
// line of bottom field)
cmd.DW3.Lumscale1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
cmd.DW3.Lumshift1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
cmd.DW3.Lumscale2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
cmd.DW3.Lumshift2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
}
if (fwdDoubleIcEnable)
{
icField++;
}
if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP))
{
fwdSingleIcEnable = TOP_FIELD;
cmd.DW2.Lumscale1SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
cmd.DW2.Lumshift1SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
}
if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP))
{
fwdSingleIcEnable |= BOTTOM_FIELD;
cmd.DW2.Lumscale2SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
cmd.DW2.Lumshift2SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
}
// If the reference picture is interlaced field, set double backward values for top
// and bottom out of bound pixels
if (fwdSingleIcEnable == (TOP_FIELD | BOTTOM_FIELD))
{
bwdDoubleIcEnable = TOP_FIELD | BOTTOM_FIELD;
cmd.DW5.Lumscale1DoubleBwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
cmd.DW5.Lumshift1DoubleBwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
cmd.DW5.Lumscale2DoubleBwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
cmd.DW5.Lumshift2DoubleBwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
}
// Backward reference IC
icField = 0;
if (MOS_IS_BIT_SET(bwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP))
{
bwdSingleIcEnable = TOP_FIELD;
cmd.DW4.Lumscale1SingleBwd = bwdRefParams->Vc1IcValues[icField].wICCScale1;
cmd.DW4.Lumshift1SingleBwd = bwdRefParams->Vc1IcValues[icField].wICCShiftL1;
}
else if (MOS_IS_BIT_SET(bwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP))
{
bwdSingleIcEnable = BOTTOM_FIELD;
cmd.DW4.Lumscale2SingleBwd = bwdRefParams->Vc1IcValues[icField].wICCScale2;
cmd.DW4.Lumshift2SingleBwd = bwdRefParams->Vc1IcValues[icField].wICCShiftL2;
}
}
}
// Interlace field
else
{
if (isPPicture)
{
fwdSingleIcEnable =
vc1PicParams->picture_fields.intensity_compensation ? (TOP_FIELD | BOTTOM_FIELD) : 0;
// Top field IC
uint16_t lumaScale = vc1PicParams->luma_scale >> 8;
uint16_t lumaShift = vc1PicParams->luma_shift >> 8;
if (CodecHal_PictureIsBottomField(vc1PicParams->CurrPic) && isSecondField)
{
fwdRefParams = destParams;
}
if (((lumaScale == 32) && (lumaShift == 0)) || !(fwdSingleIcEnable & TOP_FIELD))
{
// No IC for top field
if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP))
{
cmd.DW2.Lumscale1SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
cmd.DW2.Lumshift1SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
fwdSingleIcEnable |= TOP_FIELD;
}
else
{
fwdSingleIcEnable &= BOTTOM_FIELD;
}
}
else
{
// IC for top field is enabled
cmd.DW2.Lumscale1SingleFwd = lumaScale;
cmd.DW2.Lumshift1SingleFwd = lumaShift;
if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP))
{
fwdDoubleIcEnable = TOP_FIELD;
cmd.DW3.Lumscale1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
cmd.DW3.Lumshift1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
MOS_BIT_ON(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP_2);
icField++;
}
else
{
MOS_BIT_ON(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP);
}
// set double backward values for top out of bound pixels
if (vc1PicParams->picture_fields.intensity_compensation)
{
bwdDoubleIcEnable = TOP_FIELD;
// If the reference picture is not interlaced field and current picture is bottom field
// and second field, double backwards values are identical to the the single forward
// values used by the p interlaced field top field
if (!CodecHal_PictureIsField((params->ppVc1RefList[vc1PicParams->ForwardRefIdx])->RefPic) &&
(CodecHal_PictureIsBottomField(vc1PicParams->CurrPic) && isSecondField))
{
cmd.DW5.Lumscale1DoubleBwd =
(params->ppVc1RefList[vc1PicParams->ForwardRefIdx])->Vc1IcValues[icField].wICCScale1;
cmd.DW5.Lumshift1DoubleBwd =
(params->ppVc1RefList[vc1PicParams->ForwardRefIdx])->Vc1IcValues[icField].wICCShiftL1;
}
else
{
cmd.DW5.Lumscale1DoubleBwd = lumaScale;
cmd.DW5.Lumshift1DoubleBwd = lumaShift;
}
}
// Save IC
fwdRefParams->Vc1IcValues[icField].wICCScale1 = lumaScale;
fwdRefParams->Vc1IcValues[icField].wICCShiftL1 = lumaShift;
}
// Bottom field IC
icField = 0;
lumaScale = vc1PicParams->luma_scale & 0x00ff;
lumaShift = vc1PicParams->luma_shift & 0x00ff;
if (CodecHal_PictureIsTopField(vc1PicParams->CurrPic) && isSecondField)
{
fwdRefParams = destParams;
}
else
{
fwdRefParams = params->ppVc1RefList[vc1PicParams->ForwardRefIdx];
}
if (((lumaScale == 32) && (lumaShift == 0)) || !(fwdSingleIcEnable & BOTTOM_FIELD))
{
// No IC for bottom field
if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP))
{
cmd.DW2.Lumscale2SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
cmd.DW2.Lumshift2SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
fwdSingleIcEnable |= BOTTOM_FIELD;
}
else
{
fwdSingleIcEnable &= TOP_FIELD;
}
}
else
{
// IC is on
cmd.DW2.Lumscale2SingleFwd = lumaScale;
cmd.DW2.Lumshift2SingleFwd = lumaShift;
if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP))
{
fwdDoubleIcEnable |= BOTTOM_FIELD;
cmd.DW3.Lumscale2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
cmd.DW3.Lumshift2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
MOS_BIT_ON(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP_2);
icField++;
}
else
{
MOS_BIT_ON(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP);
}
// set double backward values for bottom out of bound pixels
if (vc1PicParams->picture_fields.intensity_compensation)
{
bwdDoubleIcEnable |= BOTTOM_FIELD;
// If the reference picture is not interlaced field and current picture is top field and
// second field, double backwards values are identical to the the single forward values
// used by the p interlaced field bottom field
if (!CodecHal_PictureIsField((params->ppVc1RefList[vc1PicParams->ForwardRefIdx])->RefPic) &&
(CodecHal_PictureIsTopField(vc1PicParams->CurrPic) && isSecondField))
{
cmd.DW5.Lumscale2DoubleBwd =
(params->ppVc1RefList[vc1PicParams->ForwardRefIdx])->Vc1IcValues[icField].wICCScale2;
cmd.DW5.Lumshift2DoubleBwd =
(params->ppVc1RefList[vc1PicParams->ForwardRefIdx])->Vc1IcValues[icField].wICCShiftL2;
}
else
{
cmd.DW5.Lumscale2DoubleBwd = lumaScale;
cmd.DW5.Lumshift2DoubleBwd = lumaShift;
}
}
// Save IC
fwdRefParams->Vc1IcValues[icField].wICCScale2 = lumaScale;
fwdRefParams->Vc1IcValues[icField].wICCShiftL2 = lumaShift;
}
}
else if (isBPicture)
{
// Forward reference IC
if (CodecHal_PictureIsTopField(vc1PicParams->CurrPic) || !isSecondField)
{
if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP_2))
{
cmd.DW3.Lumscale1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
cmd.DW3.Lumshift1DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
fwdDoubleIcEnable = TOP_FIELD;
icField++;
}
if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP))
{
cmd.DW2.Lumscale1SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale1;
cmd.DW2.Lumshift1SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL1;
fwdSingleIcEnable = TOP_FIELD;
}
}
if ((vc1PicParams->CurrPic.PicFlags == PICTURE_BOTTOM_FIELD) || !isSecondField)
{
icField = 0;
if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP_2))
{
cmd.DW3.Lumscale2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
cmd.DW3.Lumshift2DoubleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
fwdDoubleIcEnable |= BOTTOM_FIELD;
icField++;
}
if (MOS_IS_BIT_SET(fwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP))
{
cmd.DW2.Lumscale2SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCScale2;
cmd.DW2.Lumshift2SingleFwd = fwdRefParams->Vc1IcValues[icField].wICCShiftL2;
fwdSingleIcEnable |= BOTTOM_FIELD;
}
}
// Backward reference IC
icField = 0;
if (MOS_IS_BIT_SET(bwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_TOP_FIELD_COMP))
{
cmd.DW4.Lumscale1SingleBwd = bwdRefParams->Vc1IcValues[icField].wICCScale1;
cmd.DW4.Lumshift1SingleBwd = bwdRefParams->Vc1IcValues[icField].wICCShiftL1;
bwdSingleIcEnable = TOP_FIELD;
}
if (MOS_IS_BIT_SET(bwdRefParams->dwRefSurfaceFlags, CODECHAL_VC1_BOT_FIELD_COMP))
{
cmd.DW4.Lumscale2SingleBwd = bwdRefParams->Vc1IcValues[icField].wICCScale2;
cmd.DW4.Lumshift2SingleBwd = bwdRefParams->Vc1IcValues[icField].wICCShiftL2;
bwdSingleIcEnable |= BOTTOM_FIELD;
}
}
}
cmd.DW1.VinIntensitycompDoubleFwden = fwdDoubleIcEnable;
cmd.DW1.VinIntensitycompDoubleBwden = bwdDoubleIcEnable;
cmd.DW1.VinIntensitycompSingleFwden = fwdSingleIcEnable;
cmd.DW1.VinIntensitycompSingleBwden = bwdSingleIcEnable;
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
MOS_STATUS AddMfxVc1LongPicCmd(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_VDBOX_VC1_PIC_STATE vc1PicState)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(cmdBuffer);
MHW_MI_CHK_NULL(vc1PicState);
MHW_MI_CHK_NULL(vc1PicState->pVc1PicParams);
auto vc1PicParams = vc1PicState->pVc1PicParams;
bool isFramePicture =
((vc1PicParams->CurrPic.PicFlags == PICTURE_FRAME) |
(vc1PicParams->CurrPic.PicFlags == PICTURE_INTERLACED_FRAME));
uint16_t widthInMbs = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(vc1PicParams->coded_width);
uint16_t heightInMbs = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(vc1PicParams->coded_height);
uint16_t frameFieldHeightInMb = 0;
CodecHal_GetFrameFieldHeightInMb(
vc1PicParams->CurrPic,
heightInMbs,
frameFieldHeightInMb);
bool isIPicture = IsVc1IPicture(
vc1PicParams->CurrPic,
vc1PicParams->picture_fields.is_first_field,
vc1PicParams->picture_fields.picture_type);
bool isPPicture = IsVc1PPicture(
vc1PicParams->CurrPic,
vc1PicParams->picture_fields.is_first_field,
vc1PicParams->picture_fields.picture_type);
bool isBPicture = IsVc1BPicture(
vc1PicParams->CurrPic,
vc1PicParams->picture_fields.is_first_field,
vc1PicParams->picture_fields.picture_type);
bool isBIPicture = IsVc1BIPicture(
vc1PicParams->CurrPic,
vc1PicParams->picture_fields.is_first_field,
vc1PicParams->picture_fields.picture_type);
auto destParams = vc1PicState->ppVc1RefList[vc1PicParams->CurrPic.FrameIdx];
auto fwdRefParams = vc1PicState->ppVc1RefList[vc1PicParams->ForwardRefIdx];
typename TMfxCmds::MFD_VC1_LONG_PIC_STATE_CMD cmd;
cmd.DW1.Picturewidthinmbsminus1PictureWidthMinus1InMacroblocks = widthInMbs - 1;
cmd.DW1.Pictureheightinmbsminus1PictureHeightMinus1InMacroblocks = frameFieldHeightInMb - 1;
cmd.DW2.Vc1Profile = vc1PicParams->sequence_fields.AdvancedProfileFlag;
cmd.DW2.Secondfield = !vc1PicParams->picture_fields.is_first_field;
cmd.DW2.OverlapSmoothingEnableFlag = vc1PicParams->sequence_fields.overlap;
cmd.DW2.LoopfilterEnableFlag = vc1PicParams->entrypoint_fields.loopfilter;
cmd.DW2.InterpolationRounderContro = vc1PicParams->rounding_control;
cmd.DW2.MotionVectorMode = (vc1PicParams->mv_fields.MvMode & 0x9);
// Simple and Main profile dynamic range adjustment
if ((!vc1PicParams->sequence_fields.AdvancedProfileFlag) && isPPicture)
{
if ((destParams->dwRefSurfaceFlags & CODECHAL_WMV9_RANGE_ADJUSTMENT) &&
!(fwdRefParams->dwRefSurfaceFlags & CODECHAL_WMV9_RANGE_ADJUSTMENT))
{
cmd.DW2.RangereductionEnable = 1;
cmd.DW2.Rangereductionscale = 0;
}
else if (!(destParams->dwRefSurfaceFlags & CODECHAL_WMV9_RANGE_ADJUSTMENT) &&
(fwdRefParams->dwRefSurfaceFlags & CODECHAL_WMV9_RANGE_ADJUSTMENT))
{
cmd.DW2.RangereductionEnable = 1;
cmd.DW2.Rangereductionscale = 1;
}
}
cmd.DW3.PquantPictureQuantizationValue = vc1PicParams->pic_quantizer_fields.pic_quantizer_scale;
if (vc1PicState->Mode == CODECHAL_DECODE_MODE_VC1IT)
{
if (isIPicture || isBIPicture)
{
cmd.DW3.PictypePictureType = vc1IFrame; // 0 = I or I/I
}
else if (isPPicture)
{
cmd.DW3.PictypePictureType = isFramePicture ? (uint32_t)vc1PFrame: (uint32_t)vc1PPField;
}
else if (isBPicture)
{
cmd.DW3.PictypePictureType = isFramePicture ? (uint32_t)vc1BFrame: (uint32_t)vc1BBField;
}
if (isFramePicture)
{
cmd.DW3.FcmFrameCodingMode = (vc1PicParams->CurrPic.PicFlags == PICTURE_INTERLACED_FRAME);
}
else
{
cmd.DW3.FcmFrameCodingMode = (vc1PicParams->picture_fields.top_field_first) ? vc1TffFrame : vc1BffFrame;
}
cmd.DW4.FastuvmcflagFastUvMotionCompensationFlag = (vc1PicParams->mv_fields.MvMode & 0x1);
cmd.DW4.Pquantuniform = 1; // uniform
cmd.DW2.Implicitquantizer = 1; // implicit
}
else // CODECHAL_DECODE_MODE_VC1VLD
{
cmd.DW2.Syncmarker = vc1PicParams->sequence_fields.syncmarker;
cmd.DW2.Implicitquantizer = (vc1PicParams->pic_quantizer_fields.quantizer == vc1QuantizerImplicit);
if (isBPicture &&
(CodecHal_PictureIsBottomField(vc1PicParams->CurrPic) ?
vc1PicState->bPrevOddAnchorPictureIsP : vc1PicState->bPrevEvenAnchorPictureIsP)) // OR if I not before B in decoding order
{
cmd.DW2.Dmvsurfacevalid = true;
}
if (vc1PicParams->raw_coding.bitplane_present)
{
cmd.DW2.BitplaneBufferPitchMinus1 = (widthInMbs - 1) >> 1;
}
cmd.DW3.Bscalefactor = vc1PicParams->ScaleFactor;
cmd.DW3.AltpquantAlternativePictureQuantizationValue = vc1PicParams->pic_quantizer_fields.alt_pic_quantizer;
cmd.DW3.FcmFrameCodingMode = vc1PicParams->picture_fields.frame_coding_mode;
cmd.DW3.PictypePictureType = vc1PicParams->picture_fields.picture_type;
cmd.DW3.Condover = vc1PicParams->conditional_overlap_flag;
cmd.DW4.Pquantuniform = vc1PicParams->pic_quantizer_fields.pic_quantizer_type;
cmd.DW4.Halfqp = vc1PicParams->pic_quantizer_fields.half_qp;
cmd.DW4.AltpquantconfigAlternativePictureQuantizationConfiguration = vc1PicParams->pic_quantizer_fields.AltPQuantConfig;
cmd.DW4.AltpquantedgemaskAlternativePictureQuantizationEdgeMask = vc1PicParams->pic_quantizer_fields.AltPQuantEdgeMask;
// AltPQuant parameters must be set to 0 for I or BI pictures in simple/main profile
if (!vc1PicParams->sequence_fields.AdvancedProfileFlag && (isIPicture || isBIPicture))
{
cmd.DW4.AltpquantconfigAlternativePictureQuantizationConfiguration = 0;
cmd.DW4.AltpquantedgemaskAlternativePictureQuantizationEdgeMask = 0;
cmd.DW3.AltpquantAlternativePictureQuantizationValue = 0;
}
cmd.DW4.ExtendedmvrangeExtendedMotionVectorRangeFlag = vc1PicParams->mv_fields.extended_mv_range;
cmd.DW4.ExtendeddmvrangeExtendedDifferentialMotionVectorRangeFlag = vc1PicParams->mv_fields.extended_dmv_range;
cmd.DW4.FwdrefdistReferenceDistance = vc1PicParams->reference_fields.reference_distance;
cmd.DW4.BwdrefdistReferenceDistance = vc1PicParams->reference_fields.BwdReferenceDistance;
if (!isFramePicture && isBPicture)
{
// For B field pictures, NumberOfReferencePictures is always 2 (i.e. set to 1).
cmd.DW4.NumrefNumberOfReferences = 1;
}
else
{
cmd.DW4.NumrefNumberOfReferences = vc1PicParams->reference_fields.num_reference_pictures;
}
if (isPPicture &&
CodecHal_PictureIsField(vc1PicParams->CurrPic) &&
(cmd.DW4.NumrefNumberOfReferences == 0))
{
// Derive polarity of the reference field: Top = 0, Bottom = 1
if (vc1PicParams->reference_fields.reference_field_pic_indicator == 0)
{
// Temporally closest reference
if (vc1PicParams->picture_fields.is_first_field)
{
// Reference frame
cmd.DW4.ReffieldpicpolarityReferenceFieldPicturePolarity = vc1PicState->wPrevAnchorPictureTFF;
}
else
{
// Same frame
cmd.DW4.ReffieldpicpolarityReferenceFieldPicturePolarity = !vc1PicParams->picture_fields.top_field_first;
}
}
else
{
// Second most temporally closest reference
if (vc1PicParams->picture_fields.is_first_field)
{
// First field of reference frame
cmd.DW4.ReffieldpicpolarityReferenceFieldPicturePolarity = !vc1PicState->wPrevAnchorPictureTFF;
}
else
{
// Second field of reference frame
cmd.DW4.ReffieldpicpolarityReferenceFieldPicturePolarity = vc1PicState->wPrevAnchorPictureTFF;
}
}
}
cmd.DW4.FastuvmcflagFastUvMotionCompensationFlag = vc1PicParams->fast_uvmc_flag;
cmd.DW4.FourmvswitchFourMotionVectorSwitch = vc1PicParams->mv_fields.four_mv_switch;
cmd.DW4.UnifiedmvmodeUnifiedMotionVectorMode = vc1PicParams->mv_fields.UnifiedMvMode;
// If bitplane is present (BitplanePresentFlag == 1) update the "raw" bitplane
// flags. If bitplane is not present leave all "raw" flags to their initialized
// value which is all bitplanes are present "raw".
cmd.DW5.BitplanepresentflagBitplaneBufferPresentFlag = vc1PicParams->raw_coding.bitplane_present;
cmd.DW5.Fieldtxraw = vc1RawMode;
cmd.DW5.Acpredraw = vc1RawMode;
cmd.DW5.Overflagsraw = vc1RawMode;
cmd.DW5.Directmbraw = vc1RawMode;
cmd.DW5.Skipmbraw = vc1RawMode;
cmd.DW5.Mvtypembraw = vc1RawMode;
cmd.DW5.Forwardmbraw = vc1RawMode;
if (vc1PicParams->raw_coding.bitplane_present)
{
cmd.DW5.Fieldtxraw = vc1PicParams->raw_coding.field_tx;
cmd.DW5.Acpredraw = vc1PicParams->raw_coding.ac_pred;
cmd.DW5.Overflagsraw = vc1PicParams->raw_coding.overflags;
cmd.DW5.Directmbraw = vc1PicParams->raw_coding.direct_mb;
cmd.DW5.Skipmbraw = vc1PicParams->raw_coding.skip_mb;
cmd.DW5.Mvtypembraw = vc1PicParams->raw_coding.mv_type_mb;
cmd.DW5.Forwardmbraw = vc1PicParams->raw_coding.forward_mb;
}
cmd.DW5.CbptabCodedBlockPatternTable = vc1PicParams->cbp_table;
cmd.DW5.TransdctabIntraTransformDcTable = vc1PicParams->transform_fields.intra_transform_dc_table;
cmd.DW5.TransacuvPictureLevelTransformChromaAcCodingSetIndexTransactable = vc1PicParams->transform_fields.transform_ac_codingset_idx1;
cmd.DW5.TransacyPictureLevelTransformLumaAcCodingSetIndexTransactable2 = (isIPicture || isBIPicture) ?
vc1PicParams->transform_fields.transform_ac_codingset_idx2 : cmd.DW5.TransacuvPictureLevelTransformChromaAcCodingSetIndexTransactable;
cmd.DW5.MbmodetabMacroblockModeTable = vc1PicParams->mb_mode_table;
if (vc1PicParams->transform_fields.variable_sized_transform_flag == 0)
{
// H/W decodes TTMB, TTBLK and SUBBLKPAT if the picture level TTMBF flag is not set.
// If the VSTRANSFORM is 0, 8x8 TransformType is used for all the pictures belonging to this Entry-Point.
// Hence H/W overloads the TTMBF = 1 and TTFRM = 8x8 in this case.
cmd.DW5.TranstypembflagMacroblockTransformTypeFlag = 1;
cmd.DW5.TranstypePictureLevelTransformType = 0;
}
else
{
cmd.DW5.TranstypembflagMacroblockTransformTypeFlag = vc1PicParams->transform_fields.mb_level_transform_type_flag;
cmd.DW5.TranstypePictureLevelTransformType = vc1PicParams->transform_fields.frame_level_transform_type;
}
cmd.DW5.Twomvbptab2MvBlockPatternTable = vc1PicParams->mv_fields.two_mv_block_pattern_table;
cmd.DW5.Fourmvbptab4MvBlockPatternTable = vc1PicParams->mv_fields.four_mv_block_pattern_table;
cmd.DW5.MvtabMotionVectorTable = vc1PicParams->mv_fields.mv_table;
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
MOS_STATUS AddMfdVc1ShortPicCmd(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_VDBOX_VC1_PIC_STATE vc1PicState)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(cmdBuffer);
MHW_MI_CHK_NULL(vc1PicState);
MHW_MI_CHK_NULL(vc1PicState->pVc1PicParams);
auto vc1PicParams = vc1PicState->pVc1PicParams;
uint16_t widthInMbs = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(vc1PicParams->coded_width);
uint16_t heightInMbs = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(vc1PicParams->coded_height);
uint16_t frameFieldHeightInMb = 0;
CodecHal_GetFrameFieldHeightInMb(
vc1PicParams->CurrPic,
heightInMbs,
frameFieldHeightInMb);
bool isIPicture = IsVc1IPicture(
vc1PicParams->CurrPic,
vc1PicParams->picture_fields.is_first_field,
vc1PicParams->picture_fields.picture_type);
bool isPPicture = IsVc1PPicture(
vc1PicParams->CurrPic,
vc1PicParams->picture_fields.is_first_field,
vc1PicParams->picture_fields.picture_type);
bool isBPicture = IsVc1BPicture(
vc1PicParams->CurrPic,
vc1PicParams->picture_fields.is_first_field,
vc1PicParams->picture_fields.picture_type);
bool isBIPicture = IsVc1BIPicture(
vc1PicParams->CurrPic,
vc1PicParams->picture_fields.is_first_field,
vc1PicParams->picture_fields.picture_type);
typename TMfxCmds::MFD_VC1_SHORT_PIC_STATE_CMD cmd;
// DW 1
cmd.DW1.PictureWidth = widthInMbs - 1;
cmd.DW1.PictureHeight = frameFieldHeightInMb - 1;
// DW 2
cmd.DW2.PictureStructure =
(CodecHal_PictureIsTopField(vc1PicParams->CurrPic)) ?
mpeg2Vc1TopField : (CodecHal_PictureIsBottomField(vc1PicParams->CurrPic)) ?
mpeg2Vc1BottomField : mpeg2Vc1Frame;
cmd.DW2.Secondfield = !vc1PicParams->picture_fields.is_first_field;
cmd.DW2.IntraPictureFlag = isIPicture || isBIPicture;
cmd.DW2.BackwardPredictionPresentFlag = isBPicture;
cmd.DW2.Vc1Profile = vc1PicParams->sequence_fields.AdvancedProfileFlag;
if (isBPicture &&
(CodecHal_PictureIsBottomField(vc1PicParams->CurrPic) ?
vc1PicState->bPrevOddAnchorPictureIsP : vc1PicState->bPrevEvenAnchorPictureIsP)) // OR if I not before B in decoding order
{
cmd.DW2.Dmvsurfacevalid = true;
}
cmd.DW2.MotionVectorMode = vc1PicParams->mv_fields.MvMode & 0x9;
cmd.DW2.InterpolationRounderControl = vc1PicParams->rounding_control;
cmd.DW2.BitplaneBufferPitchMinus1 = (vc1PicParams->coded_width <= 2048) ?
(MHW_VDBOX_VC1_BITPLANE_BUFFER_PITCH_SMALL - 1) : (MHW_VDBOX_VC1_BITPLANE_BUFFER_PITCH_LARGE - 1);
// DW 3
cmd.DW3.VstransformFlag = vc1PicParams->transform_fields.variable_sized_transform_flag;
cmd.DW3.Dquant = vc1PicParams->pic_quantizer_fields.dquant;
cmd.DW3.ExtendedMvPresentFlag = vc1PicParams->mv_fields.extended_mv_flag;
cmd.DW3.FastuvmcflagFastUvMotionCompensationFlag = vc1PicParams->fast_uvmc_flag;
cmd.DW3.LoopfilterEnableFlag = vc1PicParams->entrypoint_fields.loopfilter;
cmd.DW3.RefdistFlag = (vc1PicParams->sequence_fields.AdvancedProfileFlag) ?
vc1PicParams->reference_fields.reference_distance_flag : 1;
cmd.DW3.PanscanPresentFlag = vc1PicParams->entrypoint_fields.panscan_flag;
cmd.DW3.Maxbframes = vc1PicParams->sequence_fields.max_b_frames;
cmd.DW3.RangeredPresentFlagForSimpleMainProfileOnly = vc1PicParams->sequence_fields.rangered;
cmd.DW3.SyncmarkerPresentFlagForSimpleMainProfileOnly = vc1PicParams->sequence_fields.syncmarker;
cmd.DW3.MultiresPresentFlagForSimpleMainProfileOnly = vc1PicParams->sequence_fields.multires;
cmd.DW3.Quantizer = vc1PicParams->pic_quantizer_fields.quantizer;
cmd.DW3.PPicRefDistance = vc1PicParams->reference_fields.reference_distance;
cmd.DW3.ProgressivePicType = (CodecHal_PictureIsFrame(vc1PicParams->CurrPic)) ? 1 : 2;
// Dynamic range adjustment disabled
cmd.DW3.RangeReductionEnable = 0;
cmd.DW3.RangeReductionScale = 1;
if (vc1PicParams->sequence_fields.AdvancedProfileFlag)
{
cmd.DW3.OverlapSmoothingEnableFlag = vc1PicParams->sequence_fields.overlap;
}
else
{
cmd.DW3.OverlapSmoothingEnableFlag = 1;
if (isBPicture || (vc1PicParams->pic_quantizer_fields.pic_quantizer_scale < 9) || !vc1PicParams->sequence_fields.overlap)
{
cmd.DW3.OverlapSmoothingEnableFlag = 0;
}
}
// DW 4
cmd.DW4.ExtendedDmvPresentFlag = vc1PicParams->mv_fields.extended_dmv_flag;
cmd.DW4.Psf = vc1PicParams->sequence_fields.psf;
cmd.DW4.Finterflag = vc1PicParams->sequence_fields.finterpflag;
cmd.DW4.Tfcntrflag = vc1PicParams->sequence_fields.tfcntrflag;
cmd.DW4.Interlace = vc1PicParams->sequence_fields.interlace;
cmd.DW4.Pulldown = vc1PicParams->sequence_fields.pulldown;
cmd.DW4.PostprocFlag = vc1PicParams->post_processing;
if (isPPicture || (isBPicture && vc1PicParams->sequence_fields.interlace))
{
cmd.DW4._4MvAllowedFlag = vc1PicParams->mv_fields.four_mv_allowed;
}
cmd.DW4.RefpicFlag = vc1PicParams->reference_fields.reference_picture_flag;
if (isBPicture)
{
cmd.DW4.BfractionEnumeration = vc1PicParams->b_picture_fraction;
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
MOS_STATUS AddMfxVc1DirectmodeCmd(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_VDBOX_VC1_DIRECTMODE_PARAMS params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(cmdBuffer);
MHW_MI_CHK_NULL(params);
typename TMfxCmds::MFX_VC1_DIRECTMODE_STATE_CMD cmd;
MHW_RESOURCE_PARAMS resourceParams;
MOS_ZeroMemory(&resourceParams, sizeof(resourceParams));
resourceParams.dwLsbNum = MHW_VDBOX_MFX_GENERAL_STATE_SHIFT;
resourceParams.HwCommandType = MOS_MFX_VC1_DIRECT_MODE;
cmd.DW3.MemoryObjectControlState =
m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_DIRECTMV_BUFFER_CODEC].Value;
resourceParams.presResource = params->presDmvWriteBuffer;
resourceParams.dwOffset = 0;
resourceParams.pdwCmd = &(cmd.DW1.Value);
resourceParams.dwLocationInCmd = 1;
resourceParams.bIsWritable = true;
MHW_MI_CHK_STATUS(AddResourceToCmd(
m_osInterface,
cmdBuffer,
&resourceParams));
cmd.DW6.MemoryObjectControlState =
m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_DIRECTMV_BUFFER_CODEC].Value;
resourceParams.presResource = params->presDmvReadBuffer;
resourceParams.dwOffset = 0;
resourceParams.pdwCmd = &(cmd.DW4.Value);
resourceParams.dwLocationInCmd = 4;
resourceParams.bIsWritable = false;
MHW_MI_CHK_STATUS(AddResourceToCmd(
m_osInterface,
cmdBuffer,
&resourceParams));
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
MOS_STATUS AddMfdVc1BsdObjectCmd(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_VDBOX_VC1_SLICE_STATE vc1SliceState)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(cmdBuffer);
MHW_MI_CHK_NULL(vc1SliceState);
MHW_MI_CHK_NULL(vc1SliceState->pSlc);
typename TMfxCmds::MFD_VC1_BSD_OBJECT_CMD cmd;
auto slcParams = vc1SliceState->pSlc;
cmd.DW1.IndirectBsdDataLength = vc1SliceState->dwLength;
cmd.DW2.IndirectDataStartAddress = slcParams->slice_data_offset + vc1SliceState->dwOffset; // byte aligned
cmd.DW3.SliceStartVerticalPosition = slcParams->slice_vertical_position;
cmd.DW3.NextSliceVerticalPosition = vc1SliceState->dwNextVerticalPosition;
cmd.DW4.FirstMbByteOffsetOfSliceDataOrSliceHeader = (slcParams->macroblock_offset >> 3) - vc1SliceState->dwOffset;
cmd.DW4.FirstmbbitoffsetFirstMacroblockBitOffset = slcParams->macroblock_offset & 0x7; // bit offset
MHW_CP_SLICE_INFO_PARAMS sliceInfoParam;
sliceInfoParam.presDataBuffer = vc1SliceState->presDataBuffer;
sliceInfoParam.dwDataStartOffset[0] = cmd.DW2.IndirectDataStartAddress;
MHW_MI_CHK_STATUS(m_cpInterface->SetMfxProtectionState(
m_decodeInUse,
cmdBuffer,
nullptr,
&sliceInfoParam));
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
//!
//! \struct MFD_VC1_IT_OBJECT_CMD
//! \brief MFD VC1 it object command
//!
struct MFD_VC1_IT_OBJECT_CMD
{
typename TMfxCmds::MFD_IT_OBJECT_CMD m_header;
typename TMfxCmds::MFD_IT_OBJECT_VC1_INLINE_DATA_CMD m_inlineData;
};
//!
//! \brief Get VC1 intra flag
//!
//! \param [in] mbState
//! Pointer to MHW vdbox VC1 mb state
//! \param [in] mbParams
//! Pointer to codec VC1 mb parameters
//!
//! \return uint8_t
//! VC1 intra flag
//!
uint8_t GetVc1IntraFlag(PMHW_VDBOX_VC1_MB_STATE mbState, PCODEC_VC1_MB_PARAMS mbParams)
{
const uint8_t PATTERN_CODE_INTRA_MB = 0xF;
uint8_t intra8x8Flag = 0;
if(mbState == nullptr || mbParams == nullptr)
{
MHW_ASSERTMESSAGE("mbState or mbParams is nullptr!");
return 0;
}
if (mbParams->mb_type.intra_mb)
{
intra8x8Flag = PATTERN_CODE_INTRA_MB;
}
else if (mbParams->mb_type.motion_4mv && (mbState->PicFlags == PICTURE_FRAME))
{
intra8x8Flag = mbParams->pattern_code.block_luma_intra;
}
else
{
intra8x8Flag = 0;
}
return intra8x8Flag;
}
#define GET_VC1_BLOCK(mb, i) ((mb >> (3 - i)) & 1)
//!
//! \brief VC1 it object set overlap smoothing filter
//!
//! \param [in] inlineDataVc1
//! MFD it object VC1 inline data command
//! \param [in] mbState
//! Pointer to MHW vdbox VC1 mb state
//! \param [in] mbParams
//! Pointer to codec VC1 mb parameters
//! \param [in] mbHorizOrigin
//! Mb horizontal origin
//! \param [in] mbVertOrigin
//! Mb vertical origin
//!
MOS_STATUS Vc1ItObjectSetOverlapSmoothingFilter(
typename TMfxCmds::MFD_IT_OBJECT_VC1_INLINE_DATA_CMD *inlineDataVc1,
PMHW_VDBOX_VC1_MB_STATE mbState,
PCODEC_VC1_MB_PARAMS mbParams,
uint8_t mbHorizOrigin,
uint8_t mbVertOrigin)
{
static const uint8_t chromaIntra[16] =
{
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1
};
MHW_CHK_NULL_RETURN(inlineDataVc1);
MHW_CHK_NULL_RETURN(mbState);
MHW_CHK_NULL_RETURN(mbParams);
auto vc1PicParams = mbState->pVc1PicParams;
MHW_CHK_NULL_RETURN(vc1PicParams);
//------------------------------------
// Overlap smoothing enabled for this mb?
//------------------------------------
uint8_t mbOverlapSmoothing = mbParams->mb_type.h261_loopfilter;
inlineDataVc1->DW0.Overlaptransform = mbOverlapSmoothing;
// Horizontal origin is last mb of the row
inlineDataVc1->DW0.Lastmbinrow = (mbHorizOrigin == (mbState->wPicWidthInMb - 1));
// Vertical origin is last mb of the column
inlineDataVc1->DW0.LastRowFlag = (mbVertOrigin == (mbState->wPicHeightInMb - 1));
if (mbOverlapSmoothing)
{
uint8_t intra8x8 = GetVc1IntraFlag(mbState, mbParams);
if ((vc1PicParams->picture_fields.picture_type == vc1BBField) || !intra8x8)
{
// Reset parameters
inlineDataVc1->DW0.Overlaptransform = 0;
inlineDataVc1->DW1.Osedgemaskluma = 0;
inlineDataVc1->DW1.Osedgemaskchroma = 0;
return MOS_STATUS_SUCCESS;
}
//------------------------------------
// Set edge control bitmasks (luma & chroma)
//------------------------------------
// Overlap smoothing applied to an edge when
// 1. Edge between two 8x8 luma regions or corresponding 4x4
// chroma regions of the same mb for which the H261loopFilter
// flag is equal to 1
// 2. Edge between 8x8 luma regions or corresponding 4x4 chroma
// regions in different MBs for which both are true:
// a. H261loopFilter flag is equal to 1 in both macroblocks, and
// b. Edge is a vertical edge between horizontally-neighboring macroblocks,
// OR is a horizontal edge between vertically-neighboring macroblocks and
// ReservedBits flag (bit 11) is equal to 0 in the wMBtype element of the
// macroblock control command for the lower macroblock and the picture is not an
// interlaced frame (i.e., a picture with bPicStructure equal to '11' and
// bPicExtrapolation equal to 2).
// Condition 1: Top Y2, Top Y3, Left Y1, Left Y3
uint16_t edgeMaskLuma = 0, edgeMaskChroma = 0;
edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 0) & GET_VC1_BLOCK(intra8x8, 2)) << 2;
edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 1) & GET_VC1_BLOCK(intra8x8, 3)) << 3;
edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 0) & GET_VC1_BLOCK(intra8x8, 1)) << 5;
edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 2) & GET_VC1_BLOCK(intra8x8, 3)) << 7;
// Condition 2:
// Top Y0, Top Y1, Top Cb/Cr: horizontal edges
if (mbVertOrigin != 0)
{
// Not the top row, so get upper pMB
auto upperMbParams = mbParams - mbState->wPicWidthInMb;
if (upperMbParams &&
upperMbParams->mb_type.h261_loopfilter &&
!mbParams->mb_type.reserved &&
(mbState->PicFlags != PICTURE_INTERLACED_FRAME))
{
uint8_t adjIntra8x8 = GetVc1IntraFlag(mbState, upperMbParams);
edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 0) & GET_VC1_BLOCK(adjIntra8x8, 2));
edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 1) & GET_VC1_BLOCK(adjIntra8x8, 3)) << 1;
edgeMaskChroma |= (chromaIntra[intra8x8] & chromaIntra[adjIntra8x8]);
}
}
// Left Y0, Left Y2, Left Cb/Cr: vertical edges
if (mbHorizOrigin != 0)
{
// Not the first column, so get left pMB
auto leftMbParams = mbParams - 1;
if (leftMbParams &&
leftMbParams->mb_type.h261_loopfilter)
{
uint8_t adjIntra8x8 = GetVc1IntraFlag(mbState, leftMbParams);
edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 0) & GET_VC1_BLOCK(adjIntra8x8, 1)) << 4;
edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 2) & GET_VC1_BLOCK(adjIntra8x8, 3)) << 6;
edgeMaskChroma |= (chromaIntra[intra8x8] & chromaIntra[adjIntra8x8]) << 1;
}
}
// Right Y1, Right Y3, Right Cb/Cr: vertical edges
if (mbHorizOrigin != (mbState->wPicWidthInMb - 1))
{
// Not the last column, so get right pMB
auto rightMbParams = mbParams + 1;
if (rightMbParams &&
rightMbParams->mb_type.h261_loopfilter)
{
uint8_t adjIntra8x8 = GetVc1IntraFlag(mbState, rightMbParams);
edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 1) & GET_VC1_BLOCK(adjIntra8x8, 0)) << 8;
edgeMaskLuma |= (GET_VC1_BLOCK(intra8x8, 3) & GET_VC1_BLOCK(adjIntra8x8, 2)) << 9;
edgeMaskChroma |= (chromaIntra[intra8x8] & chromaIntra[adjIntra8x8]) << 2;
}
}
inlineDataVc1->DW1.Osedgemaskluma = edgeMaskLuma;
inlineDataVc1->DW1.Osedgemaskchroma = edgeMaskChroma;
}
else
{
// Reset parameters
inlineDataVc1->DW1.Osedgemaskluma = 0;
inlineDataVc1->DW1.Osedgemaskchroma = 0;
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS AddMfdVc1ItObjectCmd(
PMHW_BATCH_BUFFER batchBuffer,
PMHW_VDBOX_VC1_MB_STATE mbState)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(batchBuffer);
MHW_MI_CHK_NULL(mbState);
auto mbParams = mbState->pMb;
auto vc1PicParams = mbState->pVc1PicParams;
MFD_VC1_IT_OBJECT_CMD cmd;
typename TMfxCmds::MFD_IT_OBJECT_CMD *cmdMfdItObject = &cmd.m_header;
typename TMfxCmds::MFD_IT_OBJECT_VC1_INLINE_DATA_CMD *inlineDataVc1 = &cmd.m_inlineData;
inlineDataVc1->DW0.MacroblockIntraType = mpeg2Vc1MacroblockIntra;
cmdMfdItObject->DW0.DwordLength += TMfxCmds::MFD_IT_OBJECT_VC1_INLINE_DATA_CMD::dwSize;
if (mbState->bSkipped)
{
inlineDataVc1->DW0.DctType = mbParams->mb_type.field_residual;
if (vc1PicParams->picture_fields.picture_type != vc1IIField)
{
inlineDataVc1->DW0.MacroblockIntraType = mpeg2Vc1MacroblockNonintra;
inlineDataVc1->DW0.MacroblockMotionForward = mbParams->mb_type.motion_forward;
inlineDataVc1->DW0.MacroblockMotionBackward = mbParams->mb_type.motion_backward;
inlineDataVc1->DW0.MotionType = mbParams->mb_type.motion_type;
inlineDataVc1->DW0.MotionVerticalFieldSelect = (mbParams->mb_type.value & 0xF000) >> 12;
inlineDataVc1->DW1.Horzorigin = mbState->bMbHorizOrigin;
inlineDataVc1->DW1.Vertorigin = mbState->bMbVertOrigin;
inlineDataVc1->DW0.Lastmbinrow =
((inlineDataVc1->DW1.Horzorigin == (mbState->wPicWidthInMb - 1)) &&
((inlineDataVc1->DW1.Vertorigin == (mbState->wPicHeightInMb - 1))));
}
MHW_MI_CHK_STATUS(Mhw_AddCommandBB(batchBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
// For VC-1 IT VFE Dword is Reserved : MBZ
cmdMfdItObject->DW3.IndirectItCoeffDataLength = mbState->dwLength;
cmdMfdItObject->DW4.IndirectItCoeffDataStartAddressOffset = mbState->dwOffset;
// VC-1 inline data
inlineDataVc1->DW0.MotionType = mbParams->mb_type.motion_type;
inlineDataVc1->DW0.DctType = mbParams->mb_type.field_residual;
inlineDataVc1->DW1.Horzorigin = mbState->bMbHorizOrigin;
inlineDataVc1->DW1.Vertorigin = mbState->bMbVertOrigin;
inlineDataVc1->DW7.SubblockCodeForY0 = mbParams->num_coef[0];
inlineDataVc1->DW7.SubblockCodeForY1 = mbParams->num_coef[1];
inlineDataVc1->DW7.SubblockCodeForY2 = mbParams->num_coef[2];
inlineDataVc1->DW7.SubblockCodeForY3 = mbParams->num_coef[3];
inlineDataVc1->DW8.SubblockCodeForCb = mbParams->num_coef[4];
inlineDataVc1->DW8.SubblockCodeForCr = mbParams->num_coef[5];
// Subblock coding information not present in bNumCoef for Interlace Frame
// intra MBs, so when all 0 (i.e. subblock partition is 8x8) assume subblock present = 1
if (MEDIA_IS_WA(m_waTable, WaAssumeSubblockPresent))
{
if ((mbState->PicFlags == PICTURE_INTERLACED_FRAME) && mbParams->mb_type.intra_mb &&
(inlineDataVc1->DW7.Value == 0) && (inlineDataVc1->DW8.Value == 0))
{
inlineDataVc1->DW7.SubblockCodeForY0 |= 4;
inlineDataVc1->DW7.SubblockCodeForY1 |= 4;
inlineDataVc1->DW7.SubblockCodeForY2 |= 4;
inlineDataVc1->DW7.SubblockCodeForY3 |= 4;
inlineDataVc1->DW8.SubblockCodeForCb |= 4;
inlineDataVc1->DW8.SubblockCodeForCr |= 4;
}
}
if (vc1PicParams->picture_fields.picture_type == vc1PFrame ||
vc1PicParams->sequence_fields.AdvancedProfileFlag)
{
inlineDataVc1->DW9.IldbControlDataForBlockY0 = mbState->DeblockData[0];
inlineDataVc1->DW9.IldbControlDataForBlockY1 = mbState->DeblockData[1];
inlineDataVc1->DW9.IldbControlDataForBlockY2 = mbState->DeblockData[2];
inlineDataVc1->DW9.IldbControlDataForBlockY3 = mbState->DeblockData[3];
inlineDataVc1->DW10.IldbControlDataForCbBlock = mbState->DeblockData[4];
inlineDataVc1->DW10.IldbControlDataForCrBlock = mbState->DeblockData[5];
}
else if (vc1PicParams->entrypoint_fields.loopfilter)
{
//driver generates the edge control value for I and B frames in VC1 Simple and Main profile
if (mbState->bMbHorizOrigin == 0 && mbState->bMbVertOrigin == 0)
{
inlineDataVc1->DW9.Value = MHW_VDBOX_DECODE_VC1_IT_ILDB_EDGE_CONTROL_LUMA_X0Y0;
inlineDataVc1->DW10.Value = MHW_VDBOX_DECODE_VC1_IT_ILDB_EDGE_CONTROL_CHROMA_X0Y0;
}
else if (mbState->bMbHorizOrigin == 0)
{
inlineDataVc1->DW9.Value = MHW_VDBOX_DECODE_VC1_IT_ILDB_EDGE_CONTROL_LUMA_X0Y1;
inlineDataVc1->DW10.Value = MHW_VDBOX_DECODE_VC1_IT_ILDB_EDGE_CONTROL_CHROMA_X0Y1;
}
else if (mbState->bMbVertOrigin == 0)
{
inlineDataVc1->DW9.Value = MHW_VDBOX_DECODE_VC1_IT_ILDB_EDGE_CONTROL_LUMA_X1Y0;
inlineDataVc1->DW10.Value = MHW_VDBOX_DECODE_VC1_IT_ILDB_EDGE_CONTROL_CHROMA_X1Y0;
}
else
{
inlineDataVc1->DW9.Value = MHW_VDBOX_DECODE_VC1_IT_ILDB_EDGE_CONTROL_LUMA_X1Y1;
inlineDataVc1->DW10.Value = MHW_VDBOX_DECODE_VC1_IT_ILDB_EDGE_CONTROL_CHROMA_X1Y1;
}
}
else
{
inlineDataVc1->DW9.Value = 0;
inlineDataVc1->DW10.Value = 0;
}
if (vc1PicParams->picture_fields.picture_type == vc1IFrame)
{
// Intra MB
inlineDataVc1->DW0.CodedBlockPattern = 63;
MHW_MI_CHK_STATUS(Vc1ItObjectSetOverlapSmoothingFilter(
inlineDataVc1,
mbState,
mbParams,
mbState->bMbHorizOrigin,
mbState->bMbVertOrigin));
MHW_MI_CHK_STATUS(Mhw_AddCommandBB(batchBuffer, &cmd, sizeof(cmd)));
}
else
{
// Motion vectors
inlineDataVc1->DW0.MotionVerticalFieldSelect = (mbParams->mb_type.value & 0xF000) >> 12;
inlineDataVc1->DW0.Motion4Mv = mbParams->mb_type.motion_4mv;
inlineDataVc1->DW0.MacroblockMotionForward = mbParams->mb_type.motion_forward;
inlineDataVc1->DW0.MacroblockMotionBackward = mbParams->mb_type.motion_backward;
inlineDataVc1->DW0.MacroblockIntraType = mbParams->mb_type.intra_mb;
inlineDataVc1->DW0.CodedBlockPattern =
mbParams->mb_type.intra_mb ? 63 : mbParams->pattern_code.block_coded_pattern;
if (mbParams->mb_type.motion_4mv && (mbState->PicFlags == PICTURE_FRAME))
{
uint8_t cbp = (uint8_t)mbParams->pattern_code.block_luma_intra;
inlineDataVc1->DW0.CodedBlockPattern |= (cbp << 2); // Update luma residue blocks from intra Flags
inlineDataVc1->DW0.LumaIntra8X8Flag = mbParams->pattern_code.block_luma_intra;
inlineDataVc1->DW0.ChromaIntraFlag = mbParams->pattern_code.block_chroma_intra;
if (!mbParams->mb_type.intra_mb && (cbp == 0xF)) // top 4 bits of wPatternCode all set means intra
{
mbParams->mb_type.intra_mb = 1;
inlineDataVc1->DW0.MacroblockIntraType = 1;
inlineDataVc1->DW0.MotionType = 0; // Intra
inlineDataVc1->DW0.MacroblockMotionForward = 0;
inlineDataVc1->DW0.MacroblockMotionBackward = 0;
}
}
// Next, copy in the motion vectors if not skipped frame
if (!mbParams->mb_type.intra_mb && mbState->dwDataSize)
{
inlineDataVc1->DW2.Value = mbState->PackedLumaMvs[0];
inlineDataVc1->DW3.Value = mbState->PackedLumaMvs[1];
inlineDataVc1->DW4.Value = mbState->PackedLumaMvs[2];
inlineDataVc1->DW5.Value = mbState->PackedLumaMvs[3];
inlineDataVc1->DW6.Value =
(mbState->PicFlags == PICTURE_INTERLACED_FRAME) ? 0 : mbState->PackedChromaMv;
inlineDataVc1->DW0.MotionVerticalFieldSelect = (mbParams->mb_type.value & 0xF000) >> 12;
inlineDataVc1->DW0.Mvfieldselectchroma = mbState->bFieldPolarity;
inlineDataVc1->DW0.Mvswitch = mbState->bMotionSwitch;
}
if (!mbParams->mb_skips_following)
{
MHW_MI_CHK_STATUS(Vc1ItObjectSetOverlapSmoothingFilter(
inlineDataVc1,
mbState,
mbParams,
mbState->bMbHorizOrigin,
mbState->bMbVertOrigin));
MHW_MI_CHK_STATUS(Mhw_AddCommandBB(batchBuffer, &cmd, sizeof(cmd)));
}
else
{
// Skipped MB's are inter MB's (no residual data, only MV's) so no overlap smoothing
uint16_t skippedMBs = (uint16_t)mbParams->mb_skips_following + 1;
for (uint16_t num = 0; num < skippedMBs; num++)
{
inlineDataVc1->DW0.CodedBlockPattern = 0;
inlineDataVc1->DW1.Horzorigin = (mbParams->mb_address + num) % mbState->wPicWidthInMb;
inlineDataVc1->DW1.Vertorigin = (mbParams->mb_address + num) / mbState->wPicWidthInMb;
// Reset overlap smoothing params
inlineDataVc1->DW0.Lastmbinrow = (inlineDataVc1->DW1.Horzorigin == (mbState->wPicWidthInMb - 1));
inlineDataVc1->DW0.LastRowFlag = (inlineDataVc1->DW1.Vertorigin == (mbState->wPicHeightInMb - 1));
inlineDataVc1->DW1.Osedgemaskluma = 0;
inlineDataVc1->DW1.Osedgemaskchroma = 0;
MHW_MI_CHK_STATUS(Mhw_AddCommandBB(batchBuffer, &cmd, sizeof(cmd)));
}
}
}
return eStatus;
}
MOS_STATUS AddMfxJpegHuffTableCmd(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_VDBOX_HUFF_TABLE_PARAMS params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(cmdBuffer);
MHW_MI_CHK_NULL(params);
MHW_MI_CHK_NULL(params->pDCBits);
MHW_MI_CHK_NULL(params->pDCValues);
MHW_MI_CHK_NULL(params->pACBits);
MHW_MI_CHK_NULL(params->pACValues);
typename TMfxCmds::MFX_JPEG_HUFF_TABLE_STATE_CMD cmd;
cmd.DW1.Hufftableid1Bit = params->HuffTableID;
MHW_MI_CHK_STATUS(MOS_SecureMemcpy(
cmd.DcBits128BitArray,
sizeof(cmd.DcBits128BitArray),
params->pDCBits,
sizeof(cmd.DcBits128BitArray)));
MHW_MI_CHK_STATUS(MOS_SecureMemcpy(
cmd.DcHuffval128BitArray,
sizeof(cmd.DcHuffval128BitArray),
params->pDCValues,
sizeof(cmd.DcHuffval128BitArray)));
MHW_MI_CHK_STATUS(MOS_SecureMemcpy(
cmd.AcBits168BitArray,
sizeof(cmd.AcBits168BitArray),
params->pACBits,
sizeof(cmd.AcBits168BitArray)));
MHW_MI_CHK_STATUS(MOS_SecureMemcpy(
cmd.AcHuffval1608BitArray,
sizeof(cmd.AcHuffval1608BitArray),
params->pACValues,
sizeof(cmd.AcHuffval1608BitArray)));
MHW_MI_CHK_STATUS(MOS_SecureMemcpy(
&cmd.DW52.Value,
sizeof(uint16_t),
(uint8_t*)params->pACValues + sizeof(cmd.AcHuffval1608BitArray),
sizeof(uint16_t)));
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
MOS_STATUS AddMfxJpegBsdObjCmd(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_VDBOX_JPEG_BSD_PARAMS params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(cmdBuffer);
MHW_MI_CHK_NULL(params);
typename TMfxCmds::MFD_JPEG_BSD_OBJECT_CMD cmd;
cmd.DW1.IndirectDataLength = params->dwIndirectDataLength;
cmd.DW2.IndirectDataStartAddress = params->dwDataStartAddress;
cmd.DW3.ScanVerticalPosition = params->dwScanVerticalPosition;
cmd.DW3.ScanHorizontalPosition = params->dwScanHorizontalPosition;
cmd.DW4.McuCount = params->dwMCUCount;
cmd.DW4.ScanComponents = params->sScanComponent;
cmd.DW4.Interleaved = params->bInterleaved;
cmd.DW5.Restartinterval16Bit = params->dwRestartInterval;
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
MOS_STATUS AddMfdVp8BsdObjectCmd(
PMOS_COMMAND_BUFFER cmdBuffer,
PMHW_VDBOX_VP8_BSD_PARAMS params)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MHW_FUNCTION_ENTER;
MHW_MI_CHK_NULL(cmdBuffer);
MHW_MI_CHK_NULL(params);
typename TMfxCmds::MFD_VP8_BSD_OBJECT_CMD cmd;
auto vp8PicParams = params->pVp8PicParams;
uint8_t numPartitions = (1 << vp8PicParams->CodedCoeffTokenPartition);
cmd.DW1.CodedNumOfCoeffTokenPartitions = vp8PicParams->CodedCoeffTokenPartition;
cmd.DW1.Partition0CpbacEntropyRange = vp8PicParams->uiP0EntropyRange;
cmd.DW1.Partition0CpbacEntropyCount = vp8PicParams->ucP0EntropyCount;
cmd.DW2.Partition0CpbacEntropyValue = vp8PicParams->ucP0EntropyValue;
cmd.DW3.IndirectPartition0DataLength = vp8PicParams->uiPartitionSize[0] + 1;
cmd.DW4.IndirectPartition0DataStartOffset = vp8PicParams->uiFirstMbByteOffset;
cmd.DW5.IndirectPartition1DataLength = vp8PicParams->uiPartitionSize[1] + 1;
cmd.DW6.IndirectPartition1DataStartOffset = cmd.DW4.IndirectPartition0DataStartOffset +
vp8PicParams->uiPartitionSize[0] +
(numPartitions - 1) * 3; // Account for P Sizes: 3 bytes per partition
// excluding partition 0 and last partition.
int32_t i = 2;
if (i < ((1 + numPartitions)))
{
cmd.DW7.IndirectPartition2DataLength = vp8PicParams->uiPartitionSize[i] + 1;
cmd.DW8.IndirectPartition2DataStartOffset = cmd.DW6.IndirectPartition1DataStartOffset + vp8PicParams->uiPartitionSize[i - 1];
}
i = 3;
if (i < ((1 + numPartitions)))
{
cmd.DW9.IndirectPartition3DataLength = vp8PicParams->uiPartitionSize[i] + 1;
cmd.DW10.IndirectPartition3DataStartOffset = cmd.DW8.IndirectPartition2DataStartOffset + vp8PicParams->uiPartitionSize[i - 1];
}
i = 4;
if (i < ((1 + numPartitions)))
{
cmd.DW11.IndirectPartition4DataLength = vp8PicParams->uiPartitionSize[i] + 1;
cmd.DW12.IndirectPartition4DataStartOffset = cmd.DW10.IndirectPartition3DataStartOffset + vp8PicParams->uiPartitionSize[i - 1];
}
i = 5;
if (i < ((1 + numPartitions)))
{
cmd.DW13.IndirectPartition5DataLength = vp8PicParams->uiPartitionSize[i] + 1;
cmd.DW14.IndirectPartition5DataStartOffset = cmd.DW12.IndirectPartition4DataStartOffset + vp8PicParams->uiPartitionSize[i - 1];
}
i = 6;
if (i < ((1 + numPartitions)))
{
cmd.DW15.IndirectPartition6DataLength = vp8PicParams->uiPartitionSize[i] + 1;
cmd.DW16.IndirectPartition6DataStartOffset = cmd.DW14.IndirectPartition5DataStartOffset + vp8PicParams->uiPartitionSize[i - 1];
}
i = 7;
if (i < ((1 + numPartitions)))
{
cmd.DW17.IndirectPartition7DataLength = vp8PicParams->uiPartitionSize[i] + 1;
cmd.DW18.IndirectPartition7DataStartOffset = cmd.DW16.IndirectPartition6DataStartOffset + vp8PicParams->uiPartitionSize[i - 1];
}
i = 8;
if (i < ((1 + numPartitions)))
{
cmd.DW19.IndirectPartition8DataLength = vp8PicParams->uiPartitionSize[i] + 1;
cmd.DW20.IndirectPartition8DataStartOffset = cmd.DW18.IndirectPartition7DataStartOffset + vp8PicParams->uiPartitionSize[i - 1];
}
MHW_MI_CHK_STATUS(Mos_AddCommand(cmdBuffer, &cmd, sizeof(cmd)));
return eStatus;
}
public:
inline uint32_t GetAvcImgStateSize()
{
return TMfxCmds::MFX_AVC_IMG_STATE_CMD::byteSize;
}
};
#endif