/*
* Copyright (c) 2017-2021, 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"
#include "mhw_cp_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(m_osInterface);
        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(m_osInterface->pfnAddCommand(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(m_osInterface);
        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(m_osInterface->pfnAddCommand(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(m_osInterface->pfnAddCommand(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(m_osInterface->pfnAddCommand(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(m_osInterface->pfnAddCommand(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(m_osInterface->pfnAddCommand(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(m_osInterface->pfnAddCommand(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(m_osInterface->pfnAddCommand(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(m_osInterface->pfnAddCommand(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(m_osInterface->pfnAddCommand(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(m_osInterface);
        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(m_osInterface->pfnAddCommand(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(m_osInterface->pfnAddCommand(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(m_osInterface->pfnAddCommand(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(m_osInterface->pfnAddCommand(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(m_osInterface->pfnAddCommand(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(m_osInterface->pfnAddCommand(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(m_osInterface, 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(m_osInterface, 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(m_osInterface, 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;
        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(m_osInterface, 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(m_osInterface, 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(m_osInterface);
        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(m_osInterface->pfnAddCommand(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(m_osInterface);
        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(m_osInterface->pfnAddCommand(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(m_osInterface);
        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(m_osInterface->pfnAddCommand(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(m_osInterface, 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(m_osInterface, 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(m_osInterface);
        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(m_osInterface->pfnAddCommand(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(m_osInterface);
        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(m_osInterface->pfnAddCommand(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(m_osInterface);
        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(m_osInterface->pfnAddCommand(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(m_osInterface);
        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(m_osInterface->pfnAddCommand(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(m_osInterface);
        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(m_osInterface->pfnAddCommand(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(m_osInterface);
        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(m_osInterface->pfnAddCommand(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 = static_cast<uint8_t>(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(m_osInterface);
        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(m_osInterface->pfnAddCommand(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(m_osInterface);
        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(m_osInterface->pfnAddCommand(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(m_osInterface);
        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(m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));

        return eStatus;
    }

public:
    inline uint32_t GetAvcImgStateSize()
    {
        return TMfxCmds::MFX_AVC_IMG_STATE_CMD::byteSize;
    }

    inline uint32_t GetAvcSlcStateSize()
    {
        return TMfxCmds::MFX_AVC_SLICE_STATE_CMD::byteSize;
    }

};

#endif
