/*
* Copyright (c) 2017-2020, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
//!
//! \file     codechal_encode_avc_g12.cpp
//! \brief    This file implements the C++ class/interface for Gen12 platform's AVC
//!           DualPipe encoding to be used across CODECHAL components.
//!
#include "codechal_encode_avc_g12.h"
#include "codechal_mmc_encode_avc_g12.h"
#include "codechal_kernel_header_g12.h"
#include "codechal_kernel_hme_g12.h"
#include "mhw_render_g12_X.h"
#include "codeckrnheader.h"
#include "igcodeckrn_g12.h"
#include "media_user_settings_mgr_g12.h"
#include "hal_oca_interface.h"
#if USE_CODECHAL_DEBUG_TOOL
#include "codechal_debug_encode_par_g12.h"
#include "mhw_vdbox_mfx_hwcmd_g12_X.h"
#include "mos_util_user_interface.h"
#endif

enum MbencBindingTableOffset
{
    mbencMfcAvcPakObj            = 0,
    mbencIndMvData               = 1,
    mbencBrcDistortion           = 2,  // For BRC distortion for I
    mbencCurrY                   = 3,
    mbencCurrUv                  = 4,
    mbencMbSpecificData          = 5,
    mbencAuxVmeOut               = 6,
    mbencRefpicselectL0          = 7,
    mbencMvDataFromMe            = 8,
    mbenc4xMeDistortion          = 9,
    mbencSlicemapData            = 10,
    mbencFwdMbData               = 11,
    mbencFwdMvData               = 12,
    mbencMbqp                    = 13,
    mbencMbbrcConstData          = 14,
    mbencVmeInterPredCurrPicIdx0 = 15,
    mbencVmeInterPredFwdPicIDX0  = 16,
    mbencVmeInterPredBwdPicIDX00 = 17,
    mbencVmeInterPredFwdPicIDX1  = 18,
    mbencVmeInterPredBwdPicIDX10 = 19,
    mbencVmeInterPredFwdPicIDX2  = 20,
    mbencReserved0               = 21,
    mbencVmeInterPredFwdPicIDX3  = 22,
    mbencReserved1               = 23,
    mbencVmeInterPredFwdPicIDX4  = 24,
    mbencReserved2               = 25,
    mbencVmeInterPredFwdPicIDX5  = 26,
    mbencReserved3               = 27,
    mbencVmeInterPredFwdPicIDX6  = 28,
    mbencReserved4               = 29,
    mbencVmeInterPredFwdPicIDX7  = 30,
    mbencReserved5               = 31,
    mbencVmeInterPredCurrPicIdx1 = 32,
    mbencVmeInterPredBwdPicIDX01 = 33,
    mbencReserved6               = 34,
    mbencVmeInterPredBwdPicIDX11 = 35,
    mbencReserved7               = 36,
    mbencMbStats                 = 37,
    mbencMadData                 = 38,
    mbencBrcCurbeData            = 39,
    mbencForceNonskipMbMap       = 40,
    mbEncAdv                     = 41,
    mbencSfdCostTable            = 42,
    mbencSwScoreboard            = 43,
    mbencNumSurfaces             = 44
};

enum WpBindingTableOffset
{
    wpInputRefSurface     = 0,
    wpOutputScaledSurface = 1,
    wpNumSurfaces         = 2
};

enum MbencIdOffset
{
    mbencIOffset      = 0,
    mbencPOffset      = 1,
    mbencBOffset      = 2,
    mbencFrameTypeNum = 3
};

// AVC MBEnc CURBE init data for TGL Kernel
const uint32_t CodechalEncodeAvcEncG12::MbencCurbe::m_mbEncCurbeNormalIFrame[89] =
{
    0x00000082, 0x00000000, 0x00003910, 0x00a83000, 0x00000000, 0x28300000, 0x05000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x80800000, 0x00040c24, 0x00000000, 0xffff00ff, 0x40000000, 0x00000080, 0x00003900, 0x28300000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
    0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
    0xffffffff
};

const uint32_t CodechalEncodeAvcEncG12::MbencCurbe::m_mbEncCurbeNormalIField[89] =
{
    0x00000082, 0x00000000, 0x00003910, 0x00a830c0, 0x02000000, 0x28300000, 0x05000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x80800000, 0x00040c24, 0x00000000, 0xffff00ff, 0x40000000, 0x00000080, 0x00003900, 0x28300000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
    0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
    0xffffffff
};

const uint32_t CodechalEncodeAvcEncG12::MbencCurbe::m_mbEncCurbeNormalPFrame[89] =
{
    0x000000a3, 0x00000008, 0x00003910, 0x00ae3000, 0x30000000, 0x28300000, 0x05000000, 0x01400060,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x80010000, 0x00040c24, 0x00000000, 0xffff00ff, 0x60000000, 0x000000a1, 0x00003900, 0x28300000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x08000002,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
    0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
    0xffffffff
};

const uint32_t CodechalEncodeAvcEncG12::MbencCurbe::m_mbEncCurbeNormalPField[89] =
{
    0x000000a3, 0x00000008, 0x00003910, 0x00ae30c0, 0x30000000, 0x28300000, 0x05000000, 0x01400060,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x80010000, 0x00040c24, 0x00000000, 0xffff00ff, 0x40000000, 0x000000a1, 0x00003900, 0x28300000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04000002,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
    0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
    0xffffffff
};

const uint32_t CodechalEncodeAvcEncG12::MbencCurbe::m_mbEncCurbeNormalBFrame[89] =
{
    0x000000a3, 0x00200008, 0x00003910, 0x00aa7700, 0x50020000, 0x20200000, 0x05000000, 0xff400000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x01010000, 0x00040c24, 0x00000000, 0xffff00ff, 0x60000000, 0x000000a1, 0x00003900, 0x28300000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x08000002,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
    0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
    0xffffffff
};

const uint32_t CodechalEncodeAvcEncG12::MbencCurbe::m_mbEncCurbeNormalBField[89] =
{
    0x000000a3, 0x00200008, 0x00003919, 0x00aa77c0, 0x50020000, 0x20200000, 0x05000000, 0xff400000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x01010000, 0x00040c24, 0x00000000, 0xffff00ff, 0x40000000, 0x000000a1, 0x00003900, 0x28300000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04000002,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
    0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
    0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
    0xffffffff
};

// AVC I_DIST CURBE init data for TGL Kernel
const uint32_t CodechalEncodeAvcEncG12::MbencCurbe::m_mbEncCurbeIFrameDist[89] =
{
    0x00000082, 0x00200008, 0x001e3910, 0x00a83000, 0x90000000, 0x28300000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000100,
    0x80800000, 0x00000000, 0x00000800, 0xffff00ff, 0x40000000, 0x00000080, 0x00003900, 0x28300000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
    0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
    0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0xffffffff
};

class CodechalEncodeAvcEncG12::WpCurbe
{
   public:
    WpCurbe()
    {
        memset((void *)&m_wpCurbeCmd, 0, sizeof(WpCurbe));
    }

    struct
    {
        // DW0
        union
        {
            struct
            {
                uint32_t m_defaultWeight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_defaultOffset : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW0;

        // DW1
        union
        {
            struct
            {
                uint32_t m_roi0XLeft : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi0YTop : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW1;

        // DW2
        union
        {
            struct
            {
                uint32_t m_roi0XRight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi0YBottom : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW2;

        // DW3
        union
        {
            struct
            {
                uint32_t m_roi0Weight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi0Offset : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW3;

        // DW4
        union
        {
            struct
            {
                uint32_t m_roi1XLeft : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi1YTop : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW4;

        // DW5
        union
        {
            struct
            {
                uint32_t m_roi1XRight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi1YBottom : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW5;

        // DW6
        union
        {
            struct
            {
                uint32_t m_roi1Weight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi1Offset : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW6;

        // DW7
        union
        {
            struct
            {
                uint32_t m_roi2XLeft : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi2YTop : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW7;

        // DW8
        union
        {
            struct
            {
                uint32_t m_roi2XRight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi2YBottom : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW8;

        // DW9
        union
        {
            struct
            {
                uint32_t m_roi2Weight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi2Offset : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW9;

        // DW10
        union
        {
            struct
            {
                uint32_t m_roi3XLeft : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi3YTop : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW10;

        // DW11
        union
        {
            struct
            {
                uint32_t m_roi3XRight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi3YBottom : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW11;

        // DW12
        union
        {
            struct
            {
                uint32_t m_roi3Weight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi3Offset : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW12;

        // DW13
        union
        {
            struct
            {
                uint32_t m_roi4XLeft : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi4YTop : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW13;

        // DW14
        union
        {
            struct
            {
                uint32_t m_roi4XRight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi4YBottom : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW14;

        // DW15
        union
        {
            struct
            {
                uint32_t m_roi4Weight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi4Offset : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW15;

        // DW16
        union
        {
            struct
            {
                uint32_t m_roi5XLeft : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi5YTop : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW16;

        // DW17
        union
        {
            struct
            {
                uint32_t m_roi5XRight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi5YBottom : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW17;

        // DW18
        union
        {
            struct
            {
                uint32_t m_roi5Weight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi5Offset : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW18;

        // DW19
        union
        {
            struct
            {
                uint32_t m_roi6XLeft : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi6YTop : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW19;

        // DW20
        union
        {
            struct
            {
                uint32_t m_roi6XRight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi6YBottom : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW20;

        // DW21
        union
        {
            struct
            {
                uint32_t m_roi6Weight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi6Offset : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW21;

        // DW22
        union
        {
            struct
            {
                uint32_t m_roi7XLeft : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi7YTop : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW22;

        // DW23
        union
        {
            struct
            {
                uint32_t m_roi7XRight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi7YBottom : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW23;

        // DW24
        union
        {
            struct
            {
                uint32_t m_roi7Weight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi7Offset : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW24;

        // DW25
        union
        {
            struct
            {
                uint32_t m_roi8XLeft : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi8YTop : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW25;

        // DW26
        union
        {
            struct
            {
                uint32_t m_roi8XRight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi8YBottom : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW26;

        // DW27
        union
        {
            struct
            {
                uint32_t m_roi8Weight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi8Offset : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW27;

        // DW28
        union
        {
            struct
            {
                uint32_t m_roi9XLeft : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi9YTop : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW28;

        // DW29
        union
        {
            struct
            {
                uint32_t m_roi9XRight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi9YBottom : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW29;

        // DW30
        union
        {
            struct
            {
                uint32_t m_roi9Weight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi9Offset : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW30;

        // DW31
        union
        {
            struct
            {
                uint32_t m_roi10XLeft : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi10YTop : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW31;

        // DW32
        union
        {
            struct
            {
                uint32_t m_roi10XRight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi10YBottom : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW32;

        // DW33
        union
        {
            struct
            {
                uint32_t m_roi10Weight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi10Offset : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW33;

        // DW34
        union
        {
            struct
            {
                uint32_t m_roi11XLeft : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi11YTop : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW34;

        // DW35
        union
        {
            struct
            {
                uint32_t m_roi11XRight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi11YBottom : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW35;

        // DW36
        union
        {
            struct
            {
                uint32_t m_roi11Weight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi11Offset : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW36;

        // DW37
        union
        {
            struct
            {
                uint32_t m_roi12XLeft : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi12YTop : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW37;

        // DW38
        union
        {
            struct
            {
                uint32_t m_roi12XRight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi12YBottom : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW38;

        // DW39
        union
        {
            struct
            {
                uint32_t m_roi12Weight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi12Offset : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW39;

        // DW40
        union
        {
            struct
            {
                uint32_t m_roi13XLeft : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi13YTop : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW40;

        // DW41
        union
        {
            struct
            {
                uint32_t m_roi13XRight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi13YBottom : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW41;

        // DW42
        union
        {
            struct
            {
                uint32_t m_roi13Weight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi13Offset : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW42;

        // DW43
        union
        {
            struct
            {
                uint32_t m_roi14XLeft : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi14YTop : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW43;

        // DW44
        union
        {
            struct
            {
                uint32_t m_roi14XRight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi14YBottom : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW44;

        // DW45
        union
        {
            struct
            {
                uint32_t m_roi14Weight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi14Offset : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW45;

        // DW46
        union
        {
            struct
            {
                uint32_t m_roi15XLeft : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi15YTop : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW46;

        // DW47
        union
        {
            struct
            {
                uint32_t m_roi15XRight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi15YBottom : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW47;

        // DW48
        union
        {
            struct
            {
                uint32_t m_roi15Weight : MOS_BITFIELD_RANGE(0, 15);
                uint32_t m_roi15Offset : MOS_BITFIELD_RANGE(16, 31);
            };
            struct
            {
                uint32_t m_value;
            };
        } DW48;

        // DW49
        union
        {
            struct
            {
                uint32_t m_inputSurface;
            };
            struct
            {
                uint32_t m_value;
            };
        } DW49;

        // DW50
        union
        {
            struct
            {
                uint32_t m_outputSurface;
            };
            struct
            {
                uint32_t m_value;
            };
        } DW50;
    } m_wpCurbeCmd;
};

static const uint32_t trellisQuantizationRounding[NUM_TARGET_USAGE_MODES] =
{
    0, 3, 0, 0, 0, 0, 0, 0
};

const uint8_t CodechalEncodeAvcEncG12::m_QPAdjustmentDistThresholdMaxFrameThresholdIPB[576] =
{
    0x01, 0x02, 0x03, 0x05, 0x06, 0x01, 0x01, 0x02, 0x03, 0x05, 0x00, 0x00, 0x01, 0x02, 0x03, 0xff,
    0x00, 0x00, 0x01, 0x02, 0xff, 0x00, 0x00, 0x00, 0x01, 0xfe, 0xfe, 0xff, 0x00, 0x01, 0xfd, 0xfd,
    0xff, 0xff, 0x00, 0xfb, 0xfd, 0xfe, 0xff, 0xff, 0xfa, 0xfb, 0xfd, 0xfe, 0xff, 0x00, 0x04, 0x1e,
    0x3c, 0x50, 0x78, 0x8c, 0xc8, 0xff, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x01, 0x02, 0x03, 0x05, 0x06, 0x01, 0x01, 0x02, 0x03, 0x05, 0x00, 0x01, 0x01, 0x02, 0x03, 0xff,
    0x00, 0x00, 0x01, 0x02, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x00, 0x01, 0xfe, 0xff,
    0xff, 0xff, 0x00, 0xfc, 0xfe, 0xff, 0xff, 0x00, 0xfb, 0xfc, 0xfe, 0xff, 0xff, 0x00, 0x04, 0x1e,
    0x3c, 0x50, 0x78, 0x8c, 0xc8, 0xff, 0x04, 0x05, 0x06, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x01, 0x01, 0x02, 0x04, 0x05, 0x01, 0x01, 0x01, 0x02, 0x04, 0x00, 0x00, 0x01, 0x01, 0x02, 0xff,
    0x00, 0x00, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x01, 0xfe, 0xff,
    0xff, 0xff, 0x00, 0xfd, 0xfe, 0xff, 0xff, 0x00, 0xfb, 0xfc, 0xfe, 0xff, 0xff, 0x00, 0x02, 0x14,
    0x28, 0x46, 0x82, 0xa0, 0xc8, 0xff, 0x04, 0x04, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03,
    0x03, 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0xff, 0xff, 0x00, 0x00, 0x00,
    0x01, 0x02, 0x02, 0x02, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0xfe, 0xff, 0xff,
    0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x01, 0x02, 0xfe,
    0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x01, 0xfe, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03,
    0x03, 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0xff, 0xff, 0x00, 0x00, 0x00,
    0x01, 0x02, 0x02, 0x02, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0xfe, 0xff, 0xff,
    0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x01, 0x02, 0xfe,
    0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x01, 0xfe, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03,
    0x03, 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0xff, 0xff, 0x00, 0x00, 0x00,
    0x01, 0x02, 0x02, 0x02, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0xfe, 0xff, 0xff,
    0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x01, 0x02, 0xfe,
    0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x01, 0xfe, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

const CODECHAL_ENCODE_AVC_IPCM_THRESHOLD CodechalEncodeAvcEncG12::m_IPCMThresholdTable[5] =
{
    { 2, 3000 },
    { 4, 3600 },
    { 6, 5000 },
    { 10, 7500 },
    { 18, 9000 },
};

const uint32_t CodechalEncodeAvcEncG12::m_intraModeCostForHighTextureMB[CODEC_AVC_NUM_QP]
{
    0x00000303, 0x00000304, 0x00000404, 0x00000405, 0x00000505, 0x00000506, 0x00000607, 0x00000708,
    0x00000809, 0x0000090a, 0x00000a0b, 0x00000b0c, 0x00000c0e, 0x00000e18, 0x00001819, 0x00001918,
    0x00001a19, 0x00001b19, 0x00001d19, 0x00001e18, 0x00002818, 0x00002918, 0x00002a18, 0x00002b19,
    0x00002d18, 0x00002e18, 0x00003818, 0x00003918, 0x00003a18, 0x00003b0f, 0x00003d0e, 0x00003e0e,
    0x0000480e, 0x0000490e, 0x00004a0e, 0x00004b0d, 0x00004d0d, 0x00004e0d, 0x0000580e, 0x0000590e,
    0x00005a0e, 0x00005b0d, 0x00005d0c, 0x00005e0b, 0x0000680a, 0x00006908, 0x00006a09, 0x00006b0a,
    0x00006d0b, 0x00006e0d, 0x0000780e, 0x00007918
};

const uint16_t CodechalEncodeAvcEncG12::m_lambdaData[256] = {
    9,     7,     9,     6,    12,     8,    12,     8,    15,    10,    15,     9,    19,    13,    19,    12,    24,
    17,    24,    15,    30,    21,    30,    19,    38,    27,    38,    24,    48,    34,    48,    31,    60,    43,
    60,    39,    76,    54,    76,    49,    96,    68,    96,    62,   121,    85,   121,    78,   153,   108,   153,
    99,   193,   135,   193,   125,   243,   171,   243,   157,   306,   215,   307,   199,   385,   271,   387,   251,
    485,   342,   488,   317,   612,   431,   616,   400,   771,   543,   777,   505,   971,   684,   981,   638,  1224,
    862,  1237,   806,  1542,  1086,  1562,  1018,  1991,  1402,  1971,  1287,  2534,  1785,  2488,  1626,  3077,  2167,
    3141,  2054,  3982,  2805,  3966,  2596,  4887,  3442,  5007,  3281,  6154,  4335,  6322,  4148,  7783,  5482,  7984,
    5243,  9774,  6885, 10082,  6629, 12489,  8797, 12733,  8382, 15566, 10965, 16082, 10599, 19729, 13897, 20313, 13404,
    24797, 17467, 25660, 16954, 31313, 22057, 32415, 21445, 39458, 27795, 40953, 27129, 49594, 34935, 51742, 34323, 61440,
    43987, 61440, 43428, 61440, 55462, 61440, 54954, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440,
    61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440,
    61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440, 61440,
    61440, 61440, 61440, 61440,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
    0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
    0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
    0,
};

const uint8_t CodechalEncodeAvcEncG12::m_ftQ25[64] = //27 value 4 dummy
{
    0,                                      //qp=0
    0, 0, 0, 0, 0, 0,                       //qp=1,2;3,4;5,6;
    1, 1, 3, 3, 6, 6, 8, 8, 11, 11,         //qp=7,8;9,10;11,12;13,14;15;16
    13, 13, 16, 16, 19, 19, 22, 22, 26, 26, //qp=17,18;19,20;21,22;23,24;25,26
    30, 30, 34, 34, 39, 39, 44, 44, 50, 50, //qp=27,28;29,30;31,32;33,34;35,36
    56, 56, 62, 62, 69, 69, 77, 77, 85, 85, //qp=37,38;39,40;41,42;43,44;45,46
    94, 94, 104, 104, 115, 115,             //qp=47,48;49,50;51
    0, 0, 0, 0, 0, 0, 0, 0                  //dummy
};

// AVC MBEnc RefCost tables, index [CodingType][QP]
// QP is from 0 - 51, pad it to 64 since BRC needs each subarray size to be 128bytes
const uint16_t CodechalEncodeAvcEncG12::m_refCostMultiRefQp[NUM_PIC_TYPES][64] =
{
    // I-frame
    {
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000
    },
    // P-slice
    {
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000
    },
    //B-slice
    {
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000
    }
};

const uint32_t CodechalEncodeAvcEncG12::m_multiPred[NUM_TARGET_USAGE_MODES] =
{
    0, 3, 3, 0, 0, 0, 0, 0
};

const uint32_t CodechalEncodeAvcEncG12::m_multiRefDisableQPCheck[NUM_TARGET_USAGE_MODES] =
{
    0, 1, 0, 0, 0, 0, 0, 0
};
// clang-format on

const int32_t CodechalEncodeAvcEncG12::m_brcBTCounts[CODECHAL_ENCODE_BRC_IDX_NUM] = {
    CODECHAL_ENCODE_AVC_BRC_INIT_RESET_NUM_SURFACES,
    frameBrcUpdateNumSurfaces,
    CODECHAL_ENCODE_AVC_BRC_INIT_RESET_NUM_SURFACES,
    mbencNumSurfaces,
    CODECHAL_ENCODE_AVC_BRC_BLOCK_COPY_NUM_SURFACES,
    mbBrcUpdateNumSurfaces
};

const int32_t CodechalEncodeAvcEncG12::m_brcCurbeSize[CODECHAL_ENCODE_BRC_IDX_NUM] = {
    (sizeof(BrcInitResetCurbe)),
    (sizeof(FrameBrcUpdateCurbe)),
    (sizeof(BrcInitResetCurbe)),
    (sizeof(MbencCurbe)),
    0,
    (sizeof(MbBrcUpdateCurbe))
};

class CodechalEncodeAvcEncG12::EncKernelHeader
{
public:
    int m_kernelCount;
    // Quality mode for Frame/Field
    CODECHAL_KERNEL_HEADER m_mbEncQltyI;
    CODECHAL_KERNEL_HEADER m_mbEncQltyP;
    CODECHAL_KERNEL_HEADER m_mEncQltyB;
    // Normal mode for Frame/Field
    CODECHAL_KERNEL_HEADER m_mbEncNormI;
    CODECHAL_KERNEL_HEADER m_mbEncNormP;
    CODECHAL_KERNEL_HEADER m_mbEncNormB;
    // Performance modes for Frame/Field
    CODECHAL_KERNEL_HEADER m_mbEncPerfI;
    CODECHAL_KERNEL_HEADER m_mbEncPerfP;
    CODECHAL_KERNEL_HEADER m_mbEncPerfB;
    // Modes for Frame/Field
    CODECHAL_KERNEL_HEADER m_mbEncAdvI;
    CODECHAL_KERNEL_HEADER m_mbEncAdvP;
    CODECHAL_KERNEL_HEADER m_mbEncAdvB;
    // BRC Init frame
    CODECHAL_KERNEL_HEADER m_initFrameBrc;
    // FrameBRC Update
    CODECHAL_KERNEL_HEADER m_frameEncUpdate;
    // BRC Reset frame
    CODECHAL_KERNEL_HEADER m_brcResetFrame;
    // BRC I Frame Distortion
    CODECHAL_KERNEL_HEADER m_brcIFrameDist;
    // BRCBlockCopy
    CODECHAL_KERNEL_HEADER m_brcBlockCopy;
    // MbBRC Update
    CODECHAL_KERNEL_HEADER m_mbBrcUpdate;
    //Weighted Prediction Kernel
    CODECHAL_KERNEL_HEADER m_weightedPrediction;
    // SW scoreboard initialization kernel
    CODECHAL_KERNEL_HEADER m_initSwScoreboard;
};

MOS_STATUS CodechalEncodeAvcEncG12::GetKernelHeaderAndSize(
    void                         *binary,
    EncOperation                 operation,
    uint32_t                     krnStateIdx,
    void                         *krnHeader,
    uint32_t                     *krnSize)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;
    CODECHAL_ENCODE_CHK_NULL_RETURN(binary);
    CODECHAL_ENCODE_CHK_NULL_RETURN(krnHeader);
    CODECHAL_ENCODE_CHK_NULL_RETURN(krnSize);

    auto kernelHeaderTable = (EncKernelHeader *)binary;
    auto invalidEntry = &(kernelHeaderTable->m_weightedPrediction) + 1;
    auto nextKrnOffset = *krnSize;

    PCODECHAL_KERNEL_HEADER currKrnHeader = nullptr;

    if (operation == ENC_BRC)
    {
        currKrnHeader = &kernelHeaderTable->m_initFrameBrc;
    }
    else if (operation == ENC_MBENC)
    {
        currKrnHeader = &kernelHeaderTable->m_mbEncQltyI;
    }
    else if (operation == ENC_MBENC_ADV)
    {
        currKrnHeader = &kernelHeaderTable->m_mbEncAdvI;
    }
    else if (operation == ENC_WP)
    {
        currKrnHeader = &kernelHeaderTable->m_weightedPrediction;
    }
    else
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Unsupported ENC mode requested");
        return MOS_STATUS_INVALID_PARAMETER;
    }

    currKrnHeader += krnStateIdx;
    *((PCODECHAL_KERNEL_HEADER)krnHeader) = *currKrnHeader;

    auto nextKrnHeader = (currKrnHeader + 1);
    if (nextKrnHeader < invalidEntry)
    {
        nextKrnOffset = nextKrnHeader->KernelStartPointer << MHW_KERNEL_OFFSET_SHIFT;
    }
    *krnSize = nextKrnOffset - (currKrnHeader->KernelStartPointer << MHW_KERNEL_OFFSET_SHIFT);

    return eStatus;
}

CodechalEncodeAvcEncG12::CodechalEncodeAvcEncG12(
        CodechalHwInterface *   hwInterface,
        CodechalDebugInterface *debugInterface,
        PCODECHAL_STANDARD_INFO standardInfo) : CodechalEncodeAvcEnc(hwInterface, debugInterface, standardInfo), 
        m_sinlgePipeVeState(nullptr)
{
    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_ASSERT(m_osInterface);

    Mos_CheckVirtualEngineSupported(m_osInterface, false, true);

    // Virtual Engine is enabled in default.
    Mos_SetVirtualEngineSupported(m_osInterface, true);

    bKernelTrellis             = true;
    bExtendedMvCostRange       = true;
    bBrcSplitEnable            = true;
    bDecoupleMbEncCurbeFromBRC = true;
    bHighTextureModeCostEnable = true;
    bMvDataNeededByBRC         = false;

    this->pfnGetKernelHeaderAndSize = CodechalEncodeAvcEncG12::GetKernelHeaderAndSize;

    m_cmKernelEnable         = true;
    m_mbStatsSupported       = true;
    m_useCommonKernel        = true;

    m_kernelBase = (uint8_t *)IGCODECKRN_G12;
    m_kuidCommon = IDR_CODEC_HME_DS_SCOREBOARD_KERNEL;
    AddIshSize(m_kuid, m_kernelBase);
    AddIshSize(m_kuidCommon, m_kernelBase);

    m_vdboxOneDefaultUsed = true;

    Mos_CheckVirtualEngineSupported(m_osInterface, false, false);

    CODECHAL_DEBUG_TOOL(
        CODECHAL_ENCODE_CHK_NULL_NO_STATUS_RETURN(m_encodeParState = MOS_New(CodechalDebugEncodeParG12, this));
        CreateAvcPar();
    )
}

CodechalEncodeAvcEncG12::~CodechalEncodeAvcEncG12()
{
    CODECHAL_ENCODE_FUNCTION_ENTER;

    MOS_Delete(m_intraDistKernel);

    if (m_swScoreboardState)
    {
        MOS_Delete(m_swScoreboardState);
        m_swScoreboardState = nullptr;
    }

    if (m_sinlgePipeVeState)
    {
        MOS_FreeMemAndSetNull(m_sinlgePipeVeState);
    }

    CODECHAL_DEBUG_TOOL(
        DestroyAvcPar();
        MOS_Delete(m_encodeParState);
    )
}

MOS_STATUS CodechalEncodeAvcEncG12::MbEncKernel(bool mbEncIFrameDistInUse)
{
    MOS_STATUS                                  eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    uint8_t ppsIdx          = m_avcSliceParams->pic_parameter_set_id;
    uint8_t spsIdx          = m_avcPicParams[ppsIdx]->seq_parameter_set_id;
    auto refList            = &m_refList[0];
    auto currRefList        = m_refList[m_currReconstructedPic.FrameIdx];
    bool use45DegreePattern = false;
    bool roiEnabled         = (m_avcPicParams[ppsIdx]->NumROI > 0) ? true : false;
    uint8_t refPicListIdx   = m_avcSliceParams[ppsIdx].RefPicList[0][0].FrameIdx;
    uint8_t refFrameListIdx = m_avcPicParam[ppsIdx].RefFrameList[refPicListIdx].FrameIdx;
    bool dirtyRoiEnabled    = (m_pictureCodingType == P_TYPE
        && m_avcPicParams[ppsIdx]->NumDirtyROI > 0
        && m_prevReconFrameIdx == refFrameListIdx);

    //  Two flags(bMbConstDataBufferNeeded, bMbQpBufferNeeded)
    //  would be used as there are two buffers and not all cases need both the buffers
    //  Constant Data buffer  needed for MBBRC, MBQP, ROI, RollingIntraRefresh
    //  Please note that this surface needs to be programmed for
    //  all usage cases(including CQP cases) because DWord13 includes mode cost for high texture MB?s cost.
    bool mbConstDataBufferInUse = bMbBrcEnabled || bMbQpDataEnabled || roiEnabled || dirtyRoiEnabled ||
        m_avcPicParam->EnableRollingIntraRefresh || bHighTextureModeCostEnable;

    bool mbQpBufferInUse = bMbBrcEnabled || bBrcRoiEnabled || bMbQpDataEnabled;

    if (m_feiEnable)
    {
        CODECHAL_ENCODE_CHK_NULL_RETURN(m_avcFeiPicParams);
        mbConstDataBufferInUse |= m_avcFeiPicParams->bMBQp;
        mbQpBufferInUse |= m_avcFeiPicParams->bMBQp;
    }

    PerfTagSetting perfTag;
    perfTag.Value             = 0;
    perfTag.Mode              = (uint16_t)m_mode & CODECHAL_ENCODE_MODE_BIT_MASK;
    perfTag.CallType          = (mbEncIFrameDistInUse && !m_singleTaskPhaseSupported) ?
        CODECHAL_ENCODE_PERFTAG_CALL_INTRA_DIST : CODECHAL_ENCODE_PERFTAG_CALL_MBENC_KERNEL;
    perfTag.PictureCodingType = m_pictureCodingType;
    m_osInterface->pfnSetPerfTag(m_osInterface, perfTag.Value);

    CODECHAL_MEDIA_STATE_TYPE encFunctionType;
    if (mbEncIFrameDistInUse)
    {
        encFunctionType = CODECHAL_MEDIA_STATE_ENC_I_FRAME_DIST;
    }
    else if (bUseMbEncAdvKernel)
    {
        encFunctionType = CODECHAL_MEDIA_STATE_ENC_ADV;
    }
    else if (m_kernelMode == encodeNormalMode)
    {
        encFunctionType = CODECHAL_MEDIA_STATE_ENC_NORMAL;
    }
    else if (m_kernelMode == encodePerformanceMode)
    {
        encFunctionType = CODECHAL_MEDIA_STATE_ENC_PERFORMANCE;
    }
    else
    {
        encFunctionType = CODECHAL_MEDIA_STATE_ENC_QUALITY;
    }

    // Initialize DSH kernel region
    PMHW_KERNEL_STATE kernelState;
    if (mbEncIFrameDistInUse)
    {
        kernelState = &BrcKernelStates[CODECHAL_ENCODE_BRC_IDX_IFRAMEDIST];
    }
    else
    {
        CodechalEncodeIdOffsetParams idOffsetParams;
        MOS_ZeroMemory(&idOffsetParams, sizeof(idOffsetParams));
        idOffsetParams.Standard           = m_standard;
        idOffsetParams.EncFunctionType    = encFunctionType;
        idOffsetParams.wPictureCodingType = m_pictureCodingType;
        idOffsetParams.ucDmvPredFlag      = m_avcSliceParams->direct_spatial_mv_pred_flag;
        idOffsetParams.interlacedField   = CodecHal_PictureIsField(m_currOriginalPic);

        uint32_t krnStateIdx;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(GetMbEncKernelStateIdx(
            &idOffsetParams,
            &krnStateIdx));
        kernelState = &pMbEncKernelStates[krnStateIdx];
    }

    // If Single Task Phase is not enabled, use BT count for the kernel state.
    if (m_firstTaskInPhase == true || !m_singleTaskPhaseSupported)
    {
        uint32_t maxBtCount = m_singleTaskPhaseSupported ?
            m_maxBtCount : kernelState->KernelParams.iBTCount;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnRequestSshSpaceForCmdBuf(
            m_stateHeapInterface,
            maxBtCount));
        m_vmeStatesSize = m_hwInterface->GetKernelLoadCommandSize(maxBtCount);
        CODECHAL_ENCODE_CHK_STATUS_RETURN(VerifySpaceAvailable());
    }

    // Allocate DSH and SSH for the first stream, which will be passed to other streams through the shared kernel state.
    if (!bMbEncCurbeSetInBrcUpdate)
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->AssignDshAndSshSpace(
            m_stateHeapInterface,
            kernelState,
            false,
            0,
            false,
            m_storeData));

        MHW_INTERFACE_DESCRIPTOR_PARAMS idParams;
        MOS_ZeroMemory(&idParams, sizeof(idParams));
        idParams.pKernelState = kernelState;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSetInterfaceDescriptor(
            m_stateHeapInterface,
            1,
            &idParams));
    }

    if (bMbEncCurbeSetInBrcUpdate)
    {
        // If BRC update was used to set up the DSH & SSH, SSH only needs to
        // be obtained if single task phase is enabled because the same SSH
        // could not be shared between BRC update and MbEnc
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->AssignDshAndSshSpace(
            m_stateHeapInterface,
            kernelState,
            true,
            0,
            m_singleTaskPhaseSupported,
            m_storeData));
    }
    else
    {
        // Setup AVC Curbe
        CODECHAL_ENCODE_AVC_MBENC_CURBE_PARAMS mbEncCurbeParams;
        MOS_ZeroMemory(&mbEncCurbeParams, sizeof(mbEncCurbeParams));
        mbEncCurbeParams.pPicParams              = m_avcPicParams[ppsIdx];
        mbEncCurbeParams.pSeqParams              = m_avcSeqParams[spsIdx];
        mbEncCurbeParams.pSlcParams              = m_avcSliceParams;
        mbEncCurbeParams.ppRefList               = &(m_refList[0]);
        mbEncCurbeParams.pPicIdx                 = &(m_picIdx[0]);
        mbEncCurbeParams.bRoiEnabled             = roiEnabled;
        mbEncCurbeParams.bDirtyRoiEnabled        = dirtyRoiEnabled;
        mbEncCurbeParams.bMbEncIFrameDistEnabled = mbEncIFrameDistInUse;
        mbEncCurbeParams.pdwBlockBasedSkipEn     = &dwMbEncBlockBasedSkipEn;
        if (mbEncIFrameDistInUse)
        {
            mbEncCurbeParams.bBrcEnabled           = false;
            mbEncCurbeParams.wPicWidthInMb         = (uint16_t)m_downscaledWidthInMb4x;
            mbEncCurbeParams.wFieldFrameHeightInMb = (uint16_t)m_downscaledFrameFieldHeightInMb4x;
            mbEncCurbeParams.usSliceHeight         = (m_sliceHeight + SCALE_FACTOR_4x - 1) / SCALE_FACTOR_4x;
        }
        else
        {
            mbEncCurbeParams.bBrcEnabled           = bBrcEnabled;
            mbEncCurbeParams.wPicWidthInMb         = m_picWidthInMb;
            mbEncCurbeParams.wFieldFrameHeightInMb = m_frameFieldHeightInMb;
            mbEncCurbeParams.usSliceHeight         = (m_arbitraryNumMbsInSlice) ?
                m_frameFieldHeightInMb : m_sliceHeight;
            mbEncCurbeParams.bUseMbEncAdvKernel    = bUseMbEncAdvKernel;
        }
        mbEncCurbeParams.pKernelState                     = kernelState;
        mbEncCurbeParams.pAvcQCParams                     = m_avcQCParams;
        mbEncCurbeParams.bMbDisableSkipMapEnabled         = bMbDisableSkipMapEnabled;
        mbEncCurbeParams.bStaticFrameDetectionEnabled     = bStaticFrameDetectionEnable && m_hmeEnabled;
        mbEncCurbeParams.bApdatvieSearchWindowSizeEnabled = bApdatvieSearchWindowEnable;
        mbEncCurbeParams.bSquareRollingIEnabled           = bSquareRollingIEnabled;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(SetCurbeAvcMbEnc(
            &mbEncCurbeParams));
    }

    CODECHAL_DEBUG_TOOL(
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion(
            encFunctionType,
            MHW_DSH_TYPE,
            kernelState));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCurbe(
        encFunctionType,
        kernelState));
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion(
        encFunctionType,
        MHW_ISH_TYPE,
        kernelState));
    )

        for (uint8_t i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++)
        {
            if (m_picIdx[i].bValid)
            {
                uint8_t index = m_picIdx[i].ucPicIdx;
                refList[index]->sRefBuffer = m_userFlags.bUseRawPicForRef ?
                    refList[index]->sRefRawBuffer : refList[index]->sRefReconBuffer;

                CodecHalGetResourceInfo(m_osInterface, &refList[index]->sRefBuffer);
            }
        }

    MOS_COMMAND_BUFFER cmdBuffer;
    MOS_ZeroMemory(&cmdBuffer, sizeof(cmdBuffer));
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));

    SendKernelCmdsParams sendKernelCmdsParams = SendKernelCmdsParams();
    sendKernelCmdsParams.EncFunctionType = encFunctionType;
    sendKernelCmdsParams.ucDmvPredFlag   =
        m_avcSliceParams->direct_spatial_mv_pred_flag;
    sendKernelCmdsParams.pKernelState    = kernelState;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(SendGenericKernelCmds(&cmdBuffer, &sendKernelCmdsParams));

    // Set up MB BRC Constant Data Buffer if there is QP change within a frame
    if (mbConstDataBufferInUse)
    {
        CODECHAL_ENCODE_AVC_INIT_MBBRC_CONSTANT_DATA_BUFFER_PARAMS initMbBrcConstantDataBufferParams;

        MOS_ZeroMemory(&initMbBrcConstantDataBufferParams, sizeof(initMbBrcConstantDataBufferParams));
        initMbBrcConstantDataBufferParams.pOsInterface                = m_osInterface;
        initMbBrcConstantDataBufferParams.presBrcConstantDataBuffer   =
            &BrcBuffers.resMbBrcConstDataBuffer[m_currRecycledBufIdx];
        initMbBrcConstantDataBufferParams.dwMbEncBlockBasedSkipEn     = dwMbEncBlockBasedSkipEn;
        initMbBrcConstantDataBufferParams.pPicParams                  = m_avcPicParams[ppsIdx];
        initMbBrcConstantDataBufferParams.wPictureCodingType          = m_pictureCodingType;
        initMbBrcConstantDataBufferParams.bSkipBiasAdjustmentEnable   = m_skipBiasAdjustmentEnable;
        initMbBrcConstantDataBufferParams.bAdaptiveIntraScalingEnable = bAdaptiveIntraScalingEnable;
        initMbBrcConstantDataBufferParams.bOldModeCostEnable          = bOldModeCostEnable;
        initMbBrcConstantDataBufferParams.pAvcQCParams                = m_avcQCParams;
        initMbBrcConstantDataBufferParams.bEnableKernelTrellis        = bKernelTrellis && m_trellisQuantParams.dwTqEnabled;

        // Kernel controlled Trellis Quantization
        if (bKernelTrellis && m_trellisQuantParams.dwTqEnabled)
        {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(CalcLambdaTable(
                m_pictureCodingType,
                &initMbBrcConstantDataBufferParams.Lambda[0][0]));
        }

        CODECHAL_ENCODE_CHK_STATUS_RETURN(InitMbBrcConstantDataBuffer(&initMbBrcConstantDataBufferParams));

        //dump MbBrcLut
        CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
            initMbBrcConstantDataBufferParams.presBrcConstantDataBuffer,
            CodechalDbgAttr::attrOutput,
            "MbBrcLut",
            16 * (CODEC_AVC_NUM_QP) * sizeof(uint32_t),
            0,
            CODECHAL_MEDIA_STATE_ENC_QUALITY)));
    }

    // Add binding table
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSetBindingTable(
        m_stateHeapInterface,
        kernelState));

    //Add surface states
    CODECHAL_ENCODE_AVC_MBENC_SURFACE_PARAMS mbEncSurfaceParams;
    MOS_ZeroMemory(&mbEncSurfaceParams, sizeof(mbEncSurfaceParams));
    mbEncSurfaceParams.MediaStateType        = encFunctionType;
    mbEncSurfaceParams.pAvcSlcParams         = m_avcSliceParams;
    mbEncSurfaceParams.ppRefList             = &m_refList[0];
    mbEncSurfaceParams.pAvcPicIdx            = &m_picIdx[0];
    mbEncSurfaceParams.pCurrOriginalPic      = &m_currOriginalPic;
    mbEncSurfaceParams.pCurrReconstructedPic = &m_currReconstructedPic;
    mbEncSurfaceParams.wPictureCodingType    = m_pictureCodingType;
    mbEncSurfaceParams.psCurrPicSurface      = mbEncIFrameDistInUse ? m_trackedBuf->Get4xDsSurface(CODEC_CURR_TRACKED_BUFFER) : m_rawSurfaceToEnc;
    if (mbEncIFrameDistInUse && CodecHal_PictureIsBottomField(m_currOriginalPic))
    {
        mbEncSurfaceParams.dwCurrPicSurfaceOffset = m_scaledBottomFieldOffset;
    }
    mbEncSurfaceParams.dwMbCodeBottomFieldOffset          = (uint32_t)m_mbcodeBottomFieldOffset;
    mbEncSurfaceParams.dwMvBottomFieldOffset              = (uint32_t)m_mvBottomFieldOffset;
    mbEncSurfaceParams.ps4xMeMvDataBuffer                 = m_hmeKernel->GetSurface(CodechalKernelHme::SurfaceId::me4xMvDataBuffer);
    mbEncSurfaceParams.ps4xMeDistortionBuffer             = m_hmeKernel->GetSurface(CodechalKernelHme::SurfaceId::me4xDistortionBuffer);
    mbEncSurfaceParams.dwMeMvBottomFieldOffset            = m_hmeKernel->Get4xMeMvBottomFieldOffset();
    mbEncSurfaceParams.dwMeDistortionBottomFieldOffset    = m_hmeKernel->GetDistortionBottomFieldOffset();
    mbEncSurfaceParams.psMeBrcDistortionBuffer            = &BrcBuffers.sMeBrcDistortionBuffer;
    mbEncSurfaceParams.dwMeBrcDistortionBottomFieldOffset = BrcBuffers.dwMeBrcDistortionBottomFieldOffset;
    mbEncSurfaceParams.dwRefPicSelectBottomFieldOffset    = (uint32_t)ulRefPicSelectBottomFieldOffset;
    mbEncSurfaceParams.dwFrameWidthInMb                   = (uint32_t)m_picWidthInMb;
    mbEncSurfaceParams.dwFrameFieldHeightInMb             = (uint32_t)m_frameFieldHeightInMb;
    mbEncSurfaceParams.dwFrameHeightInMb                  = (uint32_t)m_picHeightInMb;
    // Interleaved input surfaces
    mbEncSurfaceParams.dwVerticalLineStride       = m_verticalLineStride;
    mbEncSurfaceParams.dwVerticalLineStrideOffset = m_verticalLineStrideOffset;
    // Vertical line stride is not used for the case of scaled surfaces saved as separate fields
    if (!m_fieldScalingOutputInterleaved && mbEncIFrameDistInUse)
    {
        mbEncSurfaceParams.dwVerticalLineStride       = 0;
        mbEncSurfaceParams.dwVerticalLineStrideOffset = 0;
    }
    mbEncSurfaceParams.bHmeEnabled              = m_hmeSupported;
    mbEncSurfaceParams.bMbEncIFrameDistInUse    = mbEncIFrameDistInUse;
    mbEncSurfaceParams.presMbBrcConstDataBuffer = &BrcBuffers.resMbBrcConstDataBuffer[m_currRecycledBufIdx];
    mbEncSurfaceParams.psMbQpBuffer             =
        bMbQpDataEnabled ? &sMbQpDataSurface : &BrcBuffers.sBrcMbQpBuffer;
    mbEncSurfaceParams.dwMbQpBottomFieldOffset  = bMbQpDataEnabled ? 0 : BrcBuffers.dwBrcMbQpBottomFieldOffset;
    mbEncSurfaceParams.bUsedAsRef               =
        m_refList[m_currReconstructedPic.FrameIdx]->bUsedAsRef;
    mbEncSurfaceParams.presMADDataBuffer        = &m_resMadDataBuffer[m_currMadBufferIdx];
    mbEncSurfaceParams.bMbQpBufferInUse         = mbQpBufferInUse;
    mbEncSurfaceParams.bMbSpecificDataEnabled   = bMbSpecificDataEnabled;
    mbEncSurfaceParams.presMbSpecificDataBuffer = &resMbSpecificDataBuffer[m_currRecycledBufIdx];
    mbEncSurfaceParams.bMbConstDataBufferInUse  = mbConstDataBufferInUse;
    mbEncSurfaceParams.bMADEnabled              = mbEncIFrameDistInUse ? false : m_madEnabled;
    mbEncSurfaceParams.bUseMbEncAdvKernel       = mbEncIFrameDistInUse ? false : bUseMbEncAdvKernel;
    mbEncSurfaceParams.presMbEncCurbeBuffer     =
        (mbEncIFrameDistInUse && bUseMbEncAdvKernel) ? nullptr : &BrcBuffers.resMbEncAdvancedDsh;
    mbEncSurfaceParams.presMbEncBRCBuffer       = &BrcBuffers.resMbEncBrcBuffer;

    if (bDecoupleMbEncCurbeFromBRC)
    {
        mbEncSurfaceParams.dwMbEncBRCBufferSize = m_mbencBrcBufferSize;
    }

    mbEncSurfaceParams.bUseAdvancedDsh            = bAdvancedDshInUse;
    mbEncSurfaceParams.bBrcEnabled                 = bBrcEnabled;
    mbEncSurfaceParams.bArbitraryNumMbsInSlice     = m_arbitraryNumMbsInSlice;
    mbEncSurfaceParams.psSliceMapSurface           = &m_sliceMapSurface[m_currRecycledBufIdx];
    mbEncSurfaceParams.dwSliceMapBottomFieldOffset = (uint32_t)m_sliceMapBottomFieldOffset;
    mbEncSurfaceParams.pMbEncBindingTable          = &MbEncBindingTable;
    mbEncSurfaceParams.pKernelState                = kernelState;

    if (m_mbStatsSupported)
    {
        mbEncSurfaceParams.bMBVProcStatsEnabled = m_flatnessCheckEnabled ||
                                                  m_adaptiveTransformDecisionEnabled ||
                                                  bMbBrcEnabled ||
                                                  bMbQpDataEnabled;
        mbEncSurfaceParams.presMBVProcStatsBuffer          = &m_resMbStatsBuffer;
        mbEncSurfaceParams.dwMBVProcStatsBottomFieldOffset = m_mbStatsBottomFieldOffset;
    }
    else
    {
        mbEncSurfaceParams.bFlatnessCheckEnabled            = m_flatnessCheckEnabled;
        mbEncSurfaceParams.psFlatnessCheckSurface           = &m_flatnessCheckSurface;
        mbEncSurfaceParams.dwFlatnessCheckBottomFieldOffset = (uint32_t)m_flatnessCheckBottomFieldOffset;
    }

    // Set up pFeiPicParams
    mbEncSurfaceParams.pFeiPicParams = m_avcFeiPicParams;

    mbEncSurfaceParams.bMbDisableSkipMapEnabled = bMbDisableSkipMapEnabled;
    mbEncSurfaceParams.psMbDisableSkipMapSurface = psMbDisableSkipMapSurface;

    if (bUseWeightedSurfaceForL0 || bUseWeightedSurfaceForL1)
    {
        if (!m_wpUseCommonKernel)
        {
            mbEncSurfaceParams.pWeightedPredOutputPicSelectList = &WeightedPredOutputPicSelectList[0];
        }
        mbEncSurfaceParams.bUseWeightedSurfaceForL0 = bUseWeightedSurfaceForL0;
        mbEncSurfaceParams.bUseWeightedSurfaceForL1 = bUseWeightedSurfaceForL1;
    }

    // Clear the MAD buffer -- the kernel requires it to be 0 as it accumulates the result
    if (mbEncSurfaceParams.bMADEnabled)
    {
        // set lock flag to WRITE_ONLY
        MOS_LOCK_PARAMS lockFlags;
        MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
        lockFlags.WriteOnly = 1;

        uint8_t* data = (uint8_t*)m_osInterface->pfnLockResource(
            m_osInterface,
            mbEncSurfaceParams.presMADDataBuffer,
            &lockFlags);

        CODECHAL_ENCODE_CHK_NULL_RETURN(data);

        MOS_ZeroMemory(data, CODECHAL_MAD_BUFFER_SIZE);

        m_osInterface->pfnUnlockResource(
            m_osInterface,
            mbEncSurfaceParams.presMADDataBuffer);

        CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
            &m_resMadDataBuffer[m_currMadBufferIdx],
            CodechalDbgAttr::attrOutput,
            "MADRead",
            CODECHAL_MAD_BUFFER_SIZE,
            0,
            encFunctionType)));
    }

    // static frame detection buffer
    mbEncSurfaceParams.bStaticFrameDetectionEnabled = bStaticFrameDetectionEnable && m_hmeEnabled;
    mbEncSurfaceParams.presSFDOutputBuffer = &resSFDOutputBuffer[0];
    if (m_pictureCodingType == P_TYPE)
    {
        mbEncSurfaceParams.presSFDCostTableBuffer = &resSFDCostTablePFrameBuffer;
    }
    else if (m_pictureCodingType == B_TYPE)
    {
        mbEncSurfaceParams.presSFDCostTableBuffer = &resSFDCostTableBFrameBuffer;
    }

    CODECHAL_ENCODE_CHK_STATUS_RETURN(SendAvcMbEncSurfaces(&cmdBuffer, &mbEncSurfaceParams));


    uint32_t resolutionX = mbEncIFrameDistInUse ?
        m_downscaledWidthInMb4x : (uint32_t)m_picWidthInMb;
    uint32_t resolutionY = mbEncIFrameDistInUse ?
        m_downscaledFrameFieldHeightInMb4x : (uint32_t)m_frameFieldHeightInMb;

    CODECHAL_WALKER_CODEC_PARAMS walkerCodecParams;
    MOS_ZeroMemory(&walkerCodecParams, sizeof(walkerCodecParams));
    walkerCodecParams.WalkerMode               = m_walkerMode;
    walkerCodecParams.bUseScoreboard           = m_useHwScoreboard;
    walkerCodecParams.wPictureCodingType       = m_pictureCodingType;
    walkerCodecParams.bMbEncIFrameDistInUse    = mbEncIFrameDistInUse;
    walkerCodecParams.bMbaff                   = m_mbaffEnabled;
    walkerCodecParams.bDirectSpatialMVPredFlag = m_avcSliceParams->direct_spatial_mv_pred_flag;
    walkerCodecParams.bColorbitSupported       = (m_colorbitSupported && !m_arbitraryNumMbsInSlice) ? m_cmKernelEnable : false;
    walkerCodecParams.dwResolutionX            = resolutionX;
    walkerCodecParams.dwResolutionY            = resolutionY;
    walkerCodecParams.dwNumSlices              = m_numSlices;
    walkerCodecParams.usSliceHeight            = m_sliceHeight;
    walkerCodecParams.bGroupIdSelectSupported  = m_groupIdSelectSupported;
    walkerCodecParams.ucGroupId                = m_groupId;

    MHW_WALKER_PARAMS walkerParams;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalInitMediaObjectWalkerParams(
        m_hwInterface,
        &walkerParams,
        &walkerCodecParams));

    HalOcaInterface::TraceMessage(cmdBuffer, *m_osInterface->pOsContext, __FUNCTION__, sizeof(__FUNCTION__));
    HalOcaInterface::OnDispatch(cmdBuffer, *m_osInterface, *m_miInterface, *m_renderEngineInterface->GetMmioRegisters());

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_renderEngineInterface->AddMediaObjectWalkerCmd(
        &cmdBuffer,
        &walkerParams));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(EndStatusReport(&cmdBuffer, encFunctionType));

    // Add dump for MBEnc surface state heap here
    CODECHAL_DEBUG_TOOL(
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion(
            encFunctionType,
            MHW_SSH_TYPE,
            kernelState));
    )

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSubmitBlocks(
        m_stateHeapInterface,
        kernelState));

    if (!m_singleTaskPhaseSupported || m_lastTaskInPhase)
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnUpdateGlobalCmdBufId(
            m_stateHeapInterface));
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr));
    }

    CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer(
        &cmdBuffer,
        encFunctionType,
        nullptr)));
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->UpdateSSEuForCmdBuffer(&cmdBuffer, m_singleTaskPhaseSupported, m_lastTaskInPhase));

    m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);

    if ((!m_singleTaskPhaseSupported || m_lastTaskInPhase))
    {
        HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface);
        m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_renderContextUsesNullHw);
        m_lastTaskInPhase = false;
    }

    currRefList->ucMADBufferIdx = m_currMadBufferIdx;
    currRefList->bMADEnabled    = m_madEnabled;

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::SetAndPopulateVEHintParams(
    PMOS_COMMAND_BUFFER  cmdBuffer)
{
    MOS_STATUS                      eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    if (!MOS_VE_SUPPORTED(m_osInterface))
    {
        return eStatus;
    }

    if (!MOS_VE_CTXBASEDSCHEDULING_SUPPORTED(m_osInterface))
    {
        MOS_VIRTUALENGINE_SET_PARAMS  vesetParams;
        MOS_ZeroMemory(&vesetParams, sizeof(vesetParams));
        vesetParams.bNeedSyncWithPrevious = true;
        vesetParams.bSFCInUse = false;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalEncodeSinglePipeVE_SetHintParams(m_sinlgePipeVeState, &vesetParams));
    }
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalEncodeSinglePipeVE_PopulateHintParams(m_sinlgePipeVeState, cmdBuffer, true));

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::SubmitCommandBuffer(
    PMOS_COMMAND_BUFFER cmdBuffer,
    int32_t             nullRendering)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);

    CODECHAL_ENCODE_CHK_STATUS_RETURN(SetAndPopulateVEHintParams(cmdBuffer));
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, cmdBuffer, nullRendering));
    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::ExecuteKernelFunctions()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    auto slcParams = m_avcSliceParams;
    auto slcType   = Slice_Type[slcParams->slice_type];

    CODECHAL_DEBUG_TOOL(
    //    CodecHal_DbgMapSurfaceFormatToDumpFormat(m_rawSurfaceToEnc->Format, &dumpType);
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
            m_rawSurfaceToEnc,
            CodechalDbgAttr::attrEncodeRawInputSurface,
            "SrcSurf")));

    CODECHAL_ENCODE_CHK_NULL_RETURN(m_cscDsState);

    // Scaling, BRC Init/Reset and HME are included in the same task phase
    m_lastEncPhase     = false;
    m_firstTaskInPhase = true;

    // BRC init/reset needs to be called before HME since it will reset the Brc Distortion surface
    if (bBrcEnabled && (bBrcInit || bBrcReset))
    {
        bool cscEnabled            = m_cscDsState->RequireCsc() && m_firstField;
        m_lastTaskInPhase = !(cscEnabled || m_scalingEnabled || m_16xMeSupported || m_hmeEnabled);
        CODECHAL_ENCODE_CHK_STATUS_RETURN(BrcInitResetKernel());
    }

    UpdateSSDSliceCount();

    if (m_firstField)
    {
        // Csc, Downscaling, and/or 10-bit to 8-bit conversion
        CodechalEncodeCscDs::KernelParams cscScalingKernelParams;
        memset((void *)&cscScalingKernelParams, 0, sizeof(cscScalingKernelParams));
        cscScalingKernelParams.bLastTaskInPhaseCSC =
            cscScalingKernelParams.bLastTaskInPhase4xDS = !(m_16xMeSupported || m_hmeEnabled);
        cscScalingKernelParams.bLastTaskInPhase16xDS    = !(m_32xMeSupported || m_hmeEnabled);
        cscScalingKernelParams.bLastTaskInPhase32xDS    = !m_hmeEnabled;
        cscScalingKernelParams.inputColorSpace          = m_avcSeqParam->InputColorSpace;

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cscDsState->KernelFunctions(&cscScalingKernelParams));
    }

    if (m_hmeKernel && m_hmeKernel->Is4xMeEnabled())
    {
        CodechalKernelHme::CurbeParam curbeParam = {};
        curbeParam.subPelMode = 3;
        curbeParam.currOriginalPic = m_avcPicParam->CurrOriginalPic;
        curbeParam.qpPrimeY = m_avcPicParam->pic_init_qp_minus26 + 26 + m_avcSliceParams->slice_qp_delta;
        curbeParam.targetUsage = m_avcSeqParam->TargetUsage;
        curbeParam.maxMvLen = CodecHalAvcEncode_GetMaxMvLen(m_avcSeqParam->Level);
        curbeParam.numRefIdxL0Minus1 = m_avcSliceParams->num_ref_idx_l0_active_minus1;
        curbeParam.numRefIdxL1Minus1 = m_avcSliceParams->num_ref_idx_l1_active_minus1;

        auto slcParams = m_avcSliceParams;
        curbeParam.list0RefID0FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_0, CODECHAL_ENCODE_REF_ID_0);
        curbeParam.list0RefID1FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_0, CODECHAL_ENCODE_REF_ID_1);
        curbeParam.list0RefID2FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_0, CODECHAL_ENCODE_REF_ID_2);
        curbeParam.list0RefID3FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_0, CODECHAL_ENCODE_REF_ID_3);
        curbeParam.list0RefID4FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_0, CODECHAL_ENCODE_REF_ID_4);
        curbeParam.list0RefID5FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_0, CODECHAL_ENCODE_REF_ID_5);
        curbeParam.list0RefID6FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_0, CODECHAL_ENCODE_REF_ID_6);
        curbeParam.list0RefID7FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_0, CODECHAL_ENCODE_REF_ID_7);
        curbeParam.list1RefID0FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_1, CODECHAL_ENCODE_REF_ID_0);
        curbeParam.list1RefID1FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_1, CODECHAL_ENCODE_REF_ID_1);

        CodechalKernelHme::SurfaceParams surfaceParam = {};
        surfaceParam.mbaffEnabled = m_mbaffEnabled;
        surfaceParam.numRefIdxL0ActiveMinus1 = m_avcSliceParams->num_ref_idx_l0_active_minus1;
        surfaceParam.numRefIdxL1ActiveMinus1 = m_avcSliceParams->num_ref_idx_l1_active_minus1;
        surfaceParam.verticalLineStride = m_verticalLineStride;
        surfaceParam.verticalLineStrideOffset = m_verticalLineStrideOffset;
        surfaceParam.meBrcDistortionBottomFieldOffset = BrcBuffers.dwMeBrcDistortionBottomFieldOffset;
        surfaceParam.refList = &m_refList[0];
        surfaceParam.picIdx = &m_picIdx[0];
        surfaceParam.currOriginalPic = &m_currOriginalPic;
        surfaceParam.refL0List = &(m_avcSliceParams->RefPicList[LIST_0][0]);
        surfaceParam.refL1List = &(m_avcSliceParams->RefPicList[LIST_1][0]);
        surfaceParam.meBrcDistortionBuffer = &BrcBuffers.sMeBrcDistortionBuffer;

        if (m_hmeKernel->Is16xMeEnabled())
        {
            m_lastTaskInPhase = false;
            if (m_hmeKernel->Is32xMeEnabled())
            {
                surfaceParam.downScaledWidthInMb = m_downscaledWidthInMb32x;
                surfaceParam.downScaledHeightInMb = m_downscaledFrameFieldHeightInMb32x;
                surfaceParam.downScaledBottomFieldOffset = m_scaled32xBottomFieldOffset;

                CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hmeKernel->Execute(curbeParam, surfaceParam, CodechalKernelHme::HmeLevel::hmeLevel32x));
            }
            surfaceParam.downScaledWidthInMb = m_downscaledWidthInMb16x;
            surfaceParam.downScaledHeightInMb = m_downscaledFrameFieldHeightInMb16x;
            surfaceParam.downScaledBottomFieldOffset = m_scaled16xBottomFieldOffset;

            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hmeKernel->Execute(curbeParam, surfaceParam, CodechalKernelHme::HmeLevel::hmeLevel16x));
        }
        surfaceParam.downScaledWidthInMb = m_downscaledWidthInMb4x;
        surfaceParam.downScaledHeightInMb = m_downscaledFrameFieldHeightInMb4x;
        surfaceParam.downScaledBottomFieldOffset = m_scaledBottomFieldOffset;

        m_lastTaskInPhase = true;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hmeKernel->Execute(curbeParam, surfaceParam, CodechalKernelHme::HmeLevel::hmeLevel4x));
    }

    // Scaling and HME are not dependent on the output from PAK
    if (m_waitForPak && m_semaphoreObjCount && !Mos_ResourceIsNull(&m_resSyncObjectVideoContextInUse))
    {
        // Wait on PAK
        auto syncParams             = g_cInitSyncParams;
        syncParams.GpuContext       = m_renderContext;
        syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse;
        syncParams.uiSemaphoreCount = m_semaphoreObjCount;

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
        m_semaphoreObjCount = 0;  //reset
    }

    // BRC and MbEnc are included in the same task phase
    m_lastEncPhase     = true;
    m_firstTaskInPhase = true;

    // Initialize software scoreboard used by MBEnc kernel
    // Decide dependency pattern
    CodechalEncodeSwScoreboard::KernelParams swScoreboardKernelParames;
    memset((void *)&swScoreboardKernelParames, 0, sizeof(swScoreboardKernelParames));

    if (m_pictureCodingType == I_TYPE ||
        (m_pictureCodingType == B_TYPE && !m_avcSliceParams->direct_spatial_mv_pred_flag))  // I or B-temporal
    {
        swScoreboardKernelParames.surfaceIndex = dependencyWavefront45Degree;
        m_swScoreboardState->SetDependencyPattern(dependencyWavefront45Degree);
    }
    else  //P or B-spatial
    {
        swScoreboardKernelParames.surfaceIndex = dependencyWavefront26Degree;
        m_swScoreboardState->SetDependencyPattern(dependencyWavefront26Degree);
    }

    m_swScoreboardState->SetCurSwScoreboardSurfaceIndex(swScoreboardKernelParames.surfaceIndex);

    // Call SW scoreboard Init kernel
    swScoreboardKernelParames.scoreboardWidth           = m_picWidthInMb;
    swScoreboardKernelParames.scoreboardHeight          = m_frameFieldHeightInMb;
    swScoreboardKernelParames.swScoreboardSurfaceWidth  = swScoreboardKernelParames.scoreboardWidth * 4;
    swScoreboardKernelParames.swScoreboardSurfaceHeight = swScoreboardKernelParames.scoreboardHeight;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_swScoreboardState->Execute(&swScoreboardKernelParames));

    // Dump BrcDist 4X_ME buffer here because it will be overwritten in BrcFrameUpdateKernel
    CODECHAL_DEBUG_TOOL(
        if (m_hmeEnabled && bBrcDistortionBufferSupported)
        {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
                &BrcBuffers.sMeBrcDistortionBuffer.OsResource,
                CodechalDbgAttr::attrOutput,
                "BrcDist",
                BrcBuffers.sMeBrcDistortionBuffer.dwPitch * BrcBuffers.sMeBrcDistortionBuffer.dwHeight,
                BrcBuffers.dwMeBrcDistortionBottomFieldOffset,
                CODECHAL_MEDIA_STATE_4X_ME));
        })

    if (bBrcEnabled)
    {
        if (bMbEncIFrameDistEnabled)
        {
            CodechalKernelIntraDist::CurbeParam curbeParam;
            curbeParam.downScaledWidthInMb4x  = m_downscaledWidthInMb4x;
            curbeParam.downScaledHeightInMb4x = m_downscaledFrameFieldHeightInMb4x;
            CodechalKernelIntraDist::SurfaceParams surfaceParam;
            surfaceParam.input4xDsSurface           =
            surfaceParam.input4xDsVmeSurface        = m_trackedBuf->Get4xDsSurface(CODEC_CURR_TRACKED_BUFFER);
            surfaceParam.intraDistSurface           = &BrcBuffers.sMeBrcDistortionBuffer;
            surfaceParam.intraDistBottomFieldOffset = BrcBuffers.dwMeBrcDistortionBottomFieldOffset;
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_intraDistKernel->Execute(curbeParam, surfaceParam));
        }

        CODECHAL_ENCODE_CHK_STATUS_RETURN(BrcFrameUpdateKernel());
        if (bBrcSplitEnable && bMbBrcEnabled)
        {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(BrcMbUpdateKernel());
        }

        // Reset buffer ID used for BRC kernel performance reports
        m_osInterface->pfnResetPerfBufferID(m_osInterface);
    }

    bUseWeightedSurfaceForL0 = false;
    bUseWeightedSurfaceForL1 = false;

    if (bWeightedPredictionSupported &&
        ((((slcType == SLICE_P) || (slcType == SLICE_SP)) && (m_avcPicParam->weighted_pred_flag)) ||
            (((slcType == SLICE_B)) && (m_avcPicParam->weighted_bipred_idc == EXPLICIT_WEIGHTED_INTER_PRED_MODE))))
    {
        uint8_t idx;
        // Weighted Prediction to be applied for L0
        for (idx = 0; idx < (slcParams->num_ref_idx_l0_active_minus1 + 1); idx++)
        {
            if ((slcParams->luma_weight_flag[LIST_0] & (1 << idx)) && (idx < CODEC_AVC_MAX_FORWARD_WP_FRAME))
            {
                //Weighted Prediction for ith forward reference frame
                CODECHAL_ENCODE_CHK_STATUS_RETURN(WPKernel(false, idx));
            }
        }

        if (((slcType == SLICE_B)) &&
            (m_avcPicParam->weighted_bipred_idc == EXPLICIT_WEIGHTED_INTER_PRED_MODE))
        {
            for (idx = 0; idx < (slcParams->num_ref_idx_l1_active_minus1 + 1); idx++)
            {
                // Weighted Pred to be applied for L1
                if ((slcParams->luma_weight_flag[LIST_1] & 1 << idx) && (idx < CODEC_AVC_MAX_BACKWARD_WP_FRAME))
                {
                    //Weighted Prediction for ith backward reference frame
                    CODECHAL_ENCODE_CHK_STATUS_RETURN(WPKernel(false, idx));
                }
            }
        }
    }

#if (_DEBUG || _RELEASE_INTERNAL)

    MOS_USER_FEATURE_VALUE_WRITE_DATA userFeatureWriteData;

    // Weighted prediction for L0 Reporting
    userFeatureWriteData               = __NULL_USER_FEATURE_VALUE_WRITE_DATA__;
    userFeatureWriteData.Value.i32Data = bUseWeightedSurfaceForL0;
    userFeatureWriteData.ValueID       = __MEDIA_USER_FEATURE_VALUE_WEIGHTED_PREDICTION_L0_IN_USE_ID;
    MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);

    // Weighted prediction for L1 Reporting
    userFeatureWriteData               = __NULL_USER_FEATURE_VALUE_WRITE_DATA__;
    userFeatureWriteData.Value.i32Data = bUseWeightedSurfaceForL1;
    userFeatureWriteData.ValueID       = __MEDIA_USER_FEATURE_VALUE_WEIGHTED_PREDICTION_L1_IN_USE_ID;
    MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);

#endif  // _DEBUG || _RELEASE_INTERNAL

    m_lastTaskInPhase = true;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(MbEncKernel(false));

    // Reset buffer ID used for MbEnc kernel performance reports
    m_osInterface->pfnResetPerfBufferID(m_osInterface);

    if (!Mos_ResourceIsNull(&m_resSyncObjectRenderContextInUse))
    {
        auto syncParams             = g_cInitSyncParams;
        syncParams.GpuContext       = m_renderContext;
        syncParams.presSyncResource = &m_resSyncObjectRenderContextInUse;

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams));
    }

    if (m_madEnabled)
    {
        m_currMadBufferIdx = (m_currMadBufferIdx + 1) % CODECHAL_ENCODE_MAX_NUM_MAD_BUFFERS;
    }

    // Reset after BRC Init has been processed
    bBrcInit = false;

    m_setRequestedEUSlices = false;

    CODECHAL_DEBUG_TOOL(KernelDebugDumps());

    if (bBrcEnabled)
    {
        bMbEncCurbeSetInBrcUpdate = false;
    }

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::GenericEncodePictureLevel(PCODECHAL_ENCODE_AVC_GENERIC_PICTURE_LEVEL_PARAMS params)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    auto trellisQuantParams = &m_trellisQuantParams;

    PerfTagSetting perfTag;
    perfTag.Value = 0;
    perfTag.Mode = (uint16_t)m_mode & CODECHAL_ENCODE_MODE_BIT_MASK;
    perfTag.CallType = CODECHAL_ENCODE_PERFTAG_CALL_PAK_ENGINE;
    perfTag.PictureCodingType = m_pictureCodingType;
    m_osInterface->pfnSetPerfTag(m_osInterface, perfTag.Value);

    MOS_COMMAND_BUFFER cmdBuffer;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));

    MHW_MI_FORCE_WAKEUP_PARAMS forceWakeupParams;
    MOS_ZeroMemory(&forceWakeupParams, sizeof(MHW_MI_FORCE_WAKEUP_PARAMS));
    forceWakeupParams.bMFXPowerWellControl = true;
    forceWakeupParams.bMFXPowerWellControlMask = true;
    forceWakeupParams.bHEVCPowerWellControl = false;
    forceWakeupParams.bHEVCPowerWellControlMask = true;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiForceWakeupCmd(
        &cmdBuffer,
        &forceWakeupParams));

    // set MFX_PIPE_MODE_SELECT values
    MHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams;
    pipeModeSelectParams.Mode = m_mode;
    pipeModeSelectParams.bStreamOutEnabled = (m_currPass != m_numPasses);// Disable Stream Out for final pass; its important for multiple passes, because , next pass will take the qp from stream out

    pipeModeSelectParams.bDeblockerStreamOutEnable = params->bDeblockerStreamOutEnable;
    pipeModeSelectParams.bPostDeblockOutEnable = params->bPostDeblockOutEnable;
    pipeModeSelectParams.bPreDeblockOutEnable = params->bPreDeblockOutEnable;
    pipeModeSelectParams.bDynamicSliceEnable = m_avcSeqParam->EnableSliceLevelRateCtrl;

    // set MFX_PIPE_BUF_ADDR_STATE values
    MHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams;
    pipeBufAddrParams.Mode = m_mode;
    pipeBufAddrParams.psPreDeblockSurface = params->psPreDeblockSurface;
    pipeBufAddrParams.psPostDeblockSurface = params->psPostDeblockSurface;
    pipeBufAddrParams.psRawSurface = m_rawSurfaceToPak;
    pipeBufAddrParams.presStreamOutBuffer = &m_resStreamOutBuffer[m_currRecycledBufIdx];
    pipeBufAddrParams.presMfdDeblockingFilterRowStoreScratchBuffer = &m_resDeblockingFilterRowStoreScratchBuffer;
    pipeBufAddrParams.presMfdIntraRowStoreScratchBuffer = &m_intraRowStoreScratchBuffer;
    pipeBufAddrParams.presMacroblockIldbStreamOutBuffer1 = params->presMacroblockIldbStreamOutBuffer1;
    pipeBufAddrParams.presMacroblockIldbStreamOutBuffer2 = params->presMacroblockIldbStreamOutBuffer2;

    CODECHAL_DEBUG_TOOL(
    // PAK Input Raw Surface
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
        m_rawSurfaceToPak,
        CodechalDbgAttr::attrEncodeRawInputSurface,
        "PAK_Input_SrcSurf"));
    )

        auto firstValidFrame = &m_reconSurface.OsResource;

    // Setting invalid entries to nullptr
    for (uint32_t i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++)
    {
        pipeBufAddrParams.presReferences[i] = nullptr;
    }

    uint8_t firstValidFrameId = CODEC_AVC_MAX_NUM_REF_FRAME;

    for (uint32_t i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++)
    {
        if (m_picIdx[i].bValid)
        {
            uint8_t picIdx = m_picIdx[i].ucPicIdx;
            uint8_t frameStoreId = m_refList[picIdx]->ucFrameId;

            CodecHalGetResourceInfo(
                m_osInterface,
                &(m_refList[picIdx]->sRefReconBuffer));
            pipeBufAddrParams.presReferences[frameStoreId] =
                &(m_refList[picIdx]->sRefReconBuffer.OsResource);

            if (picIdx < firstValidFrameId)
            {
                firstValidFrameId = picIdx;
                firstValidFrame = pipeBufAddrParams.presReferences[picIdx];
            }

            CODECHAL_DEBUG_TOOL(
                CODECHAL_ENCODE_CHK_NULL_RETURN(m_debugInterface);
                MOS_SURFACE refSurface;

                MOS_ZeroMemory(&refSurface, sizeof(refSurface));
                refSurface.Format     = Format_NV12;
                refSurface.OsResource = *(pipeBufAddrParams.presReferences[frameStoreId]);
                CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(
                    m_osInterface,
                    &refSurface));

                m_debugInterface->m_refIndex = frameStoreId;
                std::string refSurfName      = "RefSurf" + std::to_string(static_cast<uint32_t>(m_debugInterface->m_refIndex));
                CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
                    &refSurface,
                    CodechalDbgAttr::attrReferenceSurfaces,
                    refSurfName.data()));)
        }
    }

    for (uint32_t i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++)
    {
        // error concealment for the unset reference addresses
        if (!pipeBufAddrParams.presReferences[i])
        {
            pipeBufAddrParams.presReferences[i] = firstValidFrame;
        }
    }

    if (m_sliceSizeStreamoutSupported)
    {
        pipeBufAddrParams.presSliceSizeStreamOutBuffer = &m_pakSliceSizeStreamoutBuffer;
    }

    // set MFX_IND_OBJ_BASE_ADDR_STATE values
    MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS indObjBaseAddrParams;
    MOS_ZeroMemory(&indObjBaseAddrParams, sizeof(indObjBaseAddrParams));
    indObjBaseAddrParams.Mode = CODECHAL_ENCODE_MODE_AVC;

    indObjBaseAddrParams.presMvObjectBuffer = &m_resMvDataSurface;
    indObjBaseAddrParams.dwMvObjectOffset = m_mvBottomFieldOffset;
    indObjBaseAddrParams.dwMvObjectSize = m_mvDataSize;
    indObjBaseAddrParams.presPakBaseObjectBuffer = &m_resBitstreamBuffer;
    indObjBaseAddrParams.dwPakBaseObjectSize = m_bitstreamUpperBound;

    // set MFX_BSP_BUF_BASE_ADDR_STATE values
    MHW_VDBOX_BSP_BUF_BASE_ADDR_PARAMS bspBufBaseAddrParams;
    MOS_ZeroMemory(&bspBufBaseAddrParams, sizeof(bspBufBaseAddrParams));
    bspBufBaseAddrParams.presBsdMpcRowStoreScratchBuffer = &m_resMPCRowStoreScratchBuffer;

    MHW_VDBOX_QM_PARAMS qmParams;
    qmParams.Standard = CODECHAL_AVC;
    qmParams.pAvcIqMatrix = (PMHW_VDBOX_AVC_QM_PARAMS)m_avcIQWeightScaleLists;

    MHW_VDBOX_QM_PARAMS fqmParams;
    fqmParams.Standard = CODECHAL_AVC;
    fqmParams.pAvcIqMatrix = (PMHW_VDBOX_AVC_QM_PARAMS)m_avcIQWeightScaleLists;

    // Add AVC Direct Mode command
    MHW_VDBOX_AVC_DIRECTMODE_PARAMS directmodeParams;
    MOS_ZeroMemory(&directmodeParams, sizeof(directmodeParams));
    directmodeParams.CurrPic = m_avcPicParam->CurrReconstructedPic;
    directmodeParams.isEncode = true;
    directmodeParams.uiUsedForReferenceFlags = 0xFFFFFFFF;
    directmodeParams.pAvcPicIdx = &(m_picIdx[0]);
    directmodeParams.avcRefList = (void**)m_refList;
    directmodeParams.bPicIdRemappingInUse = false;
    directmodeParams.bDisableDmvBuffers = true;

    // PAK cmd buffer header insertion for 1) non STF 2) STF (except VDEnc BRC case inserted in HuC cmd buffer)
    if (!m_singleTaskPhaseSupported || m_firstTaskInPhase)
    {
        bool requestFrameTracking = false;

        m_hwInterface->m_numRequestedEuSlices = ((m_frameHeight * m_frameWidth) >= m_ssdResolutionThreshold &&
            m_targetUsage <= m_ssdTargetUsageThreshold) ?
            m_sliceShutdownRequestState : m_sliceShutdownDefaultState;

        // Send command buffer header at the beginning (OS dependent)
        // frame tracking tag is only added in the last command buffer header
        requestFrameTracking = m_singleTaskPhaseSupported ? m_firstTaskInPhase : m_lastTaskInPhase;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(&cmdBuffer, requestFrameTracking));

        m_hwInterface->m_numRequestedEuSlices = CODECHAL_SLICE_SHUTDOWN_DEFAULT;
    }

    if (m_currPass)
    {
        MHW_MI_CONDITIONAL_BATCH_BUFFER_END_PARAMS miConditionalBatchBufferEndParams;
        // Insert conditional batch buffer end
        MOS_ZeroMemory(
            &miConditionalBatchBufferEndParams,
            sizeof(MHW_MI_CONDITIONAL_BATCH_BUFFER_END_PARAMS));

        miConditionalBatchBufferEndParams.presSemaphoreBuffer =
            &m_encodeStatusBuf.resStatusBuffer;
        miConditionalBatchBufferEndParams.dwOffset =
            (m_encodeStatusBuf.wCurrIndex * m_encodeStatusBuf.dwReportSize) +
            m_encodeStatusBuf.dwImageStatusMaskOffset +
            (sizeof(uint32_t) * 2);

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiConditionalBatchBufferEndCmd(
            &cmdBuffer,
            &miConditionalBatchBufferEndParams));
    }

    if (!m_currPass && m_osInterface->bTagResourceSync)
    {
        // This is a short term WA to solve the sync tag issue: the sync tag write for PAK is inserted at the end of 2nd pass PAK BB
        // which may be skipped in multi-pass PAK enabled case. The idea here is to insert the previous frame's tag at the beginning
        // of the BB and keep the current frame's tag at the end of the BB. There will be a delay for tag update but it should be fine
        // as long as Dec/VP/Enc won't depend on this PAK so soon.
        MHW_MI_STORE_DATA_PARAMS                        params;
        PMOS_RESOURCE                                   globalGpuContextSyncTagBuffer = nullptr;
        uint32_t                                        value;

        CODECHAL_HW_CHK_STATUS_RETURN(m_osInterface->pfnGetGpuStatusBufferResource(
            m_osInterface,
            globalGpuContextSyncTagBuffer));
        CODECHAL_ENCODE_CHK_NULL_RETURN(globalGpuContextSyncTagBuffer);

        value = m_osInterface->pfnGetGpuStatusTag(m_osInterface, m_osInterface->CurrentGpuContextOrdinal);
        params.pOsResource = globalGpuContextSyncTagBuffer;
        params.dwResourceOffset = m_osInterface->pfnGetGpuStatusTagOffset(m_osInterface, m_osInterface->CurrentGpuContextOrdinal);
        params.dwValue = (value > 0) ? (value - 1) : 0;
        CODECHAL_HW_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(&cmdBuffer, &params));
    }

    CODECHAL_ENCODE_CHK_STATUS_RETURN(StartStatusReport(&cmdBuffer, CODECHAL_NUM_MEDIA_STATES));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeModeSelectCmd(&cmdBuffer, &pipeModeSelectParams));

    // set MFX_SURFACE_STATE values
    // Ref surface
    MHW_VDBOX_SURFACE_PARAMS reconSurfaceParams;
    MOS_ZeroMemory(&reconSurfaceParams, sizeof(reconSurfaceParams));
    reconSurfaceParams.Mode = m_mode;
    reconSurfaceParams.ucSurfaceStateId = CODECHAL_MFX_REF_SURFACE_ID;
    reconSurfaceParams.psSurface = &m_reconSurface;
#ifdef _MMC_SUPPORTED
    CODECHAL_ENCODE_CHK_NULL_RETURN(m_mmcState);
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetSurfaceState(&reconSurfaceParams));
#endif
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxSurfaceCmd(&cmdBuffer, &reconSurfaceParams));

    // Src surface
    MHW_VDBOX_SURFACE_PARAMS surfaceParams;
    MOS_ZeroMemory(&surfaceParams, sizeof(surfaceParams));
    surfaceParams.Mode = m_mode;
    surfaceParams.ucSurfaceStateId = CODECHAL_MFX_SRC_SURFACE_ID;
    surfaceParams.psSurface = m_rawSurfaceToPak;
    surfaceParams.bDisplayFormatSwizzle = m_avcPicParam->bDisplayFormatSwizzle;
#ifdef _MMC_SUPPORTED
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetSurfaceState(&surfaceParams));
#endif
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxSurfaceCmd(&cmdBuffer, &surfaceParams));
#ifdef _MMC_SUPPORTED
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetPipeBufAddr(&pipeBufAddrParams));
#endif
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeBufAddrCmd(&cmdBuffer, &pipeBufAddrParams));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxIndObjBaseAddrCmd(&cmdBuffer, &indObjBaseAddrParams));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxBspBufBaseAddrCmd(&cmdBuffer, &bspBufBaseAddrParams));

    if (params->bBrcEnabled && m_avcSeqParam->RateControlMethod != RATECONTROL_ICQ)
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(
            &cmdBuffer,
            params->pImgStateBatchBuffer));
    }
    else
    {
        //Set MFX_AVC_IMG_STATE command
        MHW_VDBOX_AVC_IMG_PARAMS imageStateParams;
        imageStateParams.currPass = m_currPass;
        imageStateParams.pEncodeAvcPicParams = m_avcPicParam;
        imageStateParams.pEncodeAvcSeqParams = m_avcSeqParam;
        imageStateParams.pEncodeAvcSliceParams = m_avcSliceParams;
        if (CodecHalIsFeiEncode(m_codecFunction) && m_avcFeiPicParams && m_avcFeiPicParams->dwMaxFrameSize)
        {
            imageStateParams.pDeltaQp = m_avcFeiPicParams->pDeltaQp;
            imageStateParams.dwMaxFrameSize = m_avcFeiPicParams->dwMaxFrameSize;
        }
        imageStateParams.wPicWidthInMb = m_picWidthInMb;
        imageStateParams.wPicHeightInMb = m_picHeightInMb;
        imageStateParams.ppRefList = &(m_refList[0]);
        imageStateParams.dwTqEnabled = trellisQuantParams->dwTqEnabled;
        imageStateParams.dwTqRounding = trellisQuantParams->dwTqRounding;
        imageStateParams.ucKernelMode = m_kernelMode;
        imageStateParams.wSlcHeightInMb = m_sliceHeight;
        imageStateParams.dwMaxVmvR = CodecHalAvcEncode_GetMaxVmvR(m_avcSeqParam->Level);
        imageStateParams.bSliceSizeStreamOutEnabled = m_sliceSizeStreamoutSupported;

        if (m_currPass && (m_currPass == m_numPasses))
        {
            // Enable IPCM pass, excluding VDENC BRC case
            imageStateParams.bIPCMPass = true;
        }

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcImgCmd(&cmdBuffer, nullptr, &imageStateParams));

        CODECHAL_DEBUG_TOOL(
            CODECHAL_ENCODE_CHK_STATUS_RETURN(PopulatePakParam(
                &cmdBuffer,
                nullptr));
        )
    }

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxQmCmd(&cmdBuffer, &qmParams));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxFqmCmd(&cmdBuffer, &fqmParams));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcDirectmodeCmd(&cmdBuffer, &directmodeParams));

    m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::SceneChangeReport(PMOS_COMMAND_BUFFER    cmdBuffer, PCODECHAL_ENCODE_AVC_GENERIC_PICTURE_LEVEL_PARAMS params)
{

    MHW_MI_COPY_MEM_MEM_PARAMS                      copyMemMemParams;
    uint32_t offset = (m_encodeStatusBuf.wCurrIndex * m_encodeStatusBuf.dwReportSize)
        + (sizeof(uint32_t) * 2) + m_encodeStatusBuf.dwSceneChangedOffset;

    MOS_ZeroMemory(&copyMemMemParams, sizeof(copyMemMemParams));
    copyMemMemParams.presSrc = params->presBrcHistoryBuffer;
    copyMemMemParams.dwSrcOffset = brcHistoryBufferOffsetSceneChanged;
    copyMemMemParams.presDst = &m_encodeStatusBuf.resStatusBuffer;
    copyMemMemParams.dwDstOffset = offset;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiCopyMemMemCmd(
        cmdBuffer,
        &copyMemMemParams));

    return MOS_STATUS_SUCCESS;
}

MOS_STATUS CodechalEncodeAvcEncG12::InitializeState()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncodeAvcEnc::InitializeState());

    m_brcHistoryBufferSize  = m_initBrcHistoryBufferSize;
    m_mbencBrcBufferSize    = m_initMbencBrcBufferSize;
    m_forceBrcMbStatsEnabled = true;
    m_useHwScoreboard        = false;

    dwBrcConstantSurfaceWidth  = m_brcConstantsurfaceWidth;
    dwBrcConstantSurfaceHeight = m_brcConstantsurfaceHeight;

    // create intra distortion kernel
    m_intraDistKernel = MOS_New(CodechalKernelIntraDist, this);
    CODECHAL_ENCODE_CHK_NULL_RETURN(m_intraDistKernel);
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_intraDistKernel->Initialize(
        GetCommonKernelHeaderAndSizeG12,
        m_kernelBase,
        m_kuidCommon));

    // Create SW scoreboard init kernel state
    CODECHAL_ENCODE_CHK_NULL_RETURN(m_swScoreboardState = MOS_New(CodechalEncodeSwScoreboardG12, this));
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_swScoreboardState->InitKernelState());

    if (MOS_VE_SUPPORTED(m_osInterface))
    {
        m_sinlgePipeVeState = (PCODECHAL_ENCODE_SINGLEPIPE_VIRTUALENGINE_STATE)MOS_AllocAndZeroMemory(sizeof(CODECHAL_ENCODE_SINGLEPIPE_VIRTUALENGINE_STATE));
        CODECHAL_ENCODE_CHK_NULL_RETURN(m_sinlgePipeVeState);
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalEncodeSinglePipeVE_InitInterface(m_hwInterface, m_sinlgePipeVeState));
    }

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::InitMmcState()
{
    CODECHAL_ENCODE_FUNCTION_ENTER;
#ifdef _MMC_SUPPORTED
    m_mmcState = MOS_New(CodechalMmcEncodeAvcG12, m_hwInterface, this);
    CODECHAL_ENCODE_CHK_NULL_RETURN(m_mmcState);
#endif
    return MOS_STATUS_SUCCESS;
}

MOS_STATUS CodechalEncodeAvcEncG12::InitKernelStateBrc()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    uint8_t* kernelBinary;
    uint32_t kernelSize;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetKernelBinaryAndSize(m_kernelBase, m_kuid, &kernelBinary, &kernelSize));

    CODECHAL_KERNEL_HEADER currKrnHeader;
    for (uint32_t krnStateIdx = 0; krnStateIdx < CODECHAL_ENCODE_BRC_IDX_NUM; krnStateIdx++)
    {
        auto kernelStatePtr = &BrcKernelStates[krnStateIdx];
        CODECHAL_ENCODE_CHK_STATUS_RETURN(GetKernelHeaderAndSize(
            kernelBinary,
            ENC_BRC,
            krnStateIdx,
            (void*)&currKrnHeader,
            &kernelSize));

        kernelStatePtr->KernelParams.iBTCount     = m_brcBTCounts[krnStateIdx];
        kernelStatePtr->KernelParams.iThreadCount = m_renderEngineInterface->GetHwCaps()->dwMaxThreads;
        kernelStatePtr->KernelParams.iCurbeLength = m_brcCurbeSize[krnStateIdx];
        kernelStatePtr->KernelParams.iBlockWidth  = CODECHAL_MACROBLOCK_WIDTH;
        kernelStatePtr->KernelParams.iBlockHeight = CODECHAL_MACROBLOCK_HEIGHT;
        kernelStatePtr->KernelParams.iIdCount     = 1;

        kernelStatePtr->dwCurbeOffset        = m_stateHeapInterface->pStateHeapInterface->GetSizeofCmdInterfaceDescriptorData();
        kernelStatePtr->KernelParams.pBinary = kernelBinary + (currKrnHeader.KernelStartPointer << MHW_KERNEL_OFFSET_SHIFT);
        kernelStatePtr->KernelParams.iSize   = kernelSize;

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnCalculateSshAndBtSizesRequested(
            m_stateHeapInterface,
            kernelStatePtr->KernelParams.iBTCount,
            &kernelStatePtr->dwSshSize,
            &kernelStatePtr->dwBindingTableSize));

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->MhwInitISH(m_stateHeapInterface, kernelStatePtr));
    }

    // Until a better way can be found, maintain old binding table structures
    auto bindingTable                                 = &BrcUpdateBindingTable;
    bindingTable->dwFrameBrcHistoryBuffer             = frameBrcUpdateHistory;
    bindingTable->dwFrameBrcPakStatisticsOutputBuffer = frameBrcUpdatePakStatisticsOutput;
    bindingTable->dwFrameBrcImageStateReadBuffer      = frameBrcUpdateImageStateRead;
    bindingTable->dwFrameBrcImageStateWriteBuffer     = frameBrcUpdateImageStateWrite;

    bindingTable->dwFrameBrcMbEncCurbeWriteData = frameBrcUpdateMbencCurbeWrite;
    bindingTable->dwFrameBrcDistortionBuffer    = frameBrcUpdateDistortion;
    bindingTable->dwFrameBrcConstantData        = frameBrcUpdateConstantData;
    bindingTable->dwFrameBrcMbStatBuffer        = frameBrcUpdateMbStat;
    bindingTable->dwFrameBrcMvDataBuffer        = frameBrcUpdateMvStat;

    bindingTable->dwMbBrcHistoryBuffer = mbBrcUpdateHistory;
    bindingTable->dwMbBrcMbQpBuffer    = mbBrcUpdateMbQp;
    bindingTable->dwMbBrcROISurface    = mbBrcUpdateRoi;
    bindingTable->dwMbBrcMbStatBuffer  = mbBrcUpdateMbStat;

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::GetTrellisQuantization(
    PCODECHAL_ENCODE_AVC_TQ_INPUT_PARAMS params,
    PCODECHAL_ENCODE_AVC_TQ_PARAMS       trellisQuantParams)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(params);
    CODECHAL_ENCODE_CHK_NULL_RETURN(trellisQuantParams);

    trellisQuantParams->dwTqEnabled = TrellisQuantizationEnable[params->ucTargetUsage];
    trellisQuantParams->dwTqRounding =
        trellisQuantParams->dwTqEnabled ? trellisQuantizationRounding[params->ucTargetUsage] : 0;

    // If AdaptiveTrellisQuantization is enabled then disable trellis quantization for
    // B-frames with QP > 26 only in CQP mode
    if (trellisQuantParams->dwTqEnabled && EnableAdaptiveTrellisQuantization[params->ucTargetUsage] &&
        params->wPictureCodingType == B_TYPE && !params->bBrcEnabled && params->ucQP > 26)
    {
        trellisQuantParams->dwTqEnabled  = 0;
        trellisQuantParams->dwTqRounding = 0;
    }
    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::GetMbEncKernelStateIdx(CodechalEncodeIdOffsetParams* params, uint32_t* kernelOffset)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_CHK_NULL_RETURN(params);
    CODECHAL_ENCODE_CHK_NULL_RETURN(kernelOffset);

    *kernelOffset = mbencIOffset;

    if (params->EncFunctionType == CODECHAL_MEDIA_STATE_ENC_ADV)
    {
        *kernelOffset += m_mbencNumTargetUsages * mbencFrameTypeNum;
    }
    else
    {
        if (params->EncFunctionType == CODECHAL_MEDIA_STATE_ENC_NORMAL)
        {
            *kernelOffset += mbencFrameTypeNum;
        }
        else if (params->EncFunctionType == CODECHAL_MEDIA_STATE_ENC_PERFORMANCE)
        {
            *kernelOffset += mbencFrameTypeNum * 2;
        }
    }

    if (params->wPictureCodingType == P_TYPE)
    {
        *kernelOffset += mbencPOffset;
    }
    else if (params->wPictureCodingType == B_TYPE)
    {
        *kernelOffset += mbencBOffset;
    }

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::InitKernelStateMbEnc()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    dwNumMbEncEncKrnStates = m_mbencNumTargetUsages * mbencFrameTypeNum;
    dwNumMbEncEncKrnStates += mbencFrameTypeNum;
    pMbEncKernelStates = MOS_NewArray(MHW_KERNEL_STATE, dwNumMbEncEncKrnStates);
    CODECHAL_ENCODE_CHK_NULL_RETURN(pMbEncKernelStates);

    auto kernelStatePtr = pMbEncKernelStates;

    uint8_t* kernelBinary;
    uint32_t kernelSize;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetKernelBinaryAndSize(m_kernelBase, m_kuid, &kernelBinary, &kernelSize));
    CODECHAL_KERNEL_HEADER currKrnHeader;

    for (uint32_t krnStateIdx = 0; krnStateIdx < dwNumMbEncEncKrnStates; krnStateIdx++)
    {
        bool kernelState = (krnStateIdx >= m_mbencNumTargetUsages * mbencFrameTypeNum);

        CODECHAL_ENCODE_CHK_STATUS_RETURN(GetKernelHeaderAndSize(
            kernelBinary,
            (kernelState ? ENC_MBENC_ADV : ENC_MBENC),
            (kernelState ? krnStateIdx - m_mbencNumTargetUsages * mbencFrameTypeNum : krnStateIdx),
            &currKrnHeader,
            &kernelSize));

        kernelStatePtr->KernelParams.iBTCount     = mbencNumSurfaces;
        kernelStatePtr->KernelParams.iThreadCount = m_renderEngineInterface->GetHwCaps()->dwMaxThreads;
        kernelStatePtr->KernelParams.iCurbeLength = sizeof(CodechalEncodeAvcEncG12::MbencCurbe);
        kernelStatePtr->KernelParams.iBlockWidth  = CODECHAL_MACROBLOCK_WIDTH;
        kernelStatePtr->KernelParams.iBlockHeight = CODECHAL_MACROBLOCK_HEIGHT;
        kernelStatePtr->KernelParams.iIdCount     = 1;

        kernelStatePtr->dwCurbeOffset = m_stateHeapInterface->pStateHeapInterface->GetSizeofCmdInterfaceDescriptorData();
        kernelStatePtr->KernelParams.pBinary =
            kernelBinary +
            (currKrnHeader.KernelStartPointer << MHW_KERNEL_OFFSET_SHIFT);
        kernelStatePtr->KernelParams.iSize = kernelSize;

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnCalculateSshAndBtSizesRequested(
            m_stateHeapInterface,
            kernelStatePtr->KernelParams.iBTCount,
            &kernelStatePtr->dwSshSize,
            &kernelStatePtr->dwBindingTableSize));

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->MhwInitISH(m_stateHeapInterface, kernelStatePtr));

        kernelStatePtr++;
    }

    // Until a better way can be found, maintain old binding table structures
    auto bindingTable = &MbEncBindingTable;

    bindingTable->dwAvcMBEncMfcAvcPakObj   = mbencMfcAvcPakObj;
    bindingTable->dwAvcMBEncIndMVData      = mbencIndMvData;
    bindingTable->dwAvcMBEncBRCDist        = mbencBrcDistortion;
    bindingTable->dwAvcMBEncCurrY          = mbencCurrY;
    bindingTable->dwAvcMBEncCurrUV         = mbencCurrUv;
    bindingTable->dwAvcMBEncMbSpecificData = mbencMbSpecificData;

    bindingTable->dwAvcMBEncRefPicSelectL0           = mbencRefpicselectL0;
    bindingTable->dwAvcMBEncMVDataFromME             = mbencMvDataFromMe;
    bindingTable->dwAvcMBEncMEDist                   = mbenc4xMeDistortion;
    bindingTable->dwAvcMBEncSliceMapData             = mbencSlicemapData;
    bindingTable->dwAvcMBEncBwdRefMBData             = mbencFwdMbData;
    bindingTable->dwAvcMBEncBwdRefMVData             = mbencFwdMvData;
    bindingTable->dwAvcMBEncMbBrcConstData           = mbencMbbrcConstData;
    bindingTable->dwAvcMBEncMBStats                  = mbencMbStats;
    bindingTable->dwAvcMBEncMADData                  = mbencMadData;
    bindingTable->dwAvcMBEncMbNonSkipMap             = mbencForceNonskipMbMap;
    bindingTable->dwAvcMBEncAdv                      = mbEncAdv;
    bindingTable->dwAvcMbEncBRCCurbeData             = mbencBrcCurbeData;
    bindingTable->dwAvcMBEncStaticDetectionCostTable = mbencSfdCostTable;

    // Frame
    bindingTable->dwAvcMBEncMbQpFrame       = mbencMbqp;
    bindingTable->dwAvcMBEncCurrPicFrame[0] = mbencVmeInterPredCurrPicIdx0;
    bindingTable->dwAvcMBEncFwdPicFrame[0]  = mbencVmeInterPredFwdPicIDX0;
    bindingTable->dwAvcMBEncBwdPicFrame[0]  = mbencVmeInterPredBwdPicIDX00;
    bindingTable->dwAvcMBEncFwdPicFrame[1]  = mbencVmeInterPredFwdPicIDX1;
    bindingTable->dwAvcMBEncBwdPicFrame[1]  = mbencVmeInterPredBwdPicIDX10;
    bindingTable->dwAvcMBEncFwdPicFrame[2]  = mbencVmeInterPredFwdPicIDX2;
    bindingTable->dwAvcMBEncFwdPicFrame[3]  = mbencVmeInterPredFwdPicIDX3;
    bindingTable->dwAvcMBEncFwdPicFrame[4]  = mbencVmeInterPredFwdPicIDX4;
    bindingTable->dwAvcMBEncFwdPicFrame[5]  = mbencVmeInterPredFwdPicIDX5;
    bindingTable->dwAvcMBEncFwdPicFrame[6]  = mbencVmeInterPredFwdPicIDX6;
    bindingTable->dwAvcMBEncFwdPicFrame[7]  = mbencVmeInterPredFwdPicIDX7;
    bindingTable->dwAvcMBEncCurrPicFrame[1] = mbencVmeInterPredCurrPicIdx1;
    bindingTable->dwAvcMBEncBwdPicFrame[2]  = mbencVmeInterPredBwdPicIDX01;
    bindingTable->dwAvcMBEncBwdPicFrame[3]  = mbencVmeInterPredBwdPicIDX11;

    // Field
    bindingTable->dwAvcMBEncMbQpField         = mbencMbqp;
    bindingTable->dwAvcMBEncFieldCurrPic[0]   = mbencVmeInterPredCurrPicIdx0;
    bindingTable->dwAvcMBEncFwdPicTopField[0] = mbencVmeInterPredFwdPicIDX0;
    bindingTable->dwAvcMBEncBwdPicTopField[0] = mbencVmeInterPredBwdPicIDX00;
    bindingTable->dwAvcMBEncFwdPicBotField[0] = mbencVmeInterPredFwdPicIDX0;
    bindingTable->dwAvcMBEncBwdPicBotField[0] = mbencVmeInterPredBwdPicIDX00;
    bindingTable->dwAvcMBEncFwdPicTopField[1] = mbencVmeInterPredFwdPicIDX1;
    bindingTable->dwAvcMBEncBwdPicTopField[1] = mbencVmeInterPredBwdPicIDX10;
    bindingTable->dwAvcMBEncFwdPicBotField[1] = mbencVmeInterPredFwdPicIDX1;
    bindingTable->dwAvcMBEncBwdPicBotField[1] = mbencVmeInterPredBwdPicIDX10;
    bindingTable->dwAvcMBEncFwdPicTopField[2] = mbencVmeInterPredFwdPicIDX2;
    bindingTable->dwAvcMBEncFwdPicBotField[2] = mbencVmeInterPredFwdPicIDX2;
    bindingTable->dwAvcMBEncFwdPicTopField[3] = mbencVmeInterPredFwdPicIDX3;
    bindingTable->dwAvcMBEncFwdPicBotField[3] = mbencVmeInterPredFwdPicIDX3;
    bindingTable->dwAvcMBEncFwdPicTopField[4] = mbencVmeInterPredFwdPicIDX4;
    bindingTable->dwAvcMBEncFwdPicBotField[4] = mbencVmeInterPredFwdPicIDX4;
    bindingTable->dwAvcMBEncFwdPicTopField[5] = mbencVmeInterPredFwdPicIDX5;
    bindingTable->dwAvcMBEncFwdPicBotField[5] = mbencVmeInterPredFwdPicIDX5;
    bindingTable->dwAvcMBEncFwdPicTopField[6] = mbencVmeInterPredFwdPicIDX6;
    bindingTable->dwAvcMBEncFwdPicBotField[6] = mbencVmeInterPredFwdPicIDX6;
    bindingTable->dwAvcMBEncFwdPicTopField[7] = mbencVmeInterPredFwdPicIDX7;
    bindingTable->dwAvcMBEncFwdPicBotField[7] = mbencVmeInterPredFwdPicIDX7;
    bindingTable->dwAvcMBEncFieldCurrPic[1]   = mbencVmeInterPredCurrPicIdx1;
    bindingTable->dwAvcMBEncBwdPicTopField[2] = mbencVmeInterPredBwdPicIDX01;
    bindingTable->dwAvcMBEncBwdPicBotField[2] = mbencVmeInterPredBwdPicIDX01;
    bindingTable->dwAvcMBEncBwdPicTopField[3] = mbencVmeInterPredBwdPicIDX11;
    bindingTable->dwAvcMBEncBwdPicBotField[3] = mbencVmeInterPredBwdPicIDX11;

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::InitMbBrcConstantDataBuffer(PCODECHAL_ENCODE_AVC_INIT_MBBRC_CONSTANT_DATA_BUFFER_PARAMS params)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(params);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->pOsInterface);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->presBrcConstantDataBuffer);

    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncodeAvcEnc::InitMbBrcConstantDataBuffer(params));

    if (params->wPictureCodingType == I_TYPE)
    {
        MOS_LOCK_PARAMS lockFlags;
        memset(&lockFlags, 0, sizeof(MOS_LOCK_PARAMS));
        lockFlags.WriteOnly = 1;

        uint32_t *dataPtr = (uint32_t *)params->pOsInterface->pfnLockResource(
            params->pOsInterface,
            params->presBrcConstantDataBuffer,
            &lockFlags);
        if (dataPtr == nullptr)
        {
            eStatus = MOS_STATUS_UNKNOWN;
            return eStatus;
        }

        // Update MbBrcConstantDataBuffer with high texture cost
        for (uint8_t qp = 0; qp < CODEC_AVC_NUM_QP; qp++)
        {
            // Writing to DW13 in each sub-array of 16 DWs
            *(dataPtr + 13) = (uint32_t)m_intraModeCostForHighTextureMB[qp];
            // 16 DWs per QP value
            dataPtr += 16;
        }

        params->pOsInterface->pfnUnlockResource(
            params->pOsInterface,
            params->presBrcConstantDataBuffer);
    }

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::InitKernelStateWP()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    pWPKernelState = MOS_New(MHW_KERNEL_STATE);
    CODECHAL_ENCODE_CHK_NULL_RETURN(pWPKernelState);

    auto kernelStatePtr = pWPKernelState;

    uint8_t* kernelBinary;
    uint32_t kernelSize;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetKernelBinaryAndSize(m_kernelBase, m_kuid, &kernelBinary, &kernelSize));

    CODECHAL_KERNEL_HEADER currKrnHeader;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(pfnGetKernelHeaderAndSize(
        kernelBinary,
        ENC_WP,
        0,
        &currKrnHeader,
        &kernelSize));
    kernelStatePtr->KernelParams.iBTCount          = wpNumSurfaces;
    kernelStatePtr->KernelParams.iThreadCount      = m_renderEngineInterface->GetHwCaps()->dwMaxThreads;
    kernelStatePtr->KernelParams.iCurbeLength      = sizeof(CodechalEncodeAvcEncG12::WpCurbe);
    kernelStatePtr->KernelParams.iBlockWidth       = CODECHAL_MACROBLOCK_WIDTH;
    kernelStatePtr->KernelParams.iBlockHeight      = CODECHAL_MACROBLOCK_HEIGHT;
    kernelStatePtr->KernelParams.iIdCount          = 1;
    kernelStatePtr->KernelParams.iInlineDataLength = 0;

    kernelStatePtr->dwCurbeOffset        = m_stateHeapInterface->pStateHeapInterface->GetSizeofCmdInterfaceDescriptorData();
    kernelStatePtr->KernelParams.pBinary = kernelBinary + (currKrnHeader.KernelStartPointer << MHW_KERNEL_OFFSET_SHIFT);
    kernelStatePtr->KernelParams.iSize   = kernelSize;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnCalculateSshAndBtSizesRequested(
        m_stateHeapInterface,
        kernelStatePtr->KernelParams.iBTCount,
        &kernelStatePtr->dwSshSize,
        &kernelStatePtr->dwBindingTableSize));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->MhwInitISH(m_stateHeapInterface, kernelStatePtr));

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::InitBrcConstantBuffer(PCODECHAL_ENCODE_AVC_INIT_BRC_CONSTANT_BUFFER_PARAMS params)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(params);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->pOsInterface);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->pPicParams);

    uint8_t tableIdx               = params->wPictureCodingType - 1;

    if (tableIdx >= 3)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Invalid input parameter.");
        return MOS_STATUS_INVALID_PARAMETER;
    }

    MOS_LOCK_PARAMS lockFlags;
    memset(&lockFlags, 0, sizeof(MOS_LOCK_PARAMS));
    lockFlags.WriteOnly = 1;
    auto dataPtr         = (uint8_t*)params->pOsInterface->pfnLockResource(
        params->pOsInterface,
        &params->sBrcConstantDataBuffer.OsResource,
        &lockFlags);
    CODECHAL_ENCODE_CHK_NULL_RETURN(dataPtr);

    memset(dataPtr, 0, params->sBrcConstantDataBuffer.dwWidth * params->sBrcConstantDataBuffer.dwHeight);

    // Fill surface with QP Adjustment table, Distortion threshold table, MaxFrame threshold table, Distortion QP Adjustment Table
    eStatus = MOS_SecureMemcpy(
        dataPtr,
        sizeof(m_QPAdjustmentDistThresholdMaxFrameThresholdIPB),
        (void*)m_QPAdjustmentDistThresholdMaxFrameThresholdIPB,
        sizeof(m_QPAdjustmentDistThresholdMaxFrameThresholdIPB));
    if (eStatus != MOS_STATUS_SUCCESS)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
        return eStatus;
    }

    dataPtr += sizeof(m_QPAdjustmentDistThresholdMaxFrameThresholdIPB);

    bool    blockBasedSkipEn        = params->dwMbEncBlockBasedSkipEn ? true : false;
    bool    transform_8x8_mode_flag = params->pPicParams->transform_8x8_mode_flag ? true : false;

    // Fill surface with Skip Threshold Table
    switch (params->wPictureCodingType)
    {
    case P_TYPE:
        eStatus = MOS_SecureMemcpy(
            dataPtr,
            m_brcConstantsurfaceEarlySkipTableSize,
            (void*)&SkipVal_P_Common[blockBasedSkipEn][transform_8x8_mode_flag][0],
            m_brcConstantsurfaceEarlySkipTableSize);
        if (eStatus != MOS_STATUS_SUCCESS)
        {
            CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
            return eStatus;
        }
        break;
    case B_TYPE:
        eStatus = MOS_SecureMemcpy(
            dataPtr,
            m_brcConstantsurfaceEarlySkipTableSize,
            (void*)&SkipVal_B_Common[blockBasedSkipEn][transform_8x8_mode_flag][0],
            m_brcConstantsurfaceEarlySkipTableSize);
        if (eStatus != MOS_STATUS_SUCCESS)
        {
            CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
            return eStatus;
        }
        break;
    default:
        // do nothing for I TYPE
        break;
    }

    if ((params->wPictureCodingType != I_TYPE) && (params->pAvcQCParams != nullptr) && (params->pAvcQCParams->NonFTQSkipThresholdLUTInput))
    {
        for (uint8_t qp = 0; qp < CODEC_AVC_NUM_QP; qp++)
        {
            *(dataPtr + 1 + (qp * 2)) = (uint8_t)CalcSkipVal((params->dwMbEncBlockBasedSkipEn ? true : false),
                                                                            (params->pPicParams->transform_8x8_mode_flag ? true : false),
                                                                            params->pAvcQCParams->NonFTQSkipThresholdLUT[qp]);
        }
    }

    dataPtr += m_brcConstantsurfaceEarlySkipTableSize;

    // Fill surface with QP list

    // Initialize to -1 (0xff)
    memset(dataPtr, 0xff, m_brcConstantsurfaceQpList0);
    memset(dataPtr + m_brcConstantsurfaceQpList0 + m_brcConstantsurfaceQpList0Reserved,
           0xff, m_brcConstantsurfaceQpList1);

    switch (params->wPictureCodingType)
    {
    case B_TYPE:
        dataPtr += (m_brcConstantsurfaceQpList0 + m_brcConstantsurfaceQpList0Reserved);

        for (uint8_t refIdx = 0; refIdx <= params->pAvcSlcParams->num_ref_idx_l1_active_minus1; refIdx++)
        {
            CODEC_PICTURE refPic = params->pAvcSlcParams->RefPicList[LIST_1][refIdx];
            if (!CodecHal_PictureIsInvalid(refPic) && params->pAvcPicIdx[refPic.FrameIdx].bValid)
            {
                *(dataPtr + refIdx) = params->pAvcPicIdx[refPic.FrameIdx].ucPicIdx;
            }
        }
        dataPtr -= (m_brcConstantsurfaceQpList0 + m_brcConstantsurfaceQpList0Reserved);
    // break statement omitted intentionally
    case P_TYPE:
        for (uint8_t refIdx = 0; refIdx <= params->pAvcSlcParams->num_ref_idx_l0_active_minus1; refIdx++)
        {
            CODEC_PICTURE refPic = params->pAvcSlcParams->RefPicList[LIST_0][refIdx];
            if (!CodecHal_PictureIsInvalid(refPic) && params->pAvcPicIdx[refPic.FrameIdx].bValid)
            {
                *(dataPtr + refIdx) = params->pAvcPicIdx[refPic.FrameIdx].ucPicIdx;
            }
        }
        break;
    default:
        // do nothing for I type
        break;
    }

    dataPtr += (m_brcConstantsurfaceQpList0 + m_brcConstantsurfaceQpList0Reserved +
                m_brcConstantsurfaceQpList1 + m_brcConstantsurfaceQpList1Reserved);

    // Fill surface with Mode cost and MV cost
    eStatus = MOS_SecureMemcpy(
        dataPtr,
        m_brcConstantsurfaceModeMvCostSize,
        (void*)ModeMvCost_Cm[tableIdx],
        m_brcConstantsurfaceModeMvCostSize);
    if (eStatus != MOS_STATUS_SUCCESS)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
        return eStatus;
    }

    // If old mode cost is used the update the table
    if (params->wPictureCodingType == I_TYPE && params->bOldModeCostEnable)
    {
        auto dataTemp = (uint32_t *)dataPtr;
        for (uint8_t qp = 0; qp < CODEC_AVC_NUM_QP; qp++)
        {
            // Writing to DW0 in each sub-array of 16 DWs
            *dataTemp = (uint32_t)OldIntraModeCost_Cm_Common[qp];
            dataTemp += 16;
        }
    }

    if (params->pAvcQCParams)
    {
        for (uint8_t qp = 0; qp < CODEC_AVC_NUM_QP; qp++)
        {
            if (params->pAvcQCParams->FTQSkipThresholdLUTInput)
            {
                // clang-format off
                *(dataPtr + (qp * 32) + 24) =
                *(dataPtr + (qp * 32) + 25) =
                *(dataPtr + (qp * 32) + 27) =
                *(dataPtr + (qp * 32) + 28) =
                *(dataPtr + (qp * 32) + 29) =
                *(dataPtr + (qp * 32) + 30) =
                *(dataPtr + (qp * 32) + 31) = params->pAvcQCParams->FTQSkipThresholdLUT[qp];
                // clang-format on
            }
        }
    }

    dataPtr += m_brcConstantsurfaceModeMvCostSize;

    // Fill surface with Refcost
    eStatus = MOS_SecureMemcpy(
        dataPtr,
        m_brcConstantsurfaceRefcostSize,
        (void*)&m_refCostMultiRefQp[tableIdx][0],
        m_brcConstantsurfaceRefcostSize);
    if (eStatus != MOS_STATUS_SUCCESS)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
        return eStatus;
    }
    dataPtr += m_brcConstantsurfaceRefcostSize;

    //Fill surface with Intra cost scaling Factor
    if (params->bAdaptiveIntraScalingEnable)
    {
        eStatus = MOS_SecureMemcpy(
            dataPtr,
            m_brcConstantsurfaceIntracostScalingFactor,
            (void*)&AdaptiveIntraScalingFactor_Cm_Common[0],
            m_brcConstantsurfaceIntracostScalingFactor);
        if (eStatus != MOS_STATUS_SUCCESS)
        {
            CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
            return eStatus;
        }
    }
    else
    {
        eStatus = MOS_SecureMemcpy(
            dataPtr,
            m_brcConstantsurfaceIntracostScalingFactor,
            (void*)&IntraScalingFactor_Cm_Common[0],
            m_brcConstantsurfaceIntracostScalingFactor);
        if (eStatus != MOS_STATUS_SUCCESS)
        {
            CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
            return eStatus;
        }
    }

    dataPtr += m_brcConstantsurfaceIntracostScalingFactor;

    eStatus = MOS_SecureMemcpy(
        dataPtr,
        m_brcConstantsurfaceLambdaSize,
        (void*)&m_lambdaData[0],
        m_brcConstantsurfaceLambdaSize);
    if (eStatus != MOS_STATUS_SUCCESS)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
        return eStatus;
    }

    dataPtr += m_brcConstantsurfaceLambdaSize;

    eStatus = MOS_SecureMemcpy(
        dataPtr,
        m_brcConstantsurfaceFtq25Size,
        (void*)&m_ftQ25[0],
        m_brcConstantsurfaceFtq25Size);
    if (eStatus != MOS_STATUS_SUCCESS)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
        return eStatus;
    }

    params->pOsInterface->pfnUnlockResource(
        params->pOsInterface,
        &params->sBrcConstantDataBuffer.OsResource);

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::SetCurbeAvcMbEnc(PCODECHAL_ENCODE_AVC_MBENC_CURBE_PARAMS params)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(params);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->pPicParams);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->pSeqParams);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->pSlcParams);

    auto picParams = params->pPicParams;
    auto seqParams = params->pSeqParams;
    auto slcParams = params->pSlcParams;

    CODECHAL_ENCODE_ASSERT(seqParams->TargetUsage < NUM_TARGET_USAGE_MODES);

    uint8_t meMethod = (m_pictureCodingType == B_TYPE) ? m_bMeMethodGeneric[seqParams->TargetUsage] : m_meMethodGeneric[seqParams->TargetUsage];
    // set sliceQP to MAX_SLICE_QP for  MbEnc kernel, we can use it to verify whether QP is changed or not
    uint8_t sliceQP      = (params->bUseMbEncAdvKernel && params->bBrcEnabled) ? CODECHAL_ENCODE_AVC_MAX_SLICE_QP : picParams->pic_init_qp_minus26 + 26 + slcParams->slice_qp_delta;
    bool    framePicture = CodecHal_PictureIsFrame(picParams->CurrOriginalPic);
    bool    bottomField  = CodecHal_PictureIsBottomField(picParams->CurrOriginalPic);

    CodechalEncodeAvcEncG12::MbencCurbe::MBEncCurbeInitType curbeInitType;
    if (params->bMbEncIFrameDistEnabled)
    {
        curbeInitType = CodechalEncodeAvcEncG12::MbencCurbe::typeIDist;
    }
    else
    {
        switch (m_pictureCodingType)
        {
        case I_TYPE:
            if (framePicture)
            {
                curbeInitType = CodechalEncodeAvcEncG12::MbencCurbe::typeIFrame;
            }
            else
            {
                curbeInitType = CodechalEncodeAvcEncG12::MbencCurbe::typeIField;
            }
            break;

        case P_TYPE:
            if (framePicture)
            {
                curbeInitType = CodechalEncodeAvcEncG12::MbencCurbe::typePFrame;
            }
            else
            {
                curbeInitType = CodechalEncodeAvcEncG12::MbencCurbe::typePField;
            }
            break;
        case B_TYPE:
            if (framePicture)
            {
                curbeInitType = CodechalEncodeAvcEncG12::MbencCurbe::typeBFrame;
            }
            else
            {
                curbeInitType = CodechalEncodeAvcEncG12::MbencCurbe::typeBField;
            }
            break;
        default:
            CODECHAL_ENCODE_ASSERTMESSAGE("Invalid picture coding type.");
            eStatus = MOS_STATUS_UNKNOWN;
            return eStatus;
        }
    }

    CodechalEncodeAvcEncG12::MbencCurbe cmd;
    cmd.SetDefaultMbencCurbe(curbeInitType);
    // r1
    cmd.m_curbe.DW0.m_adaptiveEn =
        cmd.m_curbe.DW37.m_adaptiveEn = EnableAdaptiveSearch[seqParams->TargetUsage];
    cmd.m_curbe.DW0.m_t8x8FlagForInterEn =
        cmd.m_curbe.DW37.m_t8x8FlagForInterEn = picParams->transform_8x8_mode_flag;
    cmd.m_curbe.DW2.m_lenSP                   = MaxLenSP[seqParams->TargetUsage];

    cmd.m_curbe.DW1.m_extendedMvCostRange = bExtendedMvCostRange;
    cmd.m_curbe.DW36.m_mbInputEnable = bMbSpecificDataEnabled;

    cmd.m_curbe.DW38.m_lenSP = 0;  // MBZ
    cmd.m_curbe.DW3.m_srcAccess =
        cmd.m_curbe.DW3.m_refAccess = framePicture ? 0 : 1;
    if (m_pictureCodingType != I_TYPE && bFTQEnable)
    {
        if (m_pictureCodingType == P_TYPE)
        {
            cmd.m_curbe.DW3.m_fTEnable = FTQBasedSkip[seqParams->TargetUsage] & 0x01;
        }
        else  // B_TYPE
        {
            cmd.m_curbe.DW3.m_fTEnable = (FTQBasedSkip[seqParams->TargetUsage] >> 1) & 0x01;
        }
    }
    else
    {
        cmd.m_curbe.DW3.m_fTEnable = 0;
    }
    if (picParams->UserFlags.bDisableSubMBPartition)
    {
        cmd.m_curbe.DW3.m_subMbPartMask = CODECHAL_ENCODE_AVC_DISABLE_4X4_SUB_MB_PARTITION | CODECHAL_ENCODE_AVC_DISABLE_4X8_SUB_MB_PARTITION | CODECHAL_ENCODE_AVC_DISABLE_8X4_SUB_MB_PARTITION;
    }
    cmd.m_curbe.DW2.m_picWidth        = params->wPicWidthInMb;
    cmd.m_curbe.DW4.m_picHeightMinus1 = params->wFieldFrameHeightInMb - 1;
    cmd.m_curbe.DW4.m_fieldParityFlag = cmd.m_curbe.DW7.m_srcFieldPolarity = bottomField ? 1 : 0;
    cmd.m_curbe.DW4.m_enableFBRBypass                                              = bFBRBypassEnable;
    cmd.m_curbe.DW4.m_enableIntraCostScalingForStaticFrame                         = params->bStaticFrameDetectionEnabled;
    cmd.m_curbe.DW4.m_bCurFldIDR                                                   = framePicture ? 0 : (picParams->bIdrPic || m_firstFieldIdrPic);
    cmd.m_curbe.DW4.m_constrainedIntraPredFlag                                     = picParams->constrained_intra_pred_flag;
    cmd.m_curbe.DW4.m_hmeEnable                                                    = m_hmeEnabled;
    cmd.m_curbe.DW4.m_pictureType                                                  = m_pictureCodingType - 1;
    cmd.m_curbe.DW4.m_useActualRefQPValue                                          = m_hmeEnabled ? (m_multiRefDisableQPCheck[seqParams->TargetUsage] == 0) : false;
    cmd.m_curbe.DW5.m_sliceMbHeight                                                = params->usSliceHeight;
    cmd.m_curbe.DW7.m_intraPartMask                                                = picParams->transform_8x8_mode_flag ? 0 : 0x2;  // Disable 8x8 if flag is not set

    // r2
    if (params->bMbEncIFrameDistEnabled)
    {
        cmd.m_curbe.DW6.m_batchBufferEnd = 0;
    }
    else
    {
        uint8_t tableIdx = m_pictureCodingType - 1;
        eStatus          = MOS_SecureMemcpy(&(cmd.m_curbe.ModeMvCost), 8 * sizeof(uint32_t), ModeMvCost_Cm[tableIdx][sliceQP], 8 * sizeof(uint32_t));
        if (eStatus != MOS_STATUS_SUCCESS)
        {
            CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
            return eStatus;
        }

        if (m_pictureCodingType == I_TYPE && bOldModeCostEnable)
        {
            // Old intra mode cost needs to be used if bOldModeCostEnable is 1
            cmd.m_curbe.ModeMvCost.DW8.m_value = OldIntraModeCost_Cm_Common[sliceQP];
        }
        else if (m_skipBiasAdjustmentEnable)
        {
            // Load different MvCost for P picture when SkipBiasAdjustment is enabled
            // No need to check for P picture as the flag is only enabled for P picture
            cmd.m_curbe.ModeMvCost.DW11.m_value = MvCost_PSkipAdjustment_Cm_Common[sliceQP];
        }
    }

    uint8_t tableIdx;
    // r3 & r4
    if (params->bMbEncIFrameDistEnabled)
    {
        cmd.m_curbe.SPDelta.DW31.m_intraComputeType = 1;
    }
    else
    {
        tableIdx = (m_pictureCodingType == B_TYPE) ? 1 : 0;
        eStatus  = MOS_SecureMemcpy(&(cmd.m_curbe.SPDelta), 16 * sizeof(uint32_t), m_encodeSearchPath[tableIdx][meMethod], 16 * sizeof(uint32_t));
        if (eStatus != MOS_STATUS_SUCCESS)
        {
            CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
            return eStatus;
        }
    }

    // r5
    if (m_pictureCodingType == P_TYPE)
    {
        cmd.m_curbe.DW32.m_skipVal = SkipVal_P_Common
            [cmd.m_curbe.DW3.m_blockBasedSkipEnable]
            [picParams->transform_8x8_mode_flag]
            [sliceQP];
    }
    else if (m_pictureCodingType == B_TYPE)
    {
        cmd.m_curbe.DW32.m_skipVal = SkipVal_B_Common
            [cmd.m_curbe.DW3.m_blockBasedSkipEnable]
            [picParams->transform_8x8_mode_flag]
            [sliceQP];
    }

    cmd.m_curbe.ModeMvCost.DW13.m_qpPrimeY = sliceQP;
    // m_qpPrimeCb and m_qpPrimeCr are not used by Kernel. Following settings are for CModel matching.
    cmd.m_curbe.ModeMvCost.DW13.m_qpPrimeCb        = sliceQP;
    cmd.m_curbe.ModeMvCost.DW13.m_qpPrimeCr        = sliceQP;
    cmd.m_curbe.ModeMvCost.DW13.m_targetSizeInWord = 0xff;  // hardcoded for BRC disabled

    if (bMultiPredEnable && (m_pictureCodingType != I_TYPE))
    {
        switch (m_multiPred[seqParams->TargetUsage])
        {
        case 0:  // Disable multipred for both P & B picture types
            cmd.m_curbe.DW32.m_multiPredL0Disable = CODECHAL_ENCODE_AVC_MULTIPRED_DISABLE;
            cmd.m_curbe.DW32.m_multiPredL1Disable = CODECHAL_ENCODE_AVC_MULTIPRED_DISABLE;
            break;

        case 1:  // Enable multipred for P pictures only
            cmd.m_curbe.DW32.m_multiPredL0Disable = (m_pictureCodingType == P_TYPE) ? CODECHAL_ENCODE_AVC_MULTIPRED_ENABLE : CODECHAL_ENCODE_AVC_MULTIPRED_DISABLE;
            cmd.m_curbe.DW32.m_multiPredL1Disable = CODECHAL_ENCODE_AVC_MULTIPRED_DISABLE;
            break;

        case 2:  // Enable multipred for B pictures only
            cmd.m_curbe.DW32.m_multiPredL0Disable = (m_pictureCodingType == B_TYPE) ? CODECHAL_ENCODE_AVC_MULTIPRED_ENABLE : CODECHAL_ENCODE_AVC_MULTIPRED_DISABLE;
            cmd.m_curbe.DW32.m_multiPredL1Disable = (m_pictureCodingType == B_TYPE) ? CODECHAL_ENCODE_AVC_MULTIPRED_ENABLE : CODECHAL_ENCODE_AVC_MULTIPRED_DISABLE;
            break;

        case 3:  // Enable multipred for both P & B picture types
            cmd.m_curbe.DW32.m_multiPredL0Disable = CODECHAL_ENCODE_AVC_MULTIPRED_ENABLE;
            cmd.m_curbe.DW32.m_multiPredL1Disable = (m_pictureCodingType == B_TYPE) ? CODECHAL_ENCODE_AVC_MULTIPRED_ENABLE : CODECHAL_ENCODE_AVC_MULTIPRED_DISABLE;
            break;
        }
    }
    else
    {
        cmd.m_curbe.DW32.m_multiPredL0Disable = CODECHAL_ENCODE_AVC_MULTIPRED_DISABLE;
        cmd.m_curbe.DW32.m_multiPredL1Disable = CODECHAL_ENCODE_AVC_MULTIPRED_DISABLE;
    }

    if (!framePicture)
    {
        if (m_pictureCodingType != I_TYPE)
        {
            cmd.m_curbe.DW34.m_list0RefID0FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_0, CODECHAL_ENCODE_REF_ID_0);
            cmd.m_curbe.DW34.m_list0RefID1FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_0, CODECHAL_ENCODE_REF_ID_1);
            cmd.m_curbe.DW34.m_list0RefID2FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_0, CODECHAL_ENCODE_REF_ID_2);
            cmd.m_curbe.DW34.m_list0RefID3FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_0, CODECHAL_ENCODE_REF_ID_3);
            cmd.m_curbe.DW34.m_list0RefID4FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_0, CODECHAL_ENCODE_REF_ID_4);
            cmd.m_curbe.DW34.m_list0RefID5FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_0, CODECHAL_ENCODE_REF_ID_5);
            cmd.m_curbe.DW34.m_list0RefID6FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_0, CODECHAL_ENCODE_REF_ID_6);
            cmd.m_curbe.DW34.m_list0RefID7FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_0, CODECHAL_ENCODE_REF_ID_7);
        }
        if (m_pictureCodingType == B_TYPE)
        {
            cmd.m_curbe.DW34.m_list1RefID0FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_1, CODECHAL_ENCODE_REF_ID_0);
            cmd.m_curbe.DW34.m_list1RefID1FieldParity = CodecHalAvcEncode_GetFieldParity(slcParams, LIST_1, CODECHAL_ENCODE_REF_ID_1);
        }
    }

    if (m_adaptiveTransformDecisionEnabled)
    {
        if (m_pictureCodingType != I_TYPE)
        {
            cmd.m_curbe.DW34.m_enableAdaptiveTxDecision = true;
        }
        cmd.m_curbe.DW60.m_txDecisonThreshold = m_adaptiveTxDecisionThreshold;
    }

    if (m_adaptiveTransformDecisionEnabled || m_flatnessCheckEnabled)
    {
        cmd.m_curbe.DW60.m_mbTextureThreshold = m_mbTextureThreshold;
    }

    if (m_pictureCodingType == B_TYPE)
    {
        cmd.m_curbe.DW34.m_list1RefID0FrameFieldFlag = GetRefPicFieldFlag(params, LIST_1, CODECHAL_ENCODE_REF_ID_0);
        cmd.m_curbe.DW34.m_list1RefID1FrameFieldFlag = GetRefPicFieldFlag(params, LIST_1, CODECHAL_ENCODE_REF_ID_1);
        cmd.m_curbe.DW34.m_bDirectMode               = slcParams->direct_spatial_mv_pred_flag;
    }

    cmd.m_curbe.DW34.m_enablePerMBStaticCheck          = params->bStaticFrameDetectionEnabled;
    cmd.m_curbe.DW34.m_enableAdaptiveSearchWindowSize  = params->bApdatvieSearchWindowSizeEnabled;
    cmd.m_curbe.DW34.m_removeIntraRefreshOverlap       = picParams->bDisableRollingIntraRefreshOverlap;
    cmd.m_curbe.DW34.m_bOriginalBff                    = framePicture ? 0 : ((m_firstField && (bottomField)) || (!m_firstField && (!bottomField)));
    cmd.m_curbe.DW34.m_enableMBFlatnessChkOptimization = m_flatnessCheckEnabled;
    cmd.m_curbe.DW34.m_roiEnableFlag                   = params->bRoiEnabled;
    cmd.m_curbe.DW34.m_madEnableFlag                   = m_madEnabled;
    cmd.m_curbe.DW34.m_mbBrcEnable                     = bMbBrcEnabled || bMbQpDataEnabled;
    cmd.m_curbe.DW34.m_arbitraryNumMbsPerSlice         = m_arbitraryNumMbsInSlice;
    cmd.m_curbe.DW34.m_tqEnable                        = m_trellisQuantParams.dwTqEnabled;  //Enabled for KBL
    cmd.m_curbe.DW34.m_forceNonSkipMbEnable            = params->bMbDisableSkipMapEnabled;
    if (params->pAvcQCParams && !cmd.m_curbe.DW34.m_forceNonSkipMbEnable)  // ignore DisableEncSkipCheck if Mb Disable Skip Map is available
    {
        cmd.m_curbe.DW34.m_disableEncSkipCheck = params->pAvcQCParams->skipCheckDisable;
        }
        cmd.m_curbe.DW34.m_cqpFlag                    = !bBrcEnabled;  // 1 - Rate Control is CQP, 0 - Rate Control is BRC
        cmd.m_curbe.DW36.m_checkAllFractionalEnable   = bCAFEnable;
        cmd.m_curbe.DW38.m_refThreshold               = m_refThreshold;
        cmd.m_curbe.DW39.m_hmeRefWindowsCombThreshold = (m_pictureCodingType == B_TYPE) ? HMEBCombineLen[seqParams->TargetUsage] : HMECombineLen[seqParams->TargetUsage];

        // Default:2 used for MBBRC (MB QP Surface width and height are 4x downscaled picture in MB unit * 4  bytes)
        // 0 used for MBQP data surface (MB QP Surface width and height are same as the input picture size in MB unit * 1bytes)
        // BRC use split kernel, MB QP surface is same size as input picture
        cmd.m_curbe.DW47.m_mbQpReadFactor = (bMbBrcEnabled || bMbQpDataEnabled) ? 0 : 2;

        // Those fields are not really used for I_dist kernel
        if (params->bMbEncIFrameDistEnabled)
        {
            cmd.m_curbe.ModeMvCost.DW13.m_qpPrimeY        = 0;
            cmd.m_curbe.ModeMvCost.DW13.m_qpPrimeCb       = 0;
            cmd.m_curbe.ModeMvCost.DW13.m_qpPrimeCr       = 0;
            cmd.m_curbe.DW33.m_intra16x16NonDCPredPenalty = 0;
            cmd.m_curbe.DW33.m_intra4x4NonDCPredPenalty   = 0;
            cmd.m_curbe.DW33.m_intra8x8NonDCPredPenalty   = 0;
    }

    //r6
    if (cmd.m_curbe.DW4.m_useActualRefQPValue)
    {
        cmd.m_curbe.DW44.m_actualQPValueForRefID0List0 = AVCGetQPValueFromRefList(params, LIST_0, CODECHAL_ENCODE_REF_ID_0);
        cmd.m_curbe.DW44.m_actualQPValueForRefID1List0 = AVCGetQPValueFromRefList(params, LIST_0, CODECHAL_ENCODE_REF_ID_1);
        cmd.m_curbe.DW44.m_actualQPValueForRefID2List0 = AVCGetQPValueFromRefList(params, LIST_0, CODECHAL_ENCODE_REF_ID_2);
        cmd.m_curbe.DW44.m_actualQPValueForRefID3List0 = AVCGetQPValueFromRefList(params, LIST_0, CODECHAL_ENCODE_REF_ID_3);
        cmd.m_curbe.DW45.m_actualQPValueForRefID4List0 = AVCGetQPValueFromRefList(params, LIST_0, CODECHAL_ENCODE_REF_ID_4);
        cmd.m_curbe.DW45.m_actualQPValueForRefID5List0 = AVCGetQPValueFromRefList(params, LIST_0, CODECHAL_ENCODE_REF_ID_5);
        cmd.m_curbe.DW45.m_actualQPValueForRefID6List0 = AVCGetQPValueFromRefList(params, LIST_0, CODECHAL_ENCODE_REF_ID_6);
        cmd.m_curbe.DW45.m_actualQPValueForRefID7List0 = AVCGetQPValueFromRefList(params, LIST_0, CODECHAL_ENCODE_REF_ID_7);
        cmd.m_curbe.DW46.m_actualQPValueForRefID0List1 = AVCGetQPValueFromRefList(params, LIST_1, CODECHAL_ENCODE_REF_ID_0);
        cmd.m_curbe.DW46.m_actualQPValueForRefID1List1 = AVCGetQPValueFromRefList(params, LIST_1, CODECHAL_ENCODE_REF_ID_1);
    }

    tableIdx           = m_pictureCodingType - 1;
    cmd.m_curbe.DW46.m_refCost = m_refCostMultiRefQp[tableIdx][sliceQP];

    // Picture Coding Type dependent parameters
    if (m_pictureCodingType == I_TYPE)
    {
        cmd.m_curbe.DW0.m_skipModeEn                  = 0;
        cmd.m_curbe.DW37.m_skipModeEn                 = 0;
        cmd.m_curbe.DW36.m_hmeCombineOverlap          = 0;
        cmd.m_curbe.DW47.m_intraCostSF                = 16;  // This is not used but recommended to set this to 16 by Kernel team
        cmd.m_curbe.DW34.m_enableDirectBiasAdjustment = 0;
    }
    else if (m_pictureCodingType == P_TYPE)
    {
        cmd.m_curbe.DW1.m_maxNumMVs                   = GetMaxMvsPer2Mb(seqParams->Level) / 2;
        cmd.m_curbe.DW3.m_bmeDisableFBR               = 1;
        cmd.m_curbe.DW5.m_refWidth                    = SearchX[seqParams->TargetUsage];
        cmd.m_curbe.DW5.m_refHeight                   = SearchY[seqParams->TargetUsage];
        cmd.m_curbe.DW7.m_nonSkipZMvAdded             = 1;
        cmd.m_curbe.DW7.m_nonSkipModeAdded            = 1;
        cmd.m_curbe.DW7.m_skipCenterMask              = 1;
        cmd.m_curbe.DW47.m_intraCostSF                = bAdaptiveIntraScalingEnable ? AdaptiveIntraScalingFactor_Cm_Common[sliceQP] : IntraScalingFactor_Cm_Common[sliceQP];
        cmd.m_curbe.DW47.m_maxVmvR                    = (framePicture) ? CodecHalAvcEncode_GetMaxMvLen(seqParams->Level) * 4 : (CodecHalAvcEncode_GetMaxMvLen(seqParams->Level) >> 1) * 4;
        cmd.m_curbe.DW36.m_hmeCombineOverlap          = 1;
        cmd.m_curbe.DW36.m_numRefIdxL0MinusOne        = bMultiPredEnable ? slcParams->num_ref_idx_l0_active_minus1 : 0;
        cmd.m_curbe.DW39.m_refWidth                   = SearchX[seqParams->TargetUsage];
        cmd.m_curbe.DW39.m_refHeight                  = SearchY[seqParams->TargetUsage];
        cmd.m_curbe.DW34.m_enableDirectBiasAdjustment = 0;
        if (params->pAvcQCParams)
        {
            cmd.m_curbe.DW34.m_enableGlobalMotionBiasAdjustment = params->pAvcQCParams->globalMotionBiasAdjustmentEnable;
        }
    }
    else
    {
        // B_TYPE
        cmd.m_curbe.DW1.m_maxNumMVs      = GetMaxMvsPer2Mb(seqParams->Level) / 2;
        cmd.m_curbe.DW1.m_biWeight       = m_biWeight;
        cmd.m_curbe.DW3.m_searchCtrl     = 7;
        cmd.m_curbe.DW3.m_skipType       = 1;
        cmd.m_curbe.DW5.m_refWidth       = BSearchX[seqParams->TargetUsage];
        cmd.m_curbe.DW5.m_refHeight      = BSearchY[seqParams->TargetUsage];
        cmd.m_curbe.DW7.m_skipCenterMask = 0xFF;
        cmd.m_curbe.DW47.m_intraCostSF =
            bAdaptiveIntraScalingEnable ? AdaptiveIntraScalingFactor_Cm_Common[sliceQP] : IntraScalingFactor_Cm_Common[sliceQP];
        cmd.m_curbe.DW47.m_maxVmvR           = (framePicture) ? CodecHalAvcEncode_GetMaxMvLen(seqParams->Level) * 4 : (CodecHalAvcEncode_GetMaxMvLen(seqParams->Level) >> 1) * 4;
        cmd.m_curbe.DW36.m_hmeCombineOverlap = 1;
        // Checking if the forward frame (List 1 index 0) is a short term reference
        {
            auto codecHalPic = params->pSlcParams->RefPicList[LIST_1][0];
            if (codecHalPic.PicFlags != PICTURE_INVALID &&
                codecHalPic.FrameIdx != CODECHAL_ENCODE_AVC_INVALID_PIC_ID &&
                params->pPicIdx[codecHalPic.FrameIdx].bValid)
            {
                // Although its name is FWD, it actually means the future frame or the backward reference frame
                cmd.m_curbe.DW36.m_isFwdFrameShortTermRef = CodecHal_PictureIsShortTermRef(params->pPicParams->RefFrameList[codecHalPic.FrameIdx]);
            }
            else
            {
                CODECHAL_ENCODE_ASSERTMESSAGE("Invalid backward reference frame.");
                eStatus = MOS_STATUS_INVALID_PARAMETER;
                return eStatus;
            }
        }
        cmd.m_curbe.DW36.m_numRefIdxL0MinusOne        = bMultiPredEnable ? slcParams->num_ref_idx_l0_active_minus1 : 0;
        cmd.m_curbe.DW36.m_numRefIdxL1MinusOne        = bMultiPredEnable ? slcParams->num_ref_idx_l1_active_minus1 : 0;
        cmd.m_curbe.DW39.m_refWidth                   = BSearchX[seqParams->TargetUsage];
        cmd.m_curbe.DW39.m_refHeight                  = BSearchY[seqParams->TargetUsage];
        cmd.m_curbe.DW40.m_distScaleFactorRefID0List0 = m_distScaleFactorList0[0];
        cmd.m_curbe.DW40.m_distScaleFactorRefID1List0 = m_distScaleFactorList0[1];
        cmd.m_curbe.DW41.m_distScaleFactorRefID2List0 = m_distScaleFactorList0[2];
        cmd.m_curbe.DW41.m_distScaleFactorRefID3List0 = m_distScaleFactorList0[3];
        cmd.m_curbe.DW42.m_distScaleFactorRefID4List0 = m_distScaleFactorList0[4];
        cmd.m_curbe.DW42.m_distScaleFactorRefID5List0 = m_distScaleFactorList0[5];
        cmd.m_curbe.DW43.m_distScaleFactorRefID6List0 = m_distScaleFactorList0[6];
        cmd.m_curbe.DW43.m_distScaleFactorRefID7List0 = m_distScaleFactorList0[7];
        if (params->pAvcQCParams)
        {
            cmd.m_curbe.DW34.m_enableDirectBiasAdjustment = params->pAvcQCParams->directBiasAdjustmentEnable;
            if (cmd.m_curbe.DW34.m_enableDirectBiasAdjustment)
            {
                cmd.m_curbe.DW7.m_nonSkipModeAdded = 1;
                cmd.m_curbe.DW7.m_nonSkipZMvAdded  = 1;
            }

            cmd.m_curbe.DW34.m_enableGlobalMotionBiasAdjustment = params->pAvcQCParams->globalMotionBiasAdjustmentEnable;
        }
    }

    *params->pdwBlockBasedSkipEn = cmd.m_curbe.DW3.m_blockBasedSkipEnable;

    if (picParams->EnableRollingIntraRefresh)
    {
        cmd.m_curbe.DW34.m_IntraRefreshEn = picParams->EnableRollingIntraRefresh;

        /* Multiple predictor should be completely disabled for the RollingI feature. This does not lead to much quality drop for P frames especially for TU as 1 */
        cmd.m_curbe.DW32.m_multiPredL0Disable = CODECHAL_ENCODE_AVC_MULTIPRED_DISABLE;

        /* Pass the same IntraRefreshUnit to the kernel w/o the adjustment by -1, so as to have an overlap of one MB row or column of Intra macroblocks
        across one P frame to another P frame, as needed by the RollingI algo */
        if (ROLLING_I_SQUARE == picParams->EnableRollingIntraRefresh && RATECONTROL_CQP != seqParams->RateControlMethod)
        {
            /*BRC update kernel updates these CURBE to MBEnc*/
            cmd.m_curbe.DW4.m_enableIntraRefresh = false;
            cmd.m_curbe.DW34.m_IntraRefreshEn    = ROLLING_I_DISABLED;
            cmd.m_curbe.DW48.m_IntraRefreshMBx   = 0; /* MB column number */
            cmd.m_curbe.DW61.m_IntraRefreshMBy   = 0; /* MB row number */
        }
        else
        {
            cmd.m_curbe.DW4.m_enableIntraRefresh = true;
            cmd.m_curbe.DW34.m_IntraRefreshEn    = picParams->EnableRollingIntraRefresh;
            cmd.m_curbe.DW48.m_IntraRefreshMBx   = picParams->IntraRefreshMBx; /* MB column number */
            cmd.m_curbe.DW61.m_IntraRefreshMBy   = picParams->IntraRefreshMBy; /* MB row number */
        }
        cmd.m_curbe.DW48.m_IntraRefreshUnitInMBMinus1 = picParams->IntraRefreshUnitinMB;
        cmd.m_curbe.DW48.m_IntraRefreshQPDelta        = picParams->IntraRefreshQPDelta;
    }
    else
    {
        cmd.m_curbe.DW34.m_IntraRefreshEn = 0;
    }

    if (params->bRoiEnabled)
    {
        cmd.m_curbe.DW49.m_roi1XLeft   = picParams->ROI[0].Left;
        cmd.m_curbe.DW49.m_roi1YTop    = picParams->ROI[0].Top;
        cmd.m_curbe.DW50.m_roi1XRight  = picParams->ROI[0].Right;
        cmd.m_curbe.DW50.m_roi1YBottom = picParams->ROI[0].Bottom;

        cmd.m_curbe.DW51.m_roi2XLeft   = picParams->ROI[1].Left;
        cmd.m_curbe.DW51.m_roi2YTop    = picParams->ROI[1].Top;
        cmd.m_curbe.DW52.m_roi2XRight  = picParams->ROI[1].Right;
        cmd.m_curbe.DW52.m_roi2YBottom = picParams->ROI[1].Bottom;

        cmd.m_curbe.DW53.m_roi3XLeft   = picParams->ROI[2].Left;
        cmd.m_curbe.DW53.m_roi3YTop    = picParams->ROI[2].Top;
        cmd.m_curbe.DW54.m_roi3XRight  = picParams->ROI[2].Right;
        cmd.m_curbe.DW54.m_roi3YBottom = picParams->ROI[2].Bottom;

        cmd.m_curbe.DW55.m_roi4XLeft   = picParams->ROI[3].Left;
        cmd.m_curbe.DW55.m_roi4YTop    = picParams->ROI[3].Top;
        cmd.m_curbe.DW56.m_roi4XRight  = picParams->ROI[3].Right;
        cmd.m_curbe.DW56.m_roi4YBottom = picParams->ROI[3].Bottom;

        if (bBrcEnabled == false)
        {
            uint16_t numROI                                                 = picParams->NumROI;
            int8_t   priorityLevelOrDQp[CODECHAL_ENCODE_AVC_MAX_ROI_NUMBER] = {0};

            // cqp case
            for (unsigned int i = 0; i < numROI; i += 1)
            {
                int8_t dQpRoi = picParams->ROI[i].PriorityLevelOrDQp;

                // clip qp roi in order to have (qp + qpY) in range [0, 51]
                priorityLevelOrDQp[i] = (int8_t)CodecHal_Clip3(-sliceQP, CODECHAL_ENCODE_AVC_MAX_SLICE_QP - sliceQP, dQpRoi);
            }

            cmd.m_curbe.DW57.m_roi1dQpPrimeY = priorityLevelOrDQp[0];
            cmd.m_curbe.DW57.m_roi2dQpPrimeY = priorityLevelOrDQp[1];
            cmd.m_curbe.DW57.m_roi3dQpPrimeY = priorityLevelOrDQp[2];
            cmd.m_curbe.DW57.m_roi4dQpPrimeY = priorityLevelOrDQp[3];
        }
        else
        {
            // kernel does not support BRC case
            cmd.m_curbe.DW34.m_roiEnableFlag = 0;
        }
    }
    else if (params->bDirtyRoiEnabled)
    {
        // enable Dirty Rect flag
        cmd.m_curbe.DW4.m_enableDirtyRect = true;

        cmd.m_curbe.DW49.m_roi1XLeft   = params->pPicParams->DirtyROI[0].Left;
        cmd.m_curbe.DW49.m_roi1YTop    = params->pPicParams->DirtyROI[0].Top;
        cmd.m_curbe.DW50.m_roi1XRight  = params->pPicParams->DirtyROI[0].Right;
        cmd.m_curbe.DW50.m_roi1YBottom = params->pPicParams->DirtyROI[0].Bottom;

        cmd.m_curbe.DW51.m_roi2XLeft   = params->pPicParams->DirtyROI[1].Left;
        cmd.m_curbe.DW51.m_roi2YTop    = params->pPicParams->DirtyROI[1].Top;
        cmd.m_curbe.DW52.m_roi2XRight  = params->pPicParams->DirtyROI[1].Right;
        cmd.m_curbe.DW52.m_roi2YBottom = params->pPicParams->DirtyROI[1].Bottom;

        cmd.m_curbe.DW53.m_roi3XLeft   = params->pPicParams->DirtyROI[2].Left;
        cmd.m_curbe.DW53.m_roi3YTop    = params->pPicParams->DirtyROI[2].Top;
        cmd.m_curbe.DW54.m_roi3XRight  = params->pPicParams->DirtyROI[2].Right;
        cmd.m_curbe.DW54.m_roi3YBottom = params->pPicParams->DirtyROI[2].Bottom;

        cmd.m_curbe.DW55.m_roi4XLeft   = params->pPicParams->DirtyROI[3].Left;
        cmd.m_curbe.DW55.m_roi4YTop    = params->pPicParams->DirtyROI[3].Top;
        cmd.m_curbe.DW56.m_roi4XRight  = params->pPicParams->DirtyROI[3].Right;
        cmd.m_curbe.DW56.m_roi4YBottom = params->pPicParams->DirtyROI[3].Bottom;
    }

    if (m_trellisQuantParams.dwTqEnabled)
    {
        // Lambda values for TQ
        if (m_pictureCodingType == I_TYPE)
        {
            cmd.m_curbe.DW58.m_value = TQ_LAMBDA_I_FRAME[sliceQP][0];
            cmd.m_curbe.DW59.m_value = TQ_LAMBDA_I_FRAME[sliceQP][1];
        }
        else if (m_pictureCodingType == P_TYPE)
        {
            cmd.m_curbe.DW58.m_value = TQ_LAMBDA_P_FRAME[sliceQP][0];
            cmd.m_curbe.DW59.m_value = TQ_LAMBDA_P_FRAME[sliceQP][1];
        }
        else
        {
            cmd.m_curbe.DW58.m_value = TQ_LAMBDA_B_FRAME[sliceQP][0];
            cmd.m_curbe.DW59.m_value = TQ_LAMBDA_B_FRAME[sliceQP][1];
        }

        MHW_VDBOX_AVC_SLICE_STATE sliceState;
        MOS_ZeroMemory(&sliceState, sizeof(sliceState));
        sliceState.pEncodeAvcSeqParams   = seqParams;
        sliceState.pEncodeAvcPicParams   = picParams;
        sliceState.pEncodeAvcSliceParams = slcParams;

        // check if Lambda is greater than max value
        CODECHAL_ENCODE_CHK_STATUS_RETURN(GetInterRounding(&sliceState));

        if (cmd.m_curbe.DW58.m_lambda8x8Inter > m_maxLambda)
        {
            cmd.m_curbe.DW58.m_lambda8x8Inter = 0xf000 + sliceState.dwRoundingValue;
        }

        if (cmd.m_curbe.DW58.m_lambda8x8Intra > m_maxLambda)
        {
            cmd.m_curbe.DW58.m_lambda8x8Intra = 0xf000 + m_defaultTrellisQuantIntraRounding;
        }

        // check if Lambda is greater than max value
        if (cmd.m_curbe.DW59.m_lambdaInter > m_maxLambda)
        {
            cmd.m_curbe.DW59.m_lambdaInter = 0xf000 + sliceState.dwRoundingValue;
        }

        if (cmd.m_curbe.DW59.m_lambdaIntra > m_maxLambda)
        {
            cmd.m_curbe.DW59.m_lambdaIntra = 0xf000 + m_defaultTrellisQuantIntraRounding;
        }
    }

    //IPCM QP and threshold
    cmd.m_curbe.DW62.m_IPCMQP0 = m_IPCMThresholdTable[0].QP;
    cmd.m_curbe.DW62.m_IPCMQP1 = m_IPCMThresholdTable[1].QP;
    cmd.m_curbe.DW62.m_IPCMQP2 = m_IPCMThresholdTable[2].QP;
    cmd.m_curbe.DW62.m_IPCMQP3 = m_IPCMThresholdTable[3].QP;
    cmd.m_curbe.DW63.m_IPCMQP4 = m_IPCMThresholdTable[4].QP;

    cmd.m_curbe.DW63.m_IPCMThresh0 = m_IPCMThresholdTable[0].Threshold;
    cmd.m_curbe.DW64.m_IPCMThresh1 = m_IPCMThresholdTable[1].Threshold;
    cmd.m_curbe.DW64.m_IPCMThresh2 = m_IPCMThresholdTable[2].Threshold;
    cmd.m_curbe.DW65.m_IPCMThresh3 = m_IPCMThresholdTable[3].Threshold;
    cmd.m_curbe.DW65.m_IPCMThresh4 = m_IPCMThresholdTable[4].Threshold;

    cmd.m_curbe.DW66.m_mbDataSurfIndex               = mbencMfcAvcPakObj;
    cmd.m_curbe.DW67.m_mvDataSurfIndex               = mbencIndMvData;
    cmd.m_curbe.DW68.m_IDistSurfIndex                = mbencBrcDistortion;
    cmd.m_curbe.DW69.m_srcYSurfIndex                 = mbencCurrY;
    cmd.m_curbe.DW70.m_mbSpecificDataSurfIndex       = mbencMbSpecificData;
    cmd.m_curbe.DW71.m_auxVmeOutSurfIndex            = mbencAuxVmeOut;
    cmd.m_curbe.DW72.m_currRefPicSelSurfIndex        = mbencRefpicselectL0;
    cmd.m_curbe.DW73.m_hmeMVPredFwdBwdSurfIndex      = mbencMvDataFromMe;
    cmd.m_curbe.DW74.m_hmeDistSurfIndex              = mbenc4xMeDistortion;
    cmd.m_curbe.DW75.m_sliceMapSurfIndex             = mbencSlicemapData;
    cmd.m_curbe.DW76.m_fwdFrmMBDataSurfIndex         = mbencFwdMbData;
    cmd.m_curbe.DW77.m_fwdFrmMVSurfIndex             = mbencFwdMvData;
    cmd.m_curbe.DW78.m_mbQPBuffer                    = mbencMbqp;
    cmd.m_curbe.DW79.m_mbBRCLut                      = mbencMbbrcConstData;
    cmd.m_curbe.DW80.m_vmeInterPredictionSurfIndex   = mbencVmeInterPredCurrPicIdx0;
    cmd.m_curbe.DW81.m_vmeInterPredictionMRSurfIndex = mbencVmeInterPredCurrPicIdx1;
    cmd.m_curbe.DW82.m_mbStatsSurfIndex              = mbencMbStats;
    cmd.m_curbe.DW83.m_madSurfIndex                  = mbencMadData;
    cmd.m_curbe.DW84.m_brcCurbeSurfIndex             = mbencBrcCurbeData;
    cmd.m_curbe.DW85.m_forceNonSkipMBmapSurface      = mbencForceNonskipMbMap;
    cmd.m_curbe.DW86.m_reservedIndex                 = mbEncAdv;
    cmd.m_curbe.DW87.m_staticDetectionCostTableIndex = mbencSfdCostTable;
    cmd.m_curbe.DW88.m_swScoreboardIndex             = mbencSwScoreboard;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(params->pKernelState->m_dshRegion.AddData(
        &cmd,
        params->pKernelState->dwCurbeOffset,
        sizeof(cmd)));

    CODECHAL_DEBUG_TOOL(
        CODECHAL_ENCODE_CHK_STATUS_RETURN(PopulateEncParam(
            meMethod,
            &cmd));
    )

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::SetCurbeAvcWP(PCODECHAL_ENCODE_AVC_WP_CURBE_PARAMS params)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
    int16_t      weight;

    CODECHAL_ENCODE_CHK_NULL_RETURN(params);

    auto slcParams   = m_avcSliceParams;
    auto seqParams   = m_avcSeqParam;
    auto kernelState = pWPKernelState;
    CODECHAL_ENCODE_ASSERT(seqParams->TargetUsage < NUM_TARGET_USAGE_MODES);

    CodechalEncodeAvcEncG12::WpCurbe cmd;

    /* Weights[i][j][k][m] is interpreted as:

    i refers to reference picture list 0 or 1;
    j refers to reference list entry 0-31;
    k refers to data for the luma (Y) component when it is 0, the Cb chroma component when it is 1 and the Cr chroma component when it is 2;
    m refers to weight when it is 0 and offset when it is 1
    */
    weight = slcParams->Weights[params->RefPicListIdx][params->WPIdx][0][0];
        cmd.m_wpCurbeCmd.DW0.m_defaultWeight = (weight << 6) >> (slcParams->luma_log2_weight_denom);
        cmd.m_wpCurbeCmd.DW0.m_defaultOffset = slcParams->Weights[params->RefPicListIdx][0][0][1];

        cmd.m_wpCurbeCmd.DW49.m_inputSurface  = wpInputRefSurface;
        cmd.m_wpCurbeCmd.DW50.m_outputSurface = wpOutputScaledSurface;

        CODECHAL_ENCODE_CHK_STATUS_RETURN(kernelState->m_dshRegion.AddData(
            &cmd,
            kernelState->dwCurbeOffset,
            sizeof(cmd)));

        return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::SetCurbeAvcBrcInitReset(PCODECHAL_ENCODE_AVC_BRC_INIT_RESET_CURBE_PARAMS params)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_CHK_NULL_RETURN(params);

    auto     seqParams = m_avcSeqParam;
    auto     vuiParams = m_avcVuiParams;
    uint32_t profileLevelMaxFrame;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalAvcEncode_GetProfileLevelMaxFrameSize(
        seqParams,
        this,
        (uint32_t*)&profileLevelMaxFrame));

    BrcInitResetCurbe curbe;
    curbe.m_brcInitResetCurbeCmd.m_dw0.m_profileLevelMaxFrame = profileLevelMaxFrame;
    curbe.m_brcInitResetCurbeCmd.m_dw1.m_initBufFullInBits    = seqParams->InitVBVBufferFullnessInBit;
    curbe.m_brcInitResetCurbeCmd.m_dw2.m_bufSizeInBits        = seqParams->VBVBufferSizeInBit;
    curbe.m_brcInitResetCurbeCmd.m_dw3.m_averageBitRate       = seqParams->TargetBitRate;
    curbe.m_brcInitResetCurbeCmd.m_dw4.m_maxBitRate           = seqParams->MaxBitRate;
    curbe.m_brcInitResetCurbeCmd.m_dw8.m_gopP =
        (seqParams->GopRefDist) ? ((seqParams->GopPicSize - 1) / seqParams->GopRefDist) : 0;
    curbe.m_brcInitResetCurbeCmd.m_dw9.m_gopB                = seqParams->GopPicSize - 1 - curbe.m_brcInitResetCurbeCmd.m_dw8.m_gopP;
    curbe.m_brcInitResetCurbeCmd.m_dw9.m_frameWidthInBytes   = m_frameWidth;
    curbe.m_brcInitResetCurbeCmd.m_dw10.m_frameHeightInBytes = m_frameHeight;
    curbe.m_brcInitResetCurbeCmd.m_dw12.m_noSlices           = m_numSlices;

    curbe.m_brcInitResetCurbeCmd.m_dw32.m_surfaceIndexHistorybuffer    = CODECHAL_ENCODE_AVC_BRC_INIT_RESET_HISTORY;
    curbe.m_brcInitResetCurbeCmd.m_dw33.m_surfaceIndexDistortionbuffer = CODECHAL_ENCODE_AVC_BRC_INIT_RESET_DISTORTION;

    // if VUI present, VUI data has high priority
    if (seqParams->vui_parameters_present_flag && seqParams->RateControlMethod != RATECONTROL_AVBR)
    {
        curbe.m_brcInitResetCurbeCmd.m_dw4.m_maxBitRate =
            ((vuiParams->bit_rate_value_minus1[0] + 1) << (6 + vuiParams->bit_rate_scale));

        if (seqParams->RateControlMethod == RATECONTROL_CBR)
        {
            curbe.m_brcInitResetCurbeCmd.m_dw3.m_averageBitRate = curbe.m_brcInitResetCurbeCmd.m_dw4.m_maxBitRate;
        }
    }

    curbe.m_brcInitResetCurbeCmd.m_dw6.m_frameRateM = seqParams->FramesPer100Sec;
    curbe.m_brcInitResetCurbeCmd.m_dw7.m_frameRateD = 100;
    curbe.m_brcInitResetCurbeCmd.m_dw8.m_brcFlag    = (CodecHal_PictureIsFrame(m_currOriginalPic)) ? 0 : CODECHAL_ENCODE_BRCINIT_FIELD_PIC;
    // MBBRC should be skipped when BRC ROI is on
    curbe.m_brcInitResetCurbeCmd.m_dw8.m_brcFlag |= (bMbBrcEnabled && !bBrcRoiEnabled) ? 0 : CODECHAL_ENCODE_BRCINIT_DISABLE_MBBRC;

    if (seqParams->RateControlMethod == RATECONTROL_CBR)
    {
        curbe.m_brcInitResetCurbeCmd.m_dw4.m_maxBitRate = curbe.m_brcInitResetCurbeCmd.m_dw3.m_averageBitRate;
        curbe.m_brcInitResetCurbeCmd.m_dw8.m_brcFlag    = curbe.m_brcInitResetCurbeCmd.m_dw8.m_brcFlag | CODECHAL_ENCODE_BRCINIT_ISCBR;
    }
    else if (seqParams->RateControlMethod == RATECONTROL_VBR)
    {
        if (curbe.m_brcInitResetCurbeCmd.m_dw4.m_maxBitRate < curbe.m_brcInitResetCurbeCmd.m_dw3.m_averageBitRate)
        {
            curbe.m_brcInitResetCurbeCmd.m_dw3.m_averageBitRate = curbe.m_brcInitResetCurbeCmd.m_dw4.m_maxBitRate;  // Use max bit rate for HRD compliance
        }
        curbe.m_brcInitResetCurbeCmd.m_dw8.m_brcFlag = curbe.m_brcInitResetCurbeCmd.m_dw8.m_brcFlag | CODECHAL_ENCODE_BRCINIT_ISVBR;
    }
    else if (seqParams->RateControlMethod == RATECONTROL_AVBR)
    {
        curbe.m_brcInitResetCurbeCmd.m_dw8.m_brcFlag = curbe.m_brcInitResetCurbeCmd.m_dw8.m_brcFlag | CODECHAL_ENCODE_BRCINIT_ISAVBR;
        // For AVBR, max bitrate = target bitrate,
        curbe.m_brcInitResetCurbeCmd.m_dw4.m_maxBitRate = curbe.m_brcInitResetCurbeCmd.m_dw3.m_averageBitRate;
    }
    else if (seqParams->RateControlMethod == RATECONTROL_ICQ)
    {
        curbe.m_brcInitResetCurbeCmd.m_dw8.m_brcFlag = curbe.m_brcInitResetCurbeCmd.m_dw8.m_brcFlag | CODECHAL_ENCODE_BRCINIT_ISICQ;
        curbe.m_brcInitResetCurbeCmd.m_dw23.m_aCQP   = seqParams->ICQQualityFactor;
    }
    else if (seqParams->RateControlMethod == RATECONTROL_VCM)
    {
        curbe.m_brcInitResetCurbeCmd.m_dw8.m_brcFlag = curbe.m_brcInitResetCurbeCmd.m_dw8.m_brcFlag | CODECHAL_ENCODE_BRCINIT_ISVCM;
    }
    else if (seqParams->RateControlMethod == RATECONTROL_QVBR)
    {
        if (curbe.m_brcInitResetCurbeCmd.m_dw4.m_maxBitRate < curbe.m_brcInitResetCurbeCmd.m_dw3.m_averageBitRate)
        {
            curbe.m_brcInitResetCurbeCmd.m_dw3.m_averageBitRate = curbe.m_brcInitResetCurbeCmd.m_dw4.m_maxBitRate;  // Use max bit rate for HRD compliance
        }
        curbe.m_brcInitResetCurbeCmd.m_dw8.m_brcFlag = curbe.m_brcInitResetCurbeCmd.m_dw8.m_brcFlag | CODECHAL_ENCODE_BRCINIT_ISQVBR;
        // use ICQQualityFactor to determine the larger Qp for each MB
        curbe.m_brcInitResetCurbeCmd.m_dw23.m_aCQP = seqParams->ICQQualityFactor;
    }

    curbe.m_brcInitResetCurbeCmd.m_dw10.m_avbrAccuracy    = usAVBRAccuracy;
    curbe.m_brcInitResetCurbeCmd.m_dw11.m_avbrConvergence = usAVBRConvergence;

    // Set dynamic thresholds
    double inputBitsPerFrame =
        ((double)(curbe.m_brcInitResetCurbeCmd.m_dw4.m_maxBitRate) * (double)(curbe.m_brcInitResetCurbeCmd.m_dw7.m_frameRateD) /
            (double)(curbe.m_brcInitResetCurbeCmd.m_dw6.m_frameRateM));
    if (CodecHal_PictureIsField(m_currOriginalPic))
    {
        inputBitsPerFrame *= 0.5;
    }

    if (curbe.m_brcInitResetCurbeCmd.m_dw2.m_bufSizeInBits == 0)
    {
        curbe.m_brcInitResetCurbeCmd.m_dw2.m_bufSizeInBits = (uint32_t)inputBitsPerFrame * 4;
    }

    if (curbe.m_brcInitResetCurbeCmd.m_dw1.m_initBufFullInBits == 0)
    {
        curbe.m_brcInitResetCurbeCmd.m_dw1.m_initBufFullInBits = 7 * curbe.m_brcInitResetCurbeCmd.m_dw2.m_bufSizeInBits / 8;
    }
    if (curbe.m_brcInitResetCurbeCmd.m_dw1.m_initBufFullInBits < (uint32_t)(inputBitsPerFrame * 2))
    {
        curbe.m_brcInitResetCurbeCmd.m_dw1.m_initBufFullInBits = (uint32_t)(inputBitsPerFrame * 2);
    }
    if (curbe.m_brcInitResetCurbeCmd.m_dw1.m_initBufFullInBits > curbe.m_brcInitResetCurbeCmd.m_dw2.m_bufSizeInBits)
    {
        curbe.m_brcInitResetCurbeCmd.m_dw1.m_initBufFullInBits = curbe.m_brcInitResetCurbeCmd.m_dw2.m_bufSizeInBits;
    }

    if (seqParams->RateControlMethod == RATECONTROL_AVBR)
    {
        // For AVBR, Buffer size =  2*Bitrate, InitVBV = 0.75 * BufferSize
        curbe.m_brcInitResetCurbeCmd.m_dw2.m_bufSizeInBits     = 2 * seqParams->TargetBitRate;
        curbe.m_brcInitResetCurbeCmd.m_dw1.m_initBufFullInBits = (uint32_t)(0.75 * curbe.m_brcInitResetCurbeCmd.m_dw2.m_bufSizeInBits);
    }

    double bpsRatio = inputBitsPerFrame / ((double)(curbe.m_brcInitResetCurbeCmd.m_dw2.m_bufSizeInBits) / 30);
    bpsRatio        = (bpsRatio < 0.1) ? 0.1 : (bpsRatio > 3.5) ? 3.5 : bpsRatio;

    curbe.m_brcInitResetCurbeCmd.m_dw16.m_deviationThreshold0ForPandB = (uint32_t)(-50 * pow(0.90, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw16.m_deviationThreshold1ForPandB = (uint32_t)(-50 * pow(0.66, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw16.m_deviationThreshold2ForPandB = (uint32_t)(-50 * pow(0.46, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw16.m_deviationThreshold3ForPandB = (uint32_t)(-50 * pow(0.3, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw17.m_deviationThreshold4ForPandB = (uint32_t)(50 * pow(0.3, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw17.m_deviationThreshold5ForPandB = (uint32_t)(50 * pow(0.46, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw17.m_deviationThreshold6ForPandB = (uint32_t)(50 * pow(0.7, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw17.m_deviationThreshold7ForPandB = (uint32_t)(50 * pow(0.9, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw18.m_deviationThreshold0ForVBR   = (uint32_t)(-50 * pow(0.9, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw18.m_deviationThreshold1ForVBR   = (uint32_t)(-50 * pow(0.7, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw18.m_deviationThreshold2ForVBR   = (uint32_t)(-50 * pow(0.5, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw18.m_deviationThreshold3ForVBR   = (uint32_t)(-50 * pow(0.3, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw19.m_deviationThreshold4ForVBR   = (uint32_t)(100 * pow(0.4, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw19.m_deviationThreshold5ForVBR   = (uint32_t)(100 * pow(0.5, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw19.m_deviationThreshold6ForVBR   = (uint32_t)(100 * pow(0.75, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw19.m_deviationThreshold7ForVBR   = (uint32_t)(100 * pow(0.9, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw20.m_deviationThreshold0ForI     = (uint32_t)(-50 * pow(0.8, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw20.m_deviationThreshold1ForI     = (uint32_t)(-50 * pow(0.6, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw20.m_deviationThreshold2ForI     = (uint32_t)(-50 * pow(0.34, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw20.m_deviationThreshold3ForI     = (uint32_t)(-50 * pow(0.2, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw21.m_deviationThreshold4ForI     = (uint32_t)(50 * pow(0.2, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw21.m_deviationThreshold5ForI     = (uint32_t)(50 * pow(0.4, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw21.m_deviationThreshold6ForI     = (uint32_t)(50 * pow(0.66, bpsRatio));
    curbe.m_brcInitResetCurbeCmd.m_dw21.m_deviationThreshold7ForI     = (uint32_t)(50 * pow(0.9, bpsRatio));

    curbe.m_brcInitResetCurbeCmd.m_dw22.m_slidingWindowSize = dwSlidingWindowSize;

    if (bBrcInit)
    {
        *params->pdBrcInitCurrentTargetBufFullInBits = curbe.m_brcInitResetCurbeCmd.m_dw1.m_initBufFullInBits;
    }

    *params->pdwBrcInitResetBufSizeInBits    = curbe.m_brcInitResetCurbeCmd.m_dw2.m_bufSizeInBits;
    *params->pdBrcInitResetInputBitsPerFrame = inputBitsPerFrame;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(params->pKernelState->m_dshRegion.AddData(
        &curbe.m_brcInitResetCurbeCmd,
        params->pKernelState->dwCurbeOffset,
        sizeof(curbe.m_brcInitResetCurbeCmd)));

    CODECHAL_DEBUG_TOOL(
        CODECHAL_ENCODE_CHK_STATUS_RETURN(PopulateBrcInitParam(
            &curbe.m_brcInitResetCurbeCmd));
    )

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::SetCurbeAvcFrameBrcUpdate(PCODECHAL_ENCODE_AVC_BRC_UPDATE_CURBE_PARAMS params)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_CHK_NULL_RETURN(params);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->pKernelState);

    CodechalEncodeAvcEncG12::FrameBrcUpdateCurbe cmd;
    cmd.m_frameBrcUpdateCurbeCmd.m_dw5.m_targetSizeFlag = 0;
    if (*params->pdBrcInitCurrentTargetBufFullInBits > (double)dwBrcInitResetBufSizeInBits)
    {
        *params->pdBrcInitCurrentTargetBufFullInBits -= (double)dwBrcInitResetBufSizeInBits;
        cmd.m_frameBrcUpdateCurbeCmd.m_dw5.m_targetSizeFlag = 1;
    }

    // skipped frame handling
    if (params->dwNumSkipFrames)
    {
        // pass num/size of skipped frames to update BRC
        cmd.m_frameBrcUpdateCurbeCmd.m_dw6.m_numSkipFrames  = params->dwNumSkipFrames;
        cmd.m_frameBrcUpdateCurbeCmd.m_dw7.m_sizeSkipFrames = params->dwSizeSkipFrames;

        // account for skipped frame in calculating CurrentTargetBufFullInBits
        *params->pdBrcInitCurrentTargetBufFullInBits += dBrcInitResetInputBitsPerFrame * params->dwNumSkipFrames;
    }

    cmd.m_frameBrcUpdateCurbeCmd.m_dw0.m_targetSize       = (uint32_t)(*params->pdBrcInitCurrentTargetBufFullInBits);
    cmd.m_frameBrcUpdateCurbeCmd.m_dw1.m_frameNumber      = m_storeData - 1;
    cmd.m_frameBrcUpdateCurbeCmd.m_dw2.m_sizeofPicHeaders = m_headerBytesInserted << 3;  // kernel uses how many bits instead of bytes
    cmd.m_frameBrcUpdateCurbeCmd.m_dw5.m_currFrameType =
        ((m_pictureCodingType - 2) < 0) ? 2 : (m_pictureCodingType - 2);
    cmd.m_frameBrcUpdateCurbeCmd.m_dw5.m_brcFlag =
        (CodecHal_PictureIsTopField(m_currOriginalPic)) ? brcUpdateIsField : ((CodecHal_PictureIsBottomField(m_currOriginalPic)) ? (brcUpdateIsField | brcUpdateIsBottomField) : 0);
    cmd.m_frameBrcUpdateCurbeCmd.m_dw5.m_brcFlag |= (m_refList[m_currReconstructedPic.FrameIdx]->bUsedAsRef) ? brcUpdateIsReference : 0;

    if (bMultiRefQpEnabled)
    {
        cmd.m_frameBrcUpdateCurbeCmd.m_dw5.m_brcFlag |= brcUpdateIsActualQp;
        cmd.m_frameBrcUpdateCurbeCmd.m_dw14.m_qpIndexOfCurPic = m_currOriginalPic.FrameIdx;
    }

    auto seqParams = m_avcSeqParam;
    auto picParams = m_avcPicParam;
    auto slcParams = m_avcSliceParams;

    cmd.m_frameBrcUpdateCurbeCmd.m_dw5.m_brcFlag |= seqParams->bAutoMaxPBFrameSizeForSceneChange ? brcUpdateAutoPbFrameSize : 0;
    cmd.m_frameBrcUpdateCurbeCmd.m_dw5.m_maxNumPAKs           = m_hwInterface->GetMfxInterface()->GetBrcNumPakPasses();
    cmd.m_frameBrcUpdateCurbeCmd.m_dw6.m_minimumQP            = params->ucMinQP;
    cmd.m_frameBrcUpdateCurbeCmd.m_dw6.m_maximumQP            = params->ucMaxQP;
    cmd.m_frameBrcUpdateCurbeCmd.m_dw6.m_enableForceToSkip    = (bForceToSkipEnable && !m_avcPicParam->bDisableFrameSkip);
    cmd.m_frameBrcUpdateCurbeCmd.m_dw6.m_enableSlidingWindow  = (seqParams->FrameSizeTolerance == EFRAMESIZETOL_LOW);
    cmd.m_frameBrcUpdateCurbeCmd.m_dw6.m_enableExtremLowDelay = (seqParams->FrameSizeTolerance == EFRAMESIZETOL_EXTREMELY_LOW);
    cmd.m_frameBrcUpdateCurbeCmd.m_dw6.m_disableVarCompute    = bBRCVarCompuBypass;

    *params->pdBrcInitCurrentTargetBufFullInBits += dBrcInitResetInputBitsPerFrame;

    if (seqParams->RateControlMethod == RATECONTROL_AVBR)
    {
        cmd.m_frameBrcUpdateCurbeCmd.m_dw3.m_startGAdjFrame0       = (uint32_t)((10 * usAVBRConvergence) / (double)150);
        cmd.m_frameBrcUpdateCurbeCmd.m_dw3.m_startGAdjFrame1       = (uint32_t)((50 * usAVBRConvergence) / (double)150);
        cmd.m_frameBrcUpdateCurbeCmd.m_dw4.m_startGAdjFrame2       = (uint32_t)((100 * usAVBRConvergence) / (double)150);
        cmd.m_frameBrcUpdateCurbeCmd.m_dw4.m_startGAdjFrame3       = (uint32_t)((150 * usAVBRConvergence) / (double)150);
        cmd.m_frameBrcUpdateCurbeCmd.m_dw11.m_gRateRatioThreshold0 = (uint32_t)((100 - (usAVBRAccuracy / (double)30) * (100 - 40)));
        cmd.m_frameBrcUpdateCurbeCmd.m_dw11.m_gRateRatioThreshold1 = (uint32_t)((100 - (usAVBRAccuracy / (double)30) * (100 - 75)));
        cmd.m_frameBrcUpdateCurbeCmd.m_dw12.m_gRateRatioThreshold2 = (uint32_t)((100 - (usAVBRAccuracy / (double)30) * (100 - 97)));
        cmd.m_frameBrcUpdateCurbeCmd.m_dw12.m_gRateRatioThreshold3 = (uint32_t)((100 + (usAVBRAccuracy / (double)30) * (103 - 100)));
        cmd.m_frameBrcUpdateCurbeCmd.m_dw12.m_gRateRatioThreshold4 = (uint32_t)((100 + (usAVBRAccuracy / (double)30) * (125 - 100)));
        cmd.m_frameBrcUpdateCurbeCmd.m_dw12.m_gRateRatioThreshold5 = (uint32_t)((100 + (usAVBRAccuracy / (double)30) * (160 - 100)));
    }

    cmd.m_frameBrcUpdateCurbeCmd.m_dw15.m_enableROI = params->ucEnableROI;

    MHW_VDBOX_AVC_SLICE_STATE sliceState;
    MOS_ZeroMemory(&sliceState, sizeof(sliceState));
    sliceState.pEncodeAvcSeqParams   = seqParams;
    sliceState.pEncodeAvcPicParams   = picParams;
    sliceState.pEncodeAvcSliceParams = slcParams;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(GetInterRounding(&sliceState));

    cmd.m_frameBrcUpdateCurbeCmd.m_dw15.m_roundingIntra = 5;
    cmd.m_frameBrcUpdateCurbeCmd.m_dw15.m_roundingInter = sliceState.dwRoundingValue;

    uint32_t profileLevelMaxFrame;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalAvcEncode_GetProfileLevelMaxFrameSize(
        seqParams,
        this,
        (uint32_t*)&profileLevelMaxFrame));

    cmd.m_frameBrcUpdateCurbeCmd.m_dw19.m_userMaxFrame = profileLevelMaxFrame;

    cmd.m_frameBrcUpdateCurbeCmd.m_dw24.m_surfaceIndexBRCHistorybuffer                  = frameBrcUpdateHistory;
    cmd.m_frameBrcUpdateCurbeCmd.m_dw25.m_surfaceIndexPreciousPAKStatisticsOutputbuffer = frameBrcUpdatePakStatisticsOutput;
    cmd.m_frameBrcUpdateCurbeCmd.m_dw26.m_surfaceIndexAVCIMGStateInputbuffer            = frameBrcUpdateImageStateRead;
    cmd.m_frameBrcUpdateCurbeCmd.m_dw27.m_surfaceIndexAVCIMGStateOutputbuffer           = frameBrcUpdateImageStateWrite;
    cmd.m_frameBrcUpdateCurbeCmd.m_dw28.m_surfaceIndexAVC_Encbuffer                     = frameBrcUpdateMbencCurbeWrite;
    cmd.m_frameBrcUpdateCurbeCmd.m_dw29.m_surfaceIndexAVCDistortionbuffer               = frameBrcUpdateDistortion;
    cmd.m_frameBrcUpdateCurbeCmd.m_dw30.m_surfaceIndexBRCConstdatabuffer                = frameBrcUpdateConstantData;
    cmd.m_frameBrcUpdateCurbeCmd.m_dw31.m_surfaceIndexMBStatsbuffer                     = frameBrcUpdateMbStat;
    cmd.m_frameBrcUpdateCurbeCmd.m_dw32.m_surfaceIndexMotionVectorbuffer                = frameBrcUpdateMvStat;
    auto pStateHeapInterface = m_hwInterface->GetRenderInterface()->m_stateHeapInterface;
    CODECHAL_ENCODE_CHK_NULL_RETURN(pStateHeapInterface);

    CODECHAL_ENCODE_CHK_STATUS_RETURN(params->pKernelState->m_dshRegion.AddData(
        &cmd.m_frameBrcUpdateCurbeCmd,
        params->pKernelState->dwCurbeOffset,
        sizeof(cmd.m_frameBrcUpdateCurbeCmd)));

    CODECHAL_DEBUG_TOOL(
        CODECHAL_ENCODE_CHK_STATUS_RETURN(PopulateBrcUpdateParam(
            &cmd.m_frameBrcUpdateCurbeCmd));
    )

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::SetCurbeAvcMbBrcUpdate(PCODECHAL_ENCODE_AVC_BRC_UPDATE_CURBE_PARAMS params)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_CHK_NULL_RETURN(params);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->pKernelState);

    CodechalEncodeAvcEncG12::MbBrcUpdateCurbe curbe;

    // BRC curbe requires: 2 for I-frame, 0 for P-frame, 1 for B-frame
    curbe.m_mbBrcUpdateCurbeCmd.DW0.m_currFrameType = (m_pictureCodingType + 1) % 3;
    if (params->ucEnableROI)
    {
        if (bROIValueInDeltaQP)
        {
            curbe.m_mbBrcUpdateCurbeCmd.DW0.m_enableROI = 2;  // 1-Enabled ROI priority, 2-Enable ROI QP Delta,  0- disabled
            curbe.m_mbBrcUpdateCurbeCmd.DW0.m_roiRatio  = 0;
        }
        else
        {
            curbe.m_mbBrcUpdateCurbeCmd.DW0.m_enableROI = 1;  // 1-Enabled ROI priority, 2-Enable ROI QP Delta,  0- disabled

            uint32_t roiSize  = 0;
            uint32_t roiRatio = 0;

            for (uint32_t i = 0; i < m_avcPicParam->NumROI; ++i)
            {
                CODECHAL_ENCODE_VERBOSEMESSAGE("ROI[%d] = {%d, %d, %d, %d} {%d}, size = %d",
                    i,
                    m_avcPicParam->ROI[i].Left,
                    m_avcPicParam->ROI[i].Top,
                    m_avcPicParam->ROI[i].Bottom,
                    m_avcPicParam->ROI[i].Right,
                    m_avcPicParam->ROI[i].PriorityLevelOrDQp,
                    (CODECHAL_MACROBLOCK_HEIGHT * MOS_ABS(m_avcPicParam->ROI[i].Top -
                                                          m_avcPicParam->ROI[i].Bottom)) *
                        (CODECHAL_MACROBLOCK_WIDTH * MOS_ABS(m_avcPicParam->ROI[i].Right - m_avcPicParam->ROI[i].Left)));
                roiSize += (CODECHAL_MACROBLOCK_HEIGHT * MOS_ABS(m_avcPicParam->ROI[i].Top - m_avcPicParam->ROI[i].Bottom)) *
                           (CODECHAL_MACROBLOCK_WIDTH * MOS_ABS(m_avcPicParam->ROI[i].Right - m_avcPicParam->ROI[i].Left));
            }

            if (roiSize)
            {
                uint32_t numMBs = m_picWidthInMb * m_picHeightInMb;
                roiRatio        = 2 * (numMBs * 256 / roiSize - 1);
                roiRatio        = MOS_MIN(51, roiRatio);  // clip QP from 0-51
            }
            CODECHAL_ENCODE_VERBOSEMESSAGE("m_roiRatio = %d", roiRatio);
            curbe.m_mbBrcUpdateCurbeCmd.DW0.m_roiRatio = roiRatio;
        }
    }
    else
    {
        curbe.m_mbBrcUpdateCurbeCmd.DW0.m_roiRatio = 0;
    }

    curbe.m_mbBrcUpdateCurbeCmd.DW8.m_historyBufferIndex        = mbBrcUpdateHistory;
    curbe.m_mbBrcUpdateCurbeCmd.DW9.m_mbqpBufferIndex           = mbBrcUpdateMbQp;
    curbe.m_mbBrcUpdateCurbeCmd.DW10.m_roiBufferIndex           = mbBrcUpdateRoi;
    curbe.m_mbBrcUpdateCurbeCmd.DW11.m_mbStatisticalBufferIndex = mbBrcUpdateMbStat;
    auto pStateHeapInterface = m_hwInterface->GetRenderInterface()->m_stateHeapInterface;
    CODECHAL_ENCODE_CHK_NULL_RETURN(pStateHeapInterface);

    CODECHAL_ENCODE_CHK_STATUS_RETURN(params->pKernelState->m_dshRegion.AddData(
        &curbe,
        params->pKernelState->dwCurbeOffset,
        sizeof(curbe)));

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::UserFeatureKeyReport()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncodeAvcEnc::UserFeatureKeyReport());

#if (_DEBUG || _RELEASE_INTERNAL)

    // VE2.0 Reporting
    CodecHalEncode_WriteKey(__MEDIA_USER_FEATURE_VALUE_ENABLE_ENCODE_VE_CTXSCHEDULING_ID, MOS_VE_CTXBASEDSCHEDULING_SUPPORTED(m_osInterface), m_osInterface->pOsContext);

#endif // _DEBUG || _RELEASE_INTERNAL
    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::SendAvcMbEncSurfaces(PMOS_COMMAND_BUFFER cmdBuffer, PCODECHAL_ENCODE_AVC_MBENC_SURFACE_PARAMS params)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->pAvcSlcParams);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->ppRefList);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->pCurrOriginalPic);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->pCurrReconstructedPic);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->psCurrPicSurface);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->pAvcPicIdx);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->pMbEncBindingTable);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->pKernelState);

    bool currFieldPicture = CodecHal_PictureIsField(*(params->pCurrOriginalPic)) ? 1 : 0;
    bool currBottomField = CodecHal_PictureIsBottomField(*(params->pCurrOriginalPic)) ? 1 : 0;
    uint32_t refMbCodeBottomFieldOffset =
        params->dwFrameFieldHeightInMb * params->dwFrameWidthInMb * 64;
    uint32_t refMvBottomFieldOffset =
        MOS_ALIGN_CEIL(params->dwFrameFieldHeightInMb * params->dwFrameWidthInMb * (32 * 4), 0x1000);

    uint8_t vdirection, refVDirection;
    if (params->bMbEncIFrameDistInUse)
    {
        vdirection = CODECHAL_VDIRECTION_FRAME;
    }
    else
    {
        vdirection = (CodecHal_PictureIsFrame(*(params->pCurrOriginalPic))) ? CODECHAL_VDIRECTION_FRAME : (currBottomField) ? CODECHAL_VDIRECTION_BOT_FIELD : CODECHAL_VDIRECTION_TOP_FIELD;
    }

    // PAK Obj command buffer
    uint32_t size                = params->dwFrameWidthInMb * params->dwFrameFieldHeightInMb * 16 * 4;  // 11DW + 5DW padding
    auto     kernelState         = params->pKernelState;
    auto     mbEncBindingTable   = params->pMbEncBindingTable;
    auto     currPicRefListEntry = params->ppRefList[params->pCurrReconstructedPic->FrameIdx];
    auto     mbCodeBuffer        = &currPicRefListEntry->resRefMbCodeBuffer;
    auto     mvDataBuffer        = &currPicRefListEntry->resRefMvDataBuffer;

    CODECHAL_SURFACE_CODEC_PARAMS surfaceCodecParams;
    memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
    surfaceCodecParams.presBuffer            = mbCodeBuffer;
    surfaceCodecParams.dwSize                = size;
    surfaceCodecParams.dwOffset              = params->dwMbCodeBottomFieldOffset;
    surfaceCodecParams.dwBindingTableOffset  = mbEncBindingTable->dwAvcMBEncMfcAvcPakObj;
    surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_PAK_OBJECT_ENCODE].Value;
    surfaceCodecParams.bRenderTarget         = true;
    surfaceCodecParams.bIsWritable           = true;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceCodecParams,
        kernelState));

    // MV data buffer
    size = params->dwFrameWidthInMb * params->dwFrameFieldHeightInMb * 32 * 4;
    memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
    surfaceCodecParams.presBuffer            = mvDataBuffer;
    surfaceCodecParams.dwSize                = size;
    surfaceCodecParams.dwOffset              = params->dwMvBottomFieldOffset;
    surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_MV_DATA_ENCODE].Value;
    surfaceCodecParams.dwBindingTableOffset  = mbEncBindingTable->dwAvcMBEncIndMVData;
    surfaceCodecParams.bRenderTarget         = true;
    surfaceCodecParams.bIsWritable           = true;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceCodecParams,
        kernelState));

    // Current Picture Y
    memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
    surfaceCodecParams.bIs2DSurface               = true;
    surfaceCodecParams.bMediaBlockRW              = true;  // Use media block RW for DP 2D surface access
    surfaceCodecParams.bUseUVPlane                = true;
    surfaceCodecParams.psSurface                  = params->psCurrPicSurface;
    surfaceCodecParams.dwOffset                   = params->dwCurrPicSurfaceOffset;
    surfaceCodecParams.dwCacheabilityControl      = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_CURR_ENCODE].Value;
    surfaceCodecParams.dwBindingTableOffset       = mbEncBindingTable->dwAvcMBEncCurrY;
    surfaceCodecParams.dwUVBindingTableOffset     = mbEncBindingTable->dwAvcMBEncCurrUV;
    surfaceCodecParams.dwVerticalLineStride       = params->dwVerticalLineStride;
    surfaceCodecParams.dwVerticalLineStrideOffset = params->dwVerticalLineStrideOffset;
#ifdef _MMC_SUPPORTED
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetSurfaceParams(&surfaceCodecParams));
#endif
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceCodecParams,
        kernelState));

    // AVC_ME MV data buffer
    if (params->bHmeEnabled)
    {
        CODECHAL_ENCODE_CHK_NULL_RETURN(params->ps4xMeMvDataBuffer);

        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.bIs2DSurface          = true;
        surfaceCodecParams.bMediaBlockRW         = true;
        surfaceCodecParams.psSurface             = params->ps4xMeMvDataBuffer;
        surfaceCodecParams.dwOffset              = params->dwMeMvBottomFieldOffset;
        surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_MV_DATA_ENCODE].Value;
        surfaceCodecParams.dwBindingTableOffset  = mbEncBindingTable->dwAvcMBEncMVDataFromME;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));

        CODECHAL_ENCODE_CHK_NULL_RETURN(params->ps4xMeDistortionBuffer);

        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.bIs2DSurface          = true;
        surfaceCodecParams.bMediaBlockRW         = true;
        surfaceCodecParams.psSurface             = params->ps4xMeDistortionBuffer;
        surfaceCodecParams.dwOffset              = params->dwMeDistortionBottomFieldOffset;
        surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_ME_DISTORTION_ENCODE].Value;
        surfaceCodecParams.dwBindingTableOffset  = mbEncBindingTable->dwAvcMBEncMEDist;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }

    if (params->bMbConstDataBufferInUse)
    {
        // 16 DWs per QP value
        size = 16 * 52 * sizeof(uint32_t);

        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.presBuffer            = params->presMbBrcConstDataBuffer;
        surfaceCodecParams.dwSize                = size;
        surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_MB_BRC_CONST_ENCODE].Value;
        surfaceCodecParams.dwBindingTableOffset  = mbEncBindingTable->dwAvcMBEncMbBrcConstData;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }

    if (params->bMbQpBufferInUse)
    {
        // AVC MB BRC QP buffer
        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.bIs2DSurface          = true;
        surfaceCodecParams.bMediaBlockRW         = true;
        surfaceCodecParams.psSurface             = params->psMbQpBuffer;
        surfaceCodecParams.dwOffset              = params->dwMbQpBottomFieldOffset;
        surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_BRC_MB_QP_ENCODE].Value;
        surfaceCodecParams.dwBindingTableOffset  = currFieldPicture ? mbEncBindingTable->dwAvcMBEncMbQpField : mbEncBindingTable->dwAvcMBEncMbQpFrame;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }

    if (params->bMbSpecificDataEnabled)
    {
        size = params->dwFrameWidthInMb * params->dwFrameFieldHeightInMb * sizeof(CODECHAL_ENCODE_AVC_MB_SPECIFIC_PARAMS);
        CODECHAL_ENCODE_VERBOSEMESSAGE("Send MB specific surface, size = %d", size);
        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.dwSize = size;
        surfaceCodecParams.presBuffer = params->presMbSpecificDataBuffer;
        surfaceCodecParams.dwBindingTableOffset = mbEncBindingTable->dwAvcMBEncMbSpecificData;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }

    // Current Picture Y - VME
    memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
    surfaceCodecParams.bUseAdvState          = true;
    surfaceCodecParams.psSurface             = params->psCurrPicSurface;
    surfaceCodecParams.dwOffset              = params->dwCurrPicSurfaceOffset;
    surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_CURR_ENCODE].Value;
    surfaceCodecParams.dwBindingTableOffset  = currFieldPicture ? mbEncBindingTable->dwAvcMBEncFieldCurrPic[0] : mbEncBindingTable->dwAvcMBEncCurrPicFrame[0];
    surfaceCodecParams.ucVDirection          = vdirection;
#ifdef _MMC_SUPPORTED
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetSurfaceParams(&surfaceCodecParams));
#endif
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceCodecParams,
        kernelState));

    surfaceCodecParams.dwBindingTableOffset = currFieldPicture ? mbEncBindingTable->dwAvcMBEncFieldCurrPic[1] : mbEncBindingTable->dwAvcMBEncCurrPicFrame[1];
    surfaceCodecParams.ucVDirection         = vdirection;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceCodecParams,
        kernelState));

    // Setup references 1...n
    // LIST 0 references
    uint8_t refIdx;
    for (refIdx = 0; refIdx <= params->pAvcSlcParams->num_ref_idx_l0_active_minus1; refIdx++)
    {
        auto     refPic = params->pAvcSlcParams->RefPicList[LIST_0][refIdx];
        uint32_t refMbCodeBottomFieldOffsetUsed;
        uint32_t refMvBottomFieldOffsetUsed;
        uint32_t refBindingTableOffset;
        if (!CodecHal_PictureIsInvalid(refPic) && params->pAvcPicIdx[refPic.FrameIdx].bValid)
        {
            uint8_t refPicIdx      = params->pAvcPicIdx[refPic.FrameIdx].ucPicIdx;
            bool    refBottomField = (CodecHal_PictureIsBottomField(refPic)) ? true : false;
            // Program the surface based on current picture's field/frame mode
            if (currFieldPicture)  // if current picture is field
            {
                if (refBottomField)
                {
                    refVDirection       = CODECHAL_VDIRECTION_BOT_FIELD;
                    refBindingTableOffset = mbEncBindingTable->dwAvcMBEncFwdPicBotField[refIdx];
                }
                else
                {
                    refVDirection       = CODECHAL_VDIRECTION_TOP_FIELD;
                    refBindingTableOffset = mbEncBindingTable->dwAvcMBEncFwdPicTopField[refIdx];
                }
            }
            else  // if current picture is frame
            {
                refVDirection       = CODECHAL_VDIRECTION_FRAME;
                refBindingTableOffset = mbEncBindingTable->dwAvcMBEncFwdPicFrame[refIdx];
            }

            // Picture Y VME
            memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
            surfaceCodecParams.bUseAdvState = true;
            if ((0 == refIdx) && (params->bUseWeightedSurfaceForL0))
            {
                surfaceCodecParams.psSurface = &params->pWeightedPredOutputPicSelectList[CODEC_AVC_WP_OUTPUT_L0_START + refIdx].sBuffer;
            }
            else
            {
                surfaceCodecParams.psSurface = &params->ppRefList[refPicIdx]->sRefBuffer;
            }
            surfaceCodecParams.dwWidthInUse  = params->dwFrameWidthInMb * 16;
            surfaceCodecParams.dwHeightInUse = params->dwFrameHeightInMb * 16;

            surfaceCodecParams.dwBindingTableOffset  = refBindingTableOffset;
            surfaceCodecParams.ucVDirection          = refVDirection;
            surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_REF_ENCODE].Value;

#ifdef _MMC_SUPPORTED
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetSurfaceParams(&surfaceCodecParams));
#endif
            CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
                m_hwInterface,
                cmdBuffer,
                &surfaceCodecParams,
                kernelState));
        }
    }

#if 1
    for (refIdx = (params->pAvcSlcParams->num_ref_idx_l0_active_minus1 + 1); refIdx < CODECHAL_ENCODE_NUM_MAX_VME_L0_REF; refIdx++)
    {
        auto     refPic = params->pAvcSlcParams->RefPicList[LIST_0][0];
        uint32_t refMbCodeBottomFieldOffsetUsed;
        uint32_t refMvBottomFieldOffsetUsed;
        uint32_t refBindingTableOffset;
        if (!CodecHal_PictureIsInvalid(refPic) && params->pAvcPicIdx[refPic.FrameIdx].bValid)
        {
            uint8_t refPicIdx = params->pAvcPicIdx[refPic.FrameIdx].ucPicIdx;
            bool    refBottomField = (CodecHal_PictureIsBottomField(refPic)) ? true : false;
            // Program the surface based on current picture's field/frame mode
            if (currFieldPicture)  // if current picture is field
            {
                if (refBottomField)
                {
                    refVDirection = CODECHAL_VDIRECTION_BOT_FIELD;
                    refBindingTableOffset = mbEncBindingTable->dwAvcMBEncFwdPicBotField[refIdx];
                }
                else
                {
                    refVDirection = CODECHAL_VDIRECTION_TOP_FIELD;
                    refBindingTableOffset = mbEncBindingTable->dwAvcMBEncFwdPicTopField[refIdx];
                }
            }
            else  // if current picture is frame
            {
                refVDirection = CODECHAL_VDIRECTION_FRAME;
                refBindingTableOffset = mbEncBindingTable->dwAvcMBEncFwdPicFrame[refIdx];
            }

            // Picture Y VME
            memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
            surfaceCodecParams.bUseAdvState = true;
            if ((0 == refIdx) && (params->bUseWeightedSurfaceForL0))
            {
                surfaceCodecParams.psSurface = &params->pWeightedPredOutputPicSelectList[CODEC_AVC_WP_OUTPUT_L0_START + refIdx].sBuffer;
            }
            else
            {
                surfaceCodecParams.psSurface = &params->ppRefList[refPicIdx]->sRefBuffer;
            }
            surfaceCodecParams.dwWidthInUse = params->dwFrameWidthInMb * 16;
            surfaceCodecParams.dwHeightInUse = params->dwFrameHeightInMb * 16;

            surfaceCodecParams.dwBindingTableOffset = refBindingTableOffset;
            surfaceCodecParams.ucVDirection = refVDirection;
            surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_REF_ENCODE].Value;

#ifdef _MMC_SUPPORTED
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetSurfaceParams(&surfaceCodecParams));
#endif
            CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
                m_hwInterface,
                cmdBuffer,
                &surfaceCodecParams,
                kernelState));
        }
    }

    if (params->pAvcSlcParams->num_ref_idx_l1_active_minus1 == 0)
    {
        for (refIdx = 0; refIdx <= MOS_MIN(params->pAvcSlcParams->num_ref_idx_l0_active_minus1, 1); refIdx++)
        {
            auto     refPic = params->pAvcSlcParams->RefPicList[LIST_0][refIdx];
            uint32_t refMbCodeBottomFieldOffsetUsed;
            uint32_t refMvBottomFieldOffsetUsed;
            uint32_t refBindingTableOffset;
            if (!CodecHal_PictureIsInvalid(refPic) && params->pAvcPicIdx[refPic.FrameIdx].bValid)
            {
                uint8_t refPicIdx = params->pAvcPicIdx[refPic.FrameIdx].ucPicIdx;
                bool    refBottomField = (CodecHal_PictureIsBottomField(refPic)) ? true : false;
                // Program the surface based on current picture's field/frame mode
                if (currFieldPicture)  // if current picture is field
                {
                    if (refBottomField)
                    {
                        refVDirection = CODECHAL_VDIRECTION_BOT_FIELD;
                        refBindingTableOffset = mbEncBindingTable->dwAvcMBEncBwdPicBotField[refIdx];
                    }
                    else
                    {
                        refVDirection = CODECHAL_VDIRECTION_TOP_FIELD;
                        refBindingTableOffset = mbEncBindingTable->dwAvcMBEncBwdPicTopField[refIdx];
                    }
                }
                else  // if current picture is frame
                {
                    refVDirection = CODECHAL_VDIRECTION_FRAME;
                    refBindingTableOffset = mbEncBindingTable->dwAvcMBEncBwdPicFrame[refIdx];
                }

                // Picture Y VME
                memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
                surfaceCodecParams.bUseAdvState = true;
                if ((0 == refIdx) && (params->bUseWeightedSurfaceForL0))
                {
                    surfaceCodecParams.psSurface = &params->pWeightedPredOutputPicSelectList[CODEC_AVC_WP_OUTPUT_L0_START + refIdx].sBuffer;
                }
                else
                {
                    surfaceCodecParams.psSurface = &params->ppRefList[refPicIdx]->sRefBuffer;
                }
                surfaceCodecParams.dwWidthInUse = params->dwFrameWidthInMb * 16;
                surfaceCodecParams.dwHeightInUse = params->dwFrameHeightInMb * 16;

                surfaceCodecParams.dwBindingTableOffset = refBindingTableOffset;
                surfaceCodecParams.ucVDirection = refVDirection;
                surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_REF_ENCODE].Value;

#ifdef _MMC_SUPPORTED
                CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetSurfaceParams(&surfaceCodecParams));
#endif
                CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
                    m_hwInterface,
                    cmdBuffer,
                    &surfaceCodecParams,
                    kernelState));
            }
        }
    }
#endif

    // Setup references 1...n
    // LIST 1 references
    uint32_t curbeSize;
    for (refIdx = 0; refIdx <= params->pAvcSlcParams->num_ref_idx_l1_active_minus1; refIdx++)
    {
        if (!currFieldPicture && refIdx > 0)
        {
            // Only 1 LIST 1 reference required here since only single ref is supported in frame case
            break;
        }

        auto     refPic = params->pAvcSlcParams->RefPicList[LIST_1][refIdx];
        uint32_t refMbCodeBottomFieldOffsetUsed;
        uint32_t refMvBottomFieldOffsetUsed;
        uint32_t refBindingTableOffset;
        bool     refBottomField;
        uint8_t  refPicIdx;
        if (!CodecHal_PictureIsInvalid(refPic) && params->pAvcPicIdx[refPic.FrameIdx].bValid)
        {
            refPicIdx      = params->pAvcPicIdx[refPic.FrameIdx].ucPicIdx;
            refBottomField = (CodecHal_PictureIsBottomField(refPic)) ? 1 : 0;
            // Program the surface based on current picture's field/frame mode
            if (currFieldPicture)  // if current picture is field
            {
                if (refBottomField)
                {
                    refVDirection                = CODECHAL_VDIRECTION_BOT_FIELD;
                    refMbCodeBottomFieldOffsetUsed = refMbCodeBottomFieldOffset;
                    refMvBottomFieldOffsetUsed     = refMvBottomFieldOffset;
                    refBindingTableOffset          = mbEncBindingTable->dwAvcMBEncBwdPicBotField[refIdx];
                }
                else
                {
                    refVDirection                = CODECHAL_VDIRECTION_TOP_FIELD;
                    refMbCodeBottomFieldOffsetUsed = 0;
                    refMvBottomFieldOffsetUsed     = 0;
                    refBindingTableOffset          = mbEncBindingTable->dwAvcMBEncBwdPicTopField[refIdx];
                }
            }
            else  // if current picture is frame
            {
                refVDirection                = CODECHAL_VDIRECTION_FRAME;
                refMbCodeBottomFieldOffsetUsed = 0;
                refMvBottomFieldOffsetUsed     = 0;
                refBindingTableOffset          = mbEncBindingTable->dwAvcMBEncBwdPicFrame[refIdx];
            }

            // Picture Y VME
            memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
            surfaceCodecParams.bUseAdvState = true;
            if ((0 == refIdx) && (params->bUseWeightedSurfaceForL1))
            {
                surfaceCodecParams.psSurface = &params->pWeightedPredOutputPicSelectList[CODEC_AVC_WP_OUTPUT_L1_START + refIdx].sBuffer;
            }
            else
            {
                surfaceCodecParams.psSurface = &params->ppRefList[refPicIdx]->sRefBuffer;
            }
            surfaceCodecParams.dwWidthInUse  = params->dwFrameWidthInMb * 16;
            surfaceCodecParams.dwHeightInUse = params->dwFrameHeightInMb * 16;

            surfaceCodecParams.dwBindingTableOffset  = refBindingTableOffset;
            surfaceCodecParams.ucVDirection          = refVDirection;
            surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_REF_ENCODE].Value;

#ifdef _MMC_SUPPORTED
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetSurfaceParams(&surfaceCodecParams));
#endif
            CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
                m_hwInterface,
                cmdBuffer,
                &surfaceCodecParams,
                kernelState));

            if (refIdx == 0)
            {
                // MB data buffer
                size = params->dwFrameWidthInMb * params->dwFrameFieldHeightInMb * 16 * 4;
                memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
                surfaceCodecParams.dwSize                = size;
                surfaceCodecParams.presBuffer            = &params->ppRefList[refPicIdx]->resRefMbCodeBuffer;
                surfaceCodecParams.dwOffset              = refMbCodeBottomFieldOffsetUsed;
                surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_PAK_OBJECT_ENCODE].Value;
                surfaceCodecParams.dwBindingTableOffset  = mbEncBindingTable->dwAvcMBEncBwdRefMBData;
                CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
                    m_hwInterface,
                    cmdBuffer,
                    &surfaceCodecParams,
                    kernelState));

                // MV data buffer
                size = params->dwFrameWidthInMb * params->dwFrameFieldHeightInMb * 32 * 4;
                memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
                surfaceCodecParams.dwSize                = size;
                surfaceCodecParams.presBuffer            = &params->ppRefList[refPicIdx]->resRefMvDataBuffer;
                surfaceCodecParams.dwOffset              = refMvBottomFieldOffsetUsed;
                surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_MV_DATA_ENCODE].Value;
                surfaceCodecParams.dwBindingTableOffset  = mbEncBindingTable->dwAvcMBEncBwdRefMVData;
                CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
                    m_hwInterface,
                    cmdBuffer,
                    &surfaceCodecParams,
                    kernelState));
            }

            if (refIdx < CODECHAL_ENCODE_NUM_MAX_VME_L1_REF)
            {
                if (currFieldPicture)
                {
                    // The binding table contains multiple entries for IDX0 backwards references
                    if (refBottomField)
                    {
                        refBindingTableOffset = mbEncBindingTable->dwAvcMBEncBwdPicBotField[refIdx + CODECHAL_ENCODE_NUM_MAX_VME_L1_REF];
                    }
                    else
                    {
                        refBindingTableOffset = mbEncBindingTable->dwAvcMBEncBwdPicTopField[refIdx + CODECHAL_ENCODE_NUM_MAX_VME_L1_REF];
                    }
                }
                else
                {
                    refBindingTableOffset = mbEncBindingTable->dwAvcMBEncBwdPicFrame[refIdx + CODECHAL_ENCODE_NUM_MAX_VME_L1_REF];
                }

                // Picture Y VME
                memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
                surfaceCodecParams.bUseAdvState          = true;
                surfaceCodecParams.dwWidthInUse          = params->dwFrameWidthInMb * 16;
                surfaceCodecParams.dwHeightInUse         = params->dwFrameHeightInMb * 16;
                surfaceCodecParams.psSurface             = &params->ppRefList[refPicIdx]->sRefBuffer;
                surfaceCodecParams.dwBindingTableOffset  = refBindingTableOffset;
                surfaceCodecParams.ucVDirection          = refVDirection;
                surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_REF_ENCODE].Value;

#ifdef _MMC_SUPPORTED
                CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetSurfaceParams(&surfaceCodecParams));
#endif
                CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
                    m_hwInterface,
                    cmdBuffer,
                    &surfaceCodecParams,
                    kernelState));
            }
        }
    }

    // BRC distortion data buffer for I frame
    if (params->bMbEncIFrameDistInUse)
    {
        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.bIs2DSurface         = true;
        surfaceCodecParams.bMediaBlockRW        = true;
        surfaceCodecParams.psSurface            = params->psMeBrcDistortionBuffer;
        surfaceCodecParams.dwOffset             = params->dwMeBrcDistortionBottomFieldOffset;
        surfaceCodecParams.dwBindingTableOffset = mbEncBindingTable->dwAvcMBEncBRCDist;
        surfaceCodecParams.bIsWritable          = true;
        surfaceCodecParams.bRenderTarget        = true;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }

    // RefPicSelect of Current Picture
    if (params->bUsedAsRef)
    {
        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.bIs2DSurface          = true;
        surfaceCodecParams.bMediaBlockRW         = true;
        surfaceCodecParams.psSurface             = &currPicRefListEntry->pRefPicSelectListEntry->sBuffer;
        surfaceCodecParams.psSurface->dwHeight   = MOS_ALIGN_CEIL(surfaceCodecParams.psSurface->dwHeight, 8);
        surfaceCodecParams.dwOffset              = params->dwRefPicSelectBottomFieldOffset;
        surfaceCodecParams.dwBindingTableOffset  = mbEncBindingTable->dwAvcMBEncRefPicSelectL0;
        surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_REF_ENCODE].Value;
        surfaceCodecParams.bRenderTarget         = true;
        surfaceCodecParams.bIsWritable           = true;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }

    if (params->bMBVProcStatsEnabled)
    {
        size = params->dwFrameWidthInMb *
            (currFieldPicture ? params->dwFrameFieldHeightInMb : params->dwFrameHeightInMb) *
            16 * sizeof(uint32_t);

        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.dwSize               = size;
        surfaceCodecParams.presBuffer           = params->presMBVProcStatsBuffer;
        surfaceCodecParams.dwOffset             = currBottomField ? params->dwMBVProcStatsBottomFieldOffset : 0;
        surfaceCodecParams.dwBindingTableOffset = mbEncBindingTable->dwAvcMBEncMBStats;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }
    else if (params->bFlatnessCheckEnabled)
    {
        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.bIs2DSurface          = true;
        surfaceCodecParams.bMediaBlockRW         = true;
        surfaceCodecParams.psSurface             = params->psFlatnessCheckSurface;
        surfaceCodecParams.dwOffset              = currBottomField ? params->dwFlatnessCheckBottomFieldOffset : 0;
        surfaceCodecParams.dwBindingTableOffset  = mbEncBindingTable->dwAvcMBEncFlatnessChk;
        surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_FLATNESS_CHECK_ENCODE].Value;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }

    if (params->bMADEnabled)
    {
        size = CODECHAL_MAD_BUFFER_SIZE;

        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.bRawSurface           = true;
        surfaceCodecParams.dwSize                = size;
        surfaceCodecParams.presBuffer            = params->presMADDataBuffer;
        surfaceCodecParams.dwBindingTableOffset  = mbEncBindingTable->dwAvcMBEncMADData;
        surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_MAD_ENCODE].Value;
        surfaceCodecParams.bRenderTarget         = true;
        surfaceCodecParams.bIsWritable           = true;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }

    if (params->dwMbEncBRCBufferSize > 0)
    {
        // MbEnc BRC buffer - write only
        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.presBuffer            = params->presMbEncBRCBuffer;
        surfaceCodecParams.dwSize                = MOS_BYTES_TO_DWORDS(params->dwMbEncBRCBufferSize);
        surfaceCodecParams.dwBindingTableOffset  = mbEncBindingTable->dwAvcMbEncBRCCurbeData;
        surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_MBENC_CURBE_ENCODE].Value;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }
    else
    {
        if (params->bUseMbEncAdvKernel)
        {
            // For BRC the new BRC surface is used
            if (params->bUseAdvancedDsh)
            {
                memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
                surfaceCodecParams.presBuffer = params->presMbEncCurbeBuffer;
                curbeSize                     = MOS_ALIGN_CEIL(
                    params->pKernelState->KernelParams.iCurbeLength,
                    m_hwInterface->GetRenderInterface()->m_stateHeapInterface->pStateHeapInterface->GetCurbeAlignment());
                surfaceCodecParams.dwSize                = MOS_BYTES_TO_DWORDS(curbeSize);
                surfaceCodecParams.dwBindingTableOffset  = mbEncBindingTable->dwAvcMbEncBRCCurbeData;
                surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_MBENC_CURBE_ENCODE].Value;
                CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
                    m_hwInterface,
                    cmdBuffer,
                    &surfaceCodecParams,
                    kernelState));
            }
            else  // For CQP the DSH CURBE is used
            {
                MOS_RESOURCE *dsh = nullptr;
                CODECHAL_ENCODE_CHK_NULL_RETURN(dsh = params->pKernelState->m_dshRegion.GetResource());

                memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
                surfaceCodecParams.presBuffer = dsh;
                surfaceCodecParams.dwOffset =
                    params->pKernelState->m_dshRegion.GetOffset() +
                    params->pKernelState->dwCurbeOffset;
                curbeSize = MOS_ALIGN_CEIL(
                    params->pKernelState->KernelParams.iCurbeLength,
                    m_hwInterface->GetRenderInterface()->m_stateHeapInterface->pStateHeapInterface->GetCurbeAlignment());
                surfaceCodecParams.dwSize                = MOS_BYTES_TO_DWORDS(curbeSize);
                surfaceCodecParams.dwBindingTableOffset  = mbEncBindingTable->dwAvcMbEncBRCCurbeData;
                surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_MBENC_CURBE_ENCODE].Value;
                CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
                    m_hwInterface,
                    cmdBuffer,
                    &surfaceCodecParams,
                    kernelState));
            }
        }
    }

    if (params->bArbitraryNumMbsInSlice)
    {
        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.bIs2DSurface          = true;
        surfaceCodecParams.bMediaBlockRW         = true;
        surfaceCodecParams.psSurface             = params->psSliceMapSurface;
        surfaceCodecParams.bRenderTarget         = false;
        surfaceCodecParams.bIsWritable           = false;
        surfaceCodecParams.dwOffset              = currBottomField ? params->dwSliceMapBottomFieldOffset : 0;
        surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_SLICE_MAP_ENCODE].Value;
        surfaceCodecParams.dwBindingTableOffset  = mbEncBindingTable->dwAvcMBEncSliceMapData;

        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }

    if (!params->bMbEncIFrameDistInUse)
    {
        if (params->bMbDisableSkipMapEnabled)
        {
            memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
            surfaceCodecParams.bIs2DSurface          = true;
            surfaceCodecParams.bMediaBlockRW         = true;
            surfaceCodecParams.psSurface             = params->psMbDisableSkipMapSurface;
            surfaceCodecParams.dwOffset              = 0;
            surfaceCodecParams.dwBindingTableOffset  = mbEncBindingTable->dwAvcMBEncMbNonSkipMap;
            surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_MBDISABLE_SKIPMAP_CODEC].Value;
            CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
                m_hwInterface,
                cmdBuffer,
                &surfaceCodecParams,
                kernelState));
        }

        if (params->bStaticFrameDetectionEnabled)
        {
            // static frame cost table surface
            memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
            surfaceCodecParams.presBuffer            = params->presSFDCostTableBuffer;
            surfaceCodecParams.dwSize                = MOS_BYTES_TO_DWORDS(m_sfdCostTableBufferSize);
            surfaceCodecParams.dwOffset              = 0;
            surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_ME_DISTORTION_ENCODE].Value;
            surfaceCodecParams.dwBindingTableOffset  = mbEncBindingTable->dwAvcMBEncStaticDetectionCostTable;
            CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
                m_hwInterface,
                cmdBuffer,
                &surfaceCodecParams,
                kernelState));
        }

        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.bIs2DSurface = true;
        surfaceCodecParams.bMediaBlockRW = true;
        surfaceCodecParams.psSurface = m_swScoreboardState->GetCurSwScoreboardSurface();
        surfaceCodecParams.bRenderTarget = true;
        surfaceCodecParams.bIsWritable = true;
        surfaceCodecParams.dwOffset = 0;
        surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_SOFTWARE_SCOREBOARD_ENCODE].Value;
        surfaceCodecParams.dwBindingTableOffset = mbencSwScoreboard;
        surfaceCodecParams.bUse32UINTSurfaceFormat = true;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }
    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::SendAvcWPSurfaces(PMOS_COMMAND_BUFFER cmdBuffer, PCODECHAL_ENCODE_AVC_WP_SURFACE_PARAMS params)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->pKernelState);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->psInputRefBuffer);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->psOutputScaledBuffer);

    CODECHAL_SURFACE_CODEC_PARAMS surfaceParams;
    memset((void *)&surfaceParams, 0, sizeof(surfaceParams));
    surfaceParams.bIs2DSurface               = true;
    surfaceParams.bMediaBlockRW              = true;
    surfaceParams.psSurface                  = params->psInputRefBuffer;  // Input surface
    surfaceParams.bIsWritable                = false;
    surfaceParams.bRenderTarget              = false;
    surfaceParams.dwBindingTableOffset       = wpInputRefSurface;
    surfaceParams.dwCacheabilityControl      = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_WP_DOWNSAMPLED_ENCODE].Value;
    surfaceParams.dwVerticalLineStride       = params->dwVerticalLineStride;
    surfaceParams.dwVerticalLineStrideOffset = params->dwVerticalLineStrideOffset;
    surfaceParams.ucVDirection               = params->ucVDirection;
#ifdef _MMC_SUPPORTED
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetSurfaceParams(&surfaceParams));
#endif
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceParams,
        params->pKernelState));

    memset((void *)&surfaceParams, 0, sizeof(surfaceParams));
    surfaceParams.bIs2DSurface               = true;
    surfaceParams.bMediaBlockRW              = true;
    surfaceParams.psSurface                  = params->psOutputScaledBuffer;  // output surface
    surfaceParams.bIsWritable                = true;
    surfaceParams.bRenderTarget              = true;
    surfaceParams.dwBindingTableOffset       = wpOutputScaledSurface;
    surfaceParams.dwCacheabilityControl      = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_WP_DOWNSAMPLED_ENCODE].Value;
    surfaceParams.dwVerticalLineStride       = params->dwVerticalLineStride;
    surfaceParams.dwVerticalLineStrideOffset = params->dwVerticalLineStrideOffset;
    surfaceParams.ucVDirection               = params->ucVDirection;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceParams,
        params->pKernelState));

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::SendAvcBrcFrameUpdateSurfaces(PMOS_COMMAND_BUFFER cmdBuffer, PCODECHAL_ENCODE_AVC_BRC_UPDATE_SURFACE_PARAMS params)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBrcBuffers);

    // BRC history buffer
    CODECHAL_SURFACE_CODEC_PARAMS surfaceCodecParams;
    auto                          kernelState           = params->pKernelState;
    auto                          brcUpdateBindingTable = params->pBrcUpdateBindingTable;
    memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
    surfaceCodecParams.presBuffer            = &params->pBrcBuffers->resBrcHistoryBuffer;
    surfaceCodecParams.dwSize                = MOS_BYTES_TO_DWORDS(params->dwBrcHistoryBufferSize);
    surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_BRC_HISTORY_ENCODE].Value;
    surfaceCodecParams.dwBindingTableOffset  = brcUpdateBindingTable->dwFrameBrcHistoryBuffer;
    surfaceCodecParams.bIsWritable           = true;
    surfaceCodecParams.bRenderTarget         = true;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceCodecParams,
        kernelState));

    // PAK Statistics buffer
    memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
    surfaceCodecParams.presBuffer            = &params->pBrcBuffers->resBrcPakStatisticBuffer[0];
    surfaceCodecParams.dwSize                = MOS_BYTES_TO_DWORDS(params->dwBrcPakStatisticsSize);
    surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_PAK_STATS_ENCODE].Value;
    surfaceCodecParams.dwBindingTableOffset  = brcUpdateBindingTable->dwFrameBrcPakStatisticsOutputBuffer;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceCodecParams,
        kernelState));

    // PAK IMG_STATEs buffer - read only
    uint32_t size = MOS_BYTES_TO_DWORDS(BRC_IMG_STATE_SIZE_PER_PASS * m_hwInterface->GetMfxInterface()->GetBrcNumPakPasses());
    memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
    surfaceCodecParams.presBuffer            = &params->pBrcBuffers->resBrcImageStatesReadBuffer[params->ucCurrRecycledBufIdx];
    surfaceCodecParams.dwSize                = size;
    surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_PAK_IMAGESTATE_ENCODE].Value;
    surfaceCodecParams.dwBindingTableOffset  = brcUpdateBindingTable->dwFrameBrcImageStateReadBuffer;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceCodecParams,
        kernelState));

    // PAK IMG_STATEs buffer - write only
    memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
    surfaceCodecParams.presBuffer            = &params->pBrcBuffers->resBrcImageStatesWriteBuffer;
    surfaceCodecParams.dwSize                = size;
    surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_PAK_IMAGESTATE_ENCODE].Value;
    surfaceCodecParams.dwBindingTableOffset  = brcUpdateBindingTable->dwFrameBrcImageStateWriteBuffer;
    surfaceCodecParams.bIsWritable           = true;
    surfaceCodecParams.bRenderTarget         = true;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceCodecParams,
        kernelState));

    if (params->dwMbEncBRCBufferSize > 0)
    {
        // MbEnc BRC buffer - write only
        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.presBuffer            = &params->pBrcBuffers->resMbEncBrcBuffer;
        surfaceCodecParams.dwSize                = MOS_BYTES_TO_DWORDS(params->dwMbEncBRCBufferSize);
        surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_MBENC_BRC_ENCODE].Value;
        surfaceCodecParams.dwBindingTableOffset  = brcUpdateBindingTable->dwFrameBrcMbEncCurbeWriteData;
        surfaceCodecParams.bIsWritable           = true;
        surfaceCodecParams.bRenderTarget         = true;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }
    else
    {
        PMHW_KERNEL_STATE mbEncKernelState;
        CODECHAL_ENCODE_CHK_NULL_RETURN(mbEncKernelState = params->pBrcBuffers->pMbEncKernelStateInUse);

        MOS_RESOURCE *dsh = nullptr;
        CODECHAL_ENCODE_CHK_NULL_RETURN(dsh = mbEncKernelState->m_dshRegion.GetResource());

        // BRC ENC CURBE Buffer - read only
        size = MOS_ALIGN_CEIL(
            mbEncKernelState->KernelParams.iCurbeLength,
            m_renderEngineInterface->m_stateHeapInterface->pStateHeapInterface->GetCurbeAlignment());
        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.presBuffer = dsh;
        surfaceCodecParams.dwOffset =
            mbEncKernelState->m_dshRegion.GetOffset() +
            mbEncKernelState->dwCurbeOffset;
        surfaceCodecParams.dwSize               = MOS_BYTES_TO_DWORDS(size);
        surfaceCodecParams.dwBindingTableOffset = brcUpdateBindingTable->dwFrameBrcMbEncCurbeReadBuffer;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));

        // BRC ENC CURBE Buffer - write only
        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        if (params->bUseAdvancedDsh)
        {
            surfaceCodecParams.presBuffer = params->presMbEncCurbeBuffer;
        }
        else
        {
            surfaceCodecParams.presBuffer = dsh;
            surfaceCodecParams.dwOffset =
                mbEncKernelState->m_dshRegion.GetOffset() +
                mbEncKernelState->dwCurbeOffset;
        }
        surfaceCodecParams.dwSize               = MOS_BYTES_TO_DWORDS(size);
        surfaceCodecParams.dwBindingTableOffset = brcUpdateBindingTable->dwFrameBrcMbEncCurbeWriteData;
        surfaceCodecParams.bRenderTarget        = true;
        surfaceCodecParams.bIsWritable          = true;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }

    // AVC_ME BRC Distortion data buffer - input/output
    memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
    surfaceCodecParams.bIs2DSurface          = true;
    surfaceCodecParams.bMediaBlockRW         = true;
    surfaceCodecParams.psSurface             = &params->pBrcBuffers->sMeBrcDistortionBuffer;
    surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_BRC_ME_DISTORTION_ENCODE].Value;
    surfaceCodecParams.dwOffset              = params->pBrcBuffers->dwMeBrcDistortionBottomFieldOffset;
    surfaceCodecParams.dwBindingTableOffset  = brcUpdateBindingTable->dwFrameBrcDistortionBuffer;
    surfaceCodecParams.bRenderTarget         = true;
    surfaceCodecParams.bIsWritable           = true;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceCodecParams,
        kernelState));

    // BRC Constant Data Surface
    memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
    surfaceCodecParams.bIs2DSurface          = true;
    surfaceCodecParams.bMediaBlockRW         = true;
    surfaceCodecParams.psSurface             = &params->pBrcBuffers->sBrcConstantDataBuffer[params->ucCurrRecycledBufIdx];
    surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_BRC_CONSTANT_DATA_ENCODE].Value;
    surfaceCodecParams.dwBindingTableOffset  = brcUpdateBindingTable->dwFrameBrcConstantData;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceCodecParams,
        kernelState));

    // MBStat buffer - input
    memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
    surfaceCodecParams.presBuffer            = params->presMbStatBuffer;
    surfaceCodecParams.dwSize                = MOS_BYTES_TO_DWORDS(m_hwInterface->m_avcMbStatBufferSize);
    surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_MB_STATS_ENCODE].Value;
    surfaceCodecParams.dwBindingTableOffset  = brcUpdateBindingTable->dwFrameBrcMbStatBuffer;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceCodecParams,
        kernelState));

    // MV data buffer
    if (params->psMvDataBuffer)
    {
        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.bIs2DSurface          = true;
        surfaceCodecParams.bMediaBlockRW         = true;
        surfaceCodecParams.psSurface             = params->psMvDataBuffer;
        surfaceCodecParams.dwOffset              = params->dwMvBottomFieldOffset;
        surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_MV_DATA_ENCODE].Value;
        surfaceCodecParams.dwBindingTableOffset  = brcUpdateBindingTable->dwFrameBrcMvDataBuffer;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::SendAvcBrcMbUpdateSurfaces(PMOS_COMMAND_BUFFER cmdBuffer, PCODECHAL_ENCODE_AVC_BRC_UPDATE_SURFACE_PARAMS params)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBrcBuffers);

    // BRC history buffer
    auto                          kernelState           = params->pKernelState;
    auto                          brcUpdateBindingTable = params->pBrcUpdateBindingTable;
    CODECHAL_SURFACE_CODEC_PARAMS surfaceCodecParams;
    memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
    surfaceCodecParams.presBuffer            = &params->pBrcBuffers->resBrcHistoryBuffer;
    surfaceCodecParams.dwSize                = MOS_BYTES_TO_DWORDS(params->dwBrcHistoryBufferSize);
    surfaceCodecParams.bIsWritable           = true;
    surfaceCodecParams.bRenderTarget         = true;
    surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_BRC_HISTORY_ENCODE].Value;
    surfaceCodecParams.dwBindingTableOffset  = brcUpdateBindingTable->dwMbBrcHistoryBuffer;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceCodecParams,
        kernelState));

    // AVC MB QP data buffer
    if (params->bMbBrcEnabled)
    {
        params->pBrcBuffers->sBrcMbQpBuffer.dwHeight = MOS_ALIGN_CEIL((params->dwDownscaledFrameFieldHeightInMb4x << 2), 8);

        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.bIs2DSurface          = true;
        surfaceCodecParams.bMediaBlockRW         = true;
        surfaceCodecParams.bIsWritable           = true;
        surfaceCodecParams.bRenderTarget         = true;
        surfaceCodecParams.psSurface             = &params->pBrcBuffers->sBrcMbQpBuffer;
        surfaceCodecParams.dwOffset              = params->pBrcBuffers->dwBrcMbQpBottomFieldOffset;
        surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_BRC_MB_QP_ENCODE].Value;
        surfaceCodecParams.dwBindingTableOffset  = brcUpdateBindingTable->dwMbBrcMbQpBuffer;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }

    // BRC ROI feature
    if (params->bBrcRoiEnabled)
    {
        params->psRoiSurface->dwHeight = MOS_ALIGN_CEIL((params->dwDownscaledFrameFieldHeightInMb4x << 2), 8);

        memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
        surfaceCodecParams.bIs2DSurface          = true;
        surfaceCodecParams.bMediaBlockRW         = true;
        surfaceCodecParams.bIsWritable           = false;
        surfaceCodecParams.bRenderTarget         = true;
        surfaceCodecParams.psSurface             = params->psRoiSurface;
        surfaceCodecParams.dwOffset              = 0;
        surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_BRC_ROI_ENCODE].Value;
        surfaceCodecParams.dwBindingTableOffset  = brcUpdateBindingTable->dwMbBrcROISurface;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }

    // MBStat buffer
    memset((void *)&surfaceCodecParams, 0, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
    surfaceCodecParams.presBuffer            = params->presMbStatBuffer;
    surfaceCodecParams.dwSize                = MOS_BYTES_TO_DWORDS(m_hwInterface->m_avcMbStatBufferSize);
    surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_MB_STATS_ENCODE].Value;
    surfaceCodecParams.dwBindingTableOffset  = brcUpdateBindingTable->dwMbBrcMbStatBuffer;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceCodecParams,
        kernelState));

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::SetGpuCtxCreatOption()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    if (!MOS_VE_CTXBASEDSCHEDULING_SUPPORTED(m_osInterface))
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::SetGpuCtxCreatOption());
    }
    else
    {
        m_gpuCtxCreatOpt = MOS_New(MOS_GPUCTX_CREATOPTIONS_ENHANCED);
        CODECHAL_ENCODE_CHK_NULL_RETURN(m_gpuCtxCreatOpt);
         
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalEncodeSinglePipeVE_ConstructParmsForGpuCtxCreation(
            m_sinlgePipeVeState,
            (PMOS_GPUCTX_CREATOPTIONS_ENHANCED)m_gpuCtxCreatOpt));
    }

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::SetupROISurface()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    MOS_LOCK_PARAMS readOnly;
    memset(&readOnly, 0, sizeof(readOnly));
    readOnly.ReadOnly = 1;
    uint32_t * dataPtr = (uint32_t *)m_osInterface->pfnLockResource(m_osInterface, &BrcBuffers.sBrcRoiSurface.OsResource, &readOnly);
    if (!dataPtr)
    {
        eStatus = MOS_STATUS_INVALID_HANDLE;
        return eStatus;
    }

    uint32_t bufferWidthInByte  = BrcBuffers.sBrcRoiSurface.dwPitch;
    uint32_t bufferHeightInByte = MOS_ALIGN_CEIL((m_downscaledHeightInMb4x << 2), 8);
    uint32_t numMBs = m_picWidthInMb * m_picHeightInMb;
    for (uint32_t uMB = 0; uMB <= numMBs; uMB++)
    {
        int32_t curMbY = uMB / m_picWidthInMb;
        int32_t curMbX = uMB - curMbY * m_picWidthInMb;

        uint32_t outdata = 0;
        for (int32_t roiIdx = (m_avcPicParam->NumROI - 1); roiIdx >= 0; roiIdx--)
        {
            int32_t qpLevel;
            if (bROIValueInDeltaQP)
            {
                qpLevel = -m_avcPicParam->ROI[roiIdx].PriorityLevelOrDQp;
            }
            else
            {
                // QP Level sent to ROI surface is (priority * 6)
                qpLevel = m_avcPicParam->ROI[roiIdx].PriorityLevelOrDQp * 6;
            }

            if (qpLevel == 0)
            {
                continue;
            }

            if ((curMbX >= (int32_t)m_avcPicParam->ROI[roiIdx].Left) && (curMbX < (int32_t)m_avcPicParam->ROI[roiIdx].Right) &&
                (curMbY >= (int32_t)m_avcPicParam->ROI[roiIdx].Top) && (curMbY < (int32_t)m_avcPicParam->ROI[roiIdx].Bottom))
            {
                outdata = 15 | ((qpLevel & 0xFF) << 8);
            }
            else if (bROISmoothEnabled)
            {
                if ((curMbX >= (int32_t)m_avcPicParam->ROI[roiIdx].Left - 1) && (curMbX < (int32_t)m_avcPicParam->ROI[roiIdx].Right + 1) &&
                    (curMbY >= (int32_t)m_avcPicParam->ROI[roiIdx].Top - 1) && (curMbY < (int32_t)m_avcPicParam->ROI[roiIdx].Bottom + 1))
                {
                    outdata = 14 | ((qpLevel & 0xFF) << 8);
                }
                else if ((curMbX >= (int32_t)m_avcPicParam->ROI[roiIdx].Left - 2) && (curMbX < (int32_t)m_avcPicParam->ROI[roiIdx].Right + 2) &&
                    (curMbY >= (int32_t)m_avcPicParam->ROI[roiIdx].Top - 2) && (curMbY < (int32_t)m_avcPicParam->ROI[roiIdx].Bottom + 2))
                {
                    outdata = 13 | ((qpLevel & 0xFF) << 8);
                }
                else if ((curMbX >= (int32_t)m_avcPicParam->ROI[roiIdx].Left - 3) && (curMbX < (int32_t)m_avcPicParam->ROI[roiIdx].Right + 3) &&
                    (curMbY >= (int32_t)m_avcPicParam->ROI[roiIdx].Top - 3) && (curMbY < (int32_t)m_avcPicParam->ROI[roiIdx].Bottom + 3))
                {
                    outdata = 12 | ((qpLevel & 0xFF) << 8);
                }
            }
        }
        dataPtr[(curMbY * (bufferWidthInByte >> 2)) + curMbX] = outdata;
    }

    m_osInterface->pfnUnlockResource(m_osInterface, &BrcBuffers.sBrcRoiSurface.OsResource);

    uint32_t bufferSize = bufferWidthInByte * bufferHeightInByte;
    CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
        &BrcBuffers.sBrcRoiSurface.OsResource,
        CodechalDbgAttr::attrInput,
        "ROI",
        bufferSize,
        0,
        CODECHAL_MEDIA_STATE_MB_BRC_UPDATE)));
    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::SendPrologWithFrameTracking(
    PMOS_COMMAND_BUFFER         cmdBuffer,
    bool                        frameTracking,
    MHW_MI_MMIOREGISTERS       *mmioRegister)
{
    if (MOS_VE_SUPPORTED(m_osInterface) && cmdBuffer->Attributes.pAttriVe)
    {
        PMOS_CMD_BUF_ATTRI_VE attriExt =
                (PMOS_CMD_BUF_ATTRI_VE)(cmdBuffer->Attributes.pAttriVe);
        attriExt->bUseVirtualEngineHint = true;
        attriExt->VEngineHintParams.NeedSyncWithPrevious = 1;
    }

    return CodechalEncodeAvcEnc::SendPrologWithFrameTracking(cmdBuffer, frameTracking, mmioRegister);
}

void CodechalEncodeAvcEncG12::ResizeOnResChange()
{
    CODECHAL_ENCODE_FUNCTION_ENTER;

    CodechalEncoderState::ResizeOnResChange();

    // need to re-allocate surfaces according to resolution
    m_swScoreboardState->ReleaseResources();
}

MOS_STATUS CodechalEncodeAvcEncG12::InitKernelStateMe()
{
    m_hmeKernel = MOS_New(CodechalKernelHmeG12, this);
    CODECHAL_ENCODE_CHK_NULL_RETURN(m_hmeKernel);
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hmeKernel->Initialize(
        GetCommonKernelHeaderAndSizeG12,
        m_kernelBase,
        m_kuidCommon));
    return MOS_STATUS_SUCCESS;
}

MOS_STATUS CodechalEncodeAvcEncG12::UpdateCmdBufAttribute(
    PMOS_COMMAND_BUFFER cmdBuffer,
    bool                renderEngineInUse)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    // should not be there. Will remove it in the next change
    CODECHAL_ENCODE_FUNCTION_ENTER;
    if (MOS_VE_SUPPORTED(m_osInterface) && cmdBuffer->Attributes.pAttriVe)
    {
        PMOS_CMD_BUF_ATTRI_VE attriExt =
            (PMOS_CMD_BUF_ATTRI_VE)(cmdBuffer->Attributes.pAttriVe);

        memset((void *)attriExt, 0, sizeof(MOS_CMD_BUF_ATTRI_VE));
        attriExt->bUseVirtualEngineHint =
            attriExt->VEngineHintParams.NeedSyncWithPrevious = !renderEngineInUse;
    }

    return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::AddMediaVfeCmd(
    PMOS_COMMAND_BUFFER cmdBuffer,
    SendKernelCmdsParams *params)
{
    CODECHAL_ENCODE_CHK_NULL_RETURN(params);

    MHW_VFE_PARAMS_G12 vfeParams = {};
    vfeParams.pKernelState              = params->pKernelState;
    vfeParams.eVfeSliceDisable          = MHW_VFE_SLICE_ALL;
    vfeParams.dwMaximumNumberofThreads  = m_encodeVfeMaxThreads;
    vfeParams.bFusedEuDispatch          = false; // legacy mode

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_renderEngineInterface->AddMediaVfeCmd(cmdBuffer, &vfeParams));

    return MOS_STATUS_SUCCESS;
}

#if USE_CODECHAL_DEBUG_TOOL
MOS_STATUS CodechalEncodeAvcEncG12::KernelDebugDumps()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
    CODECHAL_DEBUG_TOOL(
        if (m_hmeEnabled) {
            CODECHAL_ME_OUTPUT_PARAMS meOutputParams;

            memset((void *)&meOutputParams, 0, sizeof(meOutputParams));
            meOutputParams.psMeMvBuffer = m_hmeKernel->GetSurface(CodechalKernelHme::SurfaceId::me4xMvDataBuffer);
            meOutputParams.psMeDistortionBuffer =
                m_4xMeDistortionBufferSupported ?
                m_hmeKernel->GetSurface(CodechalKernelHme::SurfaceId::me4xDistortionBuffer) : nullptr;
            meOutputParams.b16xMeInUse = false;
            meOutputParams.b32xMeInUse = false;
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
                &meOutputParams.psMeMvBuffer->OsResource,
                CodechalDbgAttr::attrOutput,
                "MvData",
                meOutputParams.psMeMvBuffer->dwHeight *meOutputParams.psMeMvBuffer->dwPitch,
                m_hmeKernel ? m_hmeKernel->Get4xMeMvBottomFieldOffset() : (uint32_t)m_meMvBottomFieldOffset,
                CODECHAL_MEDIA_STATE_4X_ME));

            if (meOutputParams.psMeDistortionBuffer)
            {
                CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
                    &meOutputParams.psMeDistortionBuffer->OsResource,
                    CodechalDbgAttr::attrOutput,
                    "MeDist",
                    meOutputParams.psMeDistortionBuffer->dwHeight *meOutputParams.psMeDistortionBuffer->dwPitch,
                    m_hmeKernel ? m_hmeKernel->GetDistortionBottomFieldOffset() : (uint32_t)m_meDistortionBottomFieldOffset,
                    CODECHAL_MEDIA_STATE_4X_ME));
            }

            if (m_16xMeEnabled)
            {
                meOutputParams.psMeMvBuffer = m_hmeKernel->GetSurface(CodechalKernelHme::SurfaceId::me16xMvDataBuffer);
                CODECHAL_ENCODE_CHK_STATUS_RETURN(
                    m_debugInterface->DumpBuffer(
                        &meOutputParams.psMeMvBuffer->OsResource,
                        CodechalDbgAttr::attrOutput,
                        "MvData",
                        meOutputParams.psMeMvBuffer->dwHeight *meOutputParams.psMeMvBuffer->dwPitch,
                        m_hmeKernel ? m_hmeKernel->Get16xMeMvBottomFieldOffset() : (uint32_t)m_meMv16xBottomFieldOffset,
                        CODECHAL_MEDIA_STATE_16X_ME));

                if (m_32xMeEnabled)
                {
                    meOutputParams.psMeMvBuffer = m_hmeKernel->GetSurface(CodechalKernelHme::SurfaceId::me32xMvDataBuffer);
                    CODECHAL_ENCODE_CHK_STATUS_RETURN(
                        m_debugInterface->DumpBuffer(
                            &meOutputParams.psMeMvBuffer->OsResource,
                            CodechalDbgAttr::attrOutput,
                            "MvData",
                            meOutputParams.psMeMvBuffer->dwHeight *meOutputParams.psMeMvBuffer->dwPitch,
                            m_hmeKernel ? m_hmeKernel->Get32xMeMvBottomFieldOffset() : (uint32_t)m_meMv32xBottomFieldOffset,
                            CODECHAL_MEDIA_STATE_32X_ME));
                }
            }
        }

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
            &BrcBuffers.resBrcImageStatesWriteBuffer,
            CodechalDbgAttr::attrOutput,
            "ImgStateWrite",
            BRC_IMG_STATE_SIZE_PER_PASS * m_hwInterface->GetMfxInterface()->GetBrcNumPakPasses(),
            0,
            CODECHAL_MEDIA_STATE_BRC_UPDATE));

        if (!Mos_ResourceIsNull(&BrcBuffers.sBrcMbQpBuffer.OsResource))
        {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
                &BrcBuffers.sBrcMbQpBuffer.OsResource,
                CodechalDbgAttr::attrOutput,
                "MbQp",
                BrcBuffers.sBrcMbQpBuffer.dwPitch*BrcBuffers.sBrcMbQpBuffer.dwHeight,
                BrcBuffers.dwBrcMbQpBottomFieldOffset,
                CODECHAL_MEDIA_STATE_MB_BRC_UPDATE));
        }
        if (bMbBrcEnabled)
        {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
                &BrcBuffers.resBrcHistoryBuffer,
                CodechalDbgAttr::attrOutput,
                "HistoryWrite",
                m_brcHistoryBufferSize,
                0,
                CODECHAL_MEDIA_STATE_MB_BRC_UPDATE));
        }
        if (BrcBuffers.pMbEncKernelStateInUse)
        {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCurbe(
                CODECHAL_MEDIA_STATE_BRC_UPDATE,
                BrcBuffers.pMbEncKernelStateInUse));
        }
        if (m_mbencBrcBufferSize > 0)
        {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
                &BrcBuffers.resMbEncBrcBuffer,
                CodechalDbgAttr::attrOutput,
                "MbEncBRCWrite",
                m_mbencBrcBufferSize,
                0,
                CODECHAL_MEDIA_STATE_BRC_UPDATE));
        }

        if (m_mbStatsSupported) {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
                &m_resMbStatsBuffer,
                CodechalDbgAttr::attrOutput,
                "MBStatsSurf",
                m_picWidthInMb * m_frameFieldHeightInMb * 16 * sizeof(uint32_t),
                CodecHal_PictureIsBottomField(m_currOriginalPic) ? m_mbStatsBottomFieldOffset : 0,
                CODECHAL_MEDIA_STATE_4X_SCALING));
        }

        else if (m_flatnessCheckEnabled) {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
                &m_flatnessCheckSurface.OsResource,
                CodechalDbgAttr::attrOutput,
                "FlatnessChkSurf",
                ((CodecHal_PictureIsField(m_currOriginalPic)) ? m_flatnessCheckSurface.dwHeight / 2 : m_flatnessCheckSurface.dwHeight) * m_flatnessCheckSurface.dwPitch,
                CodecHal_PictureIsBottomField(m_currOriginalPic) ? (m_flatnessCheckSurface.dwPitch * m_flatnessCheckSurface.dwHeight >> 1) : 0,
                CODECHAL_MEDIA_STATE_4X_SCALING));
        }
        if (bMbQpDataEnabled) {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
                &sMbQpDataSurface.OsResource,
                CodechalDbgAttr::attrInput,
                "MbQp",
                sMbQpDataSurface.dwHeight*sMbQpDataSurface.dwPitch,
                0,
                CODECHAL_MEDIA_STATE_ENC_QUALITY));
        }

        if (bMbSpecificDataEnabled) {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
                &resMbSpecificDataBuffer[m_currRecycledBufIdx],
                CodechalDbgAttr::attrInput,
                "MbSpecificData",
                m_picWidthInMb*m_frameFieldHeightInMb * 16,
                0,
                CODECHAL_MEDIA_STATE_ENC_QUALITY));
        }

        uint8_t       index;
        CODEC_PICTURE refPic;
        if (bUseWeightedSurfaceForL0) {
            refPic = m_avcSliceParams->RefPicList[LIST_0][0];
            index = m_picIdx[refPic.FrameIdx].ucPicIdx;

            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
                &m_refList[index]->sRefBuffer,
                CodechalDbgAttr::attrEncodeRawInputSurface,
                "WP_In_L0"));
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
                &WeightedPredOutputPicSelectList[LIST_0].sBuffer,
                CodechalDbgAttr::attrEncodeRawInputSurface,
                "WP_Out_L0"));

        } if (bUseWeightedSurfaceForL1) {

            refPic = m_avcSliceParams->RefPicList[LIST_1][0];
            index = m_picIdx[refPic.FrameIdx].ucPicIdx;

            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
                &m_refList[index]->sRefBuffer,
                CodechalDbgAttr::attrEncodeRawInputSurface,
                "WP_In_L1"));

            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
                &WeightedPredOutputPicSelectList[LIST_1].sBuffer,
                CodechalDbgAttr::attrEncodeRawInputSurface,
                "WP_Out_L1"));
        }

        if (m_feiEnable) {
            if (m_avcFeiPicParams->bMBQp) {
                CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
                    &m_avcFeiPicParams->resMBQp,
                    CodechalDbgAttr::attrInput,
                    "MbQp",
                    m_picWidthInMb * m_frameFieldHeightInMb + 3,
                    0,
                    CODECHAL_MEDIA_STATE_ENC_QUALITY));
            }
            if (m_avcFeiPicParams->MVPredictorEnable) {
                CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
                    &m_avcFeiPicParams->resMVPredictor,
                    CodechalDbgAttr::attrInput,
                    "MvPredictor",
                    m_picWidthInMb * m_frameFieldHeightInMb * 40,
                    0,
                    CODECHAL_MEDIA_STATE_ENC_QUALITY));
            }
        }
        if (m_arbitraryNumMbsInSlice) {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
                &m_sliceMapSurface[m_currRecycledBufIdx].OsResource,
                CodechalDbgAttr::attrInput,
                "SliceMapSurf",
                m_sliceMapSurface[m_currRecycledBufIdx].dwPitch * m_frameFieldHeightInMb,
                0,
                CODECHAL_MEDIA_STATE_ENC_QUALITY));
        }

        // Dump SW scoreboard surface
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
            &(m_swScoreboardState->GetCurSwScoreboardSurface())->OsResource,
            CodechalDbgAttr::attrOutput,
            "Out",
            (m_swScoreboardState->GetCurSwScoreboardSurface())->dwHeight * (m_swScoreboardState->GetCurSwScoreboardSurface())->dwPitch,
            0,
            CODECHAL_MEDIA_STATE_SW_SCOREBOARD_INIT));)

        return eStatus;
}

MOS_STATUS CodechalEncodeAvcEncG12::PopulateBrcInitParam(
    void *cmd)
{
    CODECHAL_DEBUG_FUNCTION_ENTER;

    CODECHAL_DEBUG_CHK_NULL(m_debugInterface);

    if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDumpEncodePar))
    {
        return MOS_STATUS_SUCCESS;
    }

    CodechalEncodeAvcEncG12::BrcInitResetCurbe *curbe = (CodechalEncodeAvcEncG12::BrcInitResetCurbe *)cmd;

    if (m_pictureCodingType == I_TYPE)
    {
        m_avcPar->MBBRCEnable          = bMbBrcEnabled;
        m_avcPar->MBRC                 = bMbBrcEnabled;
        m_avcPar->BitRate              = curbe->m_brcInitResetCurbeCmd.m_dw3.m_averageBitRate;
        m_avcPar->InitVbvFullnessInBit = curbe->m_brcInitResetCurbeCmd.m_dw1.m_initBufFullInBits;
        m_avcPar->MaxBitRate           = curbe->m_brcInitResetCurbeCmd.m_dw4.m_maxBitRate;
        m_avcPar->VbvSzInBit           = curbe->m_brcInitResetCurbeCmd.m_dw2.m_bufSizeInBits;
        m_avcPar->AvbrAccuracy         = curbe->m_brcInitResetCurbeCmd.m_dw10.m_avbrAccuracy;
        m_avcPar->AvbrConvergence      = curbe->m_brcInitResetCurbeCmd.m_dw11.m_avbrConvergence;
        m_avcPar->SlidingWindowSize    = curbe->m_brcInitResetCurbeCmd.m_dw22.m_slidingWindowSize;
        m_avcPar->LongTermInterval     = curbe->m_brcInitResetCurbeCmd.m_dw24.m_longTermInterval;
    }

    return MOS_STATUS_SUCCESS;
}

MOS_STATUS CodechalEncodeAvcEncG12::PopulateBrcUpdateParam(
    void *cmd)
{
    CODECHAL_DEBUG_FUNCTION_ENTER;

    CODECHAL_DEBUG_CHK_NULL(m_debugInterface);

    if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDumpEncodePar))
    {
        return MOS_STATUS_SUCCESS;
    }

    CodechalEncodeAvcEncG12::FrameBrcUpdateCurbe *curbe = (CodechalEncodeAvcEncG12::FrameBrcUpdateCurbe *)cmd;

    if (m_pictureCodingType == I_TYPE)
    {
        m_avcPar->EnableMultipass     = (curbe->m_frameBrcUpdateCurbeCmd.m_dw5.m_maxNumPAKs > 0) ? 1 : 0;
        m_avcPar->MaxNumPakPasses     = curbe->m_frameBrcUpdateCurbeCmd.m_dw5.m_maxNumPAKs;
        m_avcPar->SlidingWindowEnable = curbe->m_frameBrcUpdateCurbeCmd.m_dw6.m_enableSlidingWindow;
        m_avcPar->FrameSkipEnable     = curbe->m_frameBrcUpdateCurbeCmd.m_dw6.m_enableForceToSkip;
        m_avcPar->UserMaxFrame        = curbe->m_frameBrcUpdateCurbeCmd.m_dw19.m_userMaxFrame;
    }
    else
    {
        m_avcPar->UserMaxFrameP = curbe->m_frameBrcUpdateCurbeCmd.m_dw19.m_userMaxFrame;
    }

    return MOS_STATUS_SUCCESS;
}

MOS_STATUS CodechalEncodeAvcEncG12::PopulateEncParam(
    uint8_t meMethod,
    void    *cmd)
{
    CODECHAL_DEBUG_FUNCTION_ENTER;

    CODECHAL_DEBUG_CHK_NULL(m_debugInterface);

    if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDumpEncodePar))
    {
        return MOS_STATUS_SUCCESS;
    }

    MbencCurbe *curbe = (MbencCurbe *)cmd;

    if (m_pictureCodingType == I_TYPE)
    {
        m_avcPar->MRDisableQPCheck = MRDisableQPCheck[m_targetUsage];
        m_avcPar->AllFractional =
            CODECHAL_ENCODE_AVC_AllFractional_Common[m_targetUsage & 0x7];
        m_avcPar->DisableAllFractionalCheckForHighRes =
            CODECHAL_ENCODE_AVC_DisableAllFractionalCheckForHighRes_Common[m_targetUsage & 0x7];
        m_avcPar->EnableAdaptiveSearch              = curbe->m_curbe.DW37.m_adaptiveEn;
        m_avcPar->EnableFBRBypass                   = curbe->m_curbe.DW4.m_enableFBRBypass;
        m_avcPar->BlockBasedSkip                    = curbe->m_curbe.DW3.m_blockBasedSkipEnable;
        m_avcPar->MADEnableFlag                     = curbe->m_curbe.DW34.m_madEnableFlag;
        m_avcPar->MBTextureThreshold                = curbe->m_curbe.DW60.m_mbTextureThreshold;
        m_avcPar->EnableMBFlatnessCheckOptimization = curbe->m_curbe.DW34.m_enableMBFlatnessChkOptimization;
        m_avcPar->EnableArbitrarySliceSize          = curbe->m_curbe.DW34.m_arbitraryNumMbsPerSlice;
        m_avcPar->RefThresh                         = curbe->m_curbe.DW38.m_refThreshold;
        m_avcPar->EnableWavefrontOptimization       = curbe->m_curbe.DW4.m_enableWavefrontOptimization;
        m_avcPar->MaxLenSP                          = curbe->m_curbe.DW2.m_lenSP;
        m_avcPar->DisableExtendedMvCostRange        = !curbe->m_curbe.DW1.m_extendedMvCostRange;
    }
    else if (m_pictureCodingType == P_TYPE)
    {
        m_avcPar->MEMethod                             = meMethod;
        m_avcPar->HMECombineLen                        = HMECombineLen[m_targetUsage];
        m_avcPar->FTQBasedSkip                         = FTQBasedSkip[m_targetUsage];
        m_avcPar->MultiplePred                         = MultiPred[m_targetUsage];
        m_avcPar->EnableAdaptiveIntraScaling           = bAdaptiveIntraScalingEnable;
        m_avcPar->StaticFrameIntraCostScalingRatioP    = 240;
        m_avcPar->SubPelMode                           = curbe->m_curbe.DW3.m_subPelMode;
        m_avcPar->HMECombineOverlap                    = curbe->m_curbe.DW36.m_hmeCombineOverlap;
        m_avcPar->SearchX                              = curbe->m_curbe.DW5.m_refWidth;
        m_avcPar->SearchY                              = curbe->m_curbe.DW5.m_refHeight;
        m_avcPar->SearchControl                        = curbe->m_curbe.DW3.m_searchCtrl;
        m_avcPar->EnableAdaptiveTxDecision             = curbe->m_curbe.DW34.m_enableAdaptiveTxDecision;
        m_avcPar->TxDecisionThr                        = curbe->m_curbe.DW60.m_txDecisonThreshold;
        m_avcPar->EnablePerMBStaticCheck               = curbe->m_curbe.DW34.m_enablePerMBStaticCheck;
        m_avcPar->EnableAdaptiveSearchWindowSize       = curbe->m_curbe.DW34.m_enableAdaptiveSearchWindowSize;
        m_avcPar->EnableIntraCostScalingForStaticFrame = curbe->m_curbe.DW4.m_enableIntraCostScalingForStaticFrame;
        m_avcPar->BiMixDisable                         = curbe->m_curbe.DW0.m_biMixDis;
        m_avcPar->SurvivedSkipCost                     = (curbe->m_curbe.DW7.m_nonSkipZMvAdded << 1) + curbe->m_curbe.DW7.m_nonSkipModeAdded;
        m_avcPar->UniMixDisable                        = curbe->m_curbe.DW1.m_uniMixDisable;
    }
    else if (m_pictureCodingType == B_TYPE)
    {
        m_avcPar->BMEMethod                         = meMethod;
        m_avcPar->HMEBCombineLen                    = HMEBCombineLen[m_targetUsage];
        m_avcPar->StaticFrameIntraCostScalingRatioB = 200;
        m_avcPar->BSearchX                          = curbe->m_curbe.DW5.m_refWidth;
        m_avcPar->BSearchY                          = curbe->m_curbe.DW5.m_refHeight;
        m_avcPar->BSearchControl                    = curbe->m_curbe.DW3.m_searchCtrl;
        m_avcPar->BSkipType                         = curbe->m_curbe.DW3.m_skipType;
        m_avcPar->DirectMode                        = curbe->m_curbe.DW34.m_bDirectMode;
        m_avcPar->BiWeight                          = curbe->m_curbe.DW1.m_biWeight;
    }

    return MOS_STATUS_SUCCESS;
}

MOS_STATUS CodechalEncodeAvcEncG12::PopulatePakParam(
    PMOS_COMMAND_BUFFER cmdBuffer,
    PMHW_BATCH_BUFFER   secondLevelBatchBuffer)
{
    CODECHAL_DEBUG_FUNCTION_ENTER;

    CODECHAL_DEBUG_CHK_NULL(m_debugInterface);

    if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDumpEncodePar))
    {
        return MOS_STATUS_SUCCESS;
    }

    uint8_t         *data = nullptr;
    MOS_LOCK_PARAMS lockFlags;
    MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
    lockFlags.ReadOnly = 1;

    if (cmdBuffer != nullptr)
    {
        data = (uint8_t*)(cmdBuffer->pCmdPtr - (mhw_vdbox_mfx_g12_X::MFX_AVC_IMG_STATE_CMD::byteSize / sizeof(uint32_t)));
    }
    else if (secondLevelBatchBuffer != nullptr)
    {
        data = secondLevelBatchBuffer->pData;
    }
    else
    {
        data = (uint8_t*)m_osInterface->pfnLockResource(m_osInterface, &BrcBuffers.resBrcImageStatesReadBuffer[m_currRecycledBufIdx], &lockFlags);
    }

    CODECHAL_DEBUG_CHK_NULL(data);

    mhw_vdbox_mfx_g12_X::MFX_AVC_IMG_STATE_CMD mfxCmd;
    mfxCmd = *(mhw_vdbox_mfx_g12_X::MFX_AVC_IMG_STATE_CMD *)(data);

    if (m_pictureCodingType == I_TYPE)
    {
        m_avcPar->TrellisQuantizationEnable         = mfxCmd.DW5.TrellisQuantizationEnabledTqenb;
        m_avcPar->EnableAdaptiveTrellisQuantization = mfxCmd.DW5.TrellisQuantizationEnabledTqenb;
        m_avcPar->TrellisQuantizationRounding       = mfxCmd.DW5.TrellisQuantizationRoundingTqr;
        m_avcPar->TrellisQuantizationChromaDisable  = mfxCmd.DW5.TrellisQuantizationChromaDisableTqchromadisable;
        m_avcPar->ExtendedRhoDomainEn               = mfxCmd.DW17.ExtendedRhodomainStatisticsEnable;
    }

    if (data && (cmdBuffer == nullptr) && (secondLevelBatchBuffer == nullptr))
    {
        m_osInterface->pfnUnlockResource(
            m_osInterface,
            &BrcBuffers.resBrcImageStatesReadBuffer[m_currRecycledBufIdx]);
    }

    return MOS_STATUS_SUCCESS;
}
#endif
