/*===================== begin_copyright_notice ==================================

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.

======================= end_copyright_notice ==================================*/

//! \file     mhw_vdbox_vdenc_g12_X.h
//! \details  Defines functions for constructing Vdbox Vdenc commands on Gen12-based platforms
//!

#ifndef __MHW_VDBOX_VDENC_G12_X_H__
#define __MHW_VDBOX_VDENC_G12_X_H__

#include "mhw_vdbox_vdenc_generic.h"
#include "mhw_vdbox_vdenc_hwcmd_g12_X.h"
#include "mhw_vdbox_g12_X.h"
#include "mos_interface.h"

#define VDENCHEVC_RSC_OFFSET_C420OR422_DXX_LCU32OR64_4K_G12               1824
#define VDENCHEVC_RSC_OFFSET_C420OR422_DXX_LCU32OR64_8K_G12               2304
#define VDENCHEVC_RSC_OFFSET_C444_D8_LCU32OR64_4K_G12                     1568
#define VDENCHEVC_RSC_OFFSET_C444_D8_LCU32OR64_8K_G12                     2112
#define VDENCHEVC_RSC_OFFSET_C444_D10_LCU32OR64_4K_G12                    2336
#define VDENCHEVC_RSC_OFFSET_C444_D10_LCU32OR64_8K_G12                    1600
#define VDENCHEVC_RSC_OFFSET_C444_D12_LCU32OR64_4K_G12                    2336
#define VDENCHEVC_RSC_OFFSET_C444_D12_LCU32OR64_8K_G12                    1600

// TGL rowstore Cache Values
#define VP9VDENCROWSTORE_BASEADDRESS_1536                                 1536
#define VP9VDENCROWSTORE_BASEADDRESS_2304                                 2304
#define VP9VDENCROWSTORE_BASEADDRESS_2368                                 2368
#define VP9VDENCROWSTORE_BASEADDRESS_2112                                 2112
#define VP9VDENCROWSTORE_BASEADDRESS_1920                                 1920
#define VP9VDENCROWSTORE_BASEADDRESS_768                                  768
#define RESERVED_VDENC_ROWSTORE_BASEADDRESS                               2370
#define RESERVED_VDENC_IPDL_ROWSTORE_BASEADDRESS                          384
#define AVC_VDENC_IPDL_ROWSTORE_BASEADDRESS                               512

#define GEN12_AVC_VDENC_ROWSTORE_BASEADDRESS                                  1280
#define GEN12_AVC_VDENC_ROWSTORE_BASEADDRESS_MBAFF                            1536
#define GEN12_VP8_VDENC_ROWSTORE_BASEADDRESS                                  1536

#define OFFSET_OF(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER )

typedef struct _MHW_VDBOX_VDENC_CONTROL_STATE_PARAMS
{
    bool      bVdencInitialization;
}MHW_VDBOX_VDENC_CONTROL_STATE_PARAMS, *PMHW_VDBOX_VDENC_CONTROL_STATE_PARAMS;

struct MHW_VDBOX_VDENC_WALKER_STATE_PARAMS_G12 : public MHW_VDBOX_VDENC_WALKER_STATE_PARAMS
{
    // GEN11+ tiling support
    PMHW_VDBOX_HCP_TILE_CODING_PARAMS_G12   pTileCodingParams = nullptr;
    uint32_t                                dwNumberOfPipes = 0;
    uint32_t                                dwTileId = 0;
    uint32_t                                IBCControl = 0;
    uint32_t                                RowStaticInfo_31_0 = 0;
    uint32_t                                RowStaticInfo_63_32 = 0;
    uint32_t                                RowStaticInfo_95_64 = 0;
    uint32_t                                RowStaticInfo_127_96 = 0;
    uint32_t                                ctbSize = 0;
    uint32_t                                minCodingBlkSize = 0;
    uint32_t                                frameWidthMinus1 = 0;
    uint32_t                                frameHeightMinus1 = 0;
};
using PMHW_VDBOX_VDENC_WALKER_STATE_PARAMS_G12 = MHW_VDBOX_VDENC_WALKER_STATE_PARAMS_G12 *;

struct MHW_VDBOX_VD_PIPE_FLUSH_PARAMS_G12
{
    union
    {
        struct
        {
            uint16_t       bWaitDoneHEVC            : 1;
            uint16_t       bWaitDoneVDENC           : 1;
            uint16_t       bWaitDoneMFL             : 1;
            uint16_t       bWaitDoneMFX             : 1;
            uint16_t       bWaitDoneVDCmdMsgParser  : 1;
            uint16_t       bFlushHEVC               : 1;
            uint16_t       bFlushVDENC              : 1;
            uint16_t       bFlushMFL                : 1;
            uint16_t       bFlushMFX                : 1;
            uint16_t       bWaitDoneAV1             : 1;
            uint16_t       bFlushAV1                : 1;
            uint16_t                                : 5;
        };
        struct
        {
            uint16_t       Value;
        };
    }Flags;
};
using PMHW_VDBOX_VD_PIPE_FLUSH_PARAMS_G12 = MHW_VDBOX_VD_PIPE_FLUSH_PARAMS_G12 *;

//!  MHW Vdbox Vdenc interface for Gen12
/*!
This class defines the Vdenc command construction functions for Gen12 platforms as template
*/
template <typename TVdencCmds>
class MhwVdboxVdencInterfaceG12 : public MhwVdboxVdencInterfaceGeneric<TVdencCmds>
{
protected:
    enum CommandsNumberOfAddresses
    {
        MI_FLUSH_DW_CMD_NUMBER_OF_ADDRESSES = 1,
        MI_BATCH_BUFFER_START_CMD_NUMBER_OF_ADDRESSES = 1,
        VDENC_PIPE_BUF_ADDR_STATE_CMD_NUMBER_OF_ADDRESSES = 21
    };

    enum VdencSurfaceFormat
    {
        vdencSurfaceFormatYuv422          = 0x0,
        vdencSurfaceFormatRgba4444        = 0x1,
        vdencSurfaceFormatYuv444          = 0x2,
        vdencSurfaceFormatP010Variant     = 0x3,
        vdencSurfaceFormatPlanar420_8     = 0x4,
        vdencSurfaceFormatYcrcbSwapy422   = 0x5,
        vdencSurfaceFormatYcrcbSwapuv422  = 0x6,
        vdencSurfaceFormatYcrcbSwapuvy422 = 0x7,
        vdencSurfaceFormatY216            = 0x8,
        vdencSurfaceFormatY210            = 0x8,  // Same value is used to represent Y216 and Y210
        vdencSurfaceFormatRgba_10_10_10_2 = 0x9,
        vdencSurfaceFormatY410            = 0xa,
        vdencSurfaceFormatNv21            = 0xb,
        vdencSurfaceFormatY416            = 0xc,
        vdencSurfaceFormatP010            = 0xd,
        vdencSurfaceFormatPlanarP016      = 0xe,
        vdencSurfaceFormatY8Unorm         = 0xf,
        vdencSurfaceFormatY16             = 0x10,
        vdencSurfaceFormatY216Variant     = 0x11,
        vdencSurfaceFormatY416Variant     = 0x12,
        vdencSurfaceFormatYuyvVariant     = 0x13,
        vdencSurfaceFormatAyuvVariant     = 0x14,
    };

    enum VDENC_WALKER_STATE_IBC_CONTROL
    {
        VDENC_WALKER_STATE_COMMAND_IBC_CONTROL_IBC_DISABLED_G12 = 0x0,
        VDENC_WALKER_STATE_COMMAND_IBC_CONTROL_IBC_ONLY_LBC_G12 = 0x1,
        VDENC_WALKER_STATE_COMMAND_IBC_CONTROL_IBC_ENABLED_TBCLBC_G12 = 0x3,
    };

    MOS_STATUS InitRowstoreUserFeatureSettings() override
    {
        MHW_FUNCTION_ENTER;

        MOS_USER_FEATURE_VALUE_DATA userFeatureData;
        MEDIA_FEATURE_TABLE *skuTable = this->m_osInterface->pfnGetSkuTable(this->m_osInterface);

        MHW_MI_CHK_NULL(skuTable);

        MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
        if (this->m_osInterface->bSimIsActive)
        {
            // Disable RowStore Cache on simulation by default
            userFeatureData.u32Data = 1;
        }
        else
        {
            userFeatureData.u32Data = 0;
        }

        userFeatureData.i32DataFlag = MOS_USER_FEATURE_VALUE_DATA_FLAG_CUSTOM_DEFAULT_VALUE_TYPE;
#if (_DEBUG || _RELEASE_INTERNAL)
        MOS_UserFeature_ReadValue_ID(
            nullptr,
            __MEDIA_USER_FEATURE_VALUE_ROWSTORE_CACHE_DISABLE_ID,
            &userFeatureData,
            this->m_osInterface->pOsContext);
#endif // _DEBUG || _RELEASE_INTERNAL
        this->m_rowstoreCachingSupported = userFeatureData.i32Data ? false : true;

        if (this->m_rowstoreCachingSupported)
        {
            MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
#if (_DEBUG || _RELEASE_INTERNAL)
            MOS_UserFeature_ReadValue_ID(
                nullptr,
                __MEDIA_USER_FEATURE_VALUE_VDENCROWSTORECACHE_DISABLE_ID,
                &userFeatureData,
                this->m_osInterface->pOsContext);
#endif // _DEBUG || _RELEASE_INTERNAL
            this->m_vdencRowStoreCache.bSupported = userFeatureData.i32Data ? false : true;
        }

        return MOS_STATUS_SUCCESS;
    }

    //!
    //! \brief    Translate MOS type format to vdenc surface raw format
    //! \details  VDBOX protected function to translate mos format to media state format
    //! \param    MOS_FORMAT  Format
    //!           [in] MOS type format
    //! \return   VdencSurfaceFormat
    //!           media state surface format
    //!
    VdencSurfaceFormat MosFormatToVdencSurfaceRawFormat(MOS_FORMAT format)
    {
        MHW_FUNCTION_ENTER;

        switch (format)
        {
        case Format_A8R8G8B8:
        case Format_X8R8G8B8:
        case Format_A8B8G8R8:
            return vdencSurfaceFormatRgba4444;
        case Format_NV12:
        case Format_NV11:
        case Format_P208:
        case Format_IMC1:
        case Format_IMC2:
        case Format_IMC3:
        case Format_IMC4:
            return vdencSurfaceFormatPlanar420_8;
        case Format_400P:
        case Format_P8:
            return vdencSurfaceFormatY8Unorm;
        case Format_UYVY:
            return vdencSurfaceFormatYcrcbSwapy422;
        case Format_YVYU:
            return vdencSurfaceFormatYcrcbSwapuv422;
        case Format_VYUY:
            return vdencSurfaceFormatYcrcbSwapuvy422;
        case Format_444P:
        case Format_AYUV:
            return vdencSurfaceFormatYuv444;
        case Format_YUY2:
        case Format_YUYV:
            return vdencSurfaceFormatYuv422;
        case Format_P010:
            return vdencSurfaceFormatP010;
        case Format_R10G10B10A2:
        case Format_B10G10R10A2:
            return vdencSurfaceFormatRgba_10_10_10_2;
            // Only Y210 supported now, allocated as Y216 format by 3D driver
        case Format_Y210:
        case Format_Y216:
            return vdencSurfaceFormatY216;
        case Format_Y410:
            return vdencSurfaceFormatY410;
        case Format_NV21:
            return vdencSurfaceFormatNv21;
        default:
            return vdencSurfaceFormatPlanar420_8;
        }

        return vdencSurfaceFormatYuv422;
    }

    //!
    //! \brief    Translate MOS type format to vdenc surface recon format
    //! \details  VDBOX protected function to translate mos format to media state recon format
    //! \param    MOS_FORMAT  Format
    //!           [in] MOS type format
    //! \return   VdencSurfaceFormat
    //!           media state surface format
    //!
    VdencSurfaceFormat MosFormatToVdencSurfaceReconFormat(MOS_FORMAT format)
    {
        MHW_FUNCTION_ENTER;

        switch (format)
        {
        case Format_A8R8G8B8:
        case Format_X8R8G8B8:
        case Format_A8B8G8R8:
            return vdencSurfaceFormatRgba4444;
        case Format_NV12:
        case Format_IMC1:
        case Format_IMC2:
        case Format_IMC3:
        case Format_IMC4:
            return vdencSurfaceFormatPlanar420_8;
        case Format_400P:
        case Format_P8:
            return vdencSurfaceFormatY8Unorm;
        case Format_UYVY:
            return vdencSurfaceFormatYcrcbSwapy422;
        case Format_YVYU:
            return vdencSurfaceFormatYcrcbSwapuv422;
        case Format_VYUY:
            return vdencSurfaceFormatYcrcbSwapuvy422;
        case Format_444P:
        case Format_AYUV:
            return vdencSurfaceFormatAyuvVariant;
        case Format_YUY2:
        case Format_YUYV:
            return vdencSurfaceFormatYuyvVariant;
        case Format_P010:
            return vdencSurfaceFormatP010Variant;
        case Format_R10G10B10A2:
            return vdencSurfaceFormatRgba_10_10_10_2;
        case Format_Y216:
            return vdencSurfaceFormatY216Variant;
        case Format_Y410:
            return vdencSurfaceFormatY416Variant;
        case Format_NV21:
            return vdencSurfaceFormatNv21;
        default:
            return vdencSurfaceFormatPlanar420_8;
        }
    }

    //!
    //! \brief    Adds VD Pipeline Flush command in command buffer
    //! \details  Client facing function to add VD Pipeline Flush command in command buffer
    //! \param    [in] cmdBuffer
    //!           Command buffer to which HW command is added
    //! \param    [in] params
    //!           Params structure used to populate the HW command
    //! \return   MOS_STATUS
    //!           MOS_STATUS_SUCCESS if success, else fail type
    //!
    MOS_STATUS AddVdPipelineFlushCmd(
        PMOS_COMMAND_BUFFER             cmdBuffer,
        PMHW_VDBOX_VD_PIPE_FLUSH_PARAMS params) override
    {
        MHW_FUNCTION_ENTER;

        MHW_MI_CHK_NULL(this->m_osInterface);
        MHW_MI_CHK_NULL(cmdBuffer);
        MHW_MI_CHK_NULL(params);

        MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

        typename TVdencCmds::VD_PIPELINE_FLUSH_CMD cmd;
        PMHW_VDBOX_VD_PIPE_FLUSH_PARAMS_G12 paramsG12 = (PMHW_VDBOX_VD_PIPE_FLUSH_PARAMS_G12)params;

        cmd.DW1.HevcPipelineDone           = params->Flags.bWaitDoneHEVC;
        cmd.DW1.VdencPipelineDone          = params->Flags.bWaitDoneVDENC;
        cmd.DW1.MflPipelineDone            = params->Flags.bWaitDoneMFL;
        cmd.DW1.MfxPipelineDone            = params->Flags.bWaitDoneMFX;
        cmd.DW1.VdCommandMessageParserDone = params->Flags.bWaitDoneVDCmdMsgParser;
        cmd.DW1.HevcPipelineCommandFlush   = params->Flags.bFlushHEVC;
        cmd.DW1.VdencPipelineCommandFlush  = params->Flags.bFlushVDENC;
        cmd.DW1.MflPipelineCommandFlush    = params->Flags.bFlushMFL;
        cmd.DW1.MfxPipelineCommandFlush    = params->Flags.bFlushMFX;
        cmd.DW1.AvpPipelineDone            = paramsG12->Flags.bWaitDoneAV1;
        cmd.DW1.AvpPipelineCommandFlush    = paramsG12->Flags.bFlushAV1;

        MHW_MI_CHK_STATUS(this->m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));

        return MOS_STATUS_SUCCESS;
    }

public:
    //!
    //! \brief  Constructor
    //!
    MhwVdboxVdencInterfaceG12(PMOS_INTERFACE osInterface) : MhwVdboxVdencInterfaceGeneric<TVdencCmds>(osInterface)
    {
        MHW_FUNCTION_ENTER;

        this->m_rhoDomainStatsEnabled = true;
        InitRowstoreUserFeatureSettings();
    }

    inline virtual uint32_t GetVdencCmd1Size() override
    {
        return 0;
    }

    inline virtual uint32_t GetVdencCmd2Size() override
    {
        return 0;
    }

    //!
    //! \brief    Destructor
    //!
    virtual ~MhwVdboxVdencInterfaceG12() { }

    MOS_STATUS GetRowstoreCachingAddrs(
        PMHW_VDBOX_ROWSTORE_PARAMS rowstoreParams) override
    {
        MHW_FUNCTION_ENTER;

        MHW_MI_CHK_NULL(rowstoreParams);

        bool is8bit = rowstoreParams->ucBitDepthMinus8 == 0;
        bool is10bit = rowstoreParams->ucBitDepthMinus8 == 1 || rowstoreParams->ucBitDepthMinus8 == 2;
        bool is12bit = rowstoreParams->ucBitDepthMinus8 > 2;
        bool isLcu32or64 = rowstoreParams->ucLCUSize == 32 || rowstoreParams->ucLCUSize == 64;
        bool isGt2k = rowstoreParams->dwPicWidth > 2048;
        bool isGt4k = rowstoreParams->dwPicWidth > 4096;
        bool isGt8k = rowstoreParams->dwPicWidth > 8192;
        uint32_t index = 0;

        bool avc = rowstoreParams->Mode == CODECHAL_ENCODE_MODE_AVC;
        bool vp8 = rowstoreParams->Mode == CODECHAL_ENCODE_MODE_VP8;
        bool widthLE4K = rowstoreParams->dwPicWidth <= MHW_VDBOX_PICWIDTH_4K;
        bool mbaffOrField = rowstoreParams->bMbaff || !rowstoreParams->bIsFrame;
        this->m_vdencRowStoreCache.bEnabled = false;
        this->m_vdencRowStoreCache.dwAddress = 0;

        //VDENC row store cache setting for AVC and VP8
        this->m_vdencRowStoreCache.bEnabled = this->m_vdencRowStoreCache.bSupported && widthLE4K && (avc || vp8);
        this->m_vdencRowStoreCache.dwAddress = avc ? (mbaffOrField ? GEN12_AVC_VDENC_ROWSTORE_BASEADDRESS_MBAFF :
            GEN12_AVC_VDENC_ROWSTORE_BASEADDRESS) : GEN12_VP8_VDENC_ROWSTORE_BASEADDRESS;
        this->m_vdencRowStoreCache.dwAddress = this->m_vdencRowStoreCache.bEnabled ? this->m_vdencRowStoreCache.dwAddress : 0;

        if (this->m_vdencRowStoreCache.bSupported && rowstoreParams->Mode == CODECHAL_ENCODE_MODE_HEVC)
        {
            if (rowstoreParams->ucChromaFormat != HCP_CHROMA_FORMAT_YUV444)
            {
                index = 2 * isGt4k + isLcu32or64;
            }
            else
            {
                uint32_t subidx = is12bit ? 2 : (is10bit ? 1 : 0);
                index = 4 + 6 * isLcu32or64 + 2 * subidx + isGt4k;
            }

            if (!isGt8k)
            {
                this->m_vdencRowStoreCache.bEnabled  = RowStoreCacheEnableHEVC[index][3];
                this->m_vdencRowStoreCache.dwAddress = RowStoreCacheAddrHEVC[index][3];
            }
        }

        //VP9 VDENC
        if (this->m_vdencRowStoreCache.bSupported && rowstoreParams->Mode == CODECHAL_ENCODE_MODE_VP9)
        {
            if ((rowstoreParams->ucChromaFormat >= HCP_CHROMA_FORMAT_YUV420) &&
                (rowstoreParams->ucChromaFormat <= HCP_CHROMA_FORMAT_YUV444))
            {
                index = 4 * (rowstoreParams->ucChromaFormat - HCP_CHROMA_FORMAT_YUV420) + 2 * (!is8bit) + isGt4k;
            }
            else
            {
                return MOS_STATUS_SUCCESS;
            }

            if (rowstoreParams->ucChromaFormat == HCP_CHROMA_FORMAT_YUV444 && !is8bit)
            {
                index += isGt2k;
            }

            if (!isGt8k)
            {
                this->m_vdencRowStoreCache.bEnabled = RowStoreCacheEnableVP9[index][3];
                this->m_vdencRowStoreCache.dwAddress = RowStoreCacheAddrVP9[index][3];
            }
        }

        if (this->m_vdencRowStoreCache.bSupported && rowstoreParams->Mode == CODECHAL_ENCODE_MODE_AV1)
        {
            this->m_vdencRowStoreCache.bEnabled  = true;
            this->m_vdencRowStoreCache.dwAddress = RESERVED_VDENC_ROWSTORE_BASEADDRESS;

            //IPDL
            this->m_vdencIpdlRowstoreCache.dwAddress = RESERVED_VDENC_IPDL_ROWSTORE_BASEADDRESS;

        }
        else if (this->m_vdencRowStoreCache.bSupported && rowstoreParams->Mode == CODECHAL_ENCODE_MODE_AVC)
        {
            this->m_vdencRowStoreCache.bEnabled = true;

            //IPDL
            this->m_vdencIpdlRowstoreCache.dwAddress = AVC_VDENC_IPDL_ROWSTORE_BASEADDRESS;

        }

        return MOS_STATUS_SUCCESS;
    }

    uint32_t GetAvcMaxSize(uint32_t waAddDelayInVDEncDynamicSlice)
    {
        uint32_t maxSize =
            TVdencCmds::VDENC_PIPE_MODE_SELECT_CMD::byteSize +
            TVdencCmds::VDENC_SRC_SURFACE_STATE_CMD::byteSize +
            TVdencCmds::VDENC_REF_SURFACE_STATE_CMD::byteSize +
            TVdencCmds::VDENC_DS_REF_SURFACE_STATE_CMD::byteSize +
            TVdencCmds::VDENC_PIPE_BUF_ADDR_STATE_CMD::byteSize +
            TVdencCmds::VDENC_CONST_QPT_STATE_CMD::byteSize +
            TVdencCmds::VDENC_IMG_STATE_CMD::byteSize +
            TVdencCmds::VDENC_WALKER_STATE_CMD::byteSize +
            TVdencCmds::VD_PIPELINE_FLUSH_CMD::byteSize;

        if (waAddDelayInVDEncDynamicSlice)
        {
            maxSize += TVdencCmds::VD_PIPELINE_FLUSH_CMD::byteSize * MHW_VDBOX_VDENC_DYNAMIC_SLICE_WA_COUNT;
        }

        return maxSize;
    }

    uint32_t GetReserved0MaxSize()
    {
       uint32_t maxSize =
            TVdencCmds::VDENC_CONTROL_STATE_CMD::byteSize +
            TVdencCmds::VDENC_PIPE_MODE_SELECT_CMD::byteSize +
            TVdencCmds::VDENC_SRC_SURFACE_STATE_CMD::byteSize +
            TVdencCmds::VDENC_REF_SURFACE_STATE_CMD::byteSize +
            TVdencCmds::VDENC_DS_REF_SURFACE_STATE_CMD::byteSize +
            TVdencCmds::VDENC_PIPE_BUF_ADDR_STATE_CMD::byteSize +
            TVdencCmds::VDENC_WALKER_STATE_CMD::byteSize +
            TVdencCmds::VD_PIPELINE_FLUSH_CMD::byteSize;;

        return maxSize;
    }

    MOS_STATUS GetVdencStateCommandsDataSize(
        uint32_t mode,
        uint32_t waAddDelayInVDEncDynamicSlice,
        uint32_t *commandsSize,
        uint32_t *patchListSize) override
    {
        MHW_FUNCTION_ENTER;

        uint32_t            maxSize = 0;
        uint32_t            patchListMaxSize = 0;
        uint32_t            standard = CodecHal_GetStandardFromMode(mode);

        if (standard == CODECHAL_AVC)
        {
            maxSize = GetAvcMaxSize(waAddDelayInVDEncDynamicSlice);
            patchListMaxSize = VDENC_PIPE_BUF_ADDR_STATE_CMD_NUMBER_OF_ADDRESSES;
        }
        else if (standard == CODECHAL_HEVC)
        {
            maxSize =
                TVdencCmds::VDENC_PIPE_MODE_SELECT_CMD::byteSize +
                TVdencCmds::VDENC_SRC_SURFACE_STATE_CMD::byteSize +
                TVdencCmds::VDENC_REF_SURFACE_STATE_CMD::byteSize +
                TVdencCmds::VDENC_DS_REF_SURFACE_STATE_CMD::byteSize +
                TVdencCmds::VDENC_PIPE_BUF_ADDR_STATE_CMD::byteSize +
                TVdencCmds::VDENC_WEIGHTSOFFSETS_STATE_CMD::byteSize +
                TVdencCmds::VDENC_WALKER_STATE_CMD::byteSize +
                TVdencCmds::VD_PIPELINE_FLUSH_CMD::byteSize;

            if (waAddDelayInVDEncDynamicSlice)
            {
                maxSize += TVdencCmds::VD_PIPELINE_FLUSH_CMD::byteSize * MHW_VDBOX_VDENC_DYNAMIC_SLICE_WA_COUNT;
            }

            patchListMaxSize = VDENC_PIPE_BUF_ADDR_STATE_CMD_NUMBER_OF_ADDRESSES;
        }
        else if (standard == CODECHAL_VP9)
        {
            maxSize =
                TVdencCmds::VDENC_PIPE_MODE_SELECT_CMD::byteSize +
                TVdencCmds::VDENC_SRC_SURFACE_STATE_CMD::byteSize +
                TVdencCmds::VDENC_REF_SURFACE_STATE_CMD::byteSize +
                TVdencCmds::VDENC_DS_REF_SURFACE_STATE_CMD::byteSize +
                TVdencCmds::VDENC_PIPE_BUF_ADDR_STATE_CMD::byteSize +
                TVdencCmds::VDENC_WALKER_STATE_CMD::byteSize +
                TVdencCmds::VD_PIPELINE_FLUSH_CMD::byteSize;

            if (waAddDelayInVDEncDynamicSlice)
            {
                maxSize += TVdencCmds::VD_PIPELINE_FLUSH_CMD::byteSize * MHW_VDBOX_VDENC_DYNAMIC_SLICE_WA_COUNT;
            }

            patchListMaxSize =
                MI_FLUSH_DW_CMD_NUMBER_OF_ADDRESSES +
                MI_BATCH_BUFFER_START_CMD_NUMBER_OF_ADDRESSES +
                VDENC_PIPE_BUF_ADDR_STATE_CMD_NUMBER_OF_ADDRESSES;
        }
        else if (standard == CODECHAL_AV1)
        {
            maxSize = GetReserved0MaxSize();

            patchListMaxSize =
                MI_FLUSH_DW_CMD_NUMBER_OF_ADDRESSES +
                MI_BATCH_BUFFER_START_CMD_NUMBER_OF_ADDRESSES +
                VDENC_PIPE_BUF_ADDR_STATE_CMD_NUMBER_OF_ADDRESSES;
        }
        else
        {
            MHW_ASSERTMESSAGE("Unsupported encode mode.");
            *commandsSize = 0;
            *patchListSize = 0;
            return MOS_STATUS_UNKNOWN;
        }

        *commandsSize = maxSize;
        *patchListSize = patchListMaxSize;

        return MOS_STATUS_SUCCESS;
    }

    uint32_t GetAvcSliceMaxSize()
    {
        uint32_t maxSize =
            TVdencCmds::VDENC_WEIGHTSOFFSETS_STATE_CMD::byteSize +
            TVdencCmds::VDENC_WALKER_STATE_CMD::byteSize +
            TVdencCmds::VD_PIPELINE_FLUSH_CMD::byteSize;

        return maxSize;
    }

    uint32_t GetReserved0TileMaxSize()
    {
        uint32_t maxSize = GetVdencCmd1Size() +
            GetVdencCmd2Size() +
            TVdencCmds::VDENC_WALKER_STATE_CMD::byteSize;

        return maxSize;
    }

    MOS_STATUS GetVdencPrimitiveCommandsDataSize(
        uint32_t                        mode,
        uint32_t                        *commandsSize,
        uint32_t                        *patchListSize) override
    {
        MHW_FUNCTION_ENTER;

        uint32_t            maxSize = 0;
        uint32_t            patchListMaxSize = 0;
        uint32_t            standard = CodecHal_GetStandardFromMode(mode);

        if (standard == CODECHAL_AVC)
        {
            maxSize = GetAvcSliceMaxSize();
            patchListMaxSize = VDENC_PIPE_BUF_ADDR_STATE_CMD_NUMBER_OF_ADDRESSES;
        }
        else if (standard == CODECHAL_AV1)
        {
            maxSize = GetReserved0TileMaxSize();
        }
        else
        {
            MHW_ASSERTMESSAGE("Unsupported encode mode.");
            *commandsSize = 0;
            *patchListSize = 0;
            return MOS_STATUS_UNKNOWN;
        }

        *commandsSize = maxSize;
        *patchListSize = patchListMaxSize;

        return MOS_STATUS_SUCCESS;
    }

    MOS_STATUS AddVdencPipeModeSelectCmd(
        PMOS_COMMAND_BUFFER                cmdBuffer,
        PMHW_VDBOX_PIPE_MODE_SELECT_PARAMS params) override
    {
        MHW_FUNCTION_ENTER;

        MHW_MI_CHK_NULL(this->m_osInterface);
        MHW_MI_CHK_NULL(cmdBuffer);
        MHW_MI_CHK_NULL(params);
        auto paramsG12 = dynamic_cast<PMHW_VDBOX_PIPE_MODE_SELECT_PARAMS_G12>(params);
        MHW_MI_CHK_NULL(paramsG12);
        typename TVdencCmds::VDENC_PIPE_MODE_SELECT_CMD cmd;

        cmd.DW1.StandardSelect                 = CodecHal_GetStandardFromMode(params->Mode);
        cmd.DW1.ScalabilityMode                = !(paramsG12->MultiEngineMode == MHW_VDBOX_HCP_MULTI_ENGINE_MODE_FE_LEGACY);
        if (CODECHAL_ENCODE_MODE_HEVC == params->Mode || CODECHAL_ENCODE_MODE_AV1 == params->Mode)
        {
            cmd.DW1.FrameStatisticsStreamOutEnable = paramsG12->bBRCEnabled || paramsG12->bLookaheadPass;
        }
        // AVC VENC to be optimized later
        else
        {
            cmd.DW1.FrameStatisticsStreamOutEnable = 1;
        }
        cmd.DW1.VdencPakObjCmdStreamOutEnable  = params->bVdencPakObjCmdStreamOutEnable;
        cmd.DW1.TlbPrefetchEnable              = 1;
        cmd.DW1.PakThresholdCheckEnable        = params->bDynamicSliceEnable;
        cmd.DW1.VdencStreamInEnable            = params->bVdencStreamInEnable;
        cmd.DW1.BitDepth                       = params->ucVdencBitDepthMinus8;

        if (CODECHAL_ENCODE_MODE_HEVC == params->Mode || CODECHAL_ENCODE_MODE_VP9 == params->Mode || CODECHAL_ENCODE_MODE_AV1 == params->Mode)
        {
            cmd.DW1.PakChromaSubSamplingType = params->ChromaType;
        }
        // by default RGB to YUV using full to studio range
        // can add a DDI flag to control if needed
        cmd.DW1.OutputRangeControlAfterColorSpaceConversion = 1;

        // for tile encoding
        cmd.DW1.TileReplayEnable = paramsG12->bTileBasedReplayMode;

        cmd.DW1.IsRandomAccess = paramsG12->bIsRandomAccess;

        //Restriction: When this pre-fetch is enabled,TLB Prefetch Enable in VDENC_PIPE_MODE select (DW 1 bit 7) should be disabled.
        cmd.DW2.HmeRegionPreFetchenable = 0;

        // TLB prefetch performance improvement
        if (params->Mode == CODECHAL_ENCODE_MODE_AVC)
        {
            cmd.DW3.PreFetchoffsetforsource = 7;
            cmd.DW3.Numverticalreqminus1Src = 0;
        }
        else if (params->Mode == CODECHAL_ENCODE_MODE_HEVC || CODECHAL_ENCODE_MODE_AV1 == params->Mode)
        {
            cmd.DW3.PreFetchoffsetforsource = 4;
            cmd.DW3.Numverticalreqminus1Src = 1;
        }

        //Restriction : This field can be set only to planar source formats.
        if (params->Format != Format_NV12 && params->Format != Format_P010)
        {
            cmd.DW3.SourceChromaTlbPreFetchenable = 0;
        }

        // For RGB encoding
        if (paramsG12->bRGBEncodingMode)
        {
            cmd.DW1.RgbEncodingEnable    = 1;
            // To add the primary channel selection later here
        }

        // For parallel encode from display
        if (paramsG12->bWirelessEncodeEnabled)
        {
            cmd.DW5.CaptureMode                        = TVdencCmds::VDENC_PIPE_MODE_SELECT_CMD::CAPTURE_MODE_UNNAMED1;
            cmd.DW5.ParallelCaptureAndEncodeSessionId  = paramsG12->ucWirelessSessionId;
            cmd.DW5.TailPointerReadFrequency           = 0x50;
        }

        MHW_MI_CHK_STATUS(this->m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));

        return MOS_STATUS_SUCCESS;
    }

    MOS_STATUS AddVdencPipeBufAddrCmd(
        PMOS_COMMAND_BUFFER             cmdBuffer,
        PMHW_VDBOX_PIPE_BUF_ADDR_PARAMS params) override
    {
        MOS_SURFACE details;
        uint8_t     refIdx;

        MHW_FUNCTION_ENTER;

        MHW_MI_CHK_NULL(this->m_osInterface);
        MHW_MI_CHK_NULL(cmdBuffer);
        MHW_MI_CHK_NULL(params);

        typename TVdencCmds::VDENC_PIPE_BUF_ADDR_STATE_CMD cmd;

        MOS_MEMCOMP_STATE   mmcMode = MOS_MEMCOMP_DISABLED;
        MHW_RESOURCE_PARAMS resourceParams;
        MOS_ZeroMemory(&resourceParams, sizeof(resourceParams));
        resourceParams.dwLsbNum = MHW_VDBOX_MFX_GENERAL_STATE_SHIFT;
        resourceParams.HwCommandType = MOS_VDENC_PIPE_BUF_ADDR;

        if (params->psRawSurface != nullptr)
        {
            cmd.OriginalUncompressedPicture.PictureFields.DW0.MemoryCompressionEnable = MmcEnable(params->RawSurfMmcState) ? 1 : 0;
            cmd.OriginalUncompressedPicture.PictureFields.DW0.CompressionType = MmcIsRc(params->RawSurfMmcState) ? 1 : 0;
            cmd.OriginalUncompressedPicture.PictureFields.DW0.MemoryObjectControlState =
                this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_ORIGINAL_UNCOMPRESSED_PICTURE_ENCODE].Value;

            cmd.OriginalUncompressedPicture.PictureFields.DW0.TiledResourceMode = Mhw_ConvertToTRMode(params->psRawSurface->TileType);

            resourceParams.presResource    = &params->psRawSurface->OsResource;
            resourceParams.dwOffset        = params->psRawSurface->dwOffset;
            resourceParams.pdwCmd          = (uint32_t*)&(cmd.OriginalUncompressedPicture.LowerAddress);
            resourceParams.dwLocationInCmd = 10;
            resourceParams.bIsWritable     = false;

            MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                this->m_osInterface,
                cmdBuffer,
                &resourceParams));
        }

        if (this->m_vdencRowStoreCache.bEnabled)
        {
            cmd.RowStoreScratchBuffer.BufferPictureFields.DW0.CacheSelect = TVdencCmds::VDENC_Surface_Control_Bits_CMD::CACHE_SELECT_UNNAMED1;
            cmd.RowStoreScratchBuffer.LowerAddress.DW0.Value              = this->m_vdencRowStoreCache.dwAddress << 6;
        }
        else if (!Mos_ResourceIsNull(params->presVdencIntraRowStoreScratchBuffer))
        {
            cmd.RowStoreScratchBuffer.BufferPictureFields.DW0.MemoryObjectControlState =
                this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_VDENC_ROW_STORE_BUFFER_CODEC].Value;

            resourceParams.presResource    = params->presVdencIntraRowStoreScratchBuffer;
            resourceParams.dwOffset        = 0;
            resourceParams.pdwCmd          = (uint32_t*)&(cmd.RowStoreScratchBuffer.LowerAddress);
            resourceParams.dwLocationInCmd = 16;
            resourceParams.bIsWritable     = true;

            MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                this->m_osInterface,
                cmdBuffer,
                &resourceParams));
        }
        if (params->psFwdRefSurface0)
        {
            resourceParams.presResource = &params->psFwdRefSurface0->OsResource;
            resourceParams.dwOffset = 0;
            resourceParams.pdwCmd = (uint32_t*)&(cmd.FwdRef0.LowerAddress);
            resourceParams.dwLocationInCmd = 22;
            resourceParams.bIsWritable = true;

            MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                this->m_osInterface,
                cmdBuffer,
                &resourceParams));
        }

        if (params->psFwdRefSurface1)
        {
            resourceParams.presResource = &params->psFwdRefSurface1->OsResource;
            resourceParams.dwOffset = 0;
            resourceParams.pdwCmd = (uint32_t*)&(cmd.FwdRef1.LowerAddress);
            resourceParams.dwLocationInCmd = 25;
            resourceParams.bIsWritable = true;

            MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                this->m_osInterface,
                cmdBuffer,
                &resourceParams));
        }

        if (params->psFwdRefSurface2)
        {
            resourceParams.presResource = &params->psFwdRefSurface2->OsResource;
            resourceParams.dwOffset = 0;
            resourceParams.pdwCmd = (uint32_t*)&(cmd.FwdRef2.LowerAddress);
            resourceParams.dwLocationInCmd = 28;
            resourceParams.bIsWritable = true;

            MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                this->m_osInterface,
                cmdBuffer,
                &resourceParams));
        }
        if (params->presVdencStreamOutBuffer != nullptr)
        {
            cmd.VdencStatisticsStreamout.PictureFields.DW0.MemoryObjectControlState =
                this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_STREAMOUT_DATA_CODEC].Value;

            resourceParams.presResource    = params->presVdencStreamOutBuffer;
            resourceParams.dwOffset        = params->dwVdencStatsStreamOutOffset;
            resourceParams.pdwCmd          = (uint32_t*)&(cmd.VdencStatisticsStreamout.LowerAddress);
            resourceParams.dwLocationInCmd = 34;
            resourceParams.bIsWritable     = true;

            MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                this->m_osInterface,
                cmdBuffer,
                &resourceParams));
        }

        if (params->presVdencStreamInBuffer != nullptr)
        {
            cmd.StreaminDataPicture.PictureFields.DW0.MemoryObjectControlState =
                this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_VDENC_STREAMIN_CODEC].Value;

            resourceParams.presResource    = params->presVdencStreamInBuffer;
            resourceParams.dwOffset        = 0;
            resourceParams.pdwCmd          = (uint32_t*)&(cmd.StreaminDataPicture.LowerAddress);
            resourceParams.dwLocationInCmd = 13;
            resourceParams.bIsWritable     = false;

            MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                this->m_osInterface,
                cmdBuffer,
                &resourceParams));
        }

        for (refIdx = 0; refIdx <= params->dwNumRefIdxL0ActiveMinus1; refIdx++)
        {
            if (params->presVdencReferences[refIdx])
            {
                // L0 references
                MOS_ZeroMemory(&details, sizeof(details));
                details.Format = Format_Invalid;
                MHW_MI_CHK_STATUS(this->m_osInterface->pfnGetResourceInfo(this->m_osInterface, params->presVdencReferences[refIdx], &details));

                resourceParams.presResource    = params->presVdencReferences[refIdx];
                resourceParams.dwOffset        = details.RenderOffset.YUV.Y.BaseOffset;
                resourceParams.dwLocationInCmd = (refIdx * 3) + 22;
                resourceParams.bIsWritable     = false;
                switch (refIdx)
                {
                case 0:
                    resourceParams.pdwCmd = (uint32_t*)&(cmd.FwdRef0.LowerAddress);
                    break;
                case 1:
                    resourceParams.pdwCmd = (uint32_t*)&(cmd.FwdRef1.LowerAddress);
                    break;
                case 2:
                    resourceParams.pdwCmd = (uint32_t*)&(cmd.FwdRef2.LowerAddress);
                    break;
                case 3:
                    resourceParams.pdwCmd = (uint32_t*)&(cmd.BwdRef0.LowerAddress);
                    break;
                default:
                    break;
                }

                if (params->Mode == CODECHAL_ENCODE_MODE_HEVC)
                {
                    if (params->bMmcEnabled)
                    {
                        MHW_MI_CHK_STATUS(this->m_osInterface->pfnGetMemoryCompressionMode(
                        this->m_osInterface, params->presVdencReferences[refIdx], &mmcMode));
                    }
                    else
                    {
                        mmcMode = MOS_MEMCOMP_DISABLED;
                    }
                }
                else
                {
                    mmcMode = (params->PostDeblockSurfMmcState != MOS_MEMCOMP_DISABLED) ?
                        params->PostDeblockSurfMmcState : params->PreDeblockSurfMmcState;                    
                } 

                switch (refIdx)
                {
                case 0:
                    cmd.FwdRef0.PictureFields.DW0.MemoryCompressionEnable = MmcEnable(mmcMode) ? 1 : 0;
                    cmd.FwdRef0.PictureFields.DW0.CompressionType         = MmcIsRc(mmcMode) ? 1 : 0;
                    cmd.FwdRef0.PictureFields.DW0.MemoryObjectControlState =
                        this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;
                    cmd.FwdRef0.PictureFields.DW0.TiledResourceMode = Mhw_ConvertToTRMode(details.TileType);
                    break;
                case 1:
                    cmd.FwdRef1.PictureFields.DW0.MemoryCompressionEnable = MmcEnable(mmcMode) ? 1 : 0;
                    cmd.FwdRef1.PictureFields.DW0.CompressionType         = MmcIsRc(mmcMode) ? 1 : 0;
                    cmd.FwdRef1.PictureFields.DW0.MemoryObjectControlState =
                        this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;
                    cmd.FwdRef1.PictureFields.DW0.TiledResourceMode = Mhw_ConvertToTRMode(details.TileType);
                    break;
                case 2:
                    cmd.FwdRef2.PictureFields.DW0.MemoryCompressionEnable = MmcEnable(mmcMode) ? 1 : 0;
                    cmd.FwdRef2.PictureFields.DW0.CompressionType         = MmcIsRc(mmcMode) ? 1 : 0;
                    cmd.FwdRef2.PictureFields.DW0.MemoryObjectControlState =
                        this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;
                    cmd.FwdRef2.PictureFields.DW0.TiledResourceMode = Mhw_ConvertToTRMode(details.TileType);
                    break;
                case 3:
                    cmd.BwdRef0.PictureFields.DW0.MemoryCompressionEnable = MmcEnable(mmcMode) ? 1 : 0;
                    cmd.BwdRef0.PictureFields.DW0.CompressionType         = MmcIsRc(mmcMode) ? 1 : 0;
                    cmd.BwdRef0.PictureFields.DW0.MemoryObjectControlState =
                        this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;
                    cmd.BwdRef0.PictureFields.DW0.TiledResourceMode = Mhw_ConvertToTRMode(details.TileType);
                    break;
                default:
                    break;
                }

                MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                    this->m_osInterface,
                    cmdBuffer,
                    &resourceParams));
            }

            // so far VDEnc only support 2 4x/8x DS Ref Pictures
            if ((refIdx <= 1) && params->presVdenc4xDsSurface[refIdx])
            {
                if (params->Mode == CODECHAL_ENCODE_MODE_AVC)
                {
                    // 4x DS surface for VDEnc
                    MOS_ZeroMemory(&details, sizeof(details));
                    details.Format = Format_Invalid;
                    MHW_MI_CHK_STATUS(this->m_osInterface->pfnGetResourceInfo(this->m_osInterface, params->presVdenc4xDsSurface[refIdx], &details));

                    resourceParams.presResource    = params->presVdenc4xDsSurface[refIdx];
                    resourceParams.dwOffset        = details.RenderOffset.YUV.Y.BaseOffset;
                    resourceParams.dwLocationInCmd = (refIdx * 3) + 1;
                    resourceParams.bIsWritable     = false;
                    switch (refIdx)
                    {
                    case 0:
                        resourceParams.pdwCmd = (uint32_t*)&(cmd.DsFwdRef0.LowerAddress);
                        break;
                    case 1:
                        resourceParams.pdwCmd = (uint32_t*)&(cmd.DsFwdRef1.LowerAddress);
                        break;
                    default:
                        break;
                    }

                    mmcMode = params->Ps4xDsSurfMmcState;
                    switch (refIdx)
                    {
                    case 0:
                        cmd.DsFwdRef0.PictureFields.DW0.MemoryCompressionEnable = MmcEnable(mmcMode) ? 1 : 0;
                        cmd.DsFwdRef0.PictureFields.DW0.CompressionType         = MmcIsRc(mmcMode) ? 1 : 0;
                        cmd.DsFwdRef0.PictureFields.DW0.MemoryObjectControlState =
                            this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;
                        cmd.DsFwdRef0.PictureFields.DW0.TiledResourceMode = Mhw_ConvertToTRMode(details.TileType);
                        break;
                    case 1:
                        cmd.DsFwdRef1.PictureFields.DW0.MemoryCompressionEnable = MmcEnable(mmcMode) ? 1 : 0;
                        cmd.DsFwdRef1.PictureFields.DW0.CompressionType         = MmcIsRc(mmcMode) ? 1 : 0;
                        cmd.DsFwdRef1.PictureFields.DW0.MemoryObjectControlState =
                            this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;
                        cmd.DsFwdRef1.PictureFields.DW0.TiledResourceMode = Mhw_ConvertToTRMode(details.TileType);
                        break;
                    default:
                        break;
                    }

                    MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                        this->m_osInterface,
                        cmdBuffer,
                        &resourceParams));
                }
                else if (params->Mode == CODECHAL_ENCODE_MODE_HEVC || params->Mode == CODECHAL_ENCODE_MODE_VP9 || params->Mode == CODECHAL_ENCODE_MODE_AV1)
                {
                    // 8x DS surface
                    MOS_ZeroMemory(&details, sizeof(details));
                    details.Format = Format_Invalid;
                    MHW_MI_CHK_STATUS(this->m_osInterface->pfnGetResourceInfo(this->m_osInterface, params->presVdenc8xDsSurface[refIdx], &details));

                    resourceParams.presResource    = params->presVdenc8xDsSurface[refIdx];
                    resourceParams.dwOffset        = details.RenderOffset.YUV.Y.BaseOffset;
                    resourceParams.dwLocationInCmd = (refIdx * 3) + 1;
                    resourceParams.bIsWritable     = false;
                    switch (refIdx)
                    {
                    case 0:
                        resourceParams.pdwCmd = (uint32_t*)&(cmd.DsFwdRef0.LowerAddress);
                        break;
                    case 1:
                        resourceParams.pdwCmd = (uint32_t*)&(cmd.DsFwdRef1.LowerAddress);
                        break;
                    default:
                        break;
                    }

                    mmcMode = params->Ps8xDsSurfMmcState;
                    switch (refIdx)
                    {
                    case 0:
                        cmd.DsFwdRef0.PictureFields.DW0.MemoryCompressionEnable = MmcEnable(mmcMode) ? 1 : 0;
                        cmd.DsFwdRef0.PictureFields.DW0.CompressionType         = MmcIsRc(mmcMode) ? 1 : 0;
                        cmd.DsFwdRef0.PictureFields.DW0.MemoryObjectControlState =
                            this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;
                        cmd.DsFwdRef0.PictureFields.DW0.TiledResourceMode = Mhw_ConvertToTRMode(details.TileType);
                        break;
                    case 1:
                        cmd.DsFwdRef1.PictureFields.DW0.MemoryCompressionEnable = MmcEnable(mmcMode) ? 1 : 0;
                        cmd.DsFwdRef1.PictureFields.DW0.CompressionType         = MmcIsRc(mmcMode) ? 1 : 0;
                        cmd.DsFwdRef1.PictureFields.DW0.MemoryObjectControlState =
                            this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;
                        cmd.DsFwdRef1.PictureFields.DW0.TiledResourceMode = Mhw_ConvertToTRMode(details.TileType);
                        break;
                    default:
                        break;
                    }

                    MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                        this->m_osInterface,
                        cmdBuffer,
                        &resourceParams));

                    // 4x DS surface
                    MOS_ZeroMemory(&details, sizeof(details));
                    details.Format = Format_Invalid;
                    MHW_MI_CHK_STATUS(this->m_osInterface->pfnGetResourceInfo(this->m_osInterface, params->presVdenc4xDsSurface[refIdx], &details));

                    resourceParams.presResource    = params->presVdenc4xDsSurface[refIdx];
                    resourceParams.dwOffset        = details.RenderOffset.YUV.Y.BaseOffset;
                    resourceParams.dwLocationInCmd = (refIdx * 3) + 37;
                    resourceParams.bIsWritable     = false;
                    switch (refIdx)
                    {
                    case 0:
                        resourceParams.pdwCmd = (uint32_t*)&(cmd.DsFwdRef04X.LowerAddress);
                        break;
                    case 1:
                        resourceParams.pdwCmd = (uint32_t*)&(cmd.DsFwdRef14X.LowerAddress);
                        break;
                    default:
                        break;
                    }

                    mmcMode = params->Ps8xDsSurfMmcState;
                    switch (refIdx)
                    {
                    case 0:
                        cmd.DsFwdRef04X.PictureFields.DW0.MemoryCompressionEnable = MmcEnable(mmcMode) ? 1 : 0;
                        cmd.DsFwdRef04X.PictureFields.DW0.CompressionType         = MmcIsRc(mmcMode) ? 1 : 0;
                        cmd.DsFwdRef04X.PictureFields.DW0.MemoryObjectControlState =
                            this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;
                        cmd.DsFwdRef04X.PictureFields.DW0.TiledResourceMode = Mhw_ConvertToTRMode(details.TileType);
                        break;
                    case 1:
                        cmd.DsFwdRef14X.PictureFields.DW0.MemoryCompressionEnable = MmcEnable(mmcMode) ? 1 : 0;
                        cmd.DsFwdRef14X.PictureFields.DW0.CompressionType         = MmcIsRc(mmcMode) ? 1 : 0;
                        cmd.DsFwdRef14X.PictureFields.DW0.MemoryObjectControlState =
                            this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;
                        cmd.DsFwdRef14X.PictureFields.DW0.TiledResourceMode = Mhw_ConvertToTRMode(details.TileType);
                        break;
                    default:
                        break;
                    }

                    MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                        this->m_osInterface,
                        cmdBuffer,
                        &resourceParams));
                }
                else
                {
                    MHW_ASSERTMESSAGE("Encode mode = %d not supported", params->Mode);
                    return MOS_STATUS_INVALID_PARAMETER;
                }
            }
        }

        if (!params->isLowDelayB && (params->Mode == CODECHAL_ENCODE_MODE_HEVC || params->Mode == CODECHAL_ENCODE_MODE_AV1))
        {
            if (params->presVdencReferences[refIdx])
            {
                // L1 references
                MOS_ZeroMemory(&details, sizeof(details));
                details.Format = Format_Invalid;
                MHW_MI_CHK_STATUS(this->m_osInterface->pfnGetResourceInfo(this->m_osInterface, params->presVdencReferences[refIdx], &details));

                resourceParams.presResource = params->presVdencReferences[refIdx];
                resourceParams.dwOffset = details.RenderOffset.YUV.Y.BaseOffset;
                resourceParams.dwLocationInCmd = OFFSET_OF(typename TVdencCmds::VDENC_PIPE_BUF_ADDR_STATE_CMD, BwdRef0) / sizeof(uint32_t);
                resourceParams.bIsWritable = false;
                resourceParams.pdwCmd = (uint32_t*)&(cmd.BwdRef0.LowerAddress);

                if (params->Mode == CODECHAL_ENCODE_MODE_HEVC)
                {
                    if (params->bMmcEnabled)
                    {
                        MHW_MI_CHK_STATUS(this->m_osInterface->pfnGetMemoryCompressionMode(
                        this->m_osInterface, params->presVdencReferences[refIdx], &mmcMode));
                    }
                    else
                    {
                        mmcMode = MOS_MEMCOMP_DISABLED;
                    }
                }
                else
                {
                    mmcMode = (params->PostDeblockSurfMmcState != MOS_MEMCOMP_DISABLED) ?
                        params->PostDeblockSurfMmcState : params->PreDeblockSurfMmcState;                    
                } 

                cmd.BwdRef0.PictureFields.DW0.MemoryCompressionEnable = MmcEnable(mmcMode) ? 1 : 0;
                cmd.BwdRef0.PictureFields.DW0.CompressionType         = MmcIsRc(mmcMode) ? 1 : 0;
                cmd.BwdRef0.PictureFields.DW0.MemoryObjectControlState =
                    this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;
                cmd.BwdRef0.PictureFields.DW0.TiledResourceMode = Mhw_ConvertToTRMode(details.TileType);
                MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                    this->m_osInterface,
                    cmdBuffer,
                    &resourceParams));
            }

            if (params->presVdenc8xDsSurface[refIdx])
            {
                // 8x DS surface
                MOS_ZeroMemory(&details, sizeof(details));
                details.Format = Format_Invalid;
                MHW_MI_CHK_STATUS(this->m_osInterface->pfnGetResourceInfo(this->m_osInterface, params->presVdenc8xDsSurface[refIdx], &details));

                resourceParams.presResource = params->presVdenc8xDsSurface[refIdx];
                resourceParams.dwOffset = details.RenderOffset.YUV.Y.BaseOffset;
                resourceParams.dwLocationInCmd = OFFSET_OF(typename TVdencCmds::VDENC_PIPE_BUF_ADDR_STATE_CMD, DsBwdRef0) / sizeof(uint32_t);
                resourceParams.bIsWritable = false;
                resourceParams.pdwCmd = (uint32_t*)&(cmd.DsBwdRef0.LowerAddress);

                mmcMode = params->Ps8xDsSurfMmcState;

                cmd.DsBwdRef0.PictureFields.DW0.MemoryCompressionEnable = MmcEnable(mmcMode) ? 1 : 0;
                cmd.DsBwdRef0.PictureFields.DW0.CompressionType         = MmcIsRc(mmcMode) ? 1 : 0;
                cmd.DsBwdRef0.PictureFields.DW0.MemoryObjectControlState =
                    this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;
                cmd.DsBwdRef0.PictureFields.DW0.TiledResourceMode = Mhw_ConvertToTRMode(details.TileType);

                MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                    this->m_osInterface,
                    cmdBuffer,
                    &resourceParams));
            }

            if (params->presVdenc4xDsSurface[refIdx])
            {
                // 4x DS surface
                MOS_ZeroMemory(&details, sizeof(details));
                details.Format = Format_Invalid;
                MHW_MI_CHK_STATUS(this->m_osInterface->pfnGetResourceInfo(this->m_osInterface, params->presVdenc4xDsSurface[refIdx], &details));

                resourceParams.presResource = params->presVdenc4xDsSurface[refIdx];
                resourceParams.dwOffset = details.RenderOffset.YUV.Y.BaseOffset;
                resourceParams.dwLocationInCmd = OFFSET_OF(typename TVdencCmds::VDENC_PIPE_BUF_ADDR_STATE_CMD, DsBwdRef04X) / sizeof(uint32_t);
                resourceParams.bIsWritable = false;
                resourceParams.pdwCmd = (uint32_t*)&(cmd.DsBwdRef04X.LowerAddress);

                mmcMode = params->Ps4xDsSurfMmcState;
                cmd.DsBwdRef04X.PictureFields.DW0.MemoryCompressionEnable = MmcEnable(mmcMode) ? 1 : 0;
                cmd.DsBwdRef04X.PictureFields.DW0.CompressionType         = MmcIsRc(mmcMode) ? 1 : 0;
                cmd.DsBwdRef04X.PictureFields.DW0.MemoryObjectControlState =
                    this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;
                cmd.DsBwdRef04X.PictureFields.DW0.TiledResourceMode = Mhw_ConvertToTRMode(details.TileType);

                MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                    this->m_osInterface,
                    cmdBuffer,
                    &resourceParams));
            }
        }

        // extra surface for HEVC/VP9
        if ((params->Mode == CODECHAL_ENCODE_MODE_HEVC) || (params->Mode == CODECHAL_ENCODE_MODE_VP9) || (params->Mode == CODECHAL_ENCODE_MODE_AV1))
        {
            if (params->presColMvTempBuffer[0] != nullptr)
            {
                resourceParams.presResource    = params->presColMvTempBuffer[0];
                resourceParams.dwOffset        = 0;
                resourceParams.pdwCmd          = (uint32_t*)&(cmd.ColocatedMv.LowerAddress);
                resourceParams.dwLocationInCmd = 19;
                resourceParams.bIsWritable     = true;

                cmd.ColocatedMv.PictureFields.DW0.MemoryCompressionEnable = 0;
                cmd.ColocatedMv.PictureFields.DW0.CompressionType = 0;
                cmd.ColocatedMv.PictureFields.DW0.MemoryObjectControlState =
                    this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;

                MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                    this->m_osInterface,
                    cmdBuffer,
                    &resourceParams));
            }

            if (params->ps8xDsSurface != nullptr)
            {
                resourceParams.presResource    = &params->ps8xDsSurface->OsResource;
                resourceParams.dwOffset        = params->ps8xDsSurface->dwOffset;
                resourceParams.pdwCmd          = (uint32_t*)&(cmd.ScaledReferenceSurface8X.LowerAddress);
                resourceParams.dwLocationInCmd = 49;
                resourceParams.bIsWritable     = true;

                cmd.ScaledReferenceSurface8X.PictureFields.DW0.MemoryCompressionEnable = MmcEnable(params->Ps8xDsSurfMmcState) ? 1 : 0;
                cmd.ScaledReferenceSurface8X.PictureFields.DW0.CompressionType         = MmcIsRc(params->Ps8xDsSurfMmcState) ? 1 : 0;
                cmd.ScaledReferenceSurface8X.PictureFields.DW0.MemoryObjectControlState =
                    this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;

                MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                    this->m_osInterface,
                    cmdBuffer,
                    &resourceParams));
            }

            if (params->ps4xDsSurface != nullptr)
            {
                resourceParams.presResource    = &params->ps4xDsSurface->OsResource;
                resourceParams.dwOffset        = params->ps4xDsSurface->dwOffset;
                resourceParams.pdwCmd          = (uint32_t*)&(cmd.ScaledReferenceSurface4X.LowerAddress);
                resourceParams.dwLocationInCmd = 52;
                resourceParams.bIsWritable     = true;

                cmd.ScaledReferenceSurface4X.PictureFields.DW0.MemoryCompressionEnable = MmcEnable(params->Ps4xDsSurfMmcState) ? 1 : 0;
                cmd.ScaledReferenceSurface4X.PictureFields.DW0.CompressionType = MmcIsRc(params->Ps4xDsSurfMmcState) ? 1 : 0;
                cmd.ScaledReferenceSurface4X.PictureFields.DW0.MemoryObjectControlState =
                    this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;

                MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                    this->m_osInterface,
                    cmdBuffer,
                    &resourceParams));
            }

            // CuRecord stream-out buffer, not used so far
            if (params->presVdencCuObjStreamOutBuffer)
            {
                resourceParams.presResource    = params->presVdencCuObjStreamOutBuffer;
                resourceParams.dwOffset        = 0;
                resourceParams.pdwCmd          = (uint32_t*)&(cmd.VdencCuRecordStreamOutBuffer.LowerAddress);
                resourceParams.dwLocationInCmd = 43;
                resourceParams.bIsWritable     = true;

                cmd.VdencCuRecordStreamOutBuffer.PictureFields.DW0.MemoryCompressionEnable = 0;
                cmd.VdencCuRecordStreamOutBuffer.PictureFields.DW0.CompressionType = 0;
                cmd.VdencCuRecordStreamOutBuffer.PictureFields.DW0.MemoryObjectControlState =
                    this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;

                MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                    this->m_osInterface,
                    cmdBuffer,
                    &resourceParams));
            }

            if (params->presVdencPakObjCmdStreamOutBuffer)
            {
                resourceParams.presResource    = params->presVdencPakObjCmdStreamOutBuffer;
                resourceParams.dwOffset        = 0;
                resourceParams.pdwCmd          = (uint32_t*)&(cmd.VdencLcuPakObjCmdBuffer.LowerAddress);
                resourceParams.dwLocationInCmd = 46;
                resourceParams.bIsWritable     = true;

                cmd.VdencLcuPakObjCmdBuffer.PictureFields.DW0.MemoryCompressionEnable = 0;
                cmd.VdencLcuPakObjCmdBuffer.PictureFields.DW0.CompressionType = 0;
                cmd.VdencLcuPakObjCmdBuffer.PictureFields.DW0.MemoryObjectControlState =
                    this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_REFERENCE_PICTURE_CODEC].Value;

                MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                    this->m_osInterface,
                    cmdBuffer,
                    &resourceParams));
            }

            if (params->presSegmentMapStreamOut)
            {
                resourceParams.presResource = params->presSegmentMapStreamOut;
                resourceParams.dwOffset        = 0;
                resourceParams.pdwCmd          = (uint32_t*)&(cmd.Vp9SegmentationMapStreaminBuffer.LowerAddress);
                resourceParams.dwLocationInCmd = 55;
                resourceParams.bIsWritable     = true;

                MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                    this->m_osInterface,
                    cmdBuffer,
                    &resourceParams));

                resourceParams.presResource    = params->presSegmentMapStreamOut;
                resourceParams.dwOffset        = 0;
                resourceParams.pdwCmd          = (uint32_t*)&(cmd.Vp9SegmentationMapStreamoutBuffer.LowerAddress);
                resourceParams.dwLocationInCmd = 58;
                resourceParams.bIsWritable     = true;

                MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                    this->m_osInterface,
                    cmdBuffer,
                    &resourceParams));
            }
        }

        // DW61: Weights Histogram Streamout offset
        // This parameter specifies the 64 byte aligned offset in the VDEnc
        // Statistics Streamout buffer where the luma and chroma histogram for
        // the weights/offsets determination is written out.

        // The first 2 CLs(cacheline=64bytes) are ENC frame statistics data.
        // The 3rd CL is for VDL1* stats (hits & misses which doesn't model).
        // Hence it's a dummy CL for us. Histogram stats start from 4th CL onwards.
        cmd.DW61.WeightsHistogramStreamoutOffset = 3 * MHW_CACHELINE_SIZE;

        if (params->presVdencTileRowStoreBuffer != nullptr)
        {
            cmd.VdencTileRowStoreBuffer.BufferPictureFields.DW0.MemoryObjectControlState =
                this->m_cacheabilitySettings[MOS_CODEC_RESOURCE_USAGE_VDENC_ROW_STORE_BUFFER_CODEC].Value;

            resourceParams.presResource = params->presVdencTileRowStoreBuffer;
            resourceParams.dwOffset = 0;
            resourceParams.pdwCmd = (uint32_t*)&(cmd.VdencTileRowStoreBuffer.LowerAddress);
            resourceParams.dwLocationInCmd = 62;
            resourceParams.bIsWritable = true;

            MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                this->m_osInterface,
                cmdBuffer,
                &resourceParams));
        }

        if (params->presVdencCumulativeCuCountStreamoutSurface != nullptr)
        {
            resourceParams.presResource = params->presVdencCumulativeCuCountStreamoutSurface;
            resourceParams.dwOffset = 0;
            resourceParams.pdwCmd = (uint32_t*)&(cmd.VdencCumulativeCuCountStreamoutSurface.LowerAddress);
            resourceParams.dwLocationInCmd = 65;
            resourceParams.bIsWritable = true;

            MHW_MI_CHK_STATUS(this->AddResourceToCmd(
                this->m_osInterface,
                cmdBuffer,
                &resourceParams));
        }

        MHW_MI_CHK_STATUS(this->m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));

        return MOS_STATUS_SUCCESS;
    }

    uint32_t GetHWTileType(MOS_TILE_TYPE tileType, MOS_TILE_MODE_GMM tileModeGMM, bool gmmTileEnabled)
    {
        uint32_t tileMode = 0;

        if (gmmTileEnabled)
        {
            return tileModeGMM;
        }

        switch (tileType)
        {
        case MOS_TILE_LINEAR:
            tileMode = 0;
            break;
        case MOS_TILE_YS:
            tileMode = 1;
            break;
        case MOS_TILE_X:
            tileMode = 2;
            break;
        default:
            tileMode = 3;
            break;
        }
        return tileMode;
    }

    MOS_STATUS AddVdencSrcSurfaceStateCmd(
        PMOS_COMMAND_BUFFER       cmdBuffer,
        PMHW_VDBOX_SURFACE_PARAMS params) override
    {
        MHW_FUNCTION_ENTER;

        MHW_MI_CHK_NULL(this->m_osInterface);
        MHW_MI_CHK_NULL(cmdBuffer);
        MHW_MI_CHK_NULL(params);
        MHW_MI_CHK_NULL(params->psSurface);

        typename TVdencCmds::VDENC_SRC_SURFACE_STATE_CMD cmd;

        cmd.Dwords25.DW0.Width               = params->dwActualWidth - 1;
        cmd.Dwords25.DW0.Height              = params->dwActualHeight - 1;
        cmd.Dwords25.DW0.ColorSpaceSelection = params->bColorSpaceSelection;

        cmd.Dwords25.DW0.CrVCbUPixelOffsetVDirection = params->ucVDirection;

        uint32_t tilemode             = GetHWTileType(params->psSurface->TileType, params->psSurface->TileModeGMM, params->psSurface->bGMMTileEnabled);
        cmd.Dwords25.DW1.TiledSurface = (tilemode & 0x2) >> 1;
        cmd.Dwords25.DW1.TileWalk     = tilemode & 0x1;

        cmd.Dwords25.DW1.SurfaceFormat            = MosFormatToVdencSurfaceRawFormat(params->psSurface->Format);
        cmd.Dwords25.DW0.SurfaceFormatByteSwizzle = params->bDisplayFormatSwizzle;
        cmd.Dwords25.DW1.SurfacePitch             = params->psSurface->dwPitch - 1;
        cmd.Dwords25.DW2.YOffsetForUCb = cmd.Dwords25.DW3.YOffsetForVCr =
            MOS_ALIGN_CEIL((params->psSurface->UPlaneOffset.iSurfaceOffset - params->psSurface->dwOffset)/params->psSurface->dwPitch + params->psSurface->RenderOffset.YUV.U.YOffset, MHW_VDBOX_MFX_RAW_UV_PLANE_ALIGNMENT_GEN9);
        cmd.Dwords25.DW1.ChromaDownsampleFilterControl = 7;

        MHW_MI_CHK_STATUS(this->m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));

        return MOS_STATUS_SUCCESS;
    }

    MOS_STATUS AddVdencRefSurfaceStateCmd(
        PMOS_COMMAND_BUFFER       cmdBuffer,
        PMHW_VDBOX_SURFACE_PARAMS params) override
    {
        MHW_FUNCTION_ENTER;

        MHW_MI_CHK_NULL(this->m_osInterface);
        MHW_MI_CHK_NULL(cmdBuffer);
        MHW_MI_CHK_NULL(params);
        MHW_MI_CHK_NULL(params->psSurface);

        typename TVdencCmds::VDENC_REF_SURFACE_STATE_CMD cmd;

        if (params->bVdencDynamicScaling)
        {
            if (params->ucSurfaceStateId == CODECHAL_HCP_LAST_SURFACE_ID)
            {
                cmd.DW1.SurfaceId = 4;
            }
            else if (params->ucSurfaceStateId == CODECHAL_HCP_GOLDEN_SURFACE_ID)
            {
                cmd.DW1.SurfaceId = 5;
            }
            else if (params->ucSurfaceStateId == CODECHAL_HCP_ALTREF_SURFACE_ID)
            {
                cmd.DW1.SurfaceId = 6;
            }
        }

        if (params->Mode == CODECHAL_ENCODE_MODE_HEVC || params->Mode == CODECHAL_ENCODE_MODE_AV1)
        {
            cmd.Dwords25.DW0.Width  = params->dwActualWidth - 1;
            cmd.Dwords25.DW0.Height = params->dwActualHeight - 1;
        }
        else
        {
            cmd.Dwords25.DW0.Width  = params->psSurface->dwWidth - 1;
            cmd.Dwords25.DW0.Height = params->psSurface->dwHeight - 1;
        }

        cmd.Dwords25.DW0.CrVCbUPixelOffsetVDirection = params->ucVDirection;

        uint32_t tilemode             = GetHWTileType(params->psSurface->TileType, params->psSurface->TileModeGMM, params->psSurface->bGMMTileEnabled);
        cmd.Dwords25.DW1.TiledSurface = (tilemode & 0x2) >> 1;
        cmd.Dwords25.DW1.TileWalk     = tilemode & 0x1;

        cmd.Dwords25.DW1.SurfaceFormat = MosFormatToVdencSurfaceReconFormat(params->psSurface->Format);

        if (cmd.Dwords25.DW1.SurfaceFormat == TVdencCmds::VDENC_Surface_State_Fields_CMD::SURFACE_FORMAT_P010)
        {
            cmd.Dwords25.DW1.SurfaceFormat = TVdencCmds::VDENC_Surface_State_Fields_CMD::SURFACE_FORMAT_P010_VARIANT;
        }

        cmd.Dwords25.DW1.SurfacePitch = params->psSurface->dwPitch - 1;
        cmd.Dwords25.DW2.YOffsetForUCb = cmd.Dwords25.DW3.YOffsetForVCr = 
            (params->psSurface->UPlaneOffset.iSurfaceOffset - params->psSurface->dwOffset)/params->psSurface->dwPitch + params->psSurface->RenderOffset.YUV.U.YOffset;

        if (cmd.Dwords25.DW1.SurfaceFormat == vdencSurfaceFormatY416Variant ||
            cmd.Dwords25.DW1.SurfaceFormat == vdencSurfaceFormatAyuvVariant)
        {
            /* Y410/Y416 Reconstructed format handling */
            if (cmd.Dwords25.DW1.SurfaceFormat == vdencSurfaceFormatY416Variant)
                cmd.Dwords25.DW1.SurfacePitch = params->psSurface->dwPitch / 2 - 1;
            /* AYUV Reconstructed format handling */
            if (cmd.Dwords25.DW1.SurfaceFormat == vdencSurfaceFormatAyuvVariant)
                cmd.Dwords25.DW1.SurfacePitch = params->psSurface->dwPitch / 4 - 1;

            cmd.Dwords25.DW2.YOffsetForUCb = params->dwReconSurfHeight;
            cmd.Dwords25.DW3.YOffsetForVCr = params->dwReconSurfHeight << 1;
        }
        else if (cmd.Dwords25.DW1.SurfaceFormat == vdencSurfaceFormatY216Variant ||
            cmd.Dwords25.DW1.SurfaceFormat == vdencSurfaceFormatYuyvVariant)
        {
            cmd.Dwords25.DW2.YOffsetForUCb = cmd.Dwords25.DW3.YOffsetForVCr = params->dwReconSurfHeight;
        }

        MHW_MI_CHK_STATUS(this->m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));

        return MOS_STATUS_SUCCESS;
    }

    MOS_STATUS AddVdencDsRefSurfaceStateCmd(
        PMOS_COMMAND_BUFFER       cmdBuffer,
        PMHW_VDBOX_SURFACE_PARAMS params,
        uint8_t                   numSurfaces) override
    {
        uint32_t tilemode = 0;
        MHW_FUNCTION_ENTER;

        MHW_MI_CHK_NULL(this->m_osInterface);
        MHW_MI_CHK_NULL(cmdBuffer);
        MHW_MI_CHK_NULL(params);
        MHW_MI_CHK_NULL(params->psSurface);

        typename TVdencCmds::VDENC_DS_REF_SURFACE_STATE_CMD cmd;

        if (params->Mode == CODECHAL_ENCODE_MODE_HEVC || params->Mode == CODECHAL_ENCODE_MODE_AV1)
        {
            cmd.Dwords25.DW0.Width  = params->dwActualWidth - 1;
            cmd.Dwords25.DW0.Height = params->dwActualHeight - 1;
        }
        else
        {
            cmd.Dwords25.DW0.Width  = params->psSurface->dwWidth - 1;
            cmd.Dwords25.DW0.Height = params->psSurface->dwHeight - 1;
        }
        cmd.Dwords25.DW0.CrVCbUPixelOffsetVDirection = params->ucVDirection;

        tilemode                      = GetHWTileType(params->psSurface->TileType, params->psSurface->TileModeGMM, params->psSurface->bGMMTileEnabled);
        cmd.Dwords25.DW1.TiledSurface = (tilemode & 0x2) >> 1;
        cmd.Dwords25.DW1.TileWalk     = tilemode & 0x1;

        cmd.Dwords25.DW1.SurfaceFormat    = TVdencCmds::VDENC_Surface_State_Fields_CMD::SURFACE_FORMAT_PLANAR_420_8;
        cmd.Dwords25.DW1.SurfacePitch     = params->psSurface->dwPitch - 1;
        cmd.Dwords25.DW2.YOffsetForUCb    = cmd.Dwords25.DW3.YOffsetForVCr = 
            (params->psSurface->UPlaneOffset.iSurfaceOffset - params->psSurface->dwOffset)/params->psSurface->dwPitch + params->psSurface->RenderOffset.YUV.U.YOffset;

        // 2nd surface
        if (numSurfaces > 1)
        {
            params = params + 1;          // Increment pointer to move from 1st surface to 2nd surface.
            MHW_MI_CHK_NULL(params);
            MHW_MI_CHK_NULL(params->psSurface);

            if (params->Mode == CODECHAL_ENCODE_MODE_HEVC || params->Mode == CODECHAL_ENCODE_MODE_AV1)
            {
                cmd.Dwords69.DW0.Width  = params->dwActualWidth - 1;
                cmd.Dwords69.DW0.Height = params->dwActualHeight - 1;
            }
            else
            {
                cmd.Dwords69.DW0.Width  = params->psSurface->dwWidth - 1;
                cmd.Dwords69.DW0.Height = params->psSurface->dwHeight - 1;
            }
            cmd.Dwords69.DW0.CrVCbUPixelOffsetVDirection = params->ucVDirection;

            tilemode                          = GetHWTileType(params->psSurface->TileType, params->psSurface->TileModeGMM, params->psSurface->bGMMTileEnabled);
            cmd.Dwords69.DW1.TiledSurface     = (tilemode & 0x2) >> 1;
            cmd.Dwords69.DW1.TileWalk         = tilemode & 0x1;

            cmd.Dwords69.DW1.SurfaceFormat    = TVdencCmds::VDENC_Surface_State_Fields_CMD::SURFACE_FORMAT_PLANAR_420_8;
            cmd.Dwords69.DW1.SurfacePitch     = params->psSurface->dwPitch - 1;
            cmd.Dwords69.DW2.YOffsetForUCb    = cmd.Dwords69.DW3.YOffsetForVCr = 
                (params->psSurface->UPlaneOffset.iSurfaceOffset - params->psSurface->dwOffset)/params->psSurface->dwPitch + params->psSurface->RenderOffset.YUV.U.YOffset;
        }

        MHW_MI_CHK_STATUS(this->m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));

        return MOS_STATUS_SUCCESS;
    }

    MOS_STATUS AddVdencImgStateCmd(
        PMOS_COMMAND_BUFFER       cmdBuffer,
        PMHW_BATCH_BUFFER         batchBuffer,
        PMHW_VDBOX_AVC_IMG_PARAMS params) override
    {
        MHW_FUNCTION_ENTER;

        MHW_MI_CHK_NULL(params);
        MHW_MI_CHK_NULL(params->pEncodeAvcSeqParams);
        MHW_MI_CHK_NULL(params->pEncodeAvcPicParams);
 
        auto paramsG12 = dynamic_cast<PMHW_VDBOX_AVC_IMG_PARAMS_G12>(params);
        MHW_MI_CHK_NULL(paramsG12);

        typename TVdencCmds::VDENC_IMG_STATE_CMD cmd;

        auto avcSeqParams   = params->pEncodeAvcSeqParams;
        auto avcPicParams   = params->pEncodeAvcPicParams;
        auto avcSliceParams = params->pEncodeAvcSliceParams;

        // initialize
        cmd.DW1.VdencExtendedPakObjCmdEnable         = 1;
        cmd.DW2.UnidirectionalMixDisable             = false;
        cmd.DW4.IntraSadMeasureAdjustment            = 2;
        cmd.DW4.SubMacroblockSubPartitionMask        = 0x70;
        cmd.DW8.BilinearFilterEnable                 = false;
        cmd.DW9.Mode0Cost                            = 10;
        cmd.DW9.Mode1Cost                            = 0;
        cmd.DW9.Mode2Cost                            = 3;
        cmd.DW9.Mode3Cost                            = 30;
        cmd.DW20.PenaltyForIntra16X16NondcPrediction = 36;
        cmd.DW20.PenaltyForIntra8X8NondcPrediction   = 12;
        cmd.DW20.PenaltyForIntra4X4NondcPrediction   = 4;
        cmd.DW22.Smallmbsizeinword                   = 0xff;
        cmd.DW22.Largembsizeinword                   = 0xff;
        cmd.DW27.MaxHmvR                             = 0x2000;
        cmd.DW27.MaxVmvR                             = 0x200;
        cmd.DW33.Maxdeltaqp                          = 0x0f;

        // initialize for P frame
        if (avcPicParams->CodingType != I_TYPE)
        {
            cmd.DW2.BidirectionalWeight       = 0x20;
            cmd.DW4.SubPelMode                = (avcPicParams->bEnableSubPelMode) ? avcPicParams->SubPelMode : 3;
            cmd.DW4.BmeDisableForFbrMessage   = 1;
            cmd.DW4.InterSadMeasureAdjustment = 2;
            cmd.DW5.CrePrefetchEnable         = 1;
            cmd.DW8.NonSkipZeroMvCostAdded    = 1;
            cmd.DW8.NonSkipMbModeCostAdded    = 1;
            cmd.DW9.Mode0Cost                 = 7;
            cmd.DW9.Mode1Cost                 = 26;
            cmd.DW9.Mode2Cost                 = 30;
            cmd.DW9.Mode3Cost                 = 57;
            cmd.DW10.Mode4Cost                = 8;
            cmd.DW10.Mode5Cost                = 2;
            cmd.DW10.Mode6Cost                = 4;
            cmd.DW10.Mode7Cost                = 6;
            cmd.DW11.Mode8Cost                = 5;
            cmd.DW11.Mode9Cost                = 0;
            cmd.DW11.RefIdCost                = 4;
            cmd.DW12.MvCost0                  = 0;
            cmd.DW12.MvCost1                  = 6;
            cmd.DW12.MvCost2                  = 6;
            cmd.DW12.MvCost3                  = 9;
            cmd.DW13.MvCost4                  = 10;
            cmd.DW13.MvCost5                  = 13;
            cmd.DW13.MvCost6                  = 14;
            cmd.DW13.MvCost7                  = 24;
            cmd.DW31.SadHaarThreshold0        = 800;
            cmd.DW32.SadHaarThreshold1        = 1600;
            cmd.DW32.SadHaarThreshold2        = 2400;
            cmd.DW34.MidpointSadHaar          = 0x640;
        }

        cmd.DW1.VdencPerfmode                   = params->bVDEncPerfModeEnabled;
        cmd.DW1.Transform8X8Flag                = avcPicParams->transform_8x8_mode_flag;
        cmd.DW3.PictureWidth                    = params->wPicWidthInMb;
        cmd.DW4.ForwardTransformSkipCheckEnable = this->m_vdencFTQEnabled[avcSeqParams->TargetUsage];
        cmd.DW4.BlockBasedSkipEnabled           = this->m_vdencBlockBasedSkipEnabled[avcSeqParams->TargetUsage];
        cmd.DW5.CrePrefetchEnable               = params->bCrePrefetchEnable;
        cmd.DW5.PictureHeightMinusOne           = params->wPicHeightInMb - 1;
        cmd.DW5.PictureType                     = avcPicParams->CodingType - 1;
        cmd.DW5.ConstrainedIntraPredictionFlag  = avcPicParams->constrained_intra_pred_flag;

        if (paramsG12->bVDEncUltraModeEnabled)
        {
            cmd.DW1.VdencPerfmode  = true;
            cmd.DW1.VdencUltraMode = true;
        }

        // HME Ref1 Disable should be set as 0 when VDEnc Perf Mode is enabled 
        if ((avcPicParams->CodingType != I_TYPE) && 
            (!params->pEncodeAvcSliceParams->num_ref_idx_l0_active_minus1) &&
            (!params->bVDEncPerfModeEnabled))
        {
            cmd.DW5.HmeRef1Disable = true;
        }

        if (avcSeqParams->EnableSliceLevelRateCtrl)
        {
            cmd.DW5.MbSliceThresholdValue = params->dwMbSlcThresholdValue;
        }

        cmd.DW6.SliceMacroblockHeightMinusOne = params->wPicHeightInMb - 1;

        cmd.DW8.LumaIntraPartitionMask = avcPicParams->transform_8x8_mode_flag ? 0 : TVdencCmds::VDENC_IMG_STATE_CMD::LUMA_INTRA_PARTITION_MASK_UNNAMED2;

        cmd.DW14.QpPrimeY = avcPicParams->QpY + avcSliceParams->slice_qp_delta;

        if (params->pVDEncModeCost)
        {
            cmd.DW9.Mode0Cost  = *(params->pVDEncModeCost);
            cmd.DW9.Mode1Cost  = *(params->pVDEncModeCost + 1);
            cmd.DW9.Mode2Cost  = *(params->pVDEncModeCost + 2);
            cmd.DW9.Mode3Cost  = *(params->pVDEncModeCost + 3);

            cmd.DW10.Mode4Cost = *(params->pVDEncModeCost + 4);
            cmd.DW10.Mode5Cost = *(params->pVDEncModeCost + 5);
            cmd.DW10.Mode6Cost = *(params->pVDEncModeCost + 6);
            cmd.DW10.Mode7Cost = *(params->pVDEncModeCost + 7);

            cmd.DW11.Mode8Cost = *(params->pVDEncModeCost + 8);
            cmd.DW11.RefIdCost = *(params->pVDEncModeCost + 10);
        }
        if (params->pVDEncMvCost)
        {
            cmd.DW12.MvCost0 = *(params->pVDEncMvCost);
            cmd.DW12.MvCost1 = *(params->pVDEncMvCost + 1);
            cmd.DW12.MvCost2 = *(params->pVDEncMvCost + 2);
            cmd.DW12.MvCost3 = *(params->pVDEncMvCost + 3);
            cmd.DW13.MvCost4 = *(params->pVDEncMvCost + 4);
            cmd.DW13.MvCost5 = *(params->pVDEncMvCost + 5);
            cmd.DW13.MvCost6 = *(params->pVDEncMvCost + 6);
            cmd.DW13.MvCost7 = *(params->pVDEncMvCost + 7);
        }

        cmd.DW27.MaxVmvR = params->dwMaxVmvR;

        if (params->pVDEncHmeMvCost)
        {
            cmd.DW28.HmeMvCost0 = *(params->pVDEncHmeMvCost);
            cmd.DW28.HmeMvCost1 = *(params->pVDEncHmeMvCost + 1);
            cmd.DW28.HmeMvCost2 = *(params->pVDEncHmeMvCost + 2);
            cmd.DW28.HmeMvCost3 = *(params->pVDEncHmeMvCost + 3);
            cmd.DW29.HmeMvCost4 = *(params->pVDEncHmeMvCost + 4);
            cmd.DW29.HmeMvCost5 = *(params->pVDEncHmeMvCost + 5);
            cmd.DW29.HmeMvCost6 = *(params->pVDEncHmeMvCost + 6);
            cmd.DW29.HmeMvCost7 = *(params->pVDEncHmeMvCost + 7);
        }

        // HMEOffset is in range of -128 to 127, clip value to within range
        if (avcPicParams->bEnableHMEOffset)
        {
            cmd.DW7.Hme0XOffset = MOS_CLAMP_MIN_MAX(avcPicParams->HMEOffset[0][0][0], -128, 127);
            cmd.DW7.Hme0YOffset = MOS_CLAMP_MIN_MAX(avcPicParams->HMEOffset[0][0][1], -128, 127);
            cmd.DW7.Hme1XOffset = MOS_CLAMP_MIN_MAX(avcPicParams->HMEOffset[1][0][0], -128, 127);
            cmd.DW7.Hme1YOffset = MOS_CLAMP_MIN_MAX(avcPicParams->HMEOffset[1][0][1], -128, 127);
        }

        // Rolling-I settings
        if ((avcPicParams->CodingType != I_TYPE) && (avcPicParams->EnableRollingIntraRefresh != ROLLING_I_DISABLED))
        {
            cmd.DW21.IntraRefreshEnableRollingIEnable = avcPicParams->EnableRollingIntraRefresh != ROLLING_I_DISABLED ? 1 : 0;
            cmd.DW21.IntraRefreshMode                 = avcPicParams->EnableRollingIntraRefresh == ROLLING_I_ROW ? 0 : 1;        // 0->Row based ; 1->Column based
            cmd.DW21.IntraRefreshMBPos                = avcPicParams->IntraRefreshMBNum;
            cmd.DW21.IntraRefreshMBSizeMinusOne       = avcPicParams->IntraRefreshUnitinMB;
            cmd.DW21.QpAdjustmentForRollingI          = avcPicParams->IntraRefreshQPDelta;

            auto waTable = this->m_osInterface->pfnGetWaTable(this->m_osInterface);
            MHW_MI_CHK_NULL(waTable);

            // WA to prevent error propagation from top-right direction.
            // Disable prediction modes 3, 7 for 4x4
            // and modes 0, 2, 3, 4, 5, 7 for 8x8 (due to filtering)
            if (avcPicParams->EnableRollingIntraRefresh == ROLLING_I_COLUMN &&
                MEDIA_IS_WA(waTable, Wa_18011246551))
            {
                cmd.DW17.AvcIntra4X4ModeMask = 0x88;
                cmd.DW17.AvcIntra8X8ModeMask = 0xBD;
            }
        }

        // Setting MinMaxQP values if they are presented
        if (avcPicParams->ucMaximumQP && avcPicParams->ucMinimumQP)
        {
            cmd.DW33.MaxQp = avcPicParams->ucMaximumQP;
            cmd.DW33.MinQp = avcPicParams->ucMinimumQP;
        }
        else
        {
            // Set default values
            cmd.DW33.MaxQp = 0x33;
            cmd.DW33.MinQp = 0x0a;
        }

        // VDEnc CQP case ROI settings, BRC ROI will be handled in HuC FW
        if (!params->bVdencBRCEnabled && avcPicParams->NumROI && avcPicParams->bNativeROI)
        {
            MHW_ASSERT(avcPicParams->NumROI < 4);

            int8_t priorityLevelOrDQp[ENCODE_VDENC_AVC_MAX_ROI_NUMBER_G9] = { 0 };

            for (uint8_t i = 0; i < avcPicParams->NumROI; i++)
            {
                int8_t dQpRoi = avcPicParams->ROIDistinctDeltaQp[i];

                // clip delta qp roi to VDEnc supported range
                priorityLevelOrDQp[i] = (char)CodecHal_Clip3(
                    ENCODE_VDENC_AVC_MIN_ROI_DELTA_QP_G9, ENCODE_VDENC_AVC_MAX_ROI_DELTA_QP_G9, dQpRoi);
            }

            cmd.DW34.RoiEnable = true;

            // Zone0 is reserved for non-ROI region
            cmd.DW30.RoiQpAdjustmentForZone1 = priorityLevelOrDQp[0];
            cmd.DW30.RoiQpAdjustmentForZone2 = priorityLevelOrDQp[1];
            cmd.DW30.RoiQpAdjustmentForZone3 = priorityLevelOrDQp[2];
        }

        if (avcSeqParams->RateControlMethod != RATECONTROL_CQP)
        {
            cmd.DW30.QpAdjustmentForShapeBestIntra4X4Winner = 0;
            cmd.DW30.QpAdjustmentForShapeBestIntra8X8Winner = 0;
            cmd.DW30.QpAdjustmentForShapeBestIntra16X16Winner = 0;

            cmd.DW31.BestdistortionQpAdjustmentForZone0 = 0;
            cmd.DW31.BestdistortionQpAdjustmentForZone1 = 1;
            cmd.DW31.BestdistortionQpAdjustmentForZone2 = 2;
            cmd.DW31.BestdistortionQpAdjustmentForZone3 = 3;
        }

        if (avcPicParams->EnableRollingIntraRefresh == ROLLING_I_DISABLED && params->bVdencStreamInEnabled &&
            (avcPicParams->NumDirtyROI && params->bVdencBRCEnabled || avcPicParams->NumROI && avcPicParams->bNativeROI ||
                (avcPicParams->TargetFrameSize > 0 && !avcSeqParams->LookaheadDepth)))  // TCBRC (for AdaptiveRegionBoost)
        {
            cmd.DW34.RoiEnable = true;
        }

        if (params->bVdencStreamInEnabled)
        {
            cmd.DW34.FwdPredictor0MvEnable = 1;
            cmd.DW34.PpmvDisable           = 1;

            // non-native ROI in ForceQP mode (VDEnc StreamIn filled by HuC in BRC mode and by UMD driver in CQP) or MBQP
            if (avcPicParams->EnableRollingIntraRefresh == ROLLING_I_DISABLED &&
                ((avcPicParams->NumROI && !avcPicParams->bNativeROI) || paramsG12->bStreamInMbQpEnabled))
            {
                cmd.DW34.MbLevelQpEnable = 1;
            }
        }

        if (cmdBuffer == nullptr && batchBuffer == nullptr)
        {
            MHW_ASSERTMESSAGE("There was no valid buffer to add the HW command to.");
            return MOS_STATUS_NULL_POINTER;
        }

        MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(this->m_osInterface, cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));

        return MOS_STATUS_SUCCESS;
    }

    MOS_STATUS AddVdencWalkerStateCmd(
        PMOS_COMMAND_BUFFER                  cmdBuffer,
        PMHW_VDBOX_VDENC_WALKER_STATE_PARAMS params) override
    {
        MHW_FUNCTION_ENTER;

        MHW_MI_CHK_NULL(this->m_osInterface);
        MHW_MI_CHK_NULL(cmdBuffer);
        MHW_MI_CHK_NULL(params);

        typename TVdencCmds::VDENC_WALKER_STATE_CMD cmd;

        if (params->Mode == CODECHAL_ENCODE_MODE_AVC)
        {
            MHW_MI_CHK_NULL(params->pAvcSeqParams);
            MHW_MI_CHK_NULL(params->pAvcSlcParams);

            auto avcSeqParams = params->pAvcSeqParams;
            auto avcSlcParams = params->pAvcSlcParams;

            cmd.DW1.MbLcuStartYPosition = avcSlcParams->first_mb_in_slice / CODECHAL_GET_WIDTH_IN_MACROBLOCKS(avcSeqParams->FrameWidth);

            cmd.DW2.NextsliceMbStartYPosition = (avcSlcParams->first_mb_in_slice + avcSlcParams->NumMbsForSlice) / CODECHAL_GET_WIDTH_IN_MACROBLOCKS(avcSeqParams->FrameWidth);

            if (cmd.DW2.NextsliceMbStartYPosition > (uint32_t)CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(avcSeqParams->FrameHeight))
            {
                cmd.DW2.NextsliceMbStartYPosition = (uint32_t)CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(avcSeqParams->FrameHeight);
            }

            cmd.DW3.Log2WeightDenomLuma = avcSlcParams->luma_log2_weight_denom;

            cmd.DW5.TileWidth = avcSeqParams->FrameWidth - 1;
        }
        else if (params->Mode == CODECHAL_ENCODE_MODE_HEVC)
        {
            auto paramsG12 = dynamic_cast<PMHW_VDBOX_VDENC_WALKER_STATE_PARAMS_G12>(params);
            MHW_MI_CHK_NULL(paramsG12);

            MHW_MI_CHK_NULL(params->pHevcEncSeqParams);
            MHW_MI_CHK_NULL(params->pHevcEncPicParams);
            MHW_MI_CHK_NULL(params->pEncodeHevcSliceParams);

            auto seqParams   = params->pHevcEncSeqParams;
            auto picParams   = params->pHevcEncPicParams;
            auto sliceParams = params->pEncodeHevcSliceParams;

            uint32_t ctbSize     = 1 << (seqParams->log2_max_coding_block_size_minus3 + 3);
            uint32_t widthInPix  = (1 << (seqParams->log2_min_coding_block_size_minus3 + 3)) * (seqParams->wFrameWidthInMinCbMinus1 + 1);
            uint32_t widthInCtb  = (widthInPix / ctbSize) + ((widthInPix % ctbSize) ? 1 : 0);  // round up
            uint32_t heightInPix = (1 << (seqParams->log2_min_coding_block_size_minus3 + 3)) * (seqParams->wFrameHeightInMinCbMinus1 + 1);
            uint32_t heightInCtb = (heightInPix / ctbSize) + ((heightInPix % ctbSize) ? 1 : 0);  // round up
            uint32_t shift     = seqParams->log2_max_coding_block_size_minus3 - seqParams->log2_min_coding_block_size_minus3;

            cmd.DW3.Log2WeightDenomLuma = cmd.DW3.HevcLog2WeightDemonLuma =
                (picParams->weighted_pred_flag || picParams->weighted_bipred_flag) ? (picParams->bEnableGPUWeightedPrediction ? 6 : sliceParams->luma_log2_weight_denom) : 0;

            if (paramsG12->pTileCodingParams == nullptr)
            {
                // No tiling support
                cmd.DW1.MbLcuStartYPosition          = sliceParams->slice_segment_address / widthInCtb;
                cmd.DW2.NextsliceMbLcuStartXPosition = (sliceParams->slice_segment_address + sliceParams->NumLCUsInSlice) / heightInCtb;
                cmd.DW2.NextsliceMbStartYPosition    = (sliceParams->slice_segment_address + sliceParams->NumLCUsInSlice) / widthInCtb;
                cmd.DW5.TileWidth                    = widthInPix - 1;
                cmd.DW5.TileHeight                   = heightInPix - 1;
            }
            else
            {
                cmd.DW1.MbLcuStartXPosition          = paramsG12->pTileCodingParams->TileStartLCUX;
                cmd.DW1.MbLcuStartYPosition          = paramsG12->pTileCodingParams->TileStartLCUY;

                cmd.DW2.NextsliceMbLcuStartXPosition = paramsG12->pTileCodingParams->TileStartLCUX + (paramsG12->pTileCodingParams->TileWidthInMinCbMinus1 >> shift) + 1;
                cmd.DW2.NextsliceMbStartYPosition    = paramsG12->pTileCodingParams->TileStartLCUY + (paramsG12->pTileCodingParams->TileHeightInMinCbMinus1 >> shift) + 1;

                cmd.DW4.TileStartCtbX                = paramsG12->pTileCodingParams->TileStartLCUX * ctbSize;
                cmd.DW4.TileStartCtbY                = paramsG12->pTileCodingParams->TileStartLCUY * ctbSize;

                cmd.DW5.TileWidth                    = ((paramsG12->pTileCodingParams->TileWidthInMinCbMinus1 + 1) << (seqParams->log2_min_coding_block_size_minus3 + 3)) - 1;
                cmd.DW5.TileHeight                   = ((paramsG12->pTileCodingParams->TileHeightInMinCbMinus1 + 1) << (seqParams->log2_min_coding_block_size_minus3 + 3)) - 1;
                cmd.DW1.FirstSuperSlice              = 1;
                cmd.DW3.NumParEngine                 = paramsG12->dwNumberOfPipes;
                cmd.DW3.TileNumber                   = paramsG12->dwTileId;
                cmd.DW3.TileRowStoreSelect           = paramsG12->pTileCodingParams->TileRowStoreSelect;
                cmd.DW8.TileStreamoutOffsetEnable    = 1;
                cmd.DW8.TileStreamoutOffset          = paramsG12->dwTileId * 19;

                cmd.DW6.StreaminOffsetEnable         = 1;
                cmd.DW6.TileStreaminOffset           = paramsG12->pTileCodingParams->TileStreaminOffset;

                // PAK Object StreamOut Offset Computation 
                uint32_t tileLCUStreamOutByteOffset = 0;
                if (paramsG12->pTileCodingParams->TileStartLCUX != 0 || paramsG12->pTileCodingParams->TileStartLCUY != 0)
                {
                    uint32_t ctbSize = 1 << (seqParams->log2_max_coding_block_size_minus3 + 3);
                    uint32_t NumOfCUInLCU = (ctbSize >> 3) * (ctbSize >> 3);  // Min CU size is 8
                    uint32_t ImgWidthInLCU = (((seqParams->wFrameWidthInMinCbMinus1 + 1) << (seqParams->log2_min_coding_block_size_minus3 + 3)) + ctbSize - 1) / ctbSize;
                    uint32_t ImgHeightInLCU = (((seqParams->wFrameHeightInMinCbMinus1 + 1) << (seqParams->log2_min_coding_block_size_minus3 + 3)) + ctbSize - 1) / ctbSize;
                    uint32_t NumLCUsCurLocation = paramsG12->pTileCodingParams->TileStartLCUY * ImgWidthInLCU + paramsG12->pTileCodingParams->TileStartLCUX * 
                                                  ((((paramsG12->pTileCodingParams->TileHeightInMinCbMinus1 + 1) << (seqParams->log2_min_coding_block_size_minus3 + 3)) + ctbSize - 1) / ctbSize);
                    //For PAKObject Surface
                    tileLCUStreamOutByteOffset = 2 * BYTES_PER_DWORD * NumLCUsCurLocation * (NUM_PAK_DWS_PER_LCU + NumOfCUInLCU * NUM_DWS_PER_CU);
                    //Add 1 CL for size info at the beginning of each tile
                    tileLCUStreamOutByteOffset += MHW_CACHELINE_SIZE;
                    //CL alignment at end of every tile
                    tileLCUStreamOutByteOffset = MOS_ROUNDUP_DIVIDE(tileLCUStreamOutByteOffset, MHW_CACHELINE_SIZE);
                }

                cmd.DW9.TileLcuStreamOutOffset = tileLCUStreamOutByteOffset;
                cmd.DW9.LcuStreamOutOffsetEnable = 0x1;

                if (cmd.DW4.TileStartCtbY == 0)
                {
                    //RowStore Offset Computation
                    uint32_t num32x32InX = (cmd.DW4.TileStartCtbX) / 32;
                    cmd.DW7.RowStoreOffsetEnable = 1;
                    cmd.DW7.TileRowstoreOffset = num32x32InX;
                }
            }

            // for IBC
            cmd.DW11.Value &= 0xfffc00ff;
            cmd.DW12.Value = (cmd.DW12.Value & 0xfcffffff) | 0x1000000;
            cmd.DW12.IbcControl = params->pHevcEncPicParams->pps_curr_pic_ref_enabled_flag ?
                paramsG12->IBCControl : VDENC_WALKER_STATE_COMMAND_IBC_CONTROL_IBC_DISABLED_G12;

            cmd.DW12.PaletteModeEnable = (seqParams->palette_mode_enabled_flag != 0) ? 1 : 0;
            uint32_t sliceQP = picParams->QpY + sliceParams->slice_qp_delta;
            uint32_t index;
            if (sliceQP <= 12)
            {
                index = 0;
            }
            else if (sliceQP > 12 && sliceQP <= 47)
            {
                index = (sliceQP - 8) / 5;
            }
            else if (sliceQP > 47 && sliceQP <= 49)
            {
                index = 8;
            }
            else
            {
                index = 9;
            }
            const uint32_t table1[10] = {0x50001,0x50001,0x50001,0x50002,0x90002,0x90002,0x90002,0xd0002,0x190002,0x210003};
            cmd.DW12.Value = (cmd.DW12.Value & 0xff80fff8) | table1[index];
            const uint32_t table2[10] = {0x2000a,0x2000a,0x2000a,0x4000a,0x8000a,0xc0010,0xc0018,0xc0018,0x100020,0x180030};
            cmd.DW13.Value = table2[index];
            const uint32_t table3[10] = {0x101004,0x101004,0x101004,0xc1008,0x42004,0x42006,0x13f06,0x13f06,0x13f0c,0x13006};
            cmd.DW14.Value = (cmd.DW14.Value & 0xffe0c0c0) | table3[index];
            const uint32_t table4[10] = {0x100004,0x100004,0x100004,0x100004,0x200004,0x300004,0x400004,0x600004,0x800004,0x1000004};
            cmd.DW15.Value = (cmd.DW15.Value & 0xfc00) | table4[index];

            if (seqParams->bit_depth_luma_minus8 > 0 && seqParams->palette_mode_enabled_flag)
            {

                const uint32_t table1[10] = {0x3,0x3,0x3,0x4,0x4,0x4,0x4,0x4,0x4,0x5};
                cmd.DW12.Value  = (cmd.DW12.Value & 0xfffffff8) | table1[index];
                const uint32_t table2[10] = {0x80028,0x80028,0x80028,0x100028,0x200028,0x300040,0x300060,0x300060,0x400080,0x6000c0};
                cmd.DW13.Value  = table2[index];
                const uint32_t table3[10] = {0x400000,0x400000,0x400000,0x400000,0x800000,0xc00000,0x1000000,0x1800000,0x2000000,0x4000000};
                cmd.DW15.Value = (cmd.DW15.Value & 0xffff) | table3[index];
            }

            cmd.DW12.Value &= 0xffff00ff;
            cmd.DW14.Value = (cmd.DW14.Value & 0x9fffff) | 0xc8400000;
            cmd.DW16.Value = (cmd.DW16.Value & 0xffffff) | 0xa6000000;
            if (seqParams->TargetUsage == 7)
            {
                cmd.DW16.Value = (cmd.DW16.Value & 0xffc0c0c0) | 0x313131;
            }
            else
            {
                cmd.DW16.Value = (cmd.DW16.Value & 0xffc0c0c0) | 0x3f3f3f;
            }
        }
        else if (params->Mode == CODECHAL_ENCODE_MODE_VP9)
        {
            auto paramsG12 = dynamic_cast<PMHW_VDBOX_VDENC_WALKER_STATE_PARAMS_G12>(params);
            MHW_MI_CHK_NULL(paramsG12);
            MHW_MI_CHK_NULL(params->pVp9EncPicParams);
            auto vp9PicParams = params->pVp9EncPicParams;
            auto tileCodingParams = paramsG12->pTileCodingParams;

            if (tileCodingParams == nullptr)
            {
                cmd.DW2.NextsliceMbLcuStartXPosition = CODECHAL_GET_WIDTH_IN_BLOCKS(vp9PicParams->SrcFrameWidthMinus1, CODEC_VP9_SUPER_BLOCK_WIDTH);
                cmd.DW2.NextsliceMbStartYPosition    = CODECHAL_GET_HEIGHT_IN_BLOCKS(vp9PicParams->SrcFrameHeightMinus1, CODEC_VP9_SUPER_BLOCK_HEIGHT);
                cmd.DW5.TileWidth                    = vp9PicParams->SrcFrameWidthMinus1;
                cmd.DW5.TileHeight                   = vp9PicParams->SrcFrameHeightMinus1;
                cmd.DW1.FirstSuperSlice              = 1;
            }
            else
            {
                cmd.DW1.MbLcuStartXPosition          = tileCodingParams->TileStartLCUX;
                cmd.DW1.MbLcuStartYPosition          = tileCodingParams->TileStartLCUY;

                cmd.DW5.TileWidth                    = ((tileCodingParams->TileWidthInMinCbMinus1 + 1) * CODEC_VP9_MIN_BLOCK_WIDTH) - 1;
                cmd.DW5.TileHeight                   = ((tileCodingParams->TileHeightInMinCbMinus1 + 1) * CODEC_VP9_MIN_BLOCK_HEIGHT) - 1;

                cmd.DW4.TileStartCtbX                = tileCodingParams->TileStartLCUX * CODEC_VP9_SUPER_BLOCK_WIDTH;
                cmd.DW4.TileStartCtbY                = tileCodingParams->TileStartLCUY * CODEC_VP9_SUPER_BLOCK_HEIGHT;

                cmd.DW2.NextsliceMbLcuStartXPosition = CODECHAL_GET_WIDTH_IN_BLOCKS((cmd.DW4.TileStartCtbX + cmd.DW5.TileWidth + 1), CODEC_VP9_SUPER_BLOCK_WIDTH);
                cmd.DW2.NextsliceMbStartYPosition    = CODECHAL_GET_HEIGHT_IN_BLOCKS((cmd.DW4.TileStartCtbY + cmd.DW5.TileHeight + 1), CODEC_VP9_SUPER_BLOCK_HEIGHT);

                cmd.DW1.FirstSuperSlice              = 1;
                cmd.DW3.NumParEngine                 = paramsG12->dwNumberOfPipes;
                cmd.DW3.TileNumber                   = paramsG12->dwTileId;

                //Frame Stats Offset
                cmd.DW8.TileStreamoutOffsetEnable = 1;
                cmd.DW8.TileStreamoutOffset = (paramsG12->dwTileId * 19); // 3 CLs or 48 DWs of statistics data + 16CLs or 256 DWs of Histogram data

                uint32_t tileStartXInSBs = (cmd.DW4.TileStartCtbX / CODEC_VP9_SUPER_BLOCK_WIDTH);
                uint32_t tileStartYInSBs = (cmd.DW4.TileStartCtbY / CODEC_VP9_SUPER_BLOCK_HEIGHT);
                //Aligned Tile height & frame width
                uint32_t tileHeightInSBs = (cmd.DW5.TileHeight + 1 + (CODEC_VP9_SUPER_BLOCK_HEIGHT - 1)) / CODEC_VP9_SUPER_BLOCK_HEIGHT;
                uint32_t frameWidthInSBs = (vp9PicParams->SrcFrameWidthMinus1 + 1 + (CODEC_VP9_SUPER_BLOCK_WIDTH - 1)) / CODEC_VP9_SUPER_BLOCK_WIDTH;

                cmd.DW6.StreaminOffsetEnable = 1;
                //StreamIn data is 4 CLs per LCU
                cmd.DW6.TileStreaminOffset = (tileStartYInSBs * frameWidthInSBs + tileStartXInSBs * tileHeightInSBs) * (4);

                //Compute PAK Object StreamOut Offsets
                uint32_t tileLCUStreamOutOffsetInCachelines = 0;
                if (cmd.DW4.TileStartCtbY != 0 || cmd.DW4.TileStartCtbX != 0)
                {
                    //Aligned Tile width & frame height
                    uint32_t numOfSBs = tileStartYInSBs * frameWidthInSBs + tileStartXInSBs * tileHeightInSBs;
                    //max LCU size is 64, min Cu size is 8
                    uint32_t maxNumOfCUInSB = (CODEC_VP9_SUPER_BLOCK_HEIGHT / CODEC_VP9_MIN_BLOCK_HEIGHT) * (CODEC_VP9_SUPER_BLOCK_WIDTH / CODEC_VP9_MIN_BLOCK_WIDTH);
                    //(num of SBs in a tile) *  (num of cachelines needed per SB)
                    tileLCUStreamOutOffsetInCachelines = numOfSBs * (MOS_ROUNDUP_DIVIDE((2 * BYTES_PER_DWORD * (NUM_PAK_DWS_PER_LCU + maxNumOfCUInSB * NUM_DWS_PER_CU)), MHW_CACHELINE_SIZE));
                }

                cmd.DW9.LcuStreamOutOffsetEnable = 1;
                cmd.DW9.TileLcuStreamOutOffset = tileLCUStreamOutOffsetInCachelines;

                if (cmd.DW4.TileStartCtbY == 0)
                {
                    //RowStore Offset Computation
                    uint32_t num32x32sInX = (cmd.DW4.TileStartCtbX) / 32;
                    cmd.DW7.RowStoreOffsetEnable = 1;
                    cmd.DW7.TileRowstoreOffset = num32x32sInX;
                }
            }
        }

        MHW_MI_CHK_STATUS(this->m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));

        return MOS_STATUS_SUCCESS;
    }

    MOS_STATUS AddVdencAvcWeightsOffsetsStateCmd(
        PMOS_COMMAND_BUFFER                cmdBuffer,
        PMHW_VDBOX_AVC_WEIGHTOFFSET_PARAMS params) override
    {
        MHW_FUNCTION_ENTER;

        MHW_MI_CHK_NULL(this->m_osInterface);
        MHW_MI_CHK_NULL(cmdBuffer);
        MHW_MI_CHK_NULL(params);
        MHW_MI_CHK_NULL(params->pAvcPicParams);

        typename TVdencCmds::VDENC_WEIGHTSOFFSETS_STATE_CMD cmd;

        auto avcPicParams = params->pAvcPicParams;

        if (avcPicParams->weighted_pred_flag == 1)
        {
            cmd.DW1.WeightsForwardReference0 = params->Weights[0][0][0][0];
            cmd.DW1.OffsetForwardReference0  = params->Weights[0][0][0][1];
            cmd.DW1.WeightsForwardReference1 = params->Weights[0][1][0][0];
            cmd.DW1.OffsetForwardReference1  = params->Weights[0][1][0][1];
            cmd.DW2.WeightsForwardReference2 = params->Weights[0][2][0][0];
            cmd.DW2.OffsetForwardReference2  = params->Weights[0][2][0][1];
        }
        //set to default value when weighted prediction not enabled
        else
        {
            cmd.DW1.WeightsForwardReference0 = 1;
            cmd.DW1.OffsetForwardReference0  = 0;
            cmd.DW1.WeightsForwardReference1 = 1;
            cmd.DW1.OffsetForwardReference1  = 0;
            cmd.DW2.WeightsForwardReference2 = 1;
            cmd.DW2.OffsetForwardReference2  = 0;
        }

        MHW_MI_CHK_STATUS(this->m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));

        return MOS_STATUS_SUCCESS;
    }

    MOS_STATUS AddVdencWeightsOffsetsStateCmd(
        PMOS_COMMAND_BUFFER                   cmdBuffer,
        PMHW_BATCH_BUFFER                     batchBuffer,
        PMHW_VDBOX_VDENC_WEIGHT_OFFSET_PARAMS params) override
    {
        MHW_FUNCTION_ENTER;

        MHW_MI_CHK_NULL(params);

        typename TVdencCmds::VDENC_WEIGHTSOFFSETS_STATE_CMD cmd;

        cmd.DW1.WeightsForwardReference0         = 1;
        cmd.DW1.OffsetForwardReference0          = 0;
        cmd.DW1.WeightsForwardReference1         = 1;
        cmd.DW1.OffsetForwardReference1          = 0;
        cmd.DW2.WeightsForwardReference2         = 1;
        cmd.DW2.OffsetForwardReference2          = 0;
        cmd.DW2.HevcVp9WeightsBackwardReference0 = 1;
        cmd.DW2.HevcVp9OffsetBackwardReference0  = 0;

        // Luma Offsets and Weights
        if (params->bWeightedPredEnabled)
        {
            uint32_t  refPicListNum = 0;
            // DWORD 1
            cmd.DW1.WeightsForwardReference0 = CodecHal_Clip3(-128, 127,
                params->LumaWeights[refPicListNum][0] + params->dwDenom);
            cmd.DW1.OffsetForwardReference0  = params->LumaOffsets[refPicListNum][0];
            cmd.DW1.WeightsForwardReference1 = CodecHal_Clip3(-128, 127,
                params->LumaWeights[refPicListNum][1] + params->dwDenom);
            cmd.DW1.OffsetForwardReference1  = params->LumaOffsets[refPicListNum][1];

            // DWORD 2
            cmd.DW2.WeightsForwardReference2 = CodecHal_Clip3(-128, 127,
                params->LumaWeights[refPicListNum][2] + params->dwDenom);
            cmd.DW2.OffsetForwardReference2  = params->LumaOffsets[refPicListNum][2];
            if (!params->isLowDelay)
            {
                refPicListNum = 1;
                cmd.DW2.HevcVp9WeightsBackwardReference0 = CodecHal_Clip3(-128, 127,
                    params->LumaWeights[refPicListNum][0] + params->dwDenom);
                cmd.DW2.HevcVp9OffsetBackwardReference0 = params->LumaOffsets[refPicListNum][0];
            }
            else
            {
                cmd.DW2.HevcVp9WeightsBackwardReference0 = cmd.DW1.WeightsForwardReference0;
                cmd.DW2.HevcVp9OffsetBackwardReference0 = cmd.DW1.OffsetForwardReference0;
            }
        }

        if (cmdBuffer == nullptr && batchBuffer == nullptr)
        {
            MHW_ASSERTMESSAGE("There was no valid buffer to add the HW command to.");
            return MOS_STATUS_NULL_POINTER;
        }

        MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(this->m_osInterface, cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));

        return MOS_STATUS_SUCCESS;
    }

   MOS_STATUS AddVdencCmd1Cmd(
        PMOS_COMMAND_BUFFER                  cmdBuffer,
        PMHW_BATCH_BUFFER                    batchBuffer,
        PMHW_VDBOX_VDENC_CMD1_PARAMS  params) override
    {
        return MOS_STATUS_SUCCESS;
    }

    MOS_STATUS AddVdencCmd2Cmd(
        PMOS_COMMAND_BUFFER                 cmdBuffer,
        PMHW_BATCH_BUFFER                   batchBuffer,
        PMHW_VDBOX_VDENC_CMD2_STATE params) override
    {
        return MOS_STATUS_SUCCESS;
    }

    //!
    //! \brief    Adds VDEnc Pipe Control State command in command buffer
    //! \details  Client facing function to add VDEnc Pipe Control State command in command buffer
    //! \param    PMOS_COMMAND_BUFFER  cmdBuffer
    //!           [in] Command buffer to which HW command is added
    //! \param    PMHW_VDBOX_VDENC_CONTROL_STATE_PARAMS params
    //!           [in] Params structure used to populate the HW command
    //! \return   MOS_STATUS
    //!           MOS_STATUS_SUCCESS if success, else fail reason
    //!
    MOS_STATUS AddVdencControlStateCmd(
        PMOS_COMMAND_BUFFER                   cmdBuffer,
        PMHW_VDBOX_VDENC_CONTROL_STATE_PARAMS params)
    {
        MHW_FUNCTION_ENTER;

        MHW_MI_CHK_NULL(this->m_osInterface);
        MHW_MI_CHK_NULL(cmdBuffer);
        MHW_MI_CHK_NULL(params);

        typename TVdencCmds::VDENC_CONTROL_STATE_CMD    cmd;


        if (params->bVdencInitialization)
        {
            cmd.DW1.VdencInitialization     = 1;
        }
        else
        {
            MHW_ASSERTMESSAGE("Invalid parameter for VDENC_CONTROL_STATE.");
            return MOS_STATUS_INVALID_PARAMETER;
        }

        MHW_MI_CHK_STATUS(this->m_osInterface->pfnAddCommand(cmdBuffer, &cmd, sizeof(cmd)));

        return MOS_STATUS_SUCCESS;
    }

    PMHW_VDBOX_PIPE_MODE_SELECT_PARAMS CreateMhwVdboxPipeModeSelectParams() override
    {
        auto pipeModeSelectParams = MOS_New(MHW_VDBOX_PIPE_MODE_SELECT_PARAMS_G12);

        return pipeModeSelectParams;
    }

    void ReleaseMhwVdboxPipeModeSelectParams(PMHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams) override
    {
        MOS_Delete(pipeModeSelectParams);
    }
};

//!  MHW Vdbox Vdenc interface for Gen12 X
/*!
This class defines the Vdenc command construction functions for Gen12 common platforms
*/
class MhwVdboxVdencInterfaceG12X : public MhwVdboxVdencInterfaceG12<mhw_vdbox_vdenc_g12_X>
{
public:
        //!
    //! \brief  Constructor
    //!
    MhwVdboxVdencInterfaceG12X(PMOS_INTERFACE osInterface) : MhwVdboxVdencInterfaceG12(osInterface)
    {
        MHW_FUNCTION_ENTER;
    }

    inline uint32_t GetVdencCmd1Size() override
    {
        return mhw_vdbox_vdenc_g12_X::VDENC_CMD1_CMD::byteSize;
    }

    inline uint32_t GetVdencCmd2Size() override
    {
        return mhw_vdbox_vdenc_g12_X::VDENC_CMD2_CMD::byteSize;
    }

    //!
    //! \brief    Destructor
    //!
    virtual ~MhwVdboxVdencInterfaceG12X()
    {
        MHW_FUNCTION_ENTER;
    }

    MOS_STATUS AddVdencCmd1Cmd(
        PMOS_COMMAND_BUFFER                  cmdBuffer,
        PMHW_BATCH_BUFFER                    batchBuffer,
        PMHW_VDBOX_VDENC_CMD1_PARAMS  params) override
    {
        MHW_FUNCTION_ENTER;

        MHW_MI_CHK_NULL(params);

        typename mhw_vdbox_vdenc_g12_X::VDENC_CMD1_CMD cmd;

        cmd.DW22.Value = 0x10101010;
        cmd.DW23.Value = 0x10101010;
        cmd.DW24.Value = 0x10101010;
        cmd.DW25.Value = 0x10101010;
        cmd.DW26.Value = 0x10101010;
        cmd.DW27.Value = 0x10101010;
        cmd.DW28.Value = 0x10101010;
        cmd.DW29.Value = 0x10101010;
        if (params->Mode == CODECHAL_ENCODE_MODE_HEVC)
        {
            MHW_MI_CHK_NULL(params->pHevcEncPicParams);
            auto hevcPicParams = params->pHevcEncPicParams;
            MHW_MI_CHK_NULL(params->pHevcEncSlcParams);
            auto hevcSlcParams = params->pHevcEncSlcParams;

            const uint32_t table1[3] = {0x5030200,0x5030200,0x5030200};
            const uint8_t indexTable1[3] = {0,1,2};
            cmd.DW1.Value = table1[indexTable1[hevcPicParams->CodingType - 1]];
            const uint32_t table2[3] = {0xb090806,0xb090806,0xb090806};
            const uint8_t indexTable2[3] = {0,1,2};
            cmd.DW2.Value = table2[indexTable2[hevcPicParams->CodingType - 1]];

            cmd.DW3.Value = 0x1c140c04;
            cmd.DW4.Value = 0x3c342c24;
            cmd.DW5.Value = 0x5c544c44;
            cmd.DW6.Value = 0x1c140c04;
            cmd.DW7.Value = 0x3c342c24;
            cmd.DW8.Value = 0x5c544c44;
            cmd.DW14.Value = 0x0;
            cmd.DW15.Value = 0x0;
            cmd.DW16.Value &= 0xffff0000;
            cmd.DW19.Value = (cmd.DW19.Value & 0xff0000ff) | 0x140400;
            cmd.DW20.Value = 0x14141414;
            cmd.DW21.Value = 0x14141414;
            if (params->bHevcVisualQualityImprovement)
            {
                auto qpPrimeYac = CodecHal_Clip3(10, 51, hevcPicParams->QpY + hevcSlcParams->slice_qp_delta);
                if (qpPrimeYac >= 22 && qpPrimeYac <= 51)
                {
                    const uint32_t table3[30] = {0x0,0x60000,0xc0000,0x120000,0x190000,0x1f0000,0x250000,0x2c0000,0x320000,0x380000,0x3f0000,0x3f0000,0x3f0000,0x3f0000,0x3f0000,0x3f0000,0x3f0000,0x3f0000,0x3f0000,0x3f0000,0x3f0000,0x3f0000,0x3f0000,0x3f0000,0x3f0000,0x3f0000,0x3f0000,0x3f0000,0x3f0000,0x3f0000};
                    cmd.DW14.Value = (cmd.DW14.Value & 0xff00ffff) |table3[qpPrimeYac - 22];
                }
            }

            if (params->pHevcEncPicParams->CodingType == I_TYPE)
            {
                cmd.DW10.Value = 0x23131f0f;
                cmd.DW11.Value = (cmd.DW11.Value & 0xffff0000) | 0x2313;
                cmd.DW12.Value = 0x3e5c445c;
                cmd.DW13.Value = (cmd.DW13.Value & 0xff00) | 0x1e040044;
                cmd.DW16.Value = (cmd.DW16.Value & 0xffff) | 0x70000;
                cmd.DW17.Value = 0xd0e1007;
                cmd.DW18.Value = (cmd.DW18.Value & 0xffffff00) | 0x32;
                cmd.DW18.Value = (cmd.DW18.Value & 0xffff00ff) | (hevcPicParams->NumROI ? 0 : 0x1e00);
                cmd.DW30.Value = (cmd.DW30.Value & 0xff000000) | 0x101010;
            }
            else if (params->pHevcEncPicParams->CodingType == B_TYPE)
            {
                cmd.DW10.Value = 0x23131f0f;
                cmd.DW11.Value = 0x331b2313;
                cmd.DW12.Value = 0x476e4d6e;
                cmd.DW13.Value = 0x3604004d;
                cmd.DW16.Value = (cmd.DW16.Value & 0xffff) | 0x4150000;
                cmd.DW17.Value = 0x23231415;
                cmd.DW18.Value = (cmd.DW18.Value & 0xffffff00) | 0x3f;
                cmd.DW18.Value = (cmd.DW18.Value & 0xffff00ff) | (hevcPicParams->NumROI ? 0 : 0x4400);
                cmd.DW30.Value = (cmd.DW30.Value & 0xff000000) | 0x232323;
            }
        }
        else if (params->Mode == CODECHAL_ENCODE_MODE_VP9)
        {
            MHW_MI_CHK_NULL(params->pVp9EncPicParams);

            auto vp9PicParams = params->pVp9EncPicParams;
            auto qp = vp9PicParams->LumaACQIndex;
            auto vp9FrameType = vp9PicParams->PicFlags.fields.frame_type;

            const uint32_t table1[2][256] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
                                            0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
            const uint8_t indexTable1[2] = {0,1};
            cmd.DW1.Value = table1[indexTable1[vp9FrameType]][qp];
            const uint32_t table2[2][256] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
                                            0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
            const uint8_t indexTable2[2] = {0,1};
            cmd.DW2.Value = table2[indexTable2[vp9FrameType]][qp];

            cmd.DW3.Value = 0x1a130b04;
            cmd.DW4.Value = 0x3f312922;
            cmd.DW5.Value = 0x7164584b;
            cmd.DW6.Value = 0x1a130b04;
            cmd.DW7.Value = 0x3f312922;
            cmd.DW8.Value = 0x7164584b;
            cmd.DW20.Value = 0xc0c0c0c;
            cmd.DW21.Value = 0xc0c0c0c;
            cmd.DW22.Value = 0x10101010;
            cmd.DW23.Value = 0x10101010;
            cmd.DW24.Value = 0x10101010;
            cmd.DW25.Value = 0x10101010;
            cmd.DW26.Value = 0x10101010;
            cmd.DW27.Value = 0x10101010;
            cmd.DW28.Value = 0x10101010;
            cmd.DW29.Value = 0x10101010;
            if(vp9FrameType == CODEC_VP9_KEY_FRAME)
            {
                cmd.DW9.Value &= 0xff000000;
                cmd.DW10.Value = 0x0;
                cmd.DW11.Value = 0x0;
                cmd.DW12.Value = 0x0;
                cmd.DW13.Value = 0x32000000;
                cmd.DW14.Value = 0x1f5e0000;
                cmd.DW15.Value = 0x1f5e0000;
                cmd.DW16.Value = (cmd.DW16.Value & 0xff000000) | 0x4b0000;
                cmd.DW17.Value = 0x3219194b;
                cmd.DW18.Value = 0x4b5e0026;
                cmd.DW19.Value = (cmd.DW19.Value & 0xff) | 0x7d7d0000;
            }
            else
            {
                cmd.DW9.Value = (cmd.DW9.Value & 0xff000000) | 0x26191f;
                cmd.DW10.Value = 0x1e0b1e0b;
                cmd.DW11.Value = 0x19001e0b;
                cmd.DW12.Value = 0x19321f4b;
                cmd.DW13.Value = 0x4404001f;
                cmd.DW14.Value = 0x30900000;
                cmd.DW15.Value = 0x30900000;
                cmd.DW16.Value = (cmd.DW16.Value & 0xff000000) | 0x260000;
                cmd.DW17.Value = 0x13194b26;
                cmd.DW18.Value = 0x3f5e0d5e;
                cmd.DW19.Value = (cmd.DW19.Value & 0xff) | 0x4e320f00;
            }
        }

        if (cmdBuffer == nullptr && batchBuffer == nullptr)
        {
            MHW_ASSERTMESSAGE("There was no valid buffer to add the HW command to.");
            return MOS_STATUS_NULL_POINTER;
        }

        MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(this->m_osInterface, cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));

        return MOS_STATUS_SUCCESS;
    }

    MOS_STATUS AddVdencCmd2Cmd(
        PMOS_COMMAND_BUFFER                 cmdBuffer,
        PMHW_BATCH_BUFFER                   batchBuffer,
        PMHW_VDBOX_VDENC_CMD2_STATE params) override
    {
        MHW_FUNCTION_ENTER;

        MHW_MI_CHK_NULL(params);
        auto extParams = std::static_pointer_cast<MHW_VDBOX_VDENC_CMD2_STATE>(params);
        MHW_MI_CHK_NULL(extParams);

        typename mhw_vdbox_vdenc_g12_X::VDENC_CMD2_CMD cmd;

        cmd.DW2.Value = (cmd.DW2.Value & 0xdff00000) | 0x2005aff3;
        cmd.DW3.Value = 0xfe02ff01;
        cmd.DW4.Value = 0xfc04fd03;
        cmd.DW5.Value = (cmd.DW5.Value & 0xff7e03ff) | 0x80ac00;
        cmd.DW7.Value = (cmd.DW7.Value & 0xffd90ff0) | 0x62003;
        cmd.DW9.Value = (cmd.DW9.Value & 0xffff) | 0x43840000;
        cmd.DW12.Value = 0xffffffff;
        cmd.DW15.Value = 0x4e201f40;
        cmd.DW16.Value = (cmd.DW16.Value & 0xf0ff0000) | 0xf003300;
        cmd.DW17.Value = (cmd.DW17.Value & 0xfff00000) | 0x2710;
        cmd.DW19.Value = (cmd.DW19.Value & 0x80ffffff) | 0x18000000;
        cmd.DW21.Value &= 0xfffffff;
        cmd.DW22.Value = 0x1f001102;
        cmd.DW23.Value = 0xaaaa1f00;
        cmd.DW27.Value = (cmd.DW27.Value & 0xffff0000) | 0x1a1a;
        if (params->pHevcEncPicParams && params->pHevcEncSeqParams)
        {
            MHW_MI_CHK_NULL(params->pHevcEncSeqParams);
            MHW_MI_CHK_NULL(params->pHevcEncPicParams);
            MHW_MI_CHK_NULL(params->pHevcEncSlcParams);
            auto hevcSeqParams = params->pHevcEncSeqParams;
            auto hevcPicParams = params->pHevcEncPicParams;
            auto hevcSlcParams = params->pHevcEncSlcParams;

            bool vdencROIEnabled = params->bROIStreamInEnabled;
            bool vdencStreamInEnabled = params->bStreamInEnabled;

            cmd.DW1.FrameWidthInPixelsMinusOne = ((hevcSeqParams->wFrameWidthInMinCbMinus1 + 1) <<
                (hevcSeqParams->log2_min_coding_block_size_minus3 + 3)) - 1;
            cmd.DW1.FrameHeightInPixelsMinusOne = ((hevcSeqParams->wFrameHeightInMinCbMinus1 + 1) <<
                (hevcSeqParams->log2_min_coding_block_size_minus3 + 3)) - 1;

            cmd.DW2.PictureType = (hevcPicParams->CodingType == I_TYPE) ? 0 : (extParams->bIsLowDelayB ? 3 : 2);
            cmd.DW2.TemporalMvpEnableFlag = (hevcPicParams->CodingType == I_TYPE) ? 0 : params->pHevcEncSeqParams->sps_temporal_mvp_enable_flag;
            cmd.DW2.TransformSkip = hevcPicParams->transform_skip_enabled_flag;

            cmd.DW5.NumRefIdxL0Minus1 = hevcSlcParams->num_ref_idx_l0_active_minus1;
            cmd.DW5.NumRefIdxL1Minus1 = hevcSlcParams->num_ref_idx_l1_active_minus1;

            cmd.DW5.Value = (cmd.DW5.Value & 0xff83ffff) | 0x400000;
            cmd.DW14.Value = (cmd.DW14.Value & 0xffff) | 0x7d00000;
            cmd.DW15.Value = 0x4e201f40;
            cmd.DW17.Value = (cmd.DW17.Value & 0xfff00000) | 0x2710;
            cmd.DW18.Value = (cmd.DW18.Value & 0xffff) | 0x600000;
            cmd.DW19.Value = (cmd.DW19.Value & 0xffff0000) | 0xc0;
            cmd.DW20.Value &= 0xfffeffff;
            cmd.DW7.TilingEnable = hevcPicParams->tiles_enabled_flag;
            cmd.DW37.TileReplayEnable = extParams->bTileReplayEnable;

            if (hevcPicParams->CodingType != I_TYPE)
            {
                uint8_t   refFrameId;
                int8_t    diffPoc;

                refFrameId = hevcSlcParams->RefPicList[0][0].FrameIdx;
                diffPoc = ((refFrameId >= CODEC_MAX_NUM_REF_FRAME_HEVC) ? 0x0 : hevcPicParams->RefFramePOCList[refFrameId]) - hevcPicParams->CurrPicOrderCnt;
                cmd.DW3.PocNumberForRefid0InL0    = CodecHal_Clip3(-16, 16, -diffPoc);
                cmd.DW2.LongTermReferenceFlagsL0  = (refFrameId >= CODEC_MAX_NUM_REF_FRAME_HEVC) ? 0 : CodecHal_PictureIsLongTermRef(hevcPicParams->RefFrameList[refFrameId]);
                refFrameId = hevcSlcParams->RefPicList[0][1].FrameIdx;
                diffPoc = ((refFrameId >= CODEC_MAX_NUM_REF_FRAME_HEVC) ? 0x0 : hevcPicParams->RefFramePOCList[refFrameId]) - hevcPicParams->CurrPicOrderCnt;
                cmd.DW3.PocNumberForRefid1InL0    = CodecHal_Clip3(-16, 16, -diffPoc);
                cmd.DW2.LongTermReferenceFlagsL0 |= ((refFrameId >= CODEC_MAX_NUM_REF_FRAME_HEVC) ? 0 : CodecHal_PictureIsLongTermRef(hevcPicParams->RefFrameList[refFrameId])) << 1;
                refFrameId = hevcSlcParams->RefPicList[0][2].FrameIdx;
                diffPoc                        = ((refFrameId >= CODEC_MAX_NUM_REF_FRAME_HEVC) ? 0x0 : hevcPicParams->RefFramePOCList[refFrameId]) - hevcPicParams->CurrPicOrderCnt;
                cmd.DW4.PocNumberForRefid2InL0 = CodecHal_Clip3(-16, 16, -diffPoc);
                cmd.DW2.LongTermReferenceFlagsL0 |= ((refFrameId >= CODEC_MAX_NUM_REF_FRAME_HEVC) ? 0 : CodecHal_PictureIsLongTermRef(hevcPicParams->RefFrameList[refFrameId])) << 2;

                refFrameId = hevcSlcParams->RefPicList[1][0].FrameIdx;
                diffPoc                          = ((refFrameId >= CODEC_MAX_NUM_REF_FRAME_HEVC) ? 0x0 : hevcPicParams->RefFramePOCList[refFrameId]) - hevcPicParams->CurrPicOrderCnt;
                cmd.DW3.PocNumberForRefid0InL1   = CodecHal_Clip3(-16, 16, -diffPoc);
                if (refFrameId >= CODEC_MAX_NUM_REF_FRAME_HEVC)
                {
                    return MOS_STATUS_INVALID_PARAMETER;
                }
                cmd.DW2.LongTermReferenceFlagsL1 = CodecHal_PictureIsLongTermRef(hevcPicParams->RefFrameList[refFrameId]);

                cmd.DW3.PocNumberForRefid1InL1 = cmd.DW3.PocNumberForRefid1InL0;
                cmd.DW4.PocNumberForRefid2InL1 = cmd.DW4.PocNumberForRefid2InL0;
                cmd.DW5.SubPelMode = (params->bEnableSubPelMode) ? params->SubPelMode : 3;
            }
            else
            {
                cmd.DW3.Value = cmd.DW4.Value = 0;
            }

            switch (hevcSeqParams->TargetUsage)
            {
            case 1:                                 // Quality mode
                cmd.DW2.Value &= 0xdfffffff;
                cmd.DW2.Value = (cmd.DW2.Value & 0xfffffffc) | (hevcPicParams->CodingType == I_TYPE ? 2 : 3);
                cmd.DW7.Value &= 0xfffffeff;
                cmd.DW7.Value = (cmd.DW7.Value & 0xfffff7ff) | (hevcPicParams->CodingType == I_TYPE ? 0x800 : 0);
                cmd.DW9.Value = (cmd.DW9.Value & 0xfffff) | 0x43800000;
                cmd.DW12.Value = 0xffffffff;
                cmd.DW34.Value = (cmd.DW34.Value & 0xffffff) | 0x21000000;
                break;
            case 4:                                 // Normal mode
                cmd.DW2.Value &= 0xdfffffff;
                cmd.DW7.Value &= 0xfffffeff;
                cmd.DW9.Value = (cmd.DW9.Value & 0xfffff) | 0x43800000;
                cmd.DW12.Value = 0xce4014a0;
                cmd.DW34.Value = (cmd.DW34.Value & 0xffffff) | 0x21000000;
                break;
            case 7:                                 // Speed mode
                cmd.DW2.Value = (cmd.DW2.Value & 0xdfffffff) | 0x20000000;
                cmd.DW7.Value = (cmd.DW7.Value & 0xfff7feff) | 0x80100;
                cmd.DW9.Value = (cmd.DW9.Value & 0xffff) | 0x22420000;
                cmd.DW12.Value = 0x89800dc0;
                cmd.DW34.Value = (cmd.DW34.Value & 0xffffff) | 0x20000000;
                break;
            default:
                MHW_ASSERTMESSAGE("Invalid TU provided!");
                return MOS_STATUS_INVALID_PARAMETER;
            }

            if (hevcSlcParams->num_ref_idx_l0_active_minus1 == 0)
            {
                cmd.DW7.Value = (cmd.DW7.Value & 0xfff7ffff) | 0x80000;
            }

            if (!extParams->bIsLowDelayB)
            {
                cmd.DW7.Value &= 0xfff7feff;
            }

            cmd.DW7.VdencStreamInEnable = vdencStreamInEnabled;
            cmd.DW7.PakOnlyMultiPassEnable = params->bPakOnlyMultipassEnable;

            if (extParams->bIsLowDelayB)
            {
                cmd.DW8.Value = 0;
                cmd.DW9.Value &= 0xffff0000;
            }
            else
            {
                cmd.DW8.Value = 0x54555555;
                cmd.DW9.Value = (cmd.DW9.Value & 0xffff0000) | 0x5555;
            }

            cmd.DW16.MinQp = hevcPicParams->BRCMinQp < 0x0a ? 10 : hevcPicParams->BRCMinQp;
            cmd.DW16.MaxQp = hevcPicParams->BRCMaxQp < 0x0a ? 51 : (hevcPicParams->BRCMaxQp > 0x33 ? 0x33 : hevcPicParams->BRCMaxQp);
            cmd.DW17.TemporalMVEnableForIntegerSearch = cmd.DW2.TemporalMvpEnableFlag & extParams->bIsLowDelayB;

            if (vdencROIEnabled)
            {
                int8_t priorityLevelOrDQp[ENCODE_VDENC_HEVC_MAX_STREAMINROI_G10] = { 0 };

                cmd.DW5.StreaminRoiEnable = vdencROIEnabled;

                for (uint8_t i = 0; i < ENCODE_VDENC_HEVC_MAX_STREAMINROI_G10; i++)
                {
                    priorityLevelOrDQp[i] = (int8_t)CodecHal_Clip3(
                        ENCODE_VDENC_HEVC_MIN_ROI_DELTA_QP_G10, ENCODE_VDENC_HEVC_MAX_ROI_DELTA_QP_G10, hevcPicParams->ROIDistinctDeltaQp[i]);
                }

                cmd.DW13.RoiQpAdjustmentForZone1Stage3 = priorityLevelOrDQp[0];
                cmd.DW13.RoiQpAdjustmentForZone2Stage3 = priorityLevelOrDQp[1];
                cmd.DW13.RoiQpAdjustmentForZone3Stage3 = priorityLevelOrDQp[2];
            }

            if ((hevcPicParams->bEnableRollingIntraRefresh) && (hevcPicParams->CodingType != I_TYPE))
            {
                uint32_t rollingILimit = (hevcPicParams->bEnableRollingIntraRefresh == ROLLING_I_ROW) ?
                    MOS_ROUNDUP_DIVIDE(cmd.DW1.FrameHeightInPixelsMinusOne + 1, 32) :
                    MOS_ROUNDUP_DIVIDE(cmd.DW1.FrameWidthInPixelsMinusOne + 1, 32);

                cmd.DW7.Value = (cmd.DW7.Value & 0xfffffbff) | 0x400;
                cmd.DW7.Value = (cmd.DW7.Value & 0xfffffbff) | ((hevcSeqParams->TargetUsage == 1) ? 0x400 : 0);
                cmd.DW21.Value = (cmd.DW21.Value & 0xfdffffff) | 0x2000000;
                cmd.DW21.QpAdjustmentForRollingI = MOS_CLAMP_MIN_MAX(hevcPicParams->QpDeltaForInsertedIntra, -8, 7);
                cmd.DW21.IntraRefreshMode = (hevcPicParams->bEnableRollingIntraRefresh == ROLLING_I_ROW) ? 0 : 1;
                cmd.DW21.IntraRefreshMBSizeMinusOne = hevcPicParams->IntraInsertionSize - 1;
                cmd.DW21.IntraRefreshPos = hevcPicParams->IntraInsertionLocation;
                cmd.DW36.IntraRefreshBoundaryRef0 = CodecHal_Clip3(0, rollingILimit, hevcPicParams->RollingIntraReferenceLocation[0] - 1);
                cmd.DW36.IntraRefreshBoundaryRef1 = CodecHal_Clip3(0, rollingILimit, hevcPicParams->RollingIntraReferenceLocation[1] - 1);
                cmd.DW36.IntraRefreshBoundaryRef2 = CodecHal_Clip3(0, rollingILimit, hevcPicParams->RollingIntraReferenceLocation[2] - 1);
            }

            const uint32_t table1[3][42] = {0x30002,0x30002,0x30002,0x30003,0x40004,0x40005,0x50006,0x60008,0x6000a,0x7000c,0x8000f,0x90013,0xa0018,0xb001e,0xc0026,0xe0030,0x10003d,0x12004d,0x140061,0x16007a,0x19009a,0x1c00c2,0x1f00f4,0x230133,0x270183,0x2c01e8,0x320266,0x380306,0x3e03cf,0x4604cd,0x4f060c,0x58079f,0x63099a,0x6f0c18,0x7d0f3d,0x8c1333,0x9d1831,0xb11e7a,0xc62666,0xdf3062,0xfa3cf5,0x1184ccd,
                                           0x30003,0x30003,0x30003,0x40003,0x40004,0x50005,0x50007,0x60008,0x6000a,0x7000d,0x80011,0x90015,0xa001a,0xb0021,0xd002a,0xe0034,0x100042,0x120053,0x140069,0x170084,0x1a00a6,0x1d00d2,0x210108,0x24014d,0x2901a3,0x2e0210,0x34029a,0x3a0347,0x410421,0x490533,0x52068d,0x5c0841,0x670a66,0x740d1a,0x821082,0x9214cd,0xa41a35,0xb82105,0xce299a,0xe8346a,0x1044209,0x1245333,
                                           0x30003,0x30003,0x30003,0x40003,0x40004,0x50005,0x50007,0x60008,0x6000a,0x7000d,0x80011,0x90015,0xa001a,0xb0021,0xd002a,0xe0034,0x100042,0x120053,0x140069,0x170084,0x1a00a6,0x1d00d2,0x210108,0x24014d,0x2901a3,0x2e0210,0x34029a,0x3a0347,0x410421,0x490533,0x52068d,0x5c0841,0x670a66,0x740d1a,0x821082,0x9214cd,0xa41a35,0xb82105,0xce299a,0xe8346a,0x1044209,0x1245333};
            const uint8_t indexTable1[3] = {0,1,2};
            cmd.DW26.Value = (cmd.DW26.Value & 0xfe000000) | table1[indexTable1[hevcPicParams->CodingType - 1]][hevcPicParams->QpY + hevcSlcParams->slice_qp_delta - 10];

            if (params->bHevcVisualQualityImprovement)
            {
                auto qpPrimeYac = CodecHal_Clip3(10, 51, hevcPicParams->QpY + hevcSlcParams->slice_qp_delta);
                if (qpPrimeYac >= 22 && qpPrimeYac <= 51 && hevcSlcParams->slice_type == SLICE_I)
                {
                    const uint32_t table2[3][30] = {0xa,0xb,0xd,0xf,0x11,0x14,0x17,0x1a,0x1e,0x22,0x27,0x2d,0x33,0x3b,0x43,0x4d,0x57,0x64,0x72,0x82,0x95,0xa7,0xbb,0xd2,0xec,0x109,0x129,0x14e,0x177,0x1a5,
                                                    0xa,0xc,0xe,0x10,0x12,0x15,0x18,0x1b,0x1f,0x23,0x29,0x2f,0x35,0x3d,0x46,0x50,0x5b,0x68,0x77,0x88,0x9b,0xae,0xc3,0xdb,0xf6,0x114,0x136,0x15c,0x186,0x1b6,
                                                    0xa,0xc,0xe,0x10,0x12,0x15,0x18,0x1b,0x1f,0x23,0x29,0x2f,0x35,0x3d,0x46,0x50,0x5b,0x68,0x77,0x88,0x9b,0xae,0xc3,0xdb,0xf6,0x114,0x136,0x15c,0x186,0x1b6};
                    const uint8_t indexTable2[3] = {0,1,2};
                    cmd.DW26.SadQpLambda  = table2[indexTable2[hevcPicParams->CodingType - 1]][qpPrimeYac - 22];
                }

                if (hevcPicParams->QpY >= 22 && hevcPicParams->QpY <= 51)
                {
                    cmd.DW6.Value = (cmd.DW6.Value & 0xc00fffff) | 0x1fb00000;
                }
            }
            cmd.DW27.QpPrimeYAc = hevcPicParams->QpY + hevcSlcParams->slice_qp_delta;
            cmd.DW27.Value &= 0xffffff00;
            cmd.DW35.Value = (cmd.DW35.Value & 0xfffff0ff) | 0x700;

            if (params->bUseDefaultQpDeltas)
            {
                cmd.DW13.Value = (cmd.DW13.Value & 0xffff) | 0xf0120000;
                if (hevcPicParams->CodingType == I_TYPE)
                {
                    cmd.DW14.Value = (cmd.DW14.Value & 0xffff0000) | 0x21db;
                    cmd.DW16.Value = (cmd.DW16.Value & 0xf00ffff) | 0x10000;
                    cmd.DW18.Value = 0x600000;
                    cmd.DW19.Value = (cmd.DW19.Value & 0xffff0000) | 0xc0;
                }
                else // LDB frames
                {
                    cmd.DW14.Value = (cmd.DW14.Value & 0xffff0000) | 0x21ed;
                    cmd.DW16.Value = (cmd.DW16.Value & 0xf00ffff) | 0xd0010000;
                    cmd.DW18.Value = 0x60010f;
                    cmd.DW19.Value = (cmd.DW19.Value & 0xffff0000) | 0xc0;
                }
            }

            if (params->bRoundingEnabled)
            {
                cmd.DW28.Value = 0x7d00fa0;
                cmd.DW29.Value = 0x2bc0bb8;
                cmd.DW30.Value = 0x32003e8;
                cmd.DW31.Value = 0x1f4012c;
                cmd.DW32.Value = (cmd.DW32.Value & 0xffff0000) | 0x190;

                const uint32_t table3[3][3] = {0x88220000,0x99220000,0xaa220000,
                                              0x88330000,0x99330000,0xaa330000,
                                              0x88440000,0x99440000,0xaa440000};
                cmd.DW32.Value = (cmd.DW32.Value & 0xffff) | table3[params->roundInterValue - 2][params->roundIntraValue - 8];

                const uint32_t table4[3][3] = {0x22882222,0x22992222,0x22aa2222,
                                              0x33883333,0x33993333,0x33aa3333,
                                              0x44884444,0x44994444,0x44aa4444};
                cmd.DW33.Value = table4[params->roundInterValue - 2][params->roundIntraValue - 8];

                const uint32_t table5[3][3] = {0x228822,0x229922,0x22aa22,
                                              0x338833,0x339933,0x33aa33,
                                              0x448844,0x449944,0x44aa44};
                cmd.DW34.Value = (cmd.DW34.Value & 0xff000000) | table5[params->roundInterValue - 2][params->roundIntraValue - 8];
            }

            if (hevcPicParams->pps_curr_pic_ref_enabled_flag)
            {
                cmd.DW5.NumRefIdxL0Minus1++;
                cmd.DW35.Value &= 0xffff1fff;
                cmd.DW37.Value = (cmd.DW37.Value & 0xffffff9f) | 0x40;

                if (hevcPicParams->CodingType == I_TYPE)
                {
                    cmd.DW2.Value = (cmd.DW2.Value & 0xf8fffffc) | 0x1000002;
                    cmd.DW3.Value &= 0xffffff00;
                    cmd.DW5.Value &= 0xf0ffffff;
                }
                else
                {
                    switch (cmd.DW5.NumRefIdxL0Minus1)
                    {
                    case 0:
                        cmd.DW2.Value |= 0x1000000;
                        cmd.DW3.Value &= 0xffffff00;
                        break;
                    case 1:
                        cmd.DW2.Value |= 0x2000000;
                        cmd.DW3.Value &= 0xff00ffff;
                        break;
                    case 2:
                        cmd.DW2.Value |= 0x4000000;
                        cmd.DW4.Value &= 0xffffff00;
                        break;
                    case 3:
                        cmd.DW2.Value |= 0x0;
                        cmd.DW4.Value &= 0xff00ffff;
                        break;
                    default:
                        MHW_ASSERTMESSAGE("Invalid NumRefIdxL0");
                        return MOS_STATUS_INVALID_PARAMETER;
                    }
                }
            }
            if (hevcSeqParams->palette_mode_enabled_flag)
            {
                cmd.DW37.Value &= 0xffe0ffe0;
                cmd.DW38.Value &= 0xffffffbf;
                uint32_t index = hevcSeqParams->bit_depth_luma_minus8 == 0 ? 0 : 1;
                const uint32_t table1[2] = {0x8000fc,0x20003f0};
                cmd.DW39.Value = table1[index];

                const uint32_t table2[2] = {0xb10080,0x2c40200};
                cmd.DW40.Value = table2[index];

                const uint32_t table3[2] = {0x300aa,0xc02a8};
                cmd.DW41.Value = table3[index];

                const uint32_t table4[2] = {0xd30069,0x34c01a4};
                cmd.DW42.Value = table4[index];
                const uint32_t table5[2] = {0xe000e9,0x38003a4};
                cmd.DW43.Value = table5[index];

                const uint32_t table6[2] = {0x940003,0x250000c};
                cmd.DW44.Value = table6[index];

                const uint32_t table7[2] = {0x56004d,0x1580134};
                cmd.DW45.Value = table7[index];
                const uint32_t table8[2] = {0x9500fd,0x25403f4};
                cmd.DW46.Value = table8[index];

                const uint32_t table9[2] = {0x17002d,0x5c00b4};
                cmd.DW47.Value = table9[index];

                const uint32_t table10[2] = {0xfd001f,0x3f4007c};
                cmd.DW48.Value = table10[index];
                const uint32_t table11[2] = {0x2006c,0x801b0};
                cmd.DW49.Value = table11[index];

                const uint32_t table12[2] = {0x800080,0x2000200};
                cmd.DW50.Value = table12[index];
            }

            MHW_MI_CHK_NULL(extParams->pRefIdxMapping);
            for (int i = 0; i < params->ucNumRefIdxL0ActiveMinus1 + 1; i++)
            {
                uint8_t refFrameIDx = hevcSlcParams->RefPicList[0][i].FrameIdx;
                if (refFrameIDx < CODEC_MAX_NUM_REF_FRAME_HEVC)
                {
                    *((uint8_t *)&cmd.DW11.Value + i) = *(extParams->pRefIdxMapping + refFrameIDx);
                }
            }
            for (int i = params->ucNumRefIdxL0ActiveMinus1 + 1; i < 3; i++)
            {
                *((uint8_t *)&cmd.DW11.Value + i) = 0x7;
            }
            if (hevcPicParams->pps_curr_pic_ref_enabled_flag)
            {
                *((uint8_t *)&cmd.DW11.Value + params->ucNumRefIdxL0ActiveMinus1 + 1) = extParams->recNotFilteredID;
            }
            if (!extParams->bIsLowDelayB)
            {
                 uint8_t refFrameIDx = hevcSlcParams->RefPicList[1][0].FrameIdx;
                 if (refFrameIDx < CODEC_MAX_NUM_REF_FRAME_HEVC)
                 {
                     const uint8_t bwdOffset = 3;
                     *((uint8_t *)&cmd.DW11.Value + bwdOffset) = *(extParams->pRefIdxMapping + refFrameIDx);
                 }
            }
            cmd.DW11.Value = (cmd.DW11.Value & 0x7fffffff) | 0x80000000;
        }
        else if (params->pVp9EncPicParams)
        {
            MHW_MI_CHK_NULL(params->pVp9EncPicParams);
            auto vp9PicParams = params->pVp9EncPicParams;
            MHW_MI_CHK_NULL(params->pVp9EncSeqParams);
            auto vp9SeqParams = params->pVp9EncSeqParams;

            cmd.DW1.FrameWidthInPixelsMinusOne = MOS_ALIGN_CEIL(vp9PicParams->SrcFrameWidthMinus1 + 1, CODEC_VP9_MIN_BLOCK_WIDTH) - 1;
            cmd.DW1.FrameHeightInPixelsMinusOne = MOS_ALIGN_CEIL(vp9PicParams->SrcFrameHeightMinus1 + 1, CODEC_VP9_MIN_BLOCK_WIDTH) - 1;

            cmd.DW2.Value = (cmd.DW2.Value & 0x8ff00000) | 0x5aff3;
            cmd.DW5.Value = (cmd.DW5.Value & 0xf000300) | 0x80ac00;
            cmd.DW6.Value = 0x20080200;
            cmd.DW7.Value = (cmd.DW7.Value & 0x190fd0) | 0x62003;
            cmd.DW9.Value = (cmd.DW9.Value & 0xfff0ffff) | 0x40000;
            cmd.DW14.Value = (cmd.DW14.Value & 0xffff) | 0x1f40000;
            cmd.DW15.Value = 0x138807d0;
            cmd.DW16.Value = (cmd.DW16.Value & 0xff0000) | 0xf00ff00;
            cmd.DW17.Value = (cmd.DW17.Value & 0xfff00000) | 0x2710;
            cmd.DW18.Value = 0x80000;
            cmd.DW19.Value = (cmd.DW19.Value & 0xffff0000) | 0x40;
            cmd.DW22.Value = 0x1f001f00;
            cmd.DW23.Value = 0x6a1a1f00;
            cmd.DW28.Value = 0x7d00fa0;
            cmd.DW29.Value = 0x2bc0bb8;
            cmd.DW30.Value = 0x32003e8;
            cmd.DW31.Value = 0x1f4012c;
            cmd.DW32.Value = 0x55220190;
            cmd.DW33.Value = 0x22552222;
            cmd.DW34.Value = 0x21225522;
            cmd.DW2.PictureType = vp9PicParams->PicFlags.fields.frame_type;
            cmd.DW2.TemporalMvpEnableFlag = params->temporalMVpEnable;

            if (vp9PicParams->PicFlags.fields.frame_type) // P_FRAME
            {
                cmd.DW5.NumRefIdxL0Minus1 = params->ucNumRefIdxL0ActiveMinus1;
                cmd.DW7.Value = (cmd.DW7.Value & 0xfff7ffff) | 0x80000;
            }
            else // I_FRAME
            {
                cmd.DW5.Value &= 0xf0ffffff;
                cmd.DW7.Value &= 0xfff7ffff;
            }

            cmd.DW7.SegmentationEnable = (vp9PicParams->PicFlags.fields.frame_type == 0) ? 0 : vp9PicParams->PicFlags.fields.segmentation_enabled;
            cmd.DW7.TilingEnable = (vp9PicParams->log2_tile_columns != 0) || (vp9PicParams->log2_tile_rows != 0);
            cmd.DW7.PakOnlyMultiPassEnable = params->bPakOnlyMultipassEnable;
            cmd.DW7.VdencStreamInEnable = params->bStreamInEnabled;

            if (params->bSegmentationEnabled)
            {
                cmd.DW7.SegmentationEnable = true;
                cmd.DW7.SegmentationMapTemporalPredictionEnable = vp9PicParams->PicFlags.fields.frame_type ? (params->bPrevFrameSegEnabled ? 1 : 0) : 0;
                cmd.DW7.VdencStreamInEnable = params->bStreamInEnabled;

                MHW_MI_CHK_NULL(params->pVp9SegmentState);
                MHW_MI_CHK_NULL(params->pVp9SegmentState->pVp9EncodeSegmentParams);

                cmd.DW24.QpForSeg0 = vp9PicParams->LumaACQIndex + params->pVp9SegmentState->pVp9EncodeSegmentParams->SegData[0].SegmentQIndexDelta;
                cmd.DW24.QpForSeg1 = vp9PicParams->LumaACQIndex + params->pVp9SegmentState->pVp9EncodeSegmentParams->SegData[1].SegmentQIndexDelta;
                cmd.DW24.QpForSeg2 = vp9PicParams->LumaACQIndex + params->pVp9SegmentState->pVp9EncodeSegmentParams->SegData[2].SegmentQIndexDelta;
                cmd.DW24.QpForSeg3 = vp9PicParams->LumaACQIndex + params->pVp9SegmentState->pVp9EncodeSegmentParams->SegData[3].SegmentQIndexDelta;

                cmd.DW25.QpForSeg4 = vp9PicParams->LumaACQIndex + params->pVp9SegmentState->pVp9EncodeSegmentParams->SegData[4].SegmentQIndexDelta;
                cmd.DW25.QpForSeg5 = vp9PicParams->LumaACQIndex + params->pVp9SegmentState->pVp9EncodeSegmentParams->SegData[5].SegmentQIndexDelta;
                cmd.DW25.QpForSeg6 = vp9PicParams->LumaACQIndex + params->pVp9SegmentState->pVp9EncodeSegmentParams->SegData[6].SegmentQIndexDelta;
                cmd.DW25.QpForSeg7 = vp9PicParams->LumaACQIndex + params->pVp9SegmentState->pVp9EncodeSegmentParams->SegData[7].SegmentQIndexDelta;
            }
            else
            {
                cmd.DW24.QpForSeg0 = vp9PicParams->LumaACQIndex + vp9PicParams->LumaDCQIndexDelta;
                cmd.DW24.QpForSeg1 = vp9PicParams->LumaACQIndex + vp9PicParams->LumaDCQIndexDelta;
                cmd.DW24.QpForSeg2 = vp9PicParams->LumaACQIndex + vp9PicParams->LumaDCQIndexDelta;
                cmd.DW24.QpForSeg3 = vp9PicParams->LumaACQIndex + vp9PicParams->LumaDCQIndexDelta;

                cmd.DW25.QpForSeg4 = vp9PicParams->LumaACQIndex + vp9PicParams->LumaDCQIndexDelta;
                cmd.DW25.QpForSeg5 = vp9PicParams->LumaACQIndex + vp9PicParams->LumaDCQIndexDelta;
                cmd.DW25.QpForSeg6 = vp9PicParams->LumaACQIndex + vp9PicParams->LumaDCQIndexDelta;
                cmd.DW25.QpForSeg7 = vp9PicParams->LumaACQIndex + vp9PicParams->LumaDCQIndexDelta;
            }

            cmd.DW26.SadQpLambda = params->usSADQPLambda;
            cmd.DW26.RdQpLambda = params->usRDQPLambda;
            cmd.DW26.Vp9DynamicSliceEnable = params->bDynamicScalingEnabled;

            cmd.DW27.QpPrimeYAc = vp9PicParams->LumaACQIndex;
            cmd.DW27.QpPrimeYDc = cmd.DW27.QpPrimeYAc + vp9PicParams->LumaDCQIndexDelta;

            switch (vp9SeqParams->TargetUsage)
            {
            case 1:     // Quality mode
            case 4:     // Normal mode
                cmd.DW2.Value &= 0xdfffffff;
                cmd.DW7.Value &= 0xfff7feff;
                cmd.DW9.Value = (cmd.DW9.Value & 0xfffff) | 0x43800000;
                cmd.DW34.Value = (cmd.DW34.Value & 0xffffff) | 0x21000000;
                break;
            case 7:     // Speed mode
                cmd.DW2.Value = (cmd.DW2.Value & 0xdfffffff) | 0x20000000;
                cmd.DW7.Value = (cmd.DW7.Value & 0xfff7feff) | 0x80100;
                cmd.DW9.Value = (cmd.DW9.Value & 0xffff) | 0x22420000;
                cmd.DW34.Value = (cmd.DW34.Value & 0xffffff) | 0x20000000;
                break;
            default:
                MHW_ASSERTMESSAGE("Invalid TU provided!");
                return MOS_STATUS_INVALID_PARAMETER;
            }

            if (params->ucNumRefIdxL0ActiveMinus1 == 0)
            {
                cmd.DW7.Value = (cmd.DW7.Value & 0xfff7ffff) | 0x80000;
            }
        }

        if (cmdBuffer == nullptr && batchBuffer == nullptr)
        {
            MHW_ASSERTMESSAGE("There was no valid buffer to add the HW command to.");
            return MOS_STATUS_NULL_POINTER;
        }

        MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(this->m_osInterface, cmdBuffer, batchBuffer, &cmd, sizeof(cmd)));

        return MOS_STATUS_SUCCESS;
    }
};

struct MHW_VDBOX_VDENC_HEVC_VP9_TILE_SLICE_STATE_PARAMS
{
    uint32_t ctbSize          = 0;
    uint32_t widthInPix       = 0;
    uint32_t heightInPix      = 0;
    uint32_t minCodingBlkSize = 0;

    PMHW_VDBOX_HCP_TILE_CODING_PARAMS_G12 pTileCodingParams     = nullptr;
    uint32_t                              dwNumberOfPipes       = 0;
    uint32_t                              dwTileId              = 0;
    uint32_t                              IBCControl            = 0;
    uint32_t                              PaletteModeEnable     = 0;
    uint32_t                              sliceQP               = 0;
    uint32_t                              bit_depth_luma_minus8 = 0;
    uint32_t                              RowStaticInfo_31_0    = 0;
    uint32_t                              RowStaticInfo_63_32   = 0;
    uint32_t                              RowStaticInfo_95_64   = 0;
    uint32_t                              RowStaticInfo_127_96  = 0;
    uint32_t                              Log2WeightDenomLuma   = 0;
    uint32_t                              Log2WeightDenomChroma = 0;
    uint8_t                               TargetUsage           = 0;
    virtual ~MHW_VDBOX_VDENC_HEVC_VP9_TILE_SLICE_STATE_PARAMS() {}
};
using PMHW_VDBOX_VDENC_HEVC_VP9_TILE_SLICE_STATE_PARAMS = MHW_VDBOX_VDENC_HEVC_VP9_TILE_SLICE_STATE_PARAMS *;

#endif // __MHW_VDBOX_VDENC_G12_X_H__
