/*
* Copyright (c) 2017-2022, 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.
*/

/*
*  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
*  Use of this source code is governed by a BSD-style license
*  that can be found in the LICENSE file in the root of the source
*  tree. An additional intellectual property rights grant can be found
*  in the file PATENTS.  All contributing project authors may
*  be found in the AUTHORS file in the root of the source tree.
*/

//!
//! \file     codechal_vdenc_vp9_base.cpp
//! \brief    Defines base class for VP9 VDENC encoder.
//!

#include "codechal_vdenc_vp9_base.h"
#include "codechal_mmc_encode_vp9.h"
#include "codec_def_vp9_probs.h"
#include "BRCIF.h"
#include "mos_os_cp_interface_specific.h"

extern const uint8_t Keyframe_Default_Probs[2048] = {
    0x64, 0x42, 0x14, 0x98, 0x0f, 0x65, 0x03, 0x88, 0x25, 0x05, 0x34, 0x0d, 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,
    0xc3, 0x1d, 0xb7, 0x54, 0x31, 0x88, 0x08, 0x2a, 0x47, 0x1f, 0x6b, 0xa9, 0x23, 0x63, 0x9f, 0x11,
    0x52, 0x8c, 0x08, 0x42, 0x72, 0x02, 0x2c, 0x4c, 0x01, 0x13, 0x20, 0x28, 0x84, 0xc9, 0x1d, 0x72,
    0xbb, 0x0d, 0x5b, 0x9d, 0x07, 0x4b, 0x7f, 0x03, 0x3a, 0x5f, 0x01, 0x1c, 0x2f, 0x45, 0x8e, 0xdd,
    0x2a, 0x7a, 0xc9, 0x0f, 0x5b, 0x9f, 0x06, 0x43, 0x79, 0x01, 0x2a, 0x4d, 0x01, 0x11, 0x1f, 0x66,
    0x94, 0xe4, 0x43, 0x75, 0xcc, 0x11, 0x52, 0x9a, 0x06, 0x3b, 0x72, 0x02, 0x27, 0x4b, 0x01, 0x0f,
    0x1d, 0x9c, 0x39, 0xe9, 0x77, 0x39, 0xd4, 0x3a, 0x30, 0xa3, 0x1d, 0x28, 0x7c, 0x0c, 0x1e, 0x51,
    0x03, 0x0c, 0x1f, 0xbf, 0x6b, 0xe2, 0x7c, 0x75, 0xcc, 0x19, 0x63, 0x9b, 0x1d, 0x94, 0xd2, 0x25,
    0x7e, 0xc2, 0x08, 0x5d, 0x9d, 0x02, 0x44, 0x76, 0x01, 0x27, 0x45, 0x01, 0x11, 0x21, 0x29, 0x97,
    0xd5, 0x1b, 0x7b, 0xc1, 0x03, 0x52, 0x90, 0x01, 0x3a, 0x69, 0x01, 0x20, 0x3c, 0x01, 0x0d, 0x1a,
    0x3b, 0x9f, 0xdc, 0x17, 0x7e, 0xc6, 0x04, 0x58, 0x97, 0x01, 0x42, 0x72, 0x01, 0x26, 0x47, 0x01,
    0x12, 0x22, 0x72, 0x88, 0xe8, 0x33, 0x72, 0xcf, 0x0b, 0x53, 0x9b, 0x03, 0x38, 0x69, 0x01, 0x21,
    0x41, 0x01, 0x11, 0x22, 0x95, 0x41, 0xea, 0x79, 0x39, 0xd7, 0x3d, 0x31, 0xa6, 0x1c, 0x24, 0x72,
    0x0c, 0x19, 0x4c, 0x03, 0x10, 0x2a, 0xd6, 0x31, 0xdc, 0x84, 0x3f, 0xbc, 0x2a, 0x41, 0x89, 0x55,
    0x89, 0xdd, 0x68, 0x83, 0xd8, 0x31, 0x6f, 0xc0, 0x15, 0x57, 0x9b, 0x02, 0x31, 0x57, 0x01, 0x10,
    0x1c, 0x59, 0xa3, 0xe6, 0x5a, 0x89, 0xdc, 0x1d, 0x64, 0xb7, 0x0a, 0x46, 0x87, 0x02, 0x2a, 0x51,
    0x01, 0x11, 0x21, 0x6c, 0xa7, 0xed, 0x37, 0x85, 0xde, 0x0f, 0x61, 0xb3, 0x04, 0x48, 0x87, 0x01,
    0x2d, 0x55, 0x01, 0x13, 0x26, 0x7c, 0x92, 0xf0, 0x42, 0x7c, 0xe0, 0x11, 0x58, 0xaf, 0x04, 0x3a,
    0x7a, 0x01, 0x24, 0x4b, 0x01, 0x12, 0x25, 0x8d, 0x4f, 0xf1, 0x7e, 0x46, 0xe3, 0x42, 0x3a, 0xb6,
    0x1e, 0x2c, 0x88, 0x0c, 0x22, 0x60, 0x02, 0x14, 0x2f, 0xe5, 0x63, 0xf9, 0x8f, 0x6f, 0xeb, 0x2e,
    0x6d, 0xc0, 0x52, 0x9e, 0xec, 0x5e, 0x92, 0xe0, 0x19, 0x75, 0xbf, 0x09, 0x57, 0x95, 0x03, 0x38,
    0x63, 0x01, 0x21, 0x39, 0x53, 0xa7, 0xed, 0x44, 0x91, 0xde, 0x0a, 0x67, 0xb1, 0x02, 0x48, 0x83,
    0x01, 0x29, 0x4f, 0x01, 0x14, 0x27, 0x63, 0xa7, 0xef, 0x2f, 0x8d, 0xe0, 0x0a, 0x68, 0xb2, 0x02,
    0x49, 0x85, 0x01, 0x2c, 0x55, 0x01, 0x16, 0x2f, 0x7f, 0x91, 0xf3, 0x47, 0x81, 0xe4, 0x11, 0x5d,
    0xb1, 0x03, 0x3d, 0x7c, 0x01, 0x29, 0x54, 0x01, 0x15, 0x34, 0x9d, 0x4e, 0xf4, 0x8c, 0x48, 0xe7,
    0x45, 0x3a, 0xb8, 0x1f, 0x2c, 0x89, 0x0e, 0x26, 0x69, 0x08, 0x17, 0x3d, 0x7d, 0x22, 0xbb, 0x34,
    0x29, 0x85, 0x06, 0x1f, 0x38, 0x25, 0x6d, 0x99, 0x33, 0x66, 0x93, 0x17, 0x57, 0x80, 0x08, 0x43,
    0x65, 0x01, 0x29, 0x3f, 0x01, 0x13, 0x1d, 0x1f, 0x9a, 0xb9, 0x11, 0x7f, 0xaf, 0x06, 0x60, 0x91,
    0x02, 0x49, 0x72, 0x01, 0x33, 0x52, 0x01, 0x1c, 0x2d, 0x17, 0xa3, 0xc8, 0x0a, 0x83, 0xb9, 0x02,
    0x5d, 0x94, 0x01, 0x43, 0x6f, 0x01, 0x29, 0x45, 0x01, 0x0e, 0x18, 0x1d, 0xb0, 0xd9, 0x0c, 0x91,
    0xc9, 0x03, 0x65, 0x9c, 0x01, 0x45, 0x6f, 0x01, 0x27, 0x3f, 0x01, 0x0e, 0x17, 0x39, 0xc0, 0xe9,
    0x19, 0x9a, 0xd7, 0x06, 0x6d, 0xa7, 0x03, 0x4e, 0x76, 0x01, 0x30, 0x45, 0x01, 0x15, 0x1d, 0xca,
    0x69, 0xf5, 0x6c, 0x6a, 0xd8, 0x12, 0x5a, 0x90, 0x21, 0xac, 0xdb, 0x40, 0x95, 0xce, 0x0e, 0x75,
    0xb1, 0x05, 0x5a, 0x8d, 0x02, 0x3d, 0x5f, 0x01, 0x25, 0x39, 0x21, 0xb3, 0xdc, 0x0b, 0x8c, 0xc6,
    0x01, 0x59, 0x94, 0x01, 0x3c, 0x68, 0x01, 0x21, 0x39, 0x01, 0x0c, 0x15, 0x1e, 0xb5, 0xdd, 0x08,
    0x8d, 0xc6, 0x01, 0x57, 0x91, 0x01, 0x3a, 0x64, 0x01, 0x1f, 0x37, 0x01, 0x0c, 0x14, 0x20, 0xba,
    0xe0, 0x07, 0x8e, 0xc6, 0x01, 0x56, 0x8f, 0x01, 0x3a, 0x64, 0x01, 0x1f, 0x37, 0x01, 0x0c, 0x16,
    0x39, 0xc0, 0xe3, 0x14, 0x8f, 0xcc, 0x03, 0x60, 0x9a, 0x01, 0x44, 0x70, 0x01, 0x2a, 0x45, 0x01,
    0x13, 0x20, 0xd4, 0x23, 0xd7, 0x71, 0x2f, 0xa9, 0x1d, 0x30, 0x69, 0x4a, 0x81, 0xcb, 0x6a, 0x78,
    0xcb, 0x31, 0x6b, 0xb2, 0x13, 0x54, 0x90, 0x04, 0x32, 0x54, 0x01, 0x0f, 0x19, 0x47, 0xac, 0xd9,
    0x2c, 0x8d, 0xd1, 0x0f, 0x66, 0xad, 0x06, 0x4c, 0x85, 0x02, 0x33, 0x59, 0x01, 0x18, 0x2a, 0x40,
    0xb9, 0xe7, 0x1f, 0x94, 0xd8, 0x08, 0x67, 0xaf, 0x03, 0x4a, 0x83, 0x01, 0x2e, 0x51, 0x01, 0x12,
    0x1e, 0x41, 0xc4, 0xeb, 0x19, 0x9d, 0xdd, 0x05, 0x69, 0xae, 0x01, 0x43, 0x78, 0x01, 0x26, 0x45,
    0x01, 0x0f, 0x1e, 0x41, 0xcc, 0xee, 0x1e, 0x9c, 0xe0, 0x07, 0x6b, 0xb1, 0x02, 0x46, 0x7c, 0x01,
    0x2a, 0x49, 0x01, 0x12, 0x22, 0xe1, 0x56, 0xfb, 0x90, 0x68, 0xeb, 0x2a, 0x63, 0xb5, 0x55, 0xaf,
    0xef, 0x70, 0xa5, 0xe5, 0x1d, 0x88, 0xc8, 0x0c, 0x67, 0xa2, 0x06, 0x4d, 0x7b, 0x02, 0x35, 0x54,
    0x4b, 0xb7, 0xef, 0x1e, 0x9b, 0xdd, 0x03, 0x6a, 0xab, 0x01, 0x4a, 0x80, 0x01, 0x2c, 0x4c, 0x01,
    0x11, 0x1c, 0x49, 0xb9, 0xf0, 0x1b, 0x9f, 0xde, 0x02, 0x6b, 0xac, 0x01, 0x4b, 0x7f, 0x01, 0x2a,
    0x49, 0x01, 0x11, 0x1d, 0x3e, 0xbe, 0xee, 0x15, 0x9f, 0xde, 0x02, 0x6b, 0xac, 0x01, 0x48, 0x7a,
    0x01, 0x28, 0x47, 0x01, 0x12, 0x20, 0x3d, 0xc7, 0xf0, 0x1b, 0xa1, 0xe2, 0x04, 0x71, 0xb4, 0x01,
    0x4c, 0x81, 0x01, 0x2e, 0x50, 0x01, 0x17, 0x29, 0x07, 0x1b, 0x99, 0x05, 0x1e, 0x5f, 0x01, 0x10,
    0x1e, 0x32, 0x4b, 0x7f, 0x39, 0x4b, 0x7c, 0x1b, 0x43, 0x6c, 0x0a, 0x36, 0x56, 0x01, 0x21, 0x34,
    0x01, 0x0c, 0x12, 0x2b, 0x7d, 0x97, 0x1a, 0x6c, 0x94, 0x07, 0x53, 0x7a, 0x02, 0x3b, 0x59, 0x01,
    0x26, 0x3c, 0x01, 0x11, 0x1b, 0x17, 0x90, 0xa3, 0x0d, 0x70, 0x9a, 0x02, 0x4b, 0x75, 0x01, 0x32,
    0x51, 0x01, 0x1f, 0x33, 0x01, 0x0e, 0x17, 0x12, 0xa2, 0xb9, 0x06, 0x7b, 0xab, 0x01, 0x4e, 0x7d,
    0x01, 0x33, 0x56, 0x01, 0x1f, 0x36, 0x01, 0x0e, 0x17, 0x0f, 0xc7, 0xe3, 0x03, 0x96, 0xcc, 0x01,
    0x5b, 0x92, 0x01, 0x37, 0x5f, 0x01, 0x1e, 0x35, 0x01, 0x0b, 0x14, 0x13, 0x37, 0xf0, 0x13, 0x3b,
    0xc4, 0x03, 0x34, 0x69, 0x29, 0xa6, 0xcf, 0x68, 0x99, 0xc7, 0x1f, 0x7b, 0xb5, 0x0e, 0x65, 0x98,
    0x05, 0x48, 0x6a, 0x01, 0x24, 0x34, 0x23, 0xb0, 0xd3, 0x0c, 0x83, 0xbe, 0x02, 0x58, 0x90, 0x01,
    0x3c, 0x65, 0x01, 0x24, 0x3c, 0x01, 0x10, 0x1c, 0x1c, 0xb7, 0xd5, 0x08, 0x86, 0xbf, 0x01, 0x56,
    0x8e, 0x01, 0x38, 0x60, 0x01, 0x1e, 0x35, 0x01, 0x0c, 0x14, 0x14, 0xbe, 0xd7, 0x04, 0x87, 0xc0,
    0x01, 0x54, 0x8b, 0x01, 0x35, 0x5b, 0x01, 0x1c, 0x31, 0x01, 0x0b, 0x14, 0x0d, 0xc4, 0xd8, 0x02,
    0x89, 0xc0, 0x01, 0x56, 0x8f, 0x01, 0x39, 0x63, 0x01, 0x20, 0x38, 0x01, 0x0d, 0x18, 0xd3, 0x1d,
    0xd9, 0x60, 0x2f, 0x9c, 0x16, 0x2b, 0x57, 0x4e, 0x78, 0xc1, 0x6f, 0x74, 0xba, 0x2e, 0x66, 0xa4,
    0x0f, 0x50, 0x80, 0x02, 0x31, 0x4c, 0x01, 0x12, 0x1c, 0x47, 0xa1, 0xcb, 0x2a, 0x84, 0xc0, 0x0a,
    0x62, 0x96, 0x03, 0x45, 0x6d, 0x01, 0x2c, 0x46, 0x01, 0x12, 0x1d, 0x39, 0xba, 0xd3, 0x1e, 0x8c,
    0xc4, 0x04, 0x5d, 0x92, 0x01, 0x3e, 0x66, 0x01, 0x26, 0x41, 0x01, 0x10, 0x1b, 0x2f, 0xc7, 0xd9,
    0x0e, 0x91, 0xc4, 0x01, 0x58, 0x8e, 0x01, 0x39, 0x62, 0x01, 0x24, 0x3e, 0x01, 0x0f, 0x1a, 0x1a,
    0xdb, 0xe5, 0x05, 0x9b, 0xcf, 0x01, 0x5e, 0x97, 0x01, 0x3c, 0x68, 0x01, 0x24, 0x3e, 0x01, 0x10,
    0x1c, 0xe9, 0x1d, 0xf8, 0x92, 0x2f, 0xdc, 0x2b, 0x34, 0x8c, 0x64, 0xa3, 0xe8, 0xb3, 0xa1, 0xde,
    0x3f, 0x8e, 0xcc, 0x25, 0x71, 0xae, 0x1a, 0x59, 0x89, 0x12, 0x44, 0x61, 0x55, 0xb5, 0xe6, 0x20,
    0x92, 0xd1, 0x07, 0x64, 0xa4, 0x03, 0x47, 0x79, 0x01, 0x2d, 0x4d, 0x01, 0x12, 0x1e, 0x41, 0xbb,
    0xe6, 0x14, 0x94, 0xcf, 0x02, 0x61, 0x9f, 0x01, 0x44, 0x74, 0x01, 0x28, 0x46, 0x01, 0x0e, 0x1d,
    0x28, 0xc2, 0xe3, 0x08, 0x93, 0xcc, 0x01, 0x5e, 0x9b, 0x01, 0x41, 0x70, 0x01, 0x27, 0x42, 0x01,
    0x0e, 0x1a, 0x10, 0xd0, 0xe4, 0x03, 0x97, 0xcf, 0x01, 0x62, 0xa0, 0x01, 0x43, 0x75, 0x01, 0x29,
    0x4a, 0x01, 0x11, 0x1f, 0x11, 0x26, 0x8c, 0x07, 0x22, 0x50, 0x01, 0x11, 0x1d, 0x25, 0x4b, 0x80,
    0x29, 0x4c, 0x80, 0x1a, 0x42, 0x74, 0x0c, 0x34, 0x5e, 0x02, 0x20, 0x37, 0x01, 0x0a, 0x10, 0x32,
    0x7f, 0x9a, 0x25, 0x6d, 0x98, 0x10, 0x52, 0x79, 0x05, 0x3b, 0x55, 0x01, 0x23, 0x36, 0x01, 0x0d,
    0x14, 0x28, 0x8e, 0xa7, 0x11, 0x6e, 0x9d, 0x02, 0x47, 0x70, 0x01, 0x2c, 0x48, 0x01, 0x1b, 0x2d,
    0x01, 0x0b, 0x11, 0x1e, 0xaf, 0xbc, 0x09, 0x7c, 0xa9, 0x01, 0x4a, 0x74, 0x01, 0x30, 0x4e, 0x01,
    0x1e, 0x31, 0x01, 0x0b, 0x12, 0x0a, 0xde, 0xdf, 0x02, 0x96, 0xc2, 0x01, 0x53, 0x80, 0x01, 0x30,
    0x4f, 0x01, 0x1b, 0x2d, 0x01, 0x0b, 0x11, 0x24, 0x29, 0xeb, 0x1d, 0x24, 0xc1, 0x0a, 0x1b, 0x6f,
    0x55, 0xa5, 0xde, 0xb1, 0xa2, 0xd7, 0x6e, 0x87, 0xc3, 0x39, 0x71, 0xa8, 0x17, 0x53, 0x78, 0x0a,
    0x31, 0x3d, 0x55, 0xbe, 0xdf, 0x24, 0x8b, 0xc8, 0x05, 0x5a, 0x92, 0x01, 0x3c, 0x67, 0x01, 0x26,
    0x41, 0x01, 0x12, 0x1e, 0x48, 0xca, 0xdf, 0x17, 0x8d, 0xc7, 0x02, 0x56, 0x8c, 0x01, 0x38, 0x61,
    0x01, 0x24, 0x3d, 0x01, 0x10, 0x1b, 0x37, 0xda, 0xe1, 0x0d, 0x91, 0xc8, 0x01, 0x56, 0x8d, 0x01,
    0x39, 0x63, 0x01, 0x23, 0x3d, 0x01, 0x0d, 0x16, 0x0f, 0xeb, 0xd4, 0x01, 0x84, 0xb8, 0x01, 0x54,
    0x8b, 0x01, 0x39, 0x61, 0x01, 0x22, 0x38, 0x01, 0x0e, 0x17, 0xb5, 0x15, 0xc9, 0x3d, 0x25, 0x7b,
    0x0a, 0x26, 0x47, 0x2f, 0x6a, 0xac, 0x5f, 0x68, 0xad, 0x2a, 0x5d, 0x9f, 0x12, 0x4d, 0x83, 0x04,
    0x32, 0x51, 0x01, 0x11, 0x17, 0x3e, 0x93, 0xc7, 0x2c, 0x82, 0xbd, 0x1c, 0x66, 0x9a, 0x12, 0x4b,
    0x73, 0x02, 0x2c, 0x41, 0x01, 0x0c, 0x13, 0x37, 0x99, 0xd2, 0x18, 0x82, 0xc2, 0x03, 0x5d, 0x92,
    0x01, 0x3d, 0x61, 0x01, 0x1f, 0x32, 0x01, 0x0a, 0x10, 0x31, 0xba, 0xdf, 0x11, 0x94, 0xcc, 0x01,
    0x60, 0x8e, 0x01, 0x35, 0x53, 0x01, 0x1a, 0x2c, 0x01, 0x0b, 0x11, 0x0d, 0xd9, 0xd4, 0x02, 0x88,
    0xb4, 0x01, 0x4e, 0x7c, 0x01, 0x32, 0x53, 0x01, 0x1d, 0x31, 0x01, 0x0e, 0x17, 0xc5, 0x0d, 0xf7,
    0x52, 0x11, 0xde, 0x19, 0x11, 0xa2, 0x7e, 0xba, 0xf7, 0xea, 0xbf, 0xf3, 0xb0, 0xb1, 0xea, 0x68,
    0x9e, 0xdc, 0x42, 0x80, 0xba, 0x37, 0x5a, 0x89, 0x6f, 0xc5, 0xf2, 0x2e, 0x9e, 0xdb, 0x09, 0x68,
    0xab, 0x02, 0x41, 0x7d, 0x01, 0x2c, 0x50, 0x01, 0x11, 0x5b, 0x68, 0xd0, 0xf5, 0x27, 0xa8, 0xe0,
    0x03, 0x6d, 0xa2, 0x01, 0x4f, 0x7c, 0x01, 0x32, 0x66, 0x01, 0x2b, 0x66, 0x54, 0xdc, 0xf6, 0x1f,
    0xb1, 0xe7, 0x02, 0x73, 0xb4, 0x01, 0x4f, 0x86, 0x01, 0x37, 0x4d, 0x01, 0x3c, 0x4f, 0x2b, 0xf3,
    0xf0, 0x08, 0xb4, 0xd9, 0x01, 0x73, 0xa6, 0x01, 0x54, 0x79, 0x01, 0x33, 0x43, 0x01, 0x10, 0x06,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xc0, 0x80, 0x40, 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, 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, 0x9e, 0x61, 0x5e, 0x5d,
    0x18, 0x63, 0x55, 0x77, 0x2c, 0x3e, 0x3b, 0x43, 0x95, 0x35, 0x35, 0x5e, 0x14, 0x30, 0x53, 0x35,
    0x18, 0x34, 0x12, 0x12, 0x96, 0x28, 0x27, 0x4e, 0x0c, 0x1a, 0x43, 0x21, 0x0b, 0x18, 0x07, 0x05,
    0xae, 0x23, 0x31, 0x44, 0x0b, 0x1b, 0x39, 0x0f, 0x09, 0x0c, 0x03, 0x03, 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,
    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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x90, 0x0b, 0x36, 0x9d, 0xc3, 0x82, 0x2e, 0x3a, 0x6c, 0x76, 0x0f, 0x7b, 0x94, 0x83, 0x65, 0x2c,
    0x5d, 0x83, 0x71, 0x0c, 0x17, 0xbc, 0xe2, 0x8e, 0x1a, 0x20, 0x7d, 0x78, 0x0b, 0x32, 0x7b, 0xa3,
    0x87, 0x40, 0x4d, 0x67, 0x71, 0x09, 0x24, 0x9b, 0x6f, 0x9d, 0x20, 0x2c, 0xa1, 0x74, 0x09, 0x37,
    0xb0, 0x4c, 0x60, 0x25, 0x3d, 0x95, 0x73, 0x09, 0x1c, 0x8d, 0xa1, 0xa7, 0x15, 0x19, 0xc1, 0x78,
    0x0c, 0x20, 0x91, 0xc3, 0x8e, 0x20, 0x26, 0x56, 0x74, 0x0c, 0x40, 0x78, 0x8c, 0x7d, 0x31, 0x73,
    0x79, 0x66, 0x13, 0x42, 0xa2, 0xb6, 0x7a, 0x23, 0x3b, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 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
};

extern const uint8_t Inter_Default_Probs[2048] = {
    0x64, 0x42, 0x14, 0x98, 0x0f, 0x65, 0x03, 0x88, 0x25, 0x05, 0x34, 0x0d, 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,
    0xc3, 0x1d, 0xb7, 0x54, 0x31, 0x88, 0x08, 0x2a, 0x47, 0x1f, 0x6b, 0xa9, 0x23, 0x63, 0x9f, 0x11,
    0x52, 0x8c, 0x08, 0x42, 0x72, 0x02, 0x2c, 0x4c, 0x01, 0x13, 0x20, 0x28, 0x84, 0xc9, 0x1d, 0x72,
    0xbb, 0x0d, 0x5b, 0x9d, 0x07, 0x4b, 0x7f, 0x03, 0x3a, 0x5f, 0x01, 0x1c, 0x2f, 0x45, 0x8e, 0xdd,
    0x2a, 0x7a, 0xc9, 0x0f, 0x5b, 0x9f, 0x06, 0x43, 0x79, 0x01, 0x2a, 0x4d, 0x01, 0x11, 0x1f, 0x66,
    0x94, 0xe4, 0x43, 0x75, 0xcc, 0x11, 0x52, 0x9a, 0x06, 0x3b, 0x72, 0x02, 0x27, 0x4b, 0x01, 0x0f,
    0x1d, 0x9c, 0x39, 0xe9, 0x77, 0x39, 0xd4, 0x3a, 0x30, 0xa3, 0x1d, 0x28, 0x7c, 0x0c, 0x1e, 0x51,
    0x03, 0x0c, 0x1f, 0xbf, 0x6b, 0xe2, 0x7c, 0x75, 0xcc, 0x19, 0x63, 0x9b, 0x1d, 0x94, 0xd2, 0x25,
    0x7e, 0xc2, 0x08, 0x5d, 0x9d, 0x02, 0x44, 0x76, 0x01, 0x27, 0x45, 0x01, 0x11, 0x21, 0x29, 0x97,
    0xd5, 0x1b, 0x7b, 0xc1, 0x03, 0x52, 0x90, 0x01, 0x3a, 0x69, 0x01, 0x20, 0x3c, 0x01, 0x0d, 0x1a,
    0x3b, 0x9f, 0xdc, 0x17, 0x7e, 0xc6, 0x04, 0x58, 0x97, 0x01, 0x42, 0x72, 0x01, 0x26, 0x47, 0x01,
    0x12, 0x22, 0x72, 0x88, 0xe8, 0x33, 0x72, 0xcf, 0x0b, 0x53, 0x9b, 0x03, 0x38, 0x69, 0x01, 0x21,
    0x41, 0x01, 0x11, 0x22, 0x95, 0x41, 0xea, 0x79, 0x39, 0xd7, 0x3d, 0x31, 0xa6, 0x1c, 0x24, 0x72,
    0x0c, 0x19, 0x4c, 0x03, 0x10, 0x2a, 0xd6, 0x31, 0xdc, 0x84, 0x3f, 0xbc, 0x2a, 0x41, 0x89, 0x55,
    0x89, 0xdd, 0x68, 0x83, 0xd8, 0x31, 0x6f, 0xc0, 0x15, 0x57, 0x9b, 0x02, 0x31, 0x57, 0x01, 0x10,
    0x1c, 0x59, 0xa3, 0xe6, 0x5a, 0x89, 0xdc, 0x1d, 0x64, 0xb7, 0x0a, 0x46, 0x87, 0x02, 0x2a, 0x51,
    0x01, 0x11, 0x21, 0x6c, 0xa7, 0xed, 0x37, 0x85, 0xde, 0x0f, 0x61, 0xb3, 0x04, 0x48, 0x87, 0x01,
    0x2d, 0x55, 0x01, 0x13, 0x26, 0x7c, 0x92, 0xf0, 0x42, 0x7c, 0xe0, 0x11, 0x58, 0xaf, 0x04, 0x3a,
    0x7a, 0x01, 0x24, 0x4b, 0x01, 0x12, 0x25, 0x8d, 0x4f, 0xf1, 0x7e, 0x46, 0xe3, 0x42, 0x3a, 0xb6,
    0x1e, 0x2c, 0x88, 0x0c, 0x22, 0x60, 0x02, 0x14, 0x2f, 0xe5, 0x63, 0xf9, 0x8f, 0x6f, 0xeb, 0x2e,
    0x6d, 0xc0, 0x52, 0x9e, 0xec, 0x5e, 0x92, 0xe0, 0x19, 0x75, 0xbf, 0x09, 0x57, 0x95, 0x03, 0x38,
    0x63, 0x01, 0x21, 0x39, 0x53, 0xa7, 0xed, 0x44, 0x91, 0xde, 0x0a, 0x67, 0xb1, 0x02, 0x48, 0x83,
    0x01, 0x29, 0x4f, 0x01, 0x14, 0x27, 0x63, 0xa7, 0xef, 0x2f, 0x8d, 0xe0, 0x0a, 0x68, 0xb2, 0x02,
    0x49, 0x85, 0x01, 0x2c, 0x55, 0x01, 0x16, 0x2f, 0x7f, 0x91, 0xf3, 0x47, 0x81, 0xe4, 0x11, 0x5d,
    0xb1, 0x03, 0x3d, 0x7c, 0x01, 0x29, 0x54, 0x01, 0x15, 0x34, 0x9d, 0x4e, 0xf4, 0x8c, 0x48, 0xe7,
    0x45, 0x3a, 0xb8, 0x1f, 0x2c, 0x89, 0x0e, 0x26, 0x69, 0x08, 0x17, 0x3d, 0x7d, 0x22, 0xbb, 0x34,
    0x29, 0x85, 0x06, 0x1f, 0x38, 0x25, 0x6d, 0x99, 0x33, 0x66, 0x93, 0x17, 0x57, 0x80, 0x08, 0x43,
    0x65, 0x01, 0x29, 0x3f, 0x01, 0x13, 0x1d, 0x1f, 0x9a, 0xb9, 0x11, 0x7f, 0xaf, 0x06, 0x60, 0x91,
    0x02, 0x49, 0x72, 0x01, 0x33, 0x52, 0x01, 0x1c, 0x2d, 0x17, 0xa3, 0xc8, 0x0a, 0x83, 0xb9, 0x02,
    0x5d, 0x94, 0x01, 0x43, 0x6f, 0x01, 0x29, 0x45, 0x01, 0x0e, 0x18, 0x1d, 0xb0, 0xd9, 0x0c, 0x91,
    0xc9, 0x03, 0x65, 0x9c, 0x01, 0x45, 0x6f, 0x01, 0x27, 0x3f, 0x01, 0x0e, 0x17, 0x39, 0xc0, 0xe9,
    0x19, 0x9a, 0xd7, 0x06, 0x6d, 0xa7, 0x03, 0x4e, 0x76, 0x01, 0x30, 0x45, 0x01, 0x15, 0x1d, 0xca,
    0x69, 0xf5, 0x6c, 0x6a, 0xd8, 0x12, 0x5a, 0x90, 0x21, 0xac, 0xdb, 0x40, 0x95, 0xce, 0x0e, 0x75,
    0xb1, 0x05, 0x5a, 0x8d, 0x02, 0x3d, 0x5f, 0x01, 0x25, 0x39, 0x21, 0xb3, 0xdc, 0x0b, 0x8c, 0xc6,
    0x01, 0x59, 0x94, 0x01, 0x3c, 0x68, 0x01, 0x21, 0x39, 0x01, 0x0c, 0x15, 0x1e, 0xb5, 0xdd, 0x08,
    0x8d, 0xc6, 0x01, 0x57, 0x91, 0x01, 0x3a, 0x64, 0x01, 0x1f, 0x37, 0x01, 0x0c, 0x14, 0x20, 0xba,
    0xe0, 0x07, 0x8e, 0xc6, 0x01, 0x56, 0x8f, 0x01, 0x3a, 0x64, 0x01, 0x1f, 0x37, 0x01, 0x0c, 0x16,
    0x39, 0xc0, 0xe3, 0x14, 0x8f, 0xcc, 0x03, 0x60, 0x9a, 0x01, 0x44, 0x70, 0x01, 0x2a, 0x45, 0x01,
    0x13, 0x20, 0xd4, 0x23, 0xd7, 0x71, 0x2f, 0xa9, 0x1d, 0x30, 0x69, 0x4a, 0x81, 0xcb, 0x6a, 0x78,
    0xcb, 0x31, 0x6b, 0xb2, 0x13, 0x54, 0x90, 0x04, 0x32, 0x54, 0x01, 0x0f, 0x19, 0x47, 0xac, 0xd9,
    0x2c, 0x8d, 0xd1, 0x0f, 0x66, 0xad, 0x06, 0x4c, 0x85, 0x02, 0x33, 0x59, 0x01, 0x18, 0x2a, 0x40,
    0xb9, 0xe7, 0x1f, 0x94, 0xd8, 0x08, 0x67, 0xaf, 0x03, 0x4a, 0x83, 0x01, 0x2e, 0x51, 0x01, 0x12,
    0x1e, 0x41, 0xc4, 0xeb, 0x19, 0x9d, 0xdd, 0x05, 0x69, 0xae, 0x01, 0x43, 0x78, 0x01, 0x26, 0x45,
    0x01, 0x0f, 0x1e, 0x41, 0xcc, 0xee, 0x1e, 0x9c, 0xe0, 0x07, 0x6b, 0xb1, 0x02, 0x46, 0x7c, 0x01,
    0x2a, 0x49, 0x01, 0x12, 0x22, 0xe1, 0x56, 0xfb, 0x90, 0x68, 0xeb, 0x2a, 0x63, 0xb5, 0x55, 0xaf,
    0xef, 0x70, 0xa5, 0xe5, 0x1d, 0x88, 0xc8, 0x0c, 0x67, 0xa2, 0x06, 0x4d, 0x7b, 0x02, 0x35, 0x54,
    0x4b, 0xb7, 0xef, 0x1e, 0x9b, 0xdd, 0x03, 0x6a, 0xab, 0x01, 0x4a, 0x80, 0x01, 0x2c, 0x4c, 0x01,
    0x11, 0x1c, 0x49, 0xb9, 0xf0, 0x1b, 0x9f, 0xde, 0x02, 0x6b, 0xac, 0x01, 0x4b, 0x7f, 0x01, 0x2a,
    0x49, 0x01, 0x11, 0x1d, 0x3e, 0xbe, 0xee, 0x15, 0x9f, 0xde, 0x02, 0x6b, 0xac, 0x01, 0x48, 0x7a,
    0x01, 0x28, 0x47, 0x01, 0x12, 0x20, 0x3d, 0xc7, 0xf0, 0x1b, 0xa1, 0xe2, 0x04, 0x71, 0xb4, 0x01,
    0x4c, 0x81, 0x01, 0x2e, 0x50, 0x01, 0x17, 0x29, 0x07, 0x1b, 0x99, 0x05, 0x1e, 0x5f, 0x01, 0x10,
    0x1e, 0x32, 0x4b, 0x7f, 0x39, 0x4b, 0x7c, 0x1b, 0x43, 0x6c, 0x0a, 0x36, 0x56, 0x01, 0x21, 0x34,
    0x01, 0x0c, 0x12, 0x2b, 0x7d, 0x97, 0x1a, 0x6c, 0x94, 0x07, 0x53, 0x7a, 0x02, 0x3b, 0x59, 0x01,
    0x26, 0x3c, 0x01, 0x11, 0x1b, 0x17, 0x90, 0xa3, 0x0d, 0x70, 0x9a, 0x02, 0x4b, 0x75, 0x01, 0x32,
    0x51, 0x01, 0x1f, 0x33, 0x01, 0x0e, 0x17, 0x12, 0xa2, 0xb9, 0x06, 0x7b, 0xab, 0x01, 0x4e, 0x7d,
    0x01, 0x33, 0x56, 0x01, 0x1f, 0x36, 0x01, 0x0e, 0x17, 0x0f, 0xc7, 0xe3, 0x03, 0x96, 0xcc, 0x01,
    0x5b, 0x92, 0x01, 0x37, 0x5f, 0x01, 0x1e, 0x35, 0x01, 0x0b, 0x14, 0x13, 0x37, 0xf0, 0x13, 0x3b,
    0xc4, 0x03, 0x34, 0x69, 0x29, 0xa6, 0xcf, 0x68, 0x99, 0xc7, 0x1f, 0x7b, 0xb5, 0x0e, 0x65, 0x98,
    0x05, 0x48, 0x6a, 0x01, 0x24, 0x34, 0x23, 0xb0, 0xd3, 0x0c, 0x83, 0xbe, 0x02, 0x58, 0x90, 0x01,
    0x3c, 0x65, 0x01, 0x24, 0x3c, 0x01, 0x10, 0x1c, 0x1c, 0xb7, 0xd5, 0x08, 0x86, 0xbf, 0x01, 0x56,
    0x8e, 0x01, 0x38, 0x60, 0x01, 0x1e, 0x35, 0x01, 0x0c, 0x14, 0x14, 0xbe, 0xd7, 0x04, 0x87, 0xc0,
    0x01, 0x54, 0x8b, 0x01, 0x35, 0x5b, 0x01, 0x1c, 0x31, 0x01, 0x0b, 0x14, 0x0d, 0xc4, 0xd8, 0x02,
    0x89, 0xc0, 0x01, 0x56, 0x8f, 0x01, 0x39, 0x63, 0x01, 0x20, 0x38, 0x01, 0x0d, 0x18, 0xd3, 0x1d,
    0xd9, 0x60, 0x2f, 0x9c, 0x16, 0x2b, 0x57, 0x4e, 0x78, 0xc1, 0x6f, 0x74, 0xba, 0x2e, 0x66, 0xa4,
    0x0f, 0x50, 0x80, 0x02, 0x31, 0x4c, 0x01, 0x12, 0x1c, 0x47, 0xa1, 0xcb, 0x2a, 0x84, 0xc0, 0x0a,
    0x62, 0x96, 0x03, 0x45, 0x6d, 0x01, 0x2c, 0x46, 0x01, 0x12, 0x1d, 0x39, 0xba, 0xd3, 0x1e, 0x8c,
    0xc4, 0x04, 0x5d, 0x92, 0x01, 0x3e, 0x66, 0x01, 0x26, 0x41, 0x01, 0x10, 0x1b, 0x2f, 0xc7, 0xd9,
    0x0e, 0x91, 0xc4, 0x01, 0x58, 0x8e, 0x01, 0x39, 0x62, 0x01, 0x24, 0x3e, 0x01, 0x0f, 0x1a, 0x1a,
    0xdb, 0xe5, 0x05, 0x9b, 0xcf, 0x01, 0x5e, 0x97, 0x01, 0x3c, 0x68, 0x01, 0x24, 0x3e, 0x01, 0x10,
    0x1c, 0xe9, 0x1d, 0xf8, 0x92, 0x2f, 0xdc, 0x2b, 0x34, 0x8c, 0x64, 0xa3, 0xe8, 0xb3, 0xa1, 0xde,
    0x3f, 0x8e, 0xcc, 0x25, 0x71, 0xae, 0x1a, 0x59, 0x89, 0x12, 0x44, 0x61, 0x55, 0xb5, 0xe6, 0x20,
    0x92, 0xd1, 0x07, 0x64, 0xa4, 0x03, 0x47, 0x79, 0x01, 0x2d, 0x4d, 0x01, 0x12, 0x1e, 0x41, 0xbb,
    0xe6, 0x14, 0x94, 0xcf, 0x02, 0x61, 0x9f, 0x01, 0x44, 0x74, 0x01, 0x28, 0x46, 0x01, 0x0e, 0x1d,
    0x28, 0xc2, 0xe3, 0x08, 0x93, 0xcc, 0x01, 0x5e, 0x9b, 0x01, 0x41, 0x70, 0x01, 0x27, 0x42, 0x01,
    0x0e, 0x1a, 0x10, 0xd0, 0xe4, 0x03, 0x97, 0xcf, 0x01, 0x62, 0xa0, 0x01, 0x43, 0x75, 0x01, 0x29,
    0x4a, 0x01, 0x11, 0x1f, 0x11, 0x26, 0x8c, 0x07, 0x22, 0x50, 0x01, 0x11, 0x1d, 0x25, 0x4b, 0x80,
    0x29, 0x4c, 0x80, 0x1a, 0x42, 0x74, 0x0c, 0x34, 0x5e, 0x02, 0x20, 0x37, 0x01, 0x0a, 0x10, 0x32,
    0x7f, 0x9a, 0x25, 0x6d, 0x98, 0x10, 0x52, 0x79, 0x05, 0x3b, 0x55, 0x01, 0x23, 0x36, 0x01, 0x0d,
    0x14, 0x28, 0x8e, 0xa7, 0x11, 0x6e, 0x9d, 0x02, 0x47, 0x70, 0x01, 0x2c, 0x48, 0x01, 0x1b, 0x2d,
    0x01, 0x0b, 0x11, 0x1e, 0xaf, 0xbc, 0x09, 0x7c, 0xa9, 0x01, 0x4a, 0x74, 0x01, 0x30, 0x4e, 0x01,
    0x1e, 0x31, 0x01, 0x0b, 0x12, 0x0a, 0xde, 0xdf, 0x02, 0x96, 0xc2, 0x01, 0x53, 0x80, 0x01, 0x30,
    0x4f, 0x01, 0x1b, 0x2d, 0x01, 0x0b, 0x11, 0x24, 0x29, 0xeb, 0x1d, 0x24, 0xc1, 0x0a, 0x1b, 0x6f,
    0x55, 0xa5, 0xde, 0xb1, 0xa2, 0xd7, 0x6e, 0x87, 0xc3, 0x39, 0x71, 0xa8, 0x17, 0x53, 0x78, 0x0a,
    0x31, 0x3d, 0x55, 0xbe, 0xdf, 0x24, 0x8b, 0xc8, 0x05, 0x5a, 0x92, 0x01, 0x3c, 0x67, 0x01, 0x26,
    0x41, 0x01, 0x12, 0x1e, 0x48, 0xca, 0xdf, 0x17, 0x8d, 0xc7, 0x02, 0x56, 0x8c, 0x01, 0x38, 0x61,
    0x01, 0x24, 0x3d, 0x01, 0x10, 0x1b, 0x37, 0xda, 0xe1, 0x0d, 0x91, 0xc8, 0x01, 0x56, 0x8d, 0x01,
    0x39, 0x63, 0x01, 0x23, 0x3d, 0x01, 0x0d, 0x16, 0x0f, 0xeb, 0xd4, 0x01, 0x84, 0xb8, 0x01, 0x54,
    0x8b, 0x01, 0x39, 0x61, 0x01, 0x22, 0x38, 0x01, 0x0e, 0x17, 0xb5, 0x15, 0xc9, 0x3d, 0x25, 0x7b,
    0x0a, 0x26, 0x47, 0x2f, 0x6a, 0xac, 0x5f, 0x68, 0xad, 0x2a, 0x5d, 0x9f, 0x12, 0x4d, 0x83, 0x04,
    0x32, 0x51, 0x01, 0x11, 0x17, 0x3e, 0x93, 0xc7, 0x2c, 0x82, 0xbd, 0x1c, 0x66, 0x9a, 0x12, 0x4b,
    0x73, 0x02, 0x2c, 0x41, 0x01, 0x0c, 0x13, 0x37, 0x99, 0xd2, 0x18, 0x82, 0xc2, 0x03, 0x5d, 0x92,
    0x01, 0x3d, 0x61, 0x01, 0x1f, 0x32, 0x01, 0x0a, 0x10, 0x31, 0xba, 0xdf, 0x11, 0x94, 0xcc, 0x01,
    0x60, 0x8e, 0x01, 0x35, 0x53, 0x01, 0x1a, 0x2c, 0x01, 0x0b, 0x11, 0x0d, 0xd9, 0xd4, 0x02, 0x88,
    0xb4, 0x01, 0x4e, 0x7c, 0x01, 0x32, 0x53, 0x01, 0x1d, 0x31, 0x01, 0x0e, 0x17, 0xc5, 0x0d, 0xf7,
    0x52, 0x11, 0xde, 0x19, 0x11, 0xa2, 0x7e, 0xba, 0xf7, 0xea, 0xbf, 0xf3, 0xb0, 0xb1, 0xea, 0x68,
    0x9e, 0xdc, 0x42, 0x80, 0xba, 0x37, 0x5a, 0x89, 0x6f, 0xc5, 0xf2, 0x2e, 0x9e, 0xdb, 0x09, 0x68,
    0xab, 0x02, 0x41, 0x7d, 0x01, 0x2c, 0x50, 0x01, 0x11, 0x5b, 0x68, 0xd0, 0xf5, 0x27, 0xa8, 0xe0,
    0x03, 0x6d, 0xa2, 0x01, 0x4f, 0x7c, 0x01, 0x32, 0x66, 0x01, 0x2b, 0x66, 0x54, 0xdc, 0xf6, 0x1f,
    0xb1, 0xe7, 0x02, 0x73, 0xb4, 0x01, 0x4f, 0x86, 0x01, 0x37, 0x4d, 0x01, 0x3c, 0x4f, 0x2b, 0xf3,
    0xf0, 0x08, 0xb4, 0xd9, 0x01, 0x73, 0xa6, 0x01, 0x54, 0x79, 0x01, 0x33, 0x43, 0x01, 0x10, 0x06,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xc0, 0x80, 0x40, 0x02, 0xad, 0x22, 0x07, 0x91, 0x55, 0x07, 0xa6, 0x3f, 0x07, 0x5e, 0x42, 0x08,
    0x40, 0x2e, 0x11, 0x51, 0x1f, 0x19, 0x1d, 0x1e, 0xeb, 0xa2, 0x24, 0xff, 0x22, 0x03, 0x95, 0x90,
    0x09, 0x66, 0xbb, 0xe1, 0xef, 0xb7, 0x77, 0x60, 0x29, 0x21, 0x10, 0x4d, 0x4a, 0x8e, 0x8e, 0xac,
    0xaa, 0xee, 0xf7, 0x32, 0x7e, 0x7b, 0xdd, 0xe2, 0x41, 0x20, 0x12, 0x90, 0xa2, 0xc2, 0x29, 0x33,
    0x62, 0x84, 0x44, 0x12, 0xa5, 0xd9, 0xc4, 0x2d, 0x28, 0x4e, 0xad, 0x50, 0x13, 0xb0, 0xf0, 0xc1,
    0x40, 0x23, 0x2e, 0xdd, 0x87, 0x26, 0xc2, 0xf8, 0x79, 0x60, 0x55, 0x1d, 0xc7, 0x7a, 0x8d, 0x93,
    0x3f, 0x9f, 0x94, 0x85, 0x76, 0x79, 0x68, 0x72, 0xae, 0x49, 0x57, 0x5c, 0x29, 0x53, 0x52, 0x63,
    0x32, 0x35, 0x27, 0x27, 0xb1, 0x3a, 0x3b, 0x44, 0x1a, 0x3f, 0x34, 0x4f, 0x19, 0x11, 0x0e, 0x0c,
    0xde, 0x22, 0x1e, 0x48, 0x10, 0x2c, 0x3a, 0x20, 0x0c, 0x0a, 0x07, 0x06, 0x20, 0x40, 0x60, 0x80,
    0xe0, 0x90, 0xc0, 0xa8, 0xc0, 0xb0, 0xc0, 0xc6, 0xc6, 0xf5, 0xd8, 0x88, 0x8c, 0x94, 0xa0, 0xb0,
    0xc0, 0xe0, 0xea, 0xea, 0xf0, 0x80, 0xd8, 0x80, 0xb0, 0xa0, 0xb0, 0xb0, 0xc0, 0xc6, 0xc6, 0xd0,
    0xd0, 0x88, 0x8c, 0x94, 0xa0, 0xb0, 0xc0, 0xe0, 0xea, 0xea, 0xf0, 0x80, 0x80, 0x40, 0x60, 0x70,
    0x40, 0x40, 0x60, 0x40, 0x80, 0x80, 0x40, 0x60, 0x70, 0x40, 0x40, 0x60, 0x40, 0xa0, 0x80, 0xa0,
    0x80, 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,
    0x78, 0x07, 0x4c, 0xb0, 0xd0, 0x7e, 0x1c, 0x36, 0x67, 0x30, 0x0c, 0x9a, 0x9b, 0x8b, 0x5a, 0x22,
    0x75, 0x77, 0x43, 0x06, 0x19, 0xcc, 0xf3, 0x9e, 0x0d, 0x15, 0x60, 0x61, 0x05, 0x2c, 0x83, 0xb0,
    0x8b, 0x30, 0x44, 0x61, 0x53, 0x05, 0x2a, 0x9c, 0x6f, 0x98, 0x1a, 0x31, 0x98, 0x50, 0x05, 0x3a,
    0xb2, 0x4a, 0x53, 0x21, 0x3e, 0x91, 0x56, 0x05, 0x20, 0x9a, 0xc0, 0xa8, 0x0e, 0x16, 0xa3, 0x55,
    0x05, 0x20, 0x9c, 0xd8, 0x94, 0x13, 0x1d, 0x49, 0x4d, 0x07, 0x40, 0x74, 0x84, 0x7a, 0x25, 0x7e,
    0x78, 0x65, 0x15, 0x6b, 0xb5, 0xc0, 0x67, 0x13, 0x43, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 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
};

// loop filter value based on qp index look up table
extern const uint8_t LF_VALUE_QP_LOOKUP[CODEC_VP9_QINDEX_RANGE] = {
    0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03,
    0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07,
    0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
    0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a,
    0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e,
    0x0e, 0x0f, 0x0f, 0x0f, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13,
    0x13, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x16, 0x16, 0x17, 0x17, 0x17, 0x18, 0x18, 0x18, 0x19,
    0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, 0x1e, 0x1f,
    0x1f, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x25,
    0x26, 0x26, 0x27, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x29, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c,
    0x2c, 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30, 0x31, 0x31, 0x31, 0x32, 0x32,
    0x32, 0x33, 0x33, 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x37, 0x37, 0x37, 0x38,
    0x38, 0x39, 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3d, 0x3d,
    0x3d, 0x3e, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
    0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
    0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f
};

constexpr int8_t CodechalVdencVp9State::m_instRateThresholdI[CodechalVdencVp9State::m_numInstRateThresholds];
constexpr int8_t CodechalVdencVp9State::m_instRateThresholdP[CodechalVdencVp9State::m_numInstRateThresholds];
constexpr double CodechalVdencVp9State::m_devThresholdFpNegI[CodechalVdencVp9State::m_numDevThresholds / 2];
constexpr double CodechalVdencVp9State::m_devThresholdFpPosI[CodechalVdencVp9State::m_numDevThresholds / 2];
constexpr double CodechalVdencVp9State::m_devThresholdFpNegPB[CodechalVdencVp9State::m_numDevThresholds / 2];
constexpr double CodechalVdencVp9State::m_devThresholdFpPosPB[CodechalVdencVp9State::m_numDevThresholds / 2];
constexpr double CodechalVdencVp9State::m_devThresholdVbrNeg[CodechalVdencVp9State::m_numDevThresholds / 2];
constexpr double CodechalVdencVp9State::m_devThresholdVbrPos[CodechalVdencVp9State::m_numDevThresholds / 2];

const uint32_t CodechalVdencVp9State::m_vdencMeCurbeInit[48] =
{
    0x00000000, 0x00200010, 0x00003939, 0x77a43000, 0x00000000, 0x28300000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000200,
    0x00000000, 0x00000000, 0x00000000, 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
};

const uint32_t CodechalVdencVp9State::m_brcInitDmem[48] =
{
    0x00000000, 0x00038400, 0x00030D40, 0x000C3500, 0x00061A80, 0x00061A80, 0x00000000, 0x0000001E,
    0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x270F0020, 0x02800000, 0x00010168,
    0x000000FF, 0x0000000E, 0x00000073, 0x00000000, 0x00000000, 0x7846321E, 0x7846321E, 0x735A321E,
    0xE5DFD8D1, 0x2F29211B, 0xE5DDD7D1, 0x5E56463F, 0xEAE3DAD4, 0x2F281F16, 0x01007488, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
};

const uint32_t CodechalVdencVp9State::m_brcUpdateDmem[64] =
{
    0x00061A80, 0x00000000, 0x0007A120, 0x000493E0, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x0032000A, 0x00960064, 0x01680280, 0x02200000, 0x007802B8,
    0x00000000, 0x00000000, 0x00000000, 0x02032000, 0xB4785028, 0x67614B28, 0x0101A07D, 0x28010203,
    0x01030505, 0x00FEFCFA, 0x04060402, 0x78503C1E, 0x00FFC88C, 0x503C1E04, 0xFFC88C78, 0x28140200,
    0xC8A08246, 0x090800FF, 0x040C0B0A, 0x07060605, 0x06060504, 0xFB650007, 0xFB0501FF, 0x000501FE,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
};

const uint32_t CodechalVdencVp9State::m_probDmem[320] =
{
    0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000100, 0x00000000, 0x00000000,
    0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
    0x00000004, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x01000000, 0x0000FF00, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001,
    0x00540049, 0x00000060, 0x00000072, 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, 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, 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, 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, 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,
    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, 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, 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, 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, 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, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x02B80078, 0x00000001, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
};

const uint32_t CodechalVdencVp9State::m_brcConstData[2][416] =
{
    // I Frame
    {
        0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x32191900, 0x00264B4B, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x0E0A0602, 0x06040212, 0x00000E0A, 0x00080402, 0x04020000, 0x000000FE, 0xFEFCFA02, 0xF8F60000,
        0xF200FEFC, 0xFEFCF8F4, 0xFCF6F2EE, 0x0A0402FE, 0x04021410, 0x00100C08, 0x0C080402, 0x02000000,
        0x0000FE04, 0xFEFC0200, 0xFA0000FE, 0x00FEFEFC, 0xFEFCFAF6, 0xF8F4F200, 0x0402FEFC, 0x0214100A,
        0x100C0804, 0x08040200, 0x0000000C, 0x00FE0402, 0xFC020000, 0x0000FEFE, 0xFEFEFCFA, 0xFCFAF600,
        0xF4F200FE, 0x00FEFCF8, 0x00000000, 0x14100C08, 0x00000000, 0x0E0A0600, 0x0000FE12, 0x08060000,
        0xFEFC0E0C, 0x02000000, 0xFA0A0604, 0x0000FEFC, 0x0A060200, 0x00FEFCF8, 0x06020000, 0xFCFAF60A,
        0x020000FE, 0xF8F40A06, 0x0000FEFC, 0xF40A0602, 0x00FEFCF8, 0x0A060200, 0x00000000, 0x0E0A0600,
        0x00000012, 0x0A060000, 0x00FE100C, 0x06000000, 0xFC100E0A, 0x000000FE, 0x0C0A0804, 0x00FEFCFA,
        0x08020000, 0xFEFCF80A, 0x02000000, 0xFCF80A08, 0x0000FEFE, 0xF80A0800, 0x00FEFCFA, 0x0A020000,
        0xFEFCF8F6, 0x02000000, 0x00000008, 0x0A060000, 0x0000120E, 0x06000000, 0xFE100C0A, 0x00000000,
        0x100E0A06, 0x0000FEFC, 0x0A080400, 0xFEFCFA0C, 0x02000000, 0xFCF80A08, 0x000000FE, 0xF80A0802,
        0x00FEFEFC, 0x0A080000, 0xFEFCFAF8, 0x02000000, 0xFCF8F60A, 0x000000FE, 0x00000802, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
    },
    // P Frame
    {
        0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
        0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
        0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
        0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
        0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
        0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
        0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
        0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
        0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
        0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
        0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
        0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
        0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
        0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
        0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
        0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
        0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
        0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
        0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
        0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
        0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
        0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
        0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
        0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
        0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
        0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
        0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
        0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
        0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
        0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
        0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
        0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
        0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
        0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
        0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
        0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
        0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626,
        0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904,
        0x0B0B001E, 0x0000000B, 0x13194B0D, 0x1F5E2626, 0x19321F4B, 0x1E1E1904, 0x0B0B001E, 0x0000000B,
        0x0E0A0602, 0x06040212, 0x00000E0A, 0x00080402, 0x04020000, 0x000000FE, 0xFEFCFA02, 0xF8F60000,
        0xF200FEFC, 0xFEFCF8F4, 0xFCF6F2EE, 0x0A0402FE, 0x04021410, 0x00100C08, 0x0C080402, 0x02000000,
        0x0000FE04, 0xFEFC0200, 0xFA0000FE, 0x00FEFEFC, 0xFEFCFAF6, 0xF8F4F200, 0x0402FEFC, 0x0214100A,
        0x100C0804, 0x08040200, 0x0000000C, 0x00FE0402, 0xFC020000, 0x0000FEFE, 0xFEFEFCFA, 0xFCFAF600,
        0xF4F200FE, 0x00FEFCF8, 0x00000000, 0x14100C08, 0x00000000, 0x0E0A0600, 0x0000FE12, 0x08060000,
        0xFEFC0E0C, 0x02000000, 0xFA0A0604, 0x0000FEFC, 0x0A060200, 0x00FEFCF8, 0x06020000, 0xFCFAF60A,
        0x020000FE, 0xF8F40A06, 0x0000FEFC, 0xF40A0602, 0x00FEFCF8, 0x0A060200, 0x00000000, 0x0E0A0600,
        0x00000012, 0x0A060000, 0x00FE100C, 0x06000000, 0xFC100E0A, 0x000000FE, 0x0C0A0804, 0x00FEFCFA,
        0x08020000, 0xFEFCF80A, 0x02000000, 0xFCF80A08, 0x0000FEFE, 0xF80A0800, 0x00FEFCFA, 0x0A020000,
        0xFEFCF8F6, 0x02000000, 0x00000008, 0x0A060000, 0x0000120E, 0x06000000, 0xFE100C0A, 0x00000000,
        0x100E0A06, 0x0000FEFC, 0x0A080400, 0xFEFCFA0C, 0x02000000, 0xFCF80A08, 0x000000FE, 0xF80A0802,
        0x00FEFEFC, 0x0A080000, 0xFEFCFAF8, 0x02000000, 0xFCF8F60A, 0x000000FE, 0x00000802, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
    }
};

const uint32_t CodechalVdencVp9State::m_samplerFilterCoeffs[32][6] = {
    {0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x00004000, 0x00004000},
    {0x40fe01ff, 0x0001ff02, 0x40fe01ff, 0x0001ff02, 0x000140ff, 0x000140ff},
    {0x41fc02ff, 0xff01fe04, 0x41fc02ff, 0xff01fe04, 0x00033ffe, 0x00033ffe},
    {0x3ffb03ff, 0xff02fd06, 0x3ffb03ff, 0xff02fd06, 0x00053efd, 0x00053efd},
    {0x40f903fe, 0xff02fc09, 0x40f903fe, 0xff02fc09, 0x00063efc, 0x00063efc},
    {0x3ff804fe, 0xfe03fb0b, 0x3ff804fe, 0xfe03fb0b, 0x00083cfc, 0x00083cfc},
    {0x3ef705fd, 0xfe03fa0e, 0x3ef705fd, 0xfe03fa0e, 0xff0a3cfb, 0xff0a3cfb},
    {0x3df505fd, 0xfe04f911, 0x3df505fd, 0xfe04f911, 0xff0d39fb, 0xff0d39fb},
    {0x3bf506fd, 0xfd04f814, 0x3bf506fd, 0xfd04f814, 0xff0f37fb, 0xff0f37fb},
    {0x3bf406fc, 0xfd05f716, 0x3bf406fc, 0xfd05f716, 0xff1135fb, 0xff1135fb},
    {0x39f307fc, 0xfd05f619, 0x39f307fc, 0xfd05f619, 0xfe1433fb, 0xfe1433fb},
    {0x37f307fc, 0xfc06f51c, 0x37f307fc, 0xfc06f51c, 0xfe1631fb, 0xfe1631fb},
    {0x35f207fc, 0xfc06f51f, 0x35f207fc, 0xfc06f51f, 0xfe192efb, 0xfe192efb},
    {0x32f207fc, 0xfc07f422, 0x32f207fc, 0xfc07f422, 0xfd1c2cfb, 0xfd1c2cfb},
    {0x30f207fc, 0xfc07f325, 0x30f207fc, 0xfc07f325, 0xfd1f29fb, 0xfd1f29fb},
    {0x2df207fc, 0xfc07f328, 0x2df207fc, 0xfc07f328, 0xfc2127fc, 0xfc2127fc},
    {0x29f307fc, 0xfc07f32b, 0x29f307fc, 0xfc07f32b, 0xfc2424fc, 0xfc2424fc},
    {0x28f307fc, 0xfc07f22d, 0x28f307fc, 0xfc07f22d, 0xfc2721fc, 0xfc2721fc},
    {0x25f307fc, 0xfc07f230, 0x25f307fc, 0xfc07f230, 0xfb291ffd, 0xfb291ffd},
    {0x22f407fc, 0xfc07f232, 0x22f407fc, 0xfc07f232, 0xfb2c1cfd, 0xfb2c1cfd},
    {0x1ff506fc, 0xfc07f235, 0x1ff506fc, 0xfc07f235, 0xfb2e19fe, 0xfb2e19fe},
    {0x1cf506fc, 0xfc07f337, 0x1cf506fc, 0xfc07f337, 0xfb3116fe, 0xfb3116fe},
    {0x19f605fd, 0xfc07f339, 0x19f605fd, 0xfc07f339, 0xfb3314fe, 0xfb3314fe},
    {0x16f705fd, 0xfc06f43b, 0x16f705fd, 0xfc06f43b, 0xfb3511ff, 0xfb3511ff},
    {0x14f804fd, 0xfd06f53b, 0x14f804fd, 0xfd06f53b, 0xfb370fff, 0xfb370fff},
    {0x11f904fe, 0xfd05f53d, 0x11f904fe, 0xfd05f53d, 0xfb390dff, 0xfb390dff},
    {0x0efa03fe, 0xfd05f73e, 0x0efa03fe, 0xfd05f73e, 0xfb3c0aff, 0xfb3c0aff},
    {0x0bfb03fe, 0xfe04f83f, 0x0bfb03fe, 0xfe04f83f, 0xfc3c0800, 0xfc3c0800},
    {0x09fc02ff, 0xfe03f940, 0x09fc02ff, 0xfe03f940, 0xfc3e0600, 0xfc3e0600},
    {0x06fd02ff, 0xff03fb3f, 0x06fd02ff, 0xff03fb3f, 0xfd3e0500, 0xfd3e0500},
    {0x04fe01ff, 0xff02fc41, 0x04fe01ff, 0xff02fc41, 0xfe3f0300, 0xfe3f0300},
    {0x02ff0100, 0xff01fe40, 0x02ff0100, 0xff01fe40, 0xff400100, 0xff400100}
};

MOS_STATUS CodechalVdencVp9State::CalculateRePakThresholds()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    int32_t repakSavingThreshold = 0;
    if (m_prevFrameInfo.FrameWidth != m_oriFrameWidth ||
        m_prevFrameInfo.FrameHeight != m_oriFrameHeight)
    {
        switch (m_vp9SeqParams->TargetUsage)
        {
        case TU_QUALITY:
        case 2: 
            repakSavingThreshold = 2;
            break;
        case TU_PERFORMANCE:
            repakSavingThreshold = 80;
            break;
        default:  // normal settings
            repakSavingThreshold = 10;
            break;
        }

        int32_t scale = (m_oriFrameWidth * m_oriFrameHeight) / (176 * 144);
        if (!scale)
        {
            scale = 1;
        }

        for (auto i = 0; i < CODEC_VP9_QINDEX_RANGE; i += 1)
        {
            double tempQp = i - 144.0;

            int32_t b = (int32_t)(92.5 * i);
            int32_t c = (int32_t)(1.6 * tempQp * tempQp);
            int32_t d = (int32_t)(0.01 * tempQp * tempQp * tempQp);
            int32_t threshold = (int32_t)((18630 - b + c - d) / 10);
            int32_t calculatedRepakSavingThreshold = repakSavingThreshold * scale;

            // To avoid overflow of the integer threshold, it must be (RepakSavingThreshold * scale) <= CODEC_VP9_MAX_REPAK_THRESHOLD
            if (calculatedRepakSavingThreshold > CODEC_VP9_MAX_REPAK_THRESHOLD)
            {
                calculatedRepakSavingThreshold = CODEC_VP9_MAX_REPAK_THRESHOLD;
            }
            m_rePakThreshold[i] = calculatedRepakSavingThreshold * threshold;
        }
    }

    return eStatus;
}

//------------------------------------------------------------------------------
//| Purpose:    Calculate Normalized Denominator for VP9 BRC Curbe Setup
//|             based on LCM of provided framerates denominators
//| Return:     uint32_t
//------------------------------------------------------------------------------
uint32_t CodechalVdencVp9State::CalculateNormalizedDenominator(
    FRAME_RATE* frameRates,
    uint16_t numberOfLayers,
    uint32_t normalizedDenominator)
{
    CODECHAL_ENCODE_FUNCTION_ENTER;

    // If pointer to the list of FrameRates is null, return the current Normalized Denominator.
    if (!frameRates)
    {
        return normalizedDenominator;
    }

    if (numberOfLayers == 0)
    {
        return normalizedDenominator;
    }

    normalizedDenominator = normalizedDenominator * frameRates[numberOfLayers - 1].uiDenominator / MosUtilities::MosGCD(normalizedDenominator, frameRates[numberOfLayers - 1].uiDenominator);

    return CalculateNormalizedDenominator(frameRates, numberOfLayers - 1, normalizedDenominator);
}

//------------------------------------------------------------------------------
//| Purpose:    Calculate the max level ratios for temporal scalability
//| Return:     STATUS via return & max level ratios inside of maxLevelRatios
//------------------------------------------------------------------------------
MOS_STATUS CodechalVdencVp9State::CalculateTemporalRatios(
    uint16_t numberOfLayers,
    uint32_t maxTemporalBitrate,
    FRAME_RATE maxTemporalFrameRate,
    uint8_t* maxLevelRatios)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(maxLevelRatios);

    if (numberOfLayers <= 1)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Need to have multiple temporal layers to calculate ratios");
        return MOS_STATUS_INVALID_PARAMETER;
    }

    if (numberOfLayers > CODECHAL_ENCODE_VP9_MAX_NUM_TEMPORAL_LAYERS)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("VP9 VDEnc supports only %d temporal layers (%d provided)",
            CODECHAL_ENCODE_VP9_MAX_NUM_TEMPORAL_LAYERS, numberOfLayers);
        return MOS_STATUS_INVALID_PARAMETER;
    }

    if (!maxTemporalBitrate || !maxTemporalFrameRate.uiDenominator)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Invalid bitrate or framerate provided to calculate ratios");
        return MOS_STATUS_INVALID_PARAMETER;
    }

    // calculate normalized denominator as least common multiplier of all layers denominators
    uint32_t normalizedDenominator = 1;
    normalizedDenominator          = CalculateNormalizedDenominator(m_vp9SeqParams->FrameRate, numberOfLayers, normalizedDenominator);

    // calculate 0 layer framerate multiplier and apply it
    FRAME_RATE currentLayerFrameRate = m_vp9SeqParams->FrameRate[0];
    uint32_t frameRateMultiplier = normalizedDenominator / currentLayerFrameRate.uiDenominator;
    currentLayerFrameRate.uiNumerator *= frameRateMultiplier;
    currentLayerFrameRate.uiDenominator *= frameRateMultiplier;

    uint32_t currentLayerBitrate = m_vp9SeqParams->TargetBitRate[0] * CODECHAL_ENCODE_BRC_KBPS;
    maxLevelRatios[0] = (currentLayerBitrate << 6) / maxTemporalBitrate * currentLayerFrameRate.uiDenominator / maxTemporalFrameRate.uiDenominator *
        maxTemporalFrameRate.uiNumerator / currentLayerFrameRate.uiNumerator;

    for (auto i = 1; i < numberOfLayers; ++i)
    {
        // per ddi
        // framerate and bitrate are provided on asceding order
        // 0 indexed is base player properties (bitrate and framerate)
        // 1 indexed is first layer properties including layer below (which is base)
        // so on, every current layer properties values include current and all previous layers properties values

        // extract actual layer bitrate
        currentLayerBitrate = m_vp9SeqParams->TargetBitRate[i] * CODECHAL_ENCODE_BRC_KBPS - m_vp9SeqParams->TargetBitRate[i - 1] * CODECHAL_ENCODE_BRC_KBPS;

        // extract actual layer framerate
        currentLayerFrameRate.uiNumerator   = m_vp9SeqParams->FrameRate[i].uiNumerator * (normalizedDenominator / m_vp9SeqParams->FrameRate[i].uiDenominator) - m_vp9SeqParams->FrameRate[i - 1].uiNumerator * (normalizedDenominator / m_vp9SeqParams->FrameRate[i - 1].uiDenominator);
        currentLayerFrameRate.uiDenominator = normalizedDenominator;

        // based on hardware behavior calculate ratio
        // current layer bitrate is in unit of 1 / 64
        // 64 is just a number to represent a range or temporal bitrate for different layers
        // for ex: 22,22,20 means each layer splits in the ratio of 22/64, 22/64 and 20/64 in terms of bitrate that needs to be achieved
        maxLevelRatios[i] = (currentLayerBitrate << 6) / maxTemporalBitrate * currentLayerFrameRate.uiDenominator / maxTemporalFrameRate.uiDenominator *
            maxTemporalFrameRate.uiNumerator / currentLayerFrameRate.uiNumerator;
    }

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::ConstructPicStateBatchBuf(
    PMOS_RESOURCE picStateBuffer)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(picStateBuffer);

    CODECHAL_ENCODE_CHK_NULL_RETURN(m_hucCmdInitializer);

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hucCmdInitializer->CommandInitializerSetVp9Params(this));

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

    if (!m_singleTaskPhaseSupported || m_firstTaskInPhase)
    {
        // Send command buffer header at the beginning (OS dependent)
        bool requestFrameTracking = m_singleTaskPhaseSupported ? m_firstTaskInPhase : 0;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(&cmdBuffer, requestFrameTracking));
        m_firstTaskInPhase = false;
    }

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hucCmdInitializer->CmdInitializerVp9Execute(&cmdBuffer, picStateBuffer));

    MOS_LOCK_PARAMS lockFlagsWriteOnly;
    MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
    lockFlagsWriteOnly.WriteOnly = 1;
    uint8_t* data = (uint8_t*)m_osInterface->pfnLockResource(m_osInterface, picStateBuffer, &lockFlagsWriteOnly);
    CODECHAL_ENCODE_CHK_NULL_RETURN(data);

    MOS_COMMAND_BUFFER constructedCmdBuf;
    MOS_ZeroMemory(&constructedCmdBuf, sizeof(constructedCmdBuf));
    constructedCmdBuf.pCmdBase  = (uint32_t *)data;
    constructedCmdBuf.pCmdPtr   = (uint32_t *)data;
    constructedCmdBuf.iOffset   = 0;
    constructedCmdBuf.iRemaining = m_vdencPicStateSecondLevelBatchBufferSize;

    // HCP_VP9_PIC_STATE
    MHW_VDBOX_VP9_ENCODE_PIC_STATE picState;
    MOS_ZeroMemory(&picState, sizeof(picState));
    picState.pVp9PicParams                    = m_vp9PicParams;
    picState.pVp9SeqParams                    = m_vp9SeqParams;
    picState.ppVp9RefList                     = &(m_refList[0]);
    picState.PrevFrameParams.fields.KeyFrame  = m_prevFrameInfo.KeyFrame;
    picState.PrevFrameParams.fields.IntraOnly = m_prevFrameInfo.IntraOnly;
    picState.PrevFrameParams.fields.Display   = m_prevFrameInfo.ShowFrame;
    picState.dwPrevFrmWidth                   = m_prevFrameInfo.FrameWidth;
    picState.dwPrevFrmHeight                  = m_prevFrameInfo.FrameHeight;
    picState.ucTxMode                        = m_txMode;
    picState.bSSEEnable                      = m_vdencBrcEnabled;
    picState.bUseDysRefSurface               = (m_dysRefFrameFlags != DYS_REF_NONE) && m_dysVdencMultiPassEnabled;
    picState.bVdencPakOnlyPassFlag           = m_vdencPakonlyMultipassEnabled;
    picState.uiMaxBitRate                     = m_vp9SeqParams->MaxBitRate * CODECHAL_ENCODE_BRC_KBPS;
    picState.uiMinBitRate                     = m_vp9SeqParams->MinBitRate * CODECHAL_ENCODE_BRC_KBPS;
    constructedCmdBuf.iOffset += m_cmd1Size;
    m_hucPicStateOffset = (uint16_t)constructedCmdBuf.iOffset;
    constructedCmdBuf.pCmdPtr += constructedCmdBuf.iOffset/sizeof(uint32_t);
    eStatus = m_hcpInterface->AddHcpVp9PicStateEncCmd(&constructedCmdBuf, nullptr, &picState);
    if (eStatus != MOS_STATUS_SUCCESS)
    {
        m_osInterface->pfnUnlockResource(m_osInterface,picStateBuffer);
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to add HCP_VP9_PIC_STATE command.");
        return eStatus;
    }

    // HCP_VP9_SEGMENT_STATE
    MHW_VDBOX_VP9_SEGMENT_STATE segmentState;
    MOS_ZeroMemory(&segmentState, sizeof(segmentState));
    segmentState.Mode                    = m_mode;
    segmentState.pVp9EncodeSegmentParams = m_vp9SegmentParams;
    uint8_t segmentCount                 = (m_vp9PicParams->PicFlags.fields.segmentation_enabled) ? CODEC_VP9_MAX_SEGMENTS : 1;

    for (uint8_t i = 0; i < segmentCount; i++)
    {
        segmentState.ucCurrentSegmentId = i;
        eStatus = m_hcpInterface->AddHcpVp9SegmentStateCmd(&constructedCmdBuf, nullptr, &segmentState);
        if (eStatus != MOS_STATUS_SUCCESS)
        {
            m_osInterface->pfnUnlockResource(m_osInterface,picStateBuffer);
            CODECHAL_ENCODE_ASSERTMESSAGE("Failed to add MHW_VDBOX_VP9_SEGMENT_STATE command.");
            return eStatus;
        }
    }

    // Adjust cmd buffer offset to have 8 segment state blocks
    if (segmentCount < CODEC_VP9_MAX_SEGMENTS)
    {
        // Max 7 segments, 32 bytes each
        uint8_t zeroBlock[m_segmentStateBlockSize * (CODEC_VP9_MAX_SEGMENTS - 1)];
        MOS_ZeroMemory(zeroBlock, sizeof(zeroBlock));
        Mhw_AddCommandCmdOrBB(m_osInterface, &constructedCmdBuf, nullptr, zeroBlock, (CODEC_VP9_MAX_SEGMENTS - segmentCount) * m_segmentStateBlockSize);
    }
    m_slbbImgStateOffset = (uint16_t)constructedCmdBuf.iOffset;
    constructedCmdBuf.iOffset += m_cmd2Size;
    constructedCmdBuf.pCmdPtr += m_cmd2Size/ sizeof(uint32_t);

    // BB_END
    eStatus = m_miInterface->AddMiBatchBufferEnd(&constructedCmdBuf, nullptr);
    if (eStatus != MOS_STATUS_SUCCESS)
    {
        m_osInterface->pfnUnlockResource(m_osInterface,picStateBuffer);
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to add MI Batch Buffer End command.");
        return eStatus;
    }
    m_hucSlbbSize = (uint16_t)constructedCmdBuf.iOffset;

    m_osInterface->pfnUnlockResource(m_osInterface,picStateBuffer);

    return eStatus;
}

uint8_t CodechalVdencVp9State::GetReferenceBufferSlotIndex(uint8_t refreshFlags)
{
    // even if there could be multiple reference frames in the buffer
    // but here we only retrieve the one which has the smallest index

    if (refreshFlags == 0)
    {
        return 0;
    }

    refreshFlags = ~refreshFlags;

    uint8_t refSlotIndex = 0;
    while (refreshFlags & 1)
    {
        refreshFlags >>= 1;
        refSlotIndex++;
    }

    return refSlotIndex;
}

MOS_STATUS CodechalVdencVp9State::SetDmemHuCVp9Prob()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    MOS_LOCK_PARAMS lockFlagsWriteOnly;
    MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
    lockFlagsWriteOnly.WriteOnly = 1;

    HucProbDmem* dmem = nullptr;
    HucProbDmem* dmemTemp = nullptr;
    int currPass = GetCurrentPass();
    if (IsFirstPass())
    {
        for (auto i = 0; i < 3; i++)
        {
            dmem = (HucProbDmem *)m_osInterface->pfnLockResource(
                m_osInterface, &m_resHucProbDmemBuffer[i][m_currRecycledBufIdx], &lockFlagsWriteOnly);
            CODECHAL_ENCODE_CHK_NULL_RETURN(dmem);

            if (i == 0)
            {
                dmemTemp = dmem;
            }

            MOS_SecureMemcpy(dmem, sizeof(HucProbDmem),
                m_probDmem, sizeof(HucProbDmem));

            if (i != 0)
            {
                CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(m_osInterface, &m_resHucProbDmemBuffer[i][m_currRecycledBufIdx]));
                dmem = dmemTemp;
            }
        }
    }
    else
    {
        dmem = (HucProbDmem *)m_osInterface->pfnLockResource(
            m_osInterface, &m_resHucProbDmemBuffer[currPass][m_currRecycledBufIdx], &lockFlagsWriteOnly);
        CODECHAL_ENCODE_CHK_NULL_RETURN(dmem);
    }

    // for BRC cases, HuC needs to be called on Pass 1
    if (m_superFrameHucPass)
    {
        dmem->HuCPassNum = CODECHAL_ENCODE_VP9_HUC_SUPERFRAME_PASS;
    }
    else
    {
        if (m_dysBrc)
        {
            //For BRC+Dynamic Scaling, we need to run as HUC pass 1 in the last pass since the curr_pass was changed to 0.
            dmem->HuCPassNum = currPass != 0;
        }
        else
        {
            //For Non-dynamic scaling BRC cases, HuC needs to run as HuC pass one only in last pass.
            dmem->HuCPassNum = ((m_vdencBrcEnabled && currPass == 1) ? 0 : (currPass != 0));
        }
    }

    dmem->FrameWidth  = m_oriFrameWidth;
    dmem->FrameHeight = m_oriFrameHeight;

    for (auto i = 0; i < CODEC_VP9_MAX_SEGMENTS; i++)
    {
        dmem->SegmentRef[i]  = (m_vp9SegmentParams->SegData[i].SegmentFlags.fields.SegmentReferenceEnabled == true) ? m_vp9SegmentParams->SegData[i].SegmentFlags.fields.SegmentReference : CODECHAL_ENCODE_VP9_REF_SEGMENT_DISABLED;
        dmem->SegmentSkip[i] = m_vp9SegmentParams->SegData[i].SegmentFlags.fields.SegmentSkipped;
    }

    if (m_vp9PicParams->PicFlags.fields.frame_type == CODEC_VP9_KEY_FRAME && m_currPass == 0)
    {
        for (auto i = 1; i < CODEC_VP9_NUM_CONTEXTS; i++)
        {
            uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(
                m_osInterface,
                &m_resProbBuffer[i],
                &lockFlagsWriteOnly);

            CODECHAL_ENCODE_CHK_NULL_RETURN(data);

            ContextBufferInit(data, 0);
            CtxBufDiffInit(data, 0);

            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
                m_osInterface,
                &m_resProbBuffer[i]));
        }
    }

    // in multipasses, only delta seg qp (SegCodeAbs = 0) is supported, confirmed by the arch team
    dmem->SegCodeAbs                     = 0;
    dmem->SegTemporalUpdate              = m_vp9PicParams->PicFlags.fields.segmentation_temporal_update;
    dmem->LastRefIndex                   = m_vp9PicParams->RefFlags.fields.LastRefIdx;
    dmem->GoldenRefIndex                 = m_vp9PicParams->RefFlags.fields.GoldenRefIdx;
    dmem->AltRefIndex                    = m_vp9PicParams->RefFlags.fields.AltRefIdx;
    dmem->RefreshFrameFlags              = m_vp9PicParams->RefFlags.fields.refresh_frame_flags;
    dmem->RefFrameFlags                  = m_refFrameFlags;
    dmem->ContextFrameTypes              = m_contextFrameTypes[m_vp9PicParams->PicFlags.fields.frame_context_idx];
    dmem->FrameToShow                    = GetReferenceBufferSlotIndex(dmem->RefreshFrameFlags);

    dmem->FrameCtrl.FrameType            = m_vp9PicParams->PicFlags.fields.frame_type;
    dmem->FrameCtrl.ShowFrame            = m_vp9PicParams->PicFlags.fields.show_frame;
    dmem->FrameCtrl.ErrorResilientMode   = m_vp9PicParams->PicFlags.fields.error_resilient_mode;
    dmem->FrameCtrl.IntraOnly            = m_vp9PicParams->PicFlags.fields.intra_only;
    dmem->FrameCtrl.ContextReset         = m_vp9PicParams->PicFlags.fields.reset_frame_context;
    dmem->FrameCtrl.LastRefFrameBias     = m_vp9PicParams->RefFlags.fields.LastRefSignBias;
    dmem->FrameCtrl.GoldenRefFrameBias   = m_vp9PicParams->RefFlags.fields.GoldenRefSignBias;
    dmem->FrameCtrl.AltRefFrameBias      = m_vp9PicParams->RefFlags.fields.AltRefSignBias;
    dmem->FrameCtrl.AllowHighPrecisionMv = m_vp9PicParams->PicFlags.fields.allow_high_precision_mv;
    dmem->FrameCtrl.McompFilterMode      = m_vp9PicParams->PicFlags.fields.mcomp_filter_type;
    dmem->FrameCtrl.TxMode               = m_txMode;
    dmem->FrameCtrl.RefreshFrameContext  = m_vp9PicParams->PicFlags.fields.refresh_frame_context;
    dmem->FrameCtrl.FrameParallelDecode  = m_vp9PicParams->PicFlags.fields.frame_parallel_decoding_mode;
    dmem->FrameCtrl.CompPredMode         = m_vp9PicParams->PicFlags.fields.comp_prediction_mode;
    dmem->FrameCtrl.FrameContextIdx      = m_vp9PicParams->PicFlags.fields.frame_context_idx;
    dmem->FrameCtrl.SharpnessLevel       = m_vp9PicParams->sharpness_level;
    dmem->FrameCtrl.SegOn                = m_vp9PicParams->PicFlags.fields.segmentation_enabled;
    dmem->FrameCtrl.SegMapUpdate         = m_vp9PicParams->PicFlags.fields.segmentation_update_map;
    dmem->FrameCtrl.SegUpdateData        = m_vp9PicParams->PicFlags.fields.seg_update_data;
    dmem->StreamInSegEnable              = (uint8_t)m_segmentMapProvided;
    dmem->StreamInEnable                 = (uint8_t)m_segmentMapProvided; // Currently unused, if used may || with HME enabled

    dmem->FrameCtrl.log2TileRows = m_vp9PicParams->log2_tile_rows;
    dmem->FrameCtrl.log2TileCols = m_vp9PicParams->log2_tile_columns;

    dmem->PrevFrameInfo = m_prevFrameInfo;
    // For DyS CQP or BRC case there is no Repak on last pass. So disable the Repak flag here
    // We also disable repak pass in TU7 speed mode usage for performance reasons.
    if (m_dysVdencMultiPassEnabled)
    {
        dmem->RePak = (m_numPasses > 0 && IsLastPass() && !(m_dysCqp || m_dysBrc) && (m_vp9SeqParams->TargetUsage != TU_PERFORMANCE));
    }
    else
    {
        dmem->RePak = (m_numPasses > 0 && IsLastPass() && (m_vp9SeqParams->TargetUsage != TU_PERFORMANCE));
    }
    if (dmem->RePak && m_adaptiveRepakSupported)
    {
        MOS_SecureMemcpy(dmem->RePakThreshold, sizeof(uint32_t) * CODEC_VP9_QINDEX_RANGE, m_rePakThreshold, sizeof(uint32_t) * CODEC_VP9_QINDEX_RANGE);
    }

    dmem->LFLevelBitOffset           = m_vp9PicParams->BitOffsetForLFLevel;
    dmem->QIndexBitOffset            = m_vp9PicParams->BitOffsetForQIndex;
    dmem->SegBitOffset               = m_vp9PicParams->BitOffsetForSegmentation + 1;  // exclude segment_enable bit
    dmem->SegLengthInBits            = m_vp9PicParams->BitSizeForSegmentation - 1;    // exclude segment_enable bit
    dmem->UnCompHdrTotalLengthInBits = m_vp9PicParams->BitOffsetForFirstPartitionSize + 16;
    dmem->PicStateOffset = m_hucPicStateOffset;
    dmem->SLBBSize = m_hucSlbbSize;
    dmem->IVFHeaderSize = (m_frameNum == 0) ? 44 : 12;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(m_osInterface, &m_resHucProbDmemBuffer[currPass][m_currRecycledBufIdx]));

    return eStatus;
}

/*----------------------------------------------------------------------------
| Name      : StoreHuCStatus2Register
| Purpose   : Store HUC_STATUS2 register bit 6 before HUC_Start command
|             BitField: VALID IMEM LOADED - This bit will be cleared by HW at the end of a HUC workload
|
| Returns   : MOS_STATUS
\---------------------------------------------------------------------------*/
MOS_STATUS CodechalVdencVp9State::StoreHuCStatus2Register(
    PMOS_COMMAND_BUFFER cmdBuffer)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    // Write HUC_STATUS2 mask - bit 6 - valid IMEM loaded
    MHW_MI_STORE_DATA_PARAMS storeDataParams;
    MOS_ZeroMemory(&storeDataParams, sizeof(storeDataParams));
    storeDataParams.pOsResource = &m_resHucStatus2Buffer;
    storeDataParams.dwResourceOffset = 0;
    storeDataParams.dwValue = m_hucInterface->GetHucStatus2ImemLoadedMask();
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(cmdBuffer, &storeDataParams));

    // Store HUC_STATUS2 register
    MHW_MI_STORE_REGISTER_MEM_PARAMS storeRegParams;
    MOS_ZeroMemory(&storeRegParams, sizeof(storeRegParams));
    storeRegParams.presStoreBuffer = &m_resHucStatus2Buffer;
    storeRegParams.dwOffset = sizeof(uint32_t);
    storeRegParams.dwRegister = m_hucInterface->GetMmioRegisters(m_vdboxIndex)->hucStatus2RegOffset;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &storeRegParams));

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::StoreHucErrorStatus(MmioRegistersHuc *mmioRegisters, PMOS_COMMAND_BUFFER cmdBuffer, bool addToEncodeStatus)
{
    // Write Huc Error Flag mask: DW1 (mask value)
    MHW_MI_STORE_DATA_PARAMS storeDataParams;
    MOS_ZeroMemory(&storeDataParams, sizeof(storeDataParams));
    storeDataParams.pOsResource      = &m_resHucErrorStatusBuffer;
    storeDataParams.dwResourceOffset = sizeof(uint32_t);
    storeDataParams.dwValue          = CODECHAL_VDENC_VP9_BRC_HUC_STATUS_MEMORY_ACCESS_ERROR_MASK;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(cmdBuffer, &storeDataParams));

    // store HUC_STATUS register: DW0 (actual value)
    MHW_MI_STORE_REGISTER_MEM_PARAMS storeRegParams;
    MOS_ZeroMemory(&storeRegParams, sizeof(storeRegParams));
    storeRegParams.presStoreBuffer = &m_resHucErrorStatusBuffer;
    storeRegParams.dwOffset        = 0;
    storeRegParams.dwRegister      = mmioRegisters->hucStatusRegOffset;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &storeRegParams));

    if (addToEncodeStatus)
    {
        EncodeStatusBuffer encodeStatusBuf = m_encodeStatusBuf;

        uint32_t baseOffset =
            (encodeStatusBuf.wCurrIndex * encodeStatusBuf.dwReportSize) + sizeof(uint32_t) * 2;  // pEncodeStatus is offset by 2 DWs in the resource

        // store HUC_STATUS register
        MHW_MI_STORE_REGISTER_MEM_PARAMS storeRegParams;
        MOS_ZeroMemory(&storeRegParams, sizeof(storeRegParams));
        storeRegParams.presStoreBuffer = &encodeStatusBuf.resStatusBuffer;
        storeRegParams.dwOffset        = baseOffset + encodeStatusBuf.dwHuCStatusRegOffset;
        storeRegParams.dwRegister      = mmioRegisters->hucStatusRegOffset;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(
            cmdBuffer,
            &storeRegParams));
    }

    return MOS_STATUS_SUCCESS;
}

MOS_STATUS CodechalVdencVp9State::HuCVp9Prob()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_DEBUG_TOOL(
        uint32_t hucRegionSize[16] = { 0 };
        const char* hucRegionName[16] = {"\0"};

        hucRegionName[0] = "_UpdatedProbBuffer";   // hucRegionName[0] is used to dump region 0 after HuC is run, which has updated probabilities. Input Region 0 is dumped separetely before HuC.
        hucRegionSize[0] = 32 * CODECHAL_CACHELINE_SIZE;
        hucRegionName[1] = "_CountersBuffer";
        hucRegionSize[1] = 193 * CODECHAL_CACHELINE_SIZE;
        hucRegionName[2] = "_ProbBuffer";
        hucRegionSize[2] = 32 * CODECHAL_CACHELINE_SIZE;
        hucRegionName[3] = "_ProbDeltaBuffer";
        hucRegionSize[3] = 29 * CODECHAL_CACHELINE_SIZE;
        hucRegionName[4] = "_UncompressedHdr";
        hucRegionSize[4] = CODECHAL_ENCODE_VP9_PAK_INSERT_UNCOMPRESSED_HEADER;
        hucRegionName[5] = "_CompressedHdr";
        hucRegionSize[5] = 32 * CODECHAL_CACHELINE_SIZE;
        hucRegionName[6] = "_SecondLevelBatchBuffer";
        hucRegionSize[6] = m_vdencPicStateSecondLevelBatchBufferSize;
        hucRegionName[7] = "_SecondLevelBatchBuffer";
        hucRegionSize[7] = m_vdencPicStateSecondLevelBatchBufferSize;
        hucRegionName[8] = "_UncompressedHdr";
        hucRegionSize[8] = CODECHAL_ENCODE_VP9_PAK_INSERT_UNCOMPRESSED_HEADER;
        hucRegionName[9] = "_DefaultProbs";
        hucRegionSize[9] = sizeof(Keyframe_Default_Probs)+sizeof(Inter_Default_Probs);
        hucRegionName[10] = "_SuperFrameBuffer";
        hucRegionSize[10] = CODECHAL_ENCODE_VP9_BRC_SUPER_FRAME_BUFFER_SIZE;
        hucRegionName[11] = "_DataExtension";
        hucRegionSize[11] = CODECHAL_ENCODE_VP9_VDENC_DATA_EXTENSION_SIZE;
    )

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

    if (!m_singleTaskPhaseSupported || m_firstTaskInPhase)
    {
        bool requestFrameTracking = false;

        // 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, false));

        m_firstTaskInPhase = false;
    }

    // load kernel from WOPCM into L2 storage RAM
    MHW_VDBOX_HUC_IMEM_STATE_PARAMS imemParams;
    MOS_ZeroMemory(&imemParams, sizeof(imemParams));
    imemParams.dwKernelDescriptor = m_vdboxHucVp9VdencProbKernelDescriptor;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hucInterface->AddHucImemStateCmd(&cmdBuffer, &imemParams));

    // pipe mode select
    MHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams;
    pipeModeSelectParams.Mode = m_mode;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hucInterface->AddHucPipeModeSelectCmd(&cmdBuffer, &pipeModeSelectParams));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(SetDmemHuCVp9Prob());
    int currPass = GetCurrentPass();
    MHW_VDBOX_HUC_DMEM_STATE_PARAMS dmemParams;
    MOS_ZeroMemory(&dmemParams, sizeof(dmemParams));
    dmemParams.presHucDataSource = &m_resHucProbDmemBuffer[m_currPass][m_currRecycledBufIdx];
    dmemParams.dwDataLength = MOS_ALIGN_CEIL(sizeof(HucProbDmem), CODECHAL_CACHELINE_SIZE);
    dmemParams.dwDmemOffset = HUC_DMEM_OFFSET_RTOS_GEMS;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hucInterface->AddHucDmemStateCmd(&cmdBuffer, &dmemParams));

    // Add Virtual addr
    MHW_VDBOX_HUC_VIRTUAL_ADDR_PARAMS virtualAddrParams;
    MOS_ZeroMemory(&virtualAddrParams, sizeof(virtualAddrParams));
    // Input regions
    virtualAddrParams.regionParams[0].presRegion = &m_resProbBuffer[m_vp9PicParams->PicFlags.fields.frame_context_idx];
    virtualAddrParams.regionParams[0].isWritable = true;        // Region 0 is both read and write for HuC. Has input probabilities before running HuC and updated probabilities after running HuC, which will then be input to next pass
    virtualAddrParams.regionParams[1].presRegion = &m_resProbabilityCounterBuffer;
    virtualAddrParams.regionParams[7].presRegion = m_vdencBrcEnabled ? &m_resVdencPictureState2NdLevelBatchBufferWrite[m_vdencPictureState2ndLevelBBIndex] : &m_resVdencPictureState2NdLevelBatchBufferRead[m_currPass][m_vdencPictureState2ndLevelBBIndex];
    virtualAddrParams.regionParams[8].presRegion = &m_resHucPakInsertUncompressedHeaderReadBuffer[m_currRecycledBufIdx];
    virtualAddrParams.regionParams[9].presRegion = &m_resHucDefaultProbBuffer;

    // Output regions
    virtualAddrParams.regionParams[2].presRegion  = &m_resHucProbOutputBuffer;  // Final probability output from HuC after each pass
    virtualAddrParams.regionParams[2].isWritable = true;
    virtualAddrParams.regionParams[3].presRegion  = &m_resProbabilityDeltaBuffer;
    virtualAddrParams.regionParams[3].isWritable = true;
    virtualAddrParams.regionParams[4].presRegion  = &m_resHucPakInsertUncompressedHeaderWriteBuffer;
    virtualAddrParams.regionParams[4].isWritable = true;
    virtualAddrParams.regionParams[5].presRegion  = &m_resCompressedHeaderBuffer;
    virtualAddrParams.regionParams[5].isWritable = true;
    virtualAddrParams.regionParams[6].presRegion  = &m_resVdencPictureState2NdLevelBatchBufferWrite[m_vdencPictureState2ndLevelBBIndex];
    virtualAddrParams.regionParams[6].isWritable = true;
    virtualAddrParams.regionParams[10].presRegion = &m_resBitstreamBuffer;
    virtualAddrParams.regionParams[10].isWritable = true;
    virtualAddrParams.regionParams[11].presRegion = &m_resVdencDataExtensionBuffer;
    virtualAddrParams.regionParams[11].isWritable = true;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hucInterface->AddHucVirtualAddrStateCmd(&cmdBuffer, &virtualAddrParams));
    // Store HUC_STATUS2 register bit 6 before HUC_Start command
    // BitField: VALID IMEM LOADED - This bit will be cleared by HW at the end of a HUC workload
    // (HUC_Start command with last start bit set).
    CODECHAL_DEBUG_TOOL(
        CODECHAL_ENCODE_CHK_STATUS_RETURN(StoreHuCStatus2Register(&cmdBuffer));
    )

    CODECHAL_ENCODE_CHK_STATUS_RETURN(StoreHuCStatus2Report(&cmdBuffer));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hucInterface->AddHucStartCmd(&cmdBuffer, true));

    // wait Huc completion (use HEVC bit for now)
    MHW_VDBOX_VD_PIPE_FLUSH_PARAMS vdPipeFlushParams;
    MOS_ZeroMemory(&vdPipeFlushParams, sizeof(vdPipeFlushParams));
    vdPipeFlushParams.Flags.bFlushHEVC = 1;
    vdPipeFlushParams.Flags.bWaitDoneHEVC = 1;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_vdencInterface->AddVdPipelineFlushCmd(&cmdBuffer, &vdPipeFlushParams));

    // Flush the engine to ensure memory written out
    MHW_MI_FLUSH_DW_PARAMS flushDwParams;
    MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
    flushDwParams.bVideoPipelineCacheInvalidate = true;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(&cmdBuffer, &flushDwParams));

    // Write HUC_STATUS mask: DW1 (mask value)
    MHW_MI_STORE_DATA_PARAMS storeDataParams;
    MOS_ZeroMemory(&storeDataParams, sizeof(storeDataParams));
    storeDataParams.pOsResource      = &m_resHucPakMmioBuffer;
    storeDataParams.dwResourceOffset = sizeof(uint32_t);
    storeDataParams.dwValue = 1 << 31; //Repak bit for HUC is bit 31
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(&cmdBuffer, &storeDataParams) );

    // store HUC_STATUS register
    MHW_MI_STORE_REGISTER_MEM_PARAMS storeRegParams;
    MOS_ZeroMemory(&storeRegParams, sizeof(storeRegParams));
    storeRegParams.presStoreBuffer = &m_resHucPakMmioBuffer;
    storeRegParams.dwOffset = 0;
    storeRegParams.dwRegister = m_hucInterface->GetMmioRegisters(MHW_VDBOX_NODE_1)->hucStatusRegOffset;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(&cmdBuffer, &storeRegParams));

    // For superframe pass, after HuC executes, write the updated size (combined frame size) to status report
    // So app knows total size instead of just the showframe size
    if (m_superFrameHucPass)
    {
        EncodeStatusBuffer* encodeStatusBuf = &m_encodeStatusBuf;
        uint32_t baseOffset =
            (encodeStatusBuf->wCurrIndex * m_encodeStatusBuf.dwReportSize) +
            sizeof(uint32_t) * 2;  // encodeStatus is offset by 2 DWs in the resource

        MHW_MI_COPY_MEM_MEM_PARAMS copyMemMemParams;
        MOS_ZeroMemory(&copyMemMemParams, sizeof(copyMemMemParams));

        copyMemMemParams.presSrc = virtualAddrParams.regionParams[11].presRegion;
        copyMemMemParams.dwSrcOffset = 0; // Updated framesize is 1st DW in buffer
        copyMemMemParams.presDst = &encodeStatusBuf->resStatusBuffer;
        copyMemMemParams.dwDstOffset = baseOffset + encodeStatusBuf->dwBSByteCountOffset;

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiCopyMemMemCmd(
            &cmdBuffer,
            &copyMemMemParams));
    }

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

    // Dump input probabilites before running HuC
        CODECHAL_DEBUG_TOOL(m_debugInterface->DumpHucRegion(
            virtualAddrParams.regionParams[0].presRegion,
            virtualAddrParams.regionParams[0].dwOffset,
            hucRegionSize[0],
            0,
            "_ProbBuffer",
            (virtualAddrParams.regionParams[0].isWritable ? true : false),
            m_currPass,
            CodechalHucRegionDumpType::hucRegionDumpDefault);
    )

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

    // For Temporal scaling, super frame pass is initiated after the command buffer submission in ExecuteSliceLevel.
    // So if Single Task Phase is enabled, then we need to explicitly submit the command buffer here to call HuC
    if (!m_singleTaskPhaseSupported || m_superFrameHucPass)
    {
        bool renderFlags = m_videoContextUsesNullHw;

        CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer(
            &cmdBuffer,
            CODECHAL_NUM_MEDIA_STATES,
            "_ENC")));

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, renderFlags));

        CODECHAL_DEBUG_TOOL(
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpHucDmem(
                &m_resHucProbDmemBuffer[m_currPass][m_currRecycledBufIdx],
                sizeof(HucProbDmem),
                currPass,
                CodechalHucRegionDumpType::hucRegionDumpDefault));

            for (auto i = 0; i < 16; i++) {
                if (virtualAddrParams.regionParams[i].presRegion)
                {
                    m_debugInterface->DumpHucRegion(
                        virtualAddrParams.regionParams[i].presRegion,
                        virtualAddrParams.regionParams[i].dwOffset,
                        hucRegionSize[i],
                        i,
                        hucRegionName[i],
                        !virtualAddrParams.regionParams[i].isWritable,
                        m_currPass,
                        CodechalHucRegionDumpType::hucRegionDumpDefault);
                }
            })
    }

    return eStatus;
}

PMOS_RESOURCE CodechalVdencVp9State::GetBrcConstantBuffer(
    PMOS_RESOURCE brcConstResource,
    uint16_t pictureCodingType)
{
    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_ASSERT(brcConstResource != nullptr);
    CODECHAL_ENCODE_ASSERT(pictureCodingType == I_TYPE || pictureCodingType == P_TYPE);

    return brcConstResource + (pictureCodingType - 1);
}


MOS_STATUS CodechalVdencVp9State::InitBrcConstantBuffer(
    PMOS_RESOURCE brcConstResource,
    uint16_t pictureCodingType)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    if (m_initBrcConstantDataBuffer)
        return eStatus;

    CODECHAL_ENCODE_CHK_NULL_RETURN(brcConstResource);
    CODECHAL_ENCODE_ASSERT(pictureCodingType == I_TYPE || pictureCodingType == P_TYPE);

    PMOS_RESOURCE brcConstResourceI = brcConstResource;
    PMOS_RESOURCE brcConstResourceP = brcConstResource + 1;

    // I - frame const data
    {
        MOS_LOCK_PARAMS lockFlags;
        MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
        lockFlags.WriteOnly = 1;
        uint8_t* data = (uint8_t*)m_osInterface->pfnLockResource(
            m_osInterface,
            brcConstResourceI,
            &lockFlags);
        CODECHAL_ENCODE_CHK_NULL_RETURN(data);

        // Fill surface with BRC const data corresponding to I/P frame
        // -1 converts from frame type to index
        eStatus = MOS_SecureMemcpy(
            data,
            sizeof(m_brcConstData[0]),
            m_brcConstData[0],
            sizeof(m_brcConstData[0]));

        if (eStatus != MOS_STATUS_SUCCESS)
        {
            CODECHAL_ENCODE_ASSERTMESSAGE("Failed to initialize constant memory buffer.");
            return eStatus;
        }

        m_osInterface->pfnUnlockResource(
            m_osInterface,
            brcConstResourceI);
    }

    // P - frame const data
    {
        MOS_LOCK_PARAMS lockFlags;
        MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
        lockFlags.WriteOnly = 1;
        uint8_t* data = (uint8_t*)m_osInterface->pfnLockResource(
            m_osInterface,
            brcConstResourceP,
            &lockFlags);
        CODECHAL_ENCODE_CHK_NULL_RETURN(data);

        // Fill surface with BRC const data corresponding to I/P frame
        // -1 converts from frame type to index
        eStatus = MOS_SecureMemcpy(
            data,
            sizeof(m_brcConstData[1]),
            m_brcConstData[1],
            sizeof(m_brcConstData[1]));

        if (eStatus != MOS_STATUS_SUCCESS)
        {
            CODECHAL_ENCODE_ASSERTMESSAGE("Failed to initialize constant memory buffer.");
            return eStatus;
        }

        m_osInterface->pfnUnlockResource(
            m_osInterface,
            brcConstResourceP);
    }

    m_initBrcConstantDataBuffer = true;

    return eStatus;
}

/*----------------------------------------------------------------------------
| Name      : ComputeVDEncBRCInitQP
| Purpose   : Calculate VP9 BRC init QP value
|
| Returns   : MOS_STATUS
\---------------------------------------------------------------------------*/
MOS_STATUS CodechalVdencVp9State::ComputeVDEncBRCInitQP(
    int32_t* initQpI,
    int32_t* initQpP)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_CHK_NULL_RETURN(initQpI);
    CODECHAL_ENCODE_CHK_NULL_RETURN(initQpP);

    uint32_t frameSize = ((m_frameWidth * m_frameHeight * 3) >> 1);

    const float x0 = 0, y0 = 1.19f, x1 = 1.75f, y1 = 1.75f;
    int32_t     qpP = (int32_t)(1. / 1.2 * pow(10.0, (log10(frameSize * 2. / 3. * ((float)m_vp9SeqParams->FrameRate[0].uiNumerator) / ((float)m_vp9SeqParams->TargetBitRate[0] * CODECHAL_ENCODE_BRC_KBPS * m_vp9SeqParams->FrameRate[0].uiDenominator)) - x0) * (y1 - y0) / (x1 - x0) + y0) + 0.5);
    qpP = (int32_t)((float)qpP * (5.0));
    qpP -= 20;
    qpP = MOS_CLAMP_MIN_MAX(qpP, 1, 200);

    int32_t qpI = (qpP > 4) ? (qpP - 4) : qpP;
    uint16_t numP    = m_vp9SeqParams->GopPicSize - 1;
    int16_t qiboost = numP / 30 - 1;
    qiboost = MOS_CLAMP_MIN_MAX(qiboost, 0, 20);

    qpI -= qiboost;
    qpI = MOS_CLAMP_MIN_MAX(qpI, 1, 200);

    qpP = qpI + 20;

    *initQpI = qpI;
    *initQpP = qpP;

    return eStatus;
}

/*----------------------------------------------------------------------------
| Name      : SetDmemHuCBrcUpdate
| Purpose   : Setup DMEM for VP9 BrcUpdate HuC kernel
|
| Returns   : MOS_STATUS
\---------------------------------------------------------------------------*/
MOS_STATUS CodechalVdencVp9State::SetDmemHuCBrcUpdate()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    MOS_LOCK_PARAMS lockFlagsWriteOnly;
    MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
    lockFlagsWriteOnly.WriteOnly = 1;

    // Setup BRC DMEM
    int currPass = GetCurrentPass();
    HucBrcUpdateDmem *dmem     = (HucBrcUpdateDmem *)m_osInterface->pfnLockResource(
        m_osInterface, &m_resVdencBrcUpdateDmemBuffer[currPass][m_currRecycledBufIdx], &lockFlagsWriteOnly);
    CODECHAL_ENCODE_CHK_NULL_RETURN(dmem);

    MOS_SecureMemcpy(dmem, sizeof(HucBrcUpdateDmem),
        m_brcUpdateDmem, sizeof(m_brcUpdateDmem));

    // BRC Settings
    if (m_curTargetFullness > m_vp9SeqParams->VBVBufferSizeInBit)
    {
        dmem->UPD_OVERFLOW_FLAG_U8    = 0x1;
        m_curTargetFullness -= m_vp9SeqParams->VBVBufferSizeInBit;
    }
    if (IsFirstPass()) // we only set target fullness on first BRC pass
    {
        dmem->UPD_TARGET_BUF_FULLNESS_U32     = (int32_t)m_curTargetFullness;
    }
    dmem->UPD_FRAMENUM_U32                    = m_frameNum;
    dmem->UPD_Temporal_Level_U8               = m_vp9PicParams->temporal_id;
    dmem->UPD_HRD_BUFF_FULLNESS_UPPER_I32     = m_vp9SeqParams->UpperVBVBufferLevelThresholdInBit;
    dmem->UPD_HRD_BUFF_FULLNESS_LOWER_I32     = m_vp9SeqParams->LowerVBVBufferLevelThresholdInBit;

    // Frame info
    dmem->UPD_CurWidth_U16                = (uint16_t)m_frameWidth;
    dmem->UPD_CurHeight_U16               = (uint16_t)m_frameHeight;
    dmem->UPD_CurrFrameType_U8            = (m_pictureCodingType == I_TYPE) ? 2 : 0;

    // PAK info
    dmem->UPD_MaxNumPAKs_U8               = (uint8_t)GetNumPasses();        // do not add 1 because we do not run update for RePAK
    dmem->UPD_PAKPassNum_U8               = (uint8_t)currPass;

    // Offsets
    dmem->UPD_VDEncImgStateOffset         = m_slbbImgStateOffset;
    dmem->UPD_SLBBSize                    = m_hucSlbbSize;
    dmem->UPD_PicStateOffset              = m_hucPicStateOffset;

    // Thresholds not programmed by driver.currently

    // Global adjust settings not programmed by driver currently

    // QP's
    dmem->UPD_ACQQp_U8 = m_vp9PicParams->LumaACQIndex;
    // If app gives segment map, we honor the QP deltas provided, if not, and segmentation is enabled,
    // BRC generates the QP deltas and patches them into the segment states
    dmem->UPD_SegMapGenerating_U8 = m_vp9PicParams->PicFlags.fields.segmentation_enabled && !m_segmentMapProvided;

    m_osInterface->pfnUnlockResource(m_osInterface, &m_resVdencBrcUpdateDmemBuffer[currPass][m_currRecycledBufIdx]);

    return eStatus;
}

/*----------------------------------------------------------------------------
| Name      : SetDmemHuCBrcInitReset
| Purpose   : Setup DMEM for VP9 BrcInit HuC kernel
|
| Returns   : MOS_STATUS
\---------------------------------------------------------------------------*/
MOS_STATUS CodechalVdencVp9State::SetDmemHuCBrcInitReset()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_ASSERT(m_brcInit || m_brcReset);

    MOS_LOCK_PARAMS lockFlagsWriteOnly;
    MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
    lockFlagsWriteOnly.WriteOnly = 1;

    // Setup BRC DMEM
    HucBrcInitDmem *dmem = (HucBrcInitDmem *)m_osInterface->pfnLockResource(
        m_osInterface, &m_resVdencBrcInitDmemBuffer, &lockFlagsWriteOnly);
    CODECHAL_ENCODE_CHK_NULL_RETURN(dmem);

    MOS_SecureMemcpy(dmem, sizeof(HucBrcInitDmem),
        m_brcInitDmem, sizeof(m_brcInitDmem));

    dmem->BRCFunc               = m_brcInit ? 0 : 2; // 0 for init, 2 for reset
    dmem->ProfileLevelMaxFrame  = m_frameWidth * m_frameHeight;
    if (m_vp9SeqParams->UserMaxFrameSize > 0)
    {
        dmem->ProfileLevelMaxFrame = MOS_MIN(dmem->ProfileLevelMaxFrame, m_vp9SeqParams->UserMaxFrameSize);
    }
    dmem->InitBufFullness = m_vp9SeqParams->InitVBVBufferFullnessInBit;
    dmem->BufSize         = m_vp9SeqParams->VBVBufferSizeInBit;

    dmem->TargetBitrate = m_vp9SeqParams->TargetBitRate[m_vp9SeqParams->NumTemporalLayersMinus1] * CODECHAL_ENCODE_BRC_KBPS;
    dmem->MaxRate       = m_vp9SeqParams->MaxBitRate * CODECHAL_ENCODE_BRC_KBPS;

    FRAME_RATE targetFR         = m_vp9SeqParams->FrameRate[m_vp9SeqParams->NumTemporalLayersMinus1];
    dmem->FrameRateM            = targetFR.uiNumerator;
    dmem->FrameRateD            = targetFR.uiDenominator;

    switch (m_vp9SeqParams->RateControlMethod)
    {
    case RATECONTROL_CBR:
        dmem->BRCFlag           = CODECHAL_ENCODE_BRCINIT_ISCBR;
        dmem->MaxRate           = dmem->TargetBitrate;
        break;
    case RATECONTROL_VBR:
        dmem->BRCFlag           = CODECHAL_ENCODE_BRCINIT_ISVBR;
        break;
    case RATECONTROL_AVBR:
        dmem->BRCFlag           = CODECHAL_ENCODE_BRCINIT_ISAVBR;
        break;
    case RATECONTROL_CQL:
        dmem->BRCFlag           = CODECHAL_ENCODE_BRCINIT_ISCQL;
        dmem->LevelQP           = m_vp9SeqParams->ICQQualityFactor;
        break;
    default:
        CODECHAL_ENCODE_ASSERTMESSAGE("BRCInit: Invalid rate control provided (%d)", m_vp9SeqParams->RateControlMethod);
        return MOS_STATUS_INVALID_PARAMETER;
    }

    if (dmem->MaxRate < dmem->TargetBitrate)
    {
        dmem->MaxRate = 2 * dmem->TargetBitrate;
    }

    dmem->GopP                  = m_vp9SeqParams->GopPicSize - 1;
    dmem->FrameWidth            = (uint16_t)m_frameWidth;
    dmem->FrameHeight           = (uint16_t)m_frameHeight;

    /* Limit 1-255 as the QP range */
    dmem->MinQP                 = 1;
    dmem->MaxQP                 = CODEC_VP9_MAX_QP;

    dmem->EnableScaling = m_vp9SeqParams->SeqFlags.fields.EnableDynamicScaling;

    for (auto i = 0; i < m_numInstRateThresholds; i++)
    {
        dmem->InstRateThreshI0[i] = m_instRateThresholdI[i];
        dmem->InstRateThreshP0[i] = m_instRateThresholdP[i];
    }

    double m_inputBitsPerFrame = ((double)dmem->MaxRate * (double)dmem->FrameRateD) / (double)dmem->FrameRateM;

    //make sure the buffer size can contain at least 4 frames in average
    if (dmem->BufSize < (uint32_t)(m_inputBitsPerFrame * 4))
    {
        dmem->BufSize = (uint32_t)(m_inputBitsPerFrame * 4);
    }

    //make sure the initial buffer size is larger than 2 average frames and smaller than the max buffer size.
    if (dmem->InitBufFullness == 0)
    {
        dmem->InitBufFullness = 7 * dmem->BufSize / 8;
    }
    if (dmem->InitBufFullness < (uint32_t)(m_inputBitsPerFrame * 2))
    {
        dmem->InitBufFullness = (uint32_t)(m_inputBitsPerFrame * 2);
    }
    if (dmem->InitBufFullness > dmem->BufSize)
    {
        dmem->InitBufFullness = dmem->BufSize;
    }

    double bpsRatio = m_inputBitsPerFrame / ((double)dmem->BufSize / m_devStdFps);
    bpsRatio = MOS_CLAMP_MIN_MAX(bpsRatio, m_bpsRatioLow, m_bpsRatioHigh);

    for (auto i = 0; i < m_numDevThresholds / 2; i++)
    {
        dmem->DevThreshPB0[i] = (int8_t)(m_negMultPb * pow(m_devThresholdFpNegPB[i], bpsRatio));
        dmem->DevThreshPB0[i + m_numDevThresholds / 2] = (int8_t)(m_posMultPb * pow(m_devThresholdFpPosPB[i], bpsRatio));

        dmem->DevThreshI0[i] = (int8_t)(m_negMultPb * pow(m_devThresholdFpNegI[i], bpsRatio));
        dmem->DevThreshI0[i + m_numDevThresholds / 2] = (int8_t)(m_posMultPb * pow(m_devThresholdFpPosI[i], bpsRatio));

        dmem->DevThreshVBR0[i] = (int8_t)(m_negMultVbr * pow(m_devThresholdVbrNeg[i], bpsRatio));
        dmem->DevThreshVBR0[i + m_numDevThresholds / 2] = (int8_t)(m_posMultVbr * pow(m_devThresholdVbrPos[i], bpsRatio));
    }

    int32_t qpI = 0, qpP = 0;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(ComputeVDEncBRCInitQP(&qpI, &qpP));

    dmem->InitQPI = (uint8_t)qpI;
    dmem->InitQPP = (uint8_t)qpP;

    dmem->Total_Level = m_vp9SeqParams->NumTemporalLayersMinus1 + 1;
    if (dmem->Total_Level > 1)
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CalculateTemporalRatios(
            dmem->Total_Level, dmem->TargetBitrate, targetFR, dmem->MaxLevel_Ratio));
    }

    // lets allow huc to calculate it 
    dmem->GoldenFrameInterval = 0;

    m_osInterface->pfnUnlockResource(m_osInterface, &m_resVdencBrcInitDmemBuffer);

    return eStatus;
}

/*----------------------------------------------------------------------------
| Name      : HuCBrcUpdate
| Purpose   : Start/Submit VP9 HuC BrcUpdate kernel to HW
|
| Returns   : MOS_STATUS
\---------------------------------------------------------------------------*/
MOS_STATUS CodechalVdencVp9State::HuCBrcUpdate()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_DEBUG_TOOL(
        uint32_t hucRegionSize[16];
        const char* hucRegionName[16];

        hucRegionName[0]  = "_BrcHistory";
        hucRegionSize[0]  = m_brcHistoryBufferSize;
        hucRegionName[1]  = "_VDEncStats";
        hucRegionSize[1]  = m_vdencBrcStatsBufferSize;
        hucRegionName[2]  = "_PAKStats";
        hucRegionSize[2]  = m_vdencBrcPakStatsBufferSize;
        hucRegionName[3]  = "_InputSLBB";
        hucRegionSize[3]  = m_vdencPicStateSecondLevelBatchBufferSize;
        hucRegionName[4]  = "_BRCData";
        hucRegionSize[4]  = CODECHAL_ENCODE_VP9_HUC_BRC_DATA_BUFFER_SIZE;
        hucRegionName[5]  = "_ConstData";
        hucRegionSize[5]  = m_brcConstantSurfaceSize;
        hucRegionName[6]  = "_OutputSLBB";
        hucRegionSize[6]  = m_vdencPicStateSecondLevelBatchBufferSize;
        hucRegionName[7]  = "_PAKMMIO";
        hucRegionSize[7]  = CODECHAL_ENCODE_VP9_HUC_BRC_DATA_BUFFER_SIZE;
    )

    MHW_VDBOX_HUC_VIRTUAL_ADDR_PARAMS virtualAddrParams;
#if (_DEBUG || _RELEASE_INTERNAL)
    if (m_swBrcMode)
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(SetDmemHuCBrcUpdate());
        CODECHAL_ENCODE_CHK_STATUS_RETURN(InitBrcConstantBuffer(&m_brcBuffers.resBrcConstantDataBuffer[0], m_pictureCodingType));
        // Set region params for dumping only
        MOS_ZeroMemory(&virtualAddrParams, sizeof(virtualAddrParams));
        virtualAddrParams.regionParams[0].presRegion = &m_brcBuffers.resBrcHistoryBuffer;
        virtualAddrParams.regionParams[0].isWritable = true;
        virtualAddrParams.regionParams[1].presRegion = &m_resVdencBrcStatsBuffer;
        virtualAddrParams.regionParams[2].presRegion = &m_resFrameStatStreamOutBuffer;
        virtualAddrParams.regionParams[3].presRegion = &m_resVdencPictureState2NdLevelBatchBufferRead[m_currPass][m_vdencPictureState2ndLevelBBIndex];
        virtualAddrParams.regionParams[4].presRegion = &m_brcBuffers.resBrcHucDataBuffer;
        virtualAddrParams.regionParams[4].isWritable = true;
        virtualAddrParams.regionParams[5].presRegion = GetBrcConstantBuffer(&m_brcBuffers.resBrcConstantDataBuffer[0], m_pictureCodingType);
        virtualAddrParams.regionParams[6].presRegion = &m_resVdencPictureState2NdLevelBatchBufferWrite[m_vdencPictureState2ndLevelBBIndex];
        virtualAddrParams.regionParams[6].isWritable = true;
        virtualAddrParams.regionParams[7].presRegion = &m_brcBuffers.resBrcBitstreamSizeBuffer;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpHucRegion(// Dump history IN since it's both IN/OUT, OUT will dump at end of function, rest of buffers are IN XOR OUT (not both)
            virtualAddrParams.regionParams[0].presRegion,
            virtualAddrParams.regionParams[0].dwOffset,
            hucRegionSize[0],
            0,
            hucRegionName[0],
            true,
            m_currPass,
            CodechalHucRegionDumpType::hucRegionDumpUpdate));
        CODECHAL_ENCODE_CHK_STATUS_RETURN(SoftwareBRC(true));

        CODECHAL_DEBUG_TOOL(
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpHucDmem(

                &m_resVdencBrcUpdateDmemBuffer[m_currPass][m_currRecycledBufIdx],
                sizeof(HucBrcUpdateDmem),  // Change buffer and size to update dmem
                m_currPass,
                CodechalHucRegionDumpType::hucRegionDumpUpdate));

            for (auto i = 0; i < 16; i++) {
                if (virtualAddrParams.regionParams[i].presRegion)
                {
                    m_debugInterface->DumpHucRegion(
                        virtualAddrParams.regionParams[i].presRegion,
                        virtualAddrParams.regionParams[i].dwOffset,
                        hucRegionSize[i],
                        i,
                        hucRegionName[i],
                        !virtualAddrParams.regionParams[i].isWritable,
                        m_currPass,
                        CodechalHucRegionDumpType::hucRegionDumpUpdate);
                }
            })
        // We increment by the average frame value once for each frame
        if (m_currPass == 0)
        {
            m_curTargetFullness += m_inputBitsPerFrame;
        }

    return eStatus;
    }
#endif

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

    if (!m_singleTaskPhaseSupported || m_firstTaskInPhase)
    {
        bool requestFrameTracking = false;

        // Send command buffer header at the beginning (OS dependent)
        requestFrameTracking = m_singleTaskPhaseSupported ? m_firstTaskInPhase : m_lastTaskInPhase;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(&cmdBuffer, requestFrameTracking));

        m_firstTaskInPhase = false;
    }

    CODECHAL_ENCODE_CHK_STATUS_RETURN(InitBrcConstantBuffer(&m_brcBuffers.resBrcConstantDataBuffer[0], m_pictureCodingType));

    // load kernel from WOPCM into L2 storage RAM
    MHW_VDBOX_HUC_IMEM_STATE_PARAMS imemParams;
    MOS_ZeroMemory(&imemParams, sizeof(imemParams));
    imemParams.dwKernelDescriptor = m_vdboxHucVp9VdencBrcUpdateKernelDescriptor;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hucInterface->AddHucImemStateCmd(&cmdBuffer, &imemParams));

    // pipe mode select
    MHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams;
    pipeModeSelectParams.Mode = m_mode;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hucInterface->AddHucPipeModeSelectCmd(&cmdBuffer, &pipeModeSelectParams));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(SetDmemHuCBrcUpdate());

    // set HuC DMEM param
    MHW_VDBOX_HUC_DMEM_STATE_PARAMS dmemParams;
    MOS_ZeroMemory(&dmemParams, sizeof(dmemParams));
    dmemParams.presHucDataSource = &m_resVdencBrcUpdateDmemBuffer[m_currPass][m_currRecycledBufIdx];
    dmemParams.dwDataLength = MOS_ALIGN_CEIL(sizeof(HucBrcUpdateDmem), CODECHAL_CACHELINE_SIZE);
    dmemParams.dwDmemOffset = HUC_DMEM_OFFSET_RTOS_GEMS; // how to set?
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hucInterface->AddHucDmemStateCmd(&cmdBuffer, &dmemParams));

    // Set surfaces to HuC regions
    MOS_ZeroMemory(&virtualAddrParams, sizeof(virtualAddrParams));

    // History Buffer - IN/OUT
    virtualAddrParams.regionParams[0].presRegion = &m_brcBuffers.resBrcHistoryBuffer;
    virtualAddrParams.regionParams[0].isWritable = true;

    // VDEnc Stats Buffer - IN
    virtualAddrParams.regionParams[1].presRegion = &m_resVdencBrcStatsBuffer;

    // Frame (not PAK) Stats Buffer - IN
    virtualAddrParams.regionParams[2].presRegion = &m_resFrameStatStreamOutBuffer;

    // Input SLBB (second level batch buffer) - IN
    //For Dys + BRC Pass 0, use the resVdencDysPictureState2ndLevelBatchBuffer as input buffer
    virtualAddrParams.regionParams[3].presRegion = (m_dysRefFrameFlags != DYS_REF_NONE && m_dysVdencMultiPassEnabled) ? &m_resVdencDysPictureState2NdLevelBatchBuffer : &m_resVdencPictureState2NdLevelBatchBufferRead[m_currPass][m_vdencPictureState2ndLevelBBIndex];

    // BRC Data - OUT
    virtualAddrParams.regionParams[4].presRegion = &m_brcBuffers.resBrcHucDataBuffer;
    virtualAddrParams.regionParams[4].isWritable = true;

    // Const Data - IN
    virtualAddrParams.regionParams[5].presRegion = GetBrcConstantBuffer(&m_brcBuffers.resBrcConstantDataBuffer[0], m_pictureCodingType);

    // Output SLBB - OUT
    virtualAddrParams.regionParams[6].presRegion = &m_resVdencPictureState2NdLevelBatchBufferWrite[m_vdencPictureState2ndLevelBBIndex];
    virtualAddrParams.regionParams[6].isWritable = true;

    // PAK MMIO - IN
    virtualAddrParams.regionParams[7].presRegion = &m_brcBuffers.resBrcBitstreamSizeBuffer;

    // Load HuC Regions into Cmd Buf
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hucInterface->AddHucVirtualAddrStateCmd(&cmdBuffer, &virtualAddrParams));

    // Store HUC_STATUS2 register bit 6 before HUC_Start command
    // BitField: VALID IMEM LOADED - This bit will be cleared by HW at the end of a HUC workload
    // (HUC_Start command with last start bit set).
    CODECHAL_DEBUG_TOOL(
        CODECHAL_ENCODE_CHK_STATUS_RETURN(StoreHuCStatus2Register(&cmdBuffer));
    )

    CODECHAL_ENCODE_CHK_STATUS_RETURN(StoreHuCStatus2Report(&cmdBuffer));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hucInterface->AddHucStartCmd(&cmdBuffer, true));

    // wait Huc completion (use HEVC bit for now)
    MHW_VDBOX_VD_PIPE_FLUSH_PARAMS vdPipeFlushParams;
    MOS_ZeroMemory(&vdPipeFlushParams, sizeof(vdPipeFlushParams));
    vdPipeFlushParams.Flags.bFlushHEVC = 1;
    vdPipeFlushParams.Flags.bWaitDoneHEVC = 1;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_vdencInterface->AddVdPipelineFlushCmd(&cmdBuffer, &vdPipeFlushParams));

    // Flush the engine to ensure memory written out
    MHW_MI_FLUSH_DW_PARAMS flushDwParams;
    MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
    flushDwParams.bVideoPipelineCacheInvalidate = true;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(&cmdBuffer, &flushDwParams));

    if (!m_singleTaskPhaseSupported && (m_osInterface->bNoParsingAssistanceInKmd))
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr));
    }

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

    if (!m_singleTaskPhaseSupported)
    {
        bool renderingFlags = m_videoContextUsesNullHw;

        // Dump history input before HuC runs
        CODECHAL_DEBUG_TOOL(
            m_debugInterface->DumpHucRegion(
                virtualAddrParams.regionParams[0].presRegion,
                virtualAddrParams.regionParams[0].dwOffset,
                hucRegionSize[0],
                0,
                hucRegionName[0],
                true,
                m_currPass,
                CodechalHucRegionDumpType::hucRegionDumpUpdate);
        );

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, renderingFlags));

        CODECHAL_DEBUG_TOOL(
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpHucDmem(
                &m_resVdencBrcUpdateDmemBuffer[m_currPass][m_currRecycledBufIdx],
                sizeof(HucBrcUpdateDmem),  // Change buffer and size to update dmem
                m_currPass,
                CodechalHucRegionDumpType::hucRegionDumpUpdate));

            for (auto i = 0; i < 16; i++) {
                if (virtualAddrParams.regionParams[i].presRegion)
                {
                    m_debugInterface->DumpHucRegion(
                        virtualAddrParams.regionParams[i].presRegion,
                        virtualAddrParams.regionParams[i].dwOffset,
                        hucRegionSize[i],
                        i,
                        hucRegionName[i],
                        !virtualAddrParams.regionParams[i].isWritable,
                        m_currPass,
                        CodechalHucRegionDumpType::hucRegionDumpUpdate);
                }
            })
    }

    // We increment by the average frame value once for each frame
    if (m_currPass == 0)
    {
        m_curTargetFullness += m_inputBitsPerFrame;
    }

    return eStatus;
}

/*----------------------------------------------------------------------------
| Name      : ConstructSuperFrame
| Purpose   : Enable VP9 third HUC phase to construct super frame in case of temporal scalability.
\---------------------------------------------------------------------------*/
MOS_STATUS CodechalVdencVp9State::ConstructSuperFrame()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    // enable super frame state
    m_superFrameHucPass = true;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(HuCVp9Prob());

    // disable super frame state
    m_superFrameHucPass = false;

    return eStatus;
}

/*----------------------------------------------------------------------------
| Name      : HuCBrcInitReset
| Purpose   : Start/Submit VP9 HuC BrcInit kernel to HW
|
| Returns   : MOS_STATUS
\---------------------------------------------------------------------------*/
MOS_STATUS CodechalVdencVp9State::HuCBrcInitReset()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_DEBUG_TOOL(
        uint32_t hucRegionSize[16];
        const char* hucRegionName[16];

        hucRegionName[0] = "_BrcHistoryBuffer";
        hucRegionSize[0] = m_brcHistoryBufferSize;
    )

    MHW_VDBOX_HUC_VIRTUAL_ADDR_PARAMS virtualAddrParams;
#if (_DEBUG || _RELEASE_INTERNAL)
    if (m_swBrcMode)
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(SetDmemHuCBrcInitReset());
        CODECHAL_ENCODE_CHK_STATUS_RETURN(SoftwareBRC(false));
        // Set region params for dumping only
        MOS_ZeroMemory(&virtualAddrParams, sizeof(virtualAddrParams));
        virtualAddrParams.regionParams[0].presRegion = &m_brcBuffers.resBrcHistoryBuffer;
        virtualAddrParams.regionParams[0].isWritable = true;
        m_inputBitsPerFrame                          = ((m_vp9SeqParams->MaxBitRate * CODECHAL_ENCODE_BRC_KBPS) * 100.) / ((m_vp9SeqParams->FrameRate[m_vp9SeqParams->NumTemporalLayersMinus1].uiNumerator * 100.) / m_vp9SeqParams->FrameRate[m_vp9SeqParams->NumTemporalLayersMinus1].uiDenominator);
        m_curTargetFullness                          = m_vp9SeqParams->TargetBitRate[m_vp9SeqParams->NumTemporalLayersMinus1] * CODECHAL_ENCODE_BRC_KBPS;

        CODECHAL_DEBUG_TOOL(
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpHucDmem(
                &m_resVdencBrcInitDmemBuffer,
                sizeof(HucBrcInitDmem),
                0,
                CodechalHucRegionDumpType::hucRegionDumpInit));

            for (auto i = 0; i < 16; i++) {
                if (virtualAddrParams.regionParams[i].presRegion)
                {
                    m_debugInterface->DumpHucRegion(
                        virtualAddrParams.regionParams[i].presRegion,
                        virtualAddrParams.regionParams[i].dwOffset,
                        hucRegionSize[i],
                        i,
                        hucRegionName[i],
                        !virtualAddrParams.regionParams[i].isWritable,
                        0,
                        CodechalHucRegionDumpType::hucRegionDumpInit);
                }
            })
        return eStatus;
    }
#endif
    MOS_COMMAND_BUFFER cmdBuffer;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));

    if (!m_singleTaskPhaseSupported || m_firstTaskInPhase)
    {
        bool requestFrameTracking = false;

        // Send command buffer header at the beginning (OS dependent)
        requestFrameTracking = m_singleTaskPhaseSupported ? m_firstTaskInPhase : m_lastTaskInPhase;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(&cmdBuffer, requestFrameTracking));

        m_firstTaskInPhase = false;
    }

    // load kernel from WOPCM into L2 storage RAM
    MHW_VDBOX_HUC_IMEM_STATE_PARAMS imemParams;
    MOS_ZeroMemory(&imemParams, sizeof(imemParams));
    imemParams.dwKernelDescriptor = m_vdboxHucVp9VdencBrcInitKernelDescriptor;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hucInterface->AddHucImemStateCmd(&cmdBuffer, &imemParams));

    // pipe mode select
    MHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams;
    pipeModeSelectParams.Mode = m_mode;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hucInterface->AddHucPipeModeSelectCmd(&cmdBuffer, &pipeModeSelectParams));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(SetDmemHuCBrcInitReset());

    m_inputBitsPerFrame = ((m_vp9SeqParams->MaxBitRate * CODECHAL_ENCODE_BRC_KBPS) * 100.) / ((m_vp9SeqParams->FrameRate[m_vp9SeqParams->NumTemporalLayersMinus1].uiNumerator * 100.) / m_vp9SeqParams->FrameRate[m_vp9SeqParams->NumTemporalLayersMinus1].uiDenominator);
    m_curTargetFullness = m_vp9SeqParams->TargetBitRate[m_vp9SeqParams->NumTemporalLayersMinus1] * CODECHAL_ENCODE_BRC_KBPS;

    // set HuC DMEM param
    MHW_VDBOX_HUC_DMEM_STATE_PARAMS dmemParams;
    MOS_ZeroMemory(&dmemParams, sizeof(dmemParams));
    dmemParams.presHucDataSource = &m_resVdencBrcInitDmemBuffer;
    dmemParams.dwDataLength = MOS_ALIGN_CEIL(sizeof(HucBrcInitDmem), CODECHAL_CACHELINE_SIZE);
    dmemParams.dwDmemOffset = HUC_DMEM_OFFSET_RTOS_GEMS;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hucInterface->AddHucDmemStateCmd(&cmdBuffer, &dmemParams));

    MOS_ZeroMemory(&virtualAddrParams, sizeof(virtualAddrParams));
    virtualAddrParams.regionParams[0].presRegion = &m_brcBuffers.resBrcHistoryBuffer;
    virtualAddrParams.regionParams[0].isWritable = true;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hucInterface->AddHucVirtualAddrStateCmd(&cmdBuffer, &virtualAddrParams));

    // Store HUC_STATUS2 register bit 6 before HUC_Start command
    // BitField: VALID IMEM LOADED - This bit will be cleared by HW at the end of a HUC workload
    // (HUC_Start command with last start bit set).
    CODECHAL_DEBUG_TOOL(
        CODECHAL_ENCODE_CHK_STATUS_RETURN(StoreHuCStatus2Register(&cmdBuffer));
    )

    CODECHAL_ENCODE_CHK_STATUS_RETURN(StoreHuCStatus2Report(&cmdBuffer));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hucInterface->AddHucStartCmd(&cmdBuffer, true));

    // wait Huc completion (use HEVC bit for now)
    MHW_VDBOX_VD_PIPE_FLUSH_PARAMS vdPipeFlushParams;
    MOS_ZeroMemory(&vdPipeFlushParams, sizeof(vdPipeFlushParams));
    vdPipeFlushParams.Flags.bFlushHEVC = 1;
    vdPipeFlushParams.Flags.bWaitDoneHEVC = 1;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_vdencInterface->AddVdPipelineFlushCmd(&cmdBuffer, &vdPipeFlushParams));

    // Flush the engine to ensure memory written out
    MHW_MI_FLUSH_DW_PARAMS flushDwParams;
    MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
    flushDwParams.bVideoPipelineCacheInvalidate = true;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(&cmdBuffer, &flushDwParams));

    if (!m_singleTaskPhaseSupported && (m_osInterface->bNoParsingAssistanceInKmd))
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr));
    }

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

    if (!m_singleTaskPhaseSupported)
    {
        bool renderingFlags = m_videoContextUsesNullHw;

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, renderingFlags));

        CODECHAL_DEBUG_TOOL(
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpHucDmem(
                &m_resVdencBrcInitDmemBuffer,
                sizeof(HucBrcInitDmem),
                0,
                CodechalHucRegionDumpType::hucRegionDumpInit));

            for (auto i = 0; i < 16; i++) {
                if (virtualAddrParams.regionParams[i].presRegion)
                {
                    m_debugInterface->DumpHucRegion(
                        virtualAddrParams.regionParams[i].presRegion,
                        virtualAddrParams.regionParams[i].dwOffset,
                        hucRegionSize[i],
                        i,
                        hucRegionName[i],
                        !virtualAddrParams.regionParams[i].isWritable,
                        0,
                        CodechalHucRegionDumpType::hucRegionDumpInit);
                }
            })
    }

    return eStatus;
}

#if (_DEBUG || _RELEASE_INTERNAL)
MOS_STATUS CodechalVdencVp9State::SoftwareBRC(bool update)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    typedef void*   (*BrcCreateInstance)();
    typedef void(*BrcReleaseInstance)(void*);
    typedef int(*BrcProcess)(void*, ProcessType);
    typedef int(*BrcSetBuff)(uint8_t*, VP9BufferType, void*);

    CODECHAL_DEBUG_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(m_swBrcMode);

    MOS_LOCK_PARAMS lpReadOnly;
    MOS_ZeroMemory(&lpReadOnly, sizeof(lpReadOnly));
    lpReadOnly.ReadOnly = 1;

    MOS_LOCK_PARAMS lpWriteOnly;
    MOS_ZeroMemory(&lpWriteOnly, sizeof(lpWriteOnly));
    lpWriteOnly.WriteOnly = 1;

    MOS_LOCK_PARAMS lpReadWrite;
    MOS_ZeroMemory(&lpReadWrite, sizeof(lpReadWrite));
    lpReadWrite.ReadOnly = lpReadWrite.WriteOnly = 1;

    BrcCreateInstance pfnCreateInstance = (BrcCreateInstance)MosUtilities::MosGetProcAddress(m_swBrcMode, "VP9BRC_CreateInstance");
    CODECHAL_ENCODE_CHK_NULL_RETURN(pfnCreateInstance);
    BrcReleaseInstance pfnReleaseInstance = (BrcReleaseInstance)MosUtilities::MosGetProcAddress(m_swBrcMode, "VP9BRC_ReleaseInstance");
    CODECHAL_ENCODE_CHK_NULL_RETURN(pfnReleaseInstance);
    BrcProcess pfnProcess = (BrcProcess)MosUtilities::MosGetProcAddress(m_swBrcMode, "VP9BRC_Process");
    CODECHAL_ENCODE_CHK_NULL_RETURN(pfnProcess);
    BrcSetBuff pfnSetBuffer = (BrcSetBuff)MosUtilities::MosGetProcAddress(m_swBrcMode, "VP9BRC_SetBuff");
    CODECHAL_ENCODE_CHK_NULL_RETURN(pfnSetBuffer);

    void* pvBrcIfHandle = pfnCreateInstance();
    CODECHAL_ENCODE_CHK_NULL_RETURN(pvBrcIfHandle);

    if (!update) // BRC INIT / RESET
    {
        // Set DMEM
        uint8_t* data_dmem = NULL;
        data_dmem          = (uint8_t *)m_osInterface->pfnLockResource(
            m_osInterface, &m_resVdencBrcInitDmemBuffer, &lpReadOnly);
        CODECHAL_ENCODE_CHK_NULL_RETURN(data_dmem);
        CODECHAL_ENCODE_CHK_STATUS_RETURN(pfnSetBuffer(data_dmem, eVp9INLINE_DMEM, pvBrcIfHandle));
        
        // Set History OUT Buffer
        uint8_t* data_history_out = (uint8_t *)m_osInterface->pfnLockResource(
            m_osInterface, &m_brcBuffers.resBrcHistoryBuffer, &lpWriteOnly);
        CODECHAL_ENCODE_CHK_NULL_RETURN(data_history_out);
        CODECHAL_ENCODE_CHK_STATUS_RETURN(pfnSetBuffer(data_history_out, eVp9HISTORY_BUFF, pvBrcIfHandle));

        // Execute init/reset firmware
        CODECHAL_ENCODE_CHK_STATUS_RETURN(pfnProcess(pvBrcIfHandle, m_brcInit ? BRCInit : BRCReset));

        m_osInterface->pfnUnlockResource(m_osInterface, &m_resVdencBrcInitDmemBuffer);
        m_osInterface->pfnUnlockResource(m_osInterface, &m_brcBuffers.resBrcHistoryBuffer);
    }
    else // BRC UPDATE
    {
        // Set DMEM
        uint8_t *data_dmem = (uint8_t *)m_osInterface->pfnLockResource(
            m_osInterface, &m_resVdencBrcUpdateDmemBuffer[m_currPass][m_currRecycledBufIdx], &lpReadOnly);
        CODECHAL_ENCODE_CHK_NULL_RETURN(data_dmem);
        CODECHAL_ENCODE_CHK_STATUS_RETURN(pfnSetBuffer(data_dmem, eVp9INLINE_DMEM, pvBrcIfHandle));

        // Set History IN/OUT Buffer
        uint8_t *data_history_in_out = (uint8_t *)m_osInterface->pfnLockResource(
            m_osInterface, &m_brcBuffers.resBrcHistoryBuffer, &lpReadWrite);
        CODECHAL_ENCODE_CHK_NULL_RETURN(data_history_in_out);
        CODECHAL_ENCODE_CHK_STATUS_RETURN(pfnSetBuffer(data_history_in_out, eVp9HISTORY_BUFF, pvBrcIfHandle));

        // Set VDEnc Stats IN
        uint8_t *data_vdenc_stat = (uint8_t *)m_osInterface->pfnLockResource(
            m_osInterface, &m_resVdencBrcStatsBuffer, &lpReadOnly);
        CODECHAL_ENCODE_CHK_NULL_RETURN(data_vdenc_stat);
        CODECHAL_ENCODE_CHK_STATUS_RETURN(pfnSetBuffer(data_vdenc_stat, eVp9VDENC_STATISTICS_BUFF, pvBrcIfHandle));

        // Set Frame Stats IN
        uint8_t *data_frame_stat = (uint8_t *)m_osInterface->pfnLockResource(
            m_osInterface, &m_resFrameStatStreamOutBuffer, &lpReadOnly);
        CODECHAL_ENCODE_CHK_NULL_RETURN(data_frame_stat);
        CODECHAL_ENCODE_CHK_STATUS_RETURN(pfnSetBuffer(data_frame_stat, eVp9PAK_STATISTICS_BUFF, pvBrcIfHandle));

        // Set SLBB IN
        uint8_t *data_slbb_in = (uint8_t *)m_osInterface->pfnLockResource(
            m_osInterface, &m_resVdencPictureState2NdLevelBatchBufferRead[m_currPass][m_vdencPictureState2ndLevelBBIndex], &lpReadOnly);
        CODECHAL_ENCODE_CHK_NULL_RETURN(data_slbb_in);
        CODECHAL_ENCODE_CHK_STATUS_RETURN(pfnSetBuffer(data_slbb_in, eVp9INPUT_SLBB_BUFF, pvBrcIfHandle));

        // Set BRC data OUT
        uint8_t *data_brc_out = (uint8_t *)m_osInterface->pfnLockResource(
            m_osInterface, &m_brcBuffers.resBrcHucDataBuffer, &lpWriteOnly);
        CODECHAL_ENCODE_CHK_NULL_RETURN(data_brc_out);
        CODECHAL_ENCODE_CHK_STATUS_RETURN(pfnSetBuffer(data_brc_out, eVp9BRC_DATA_BUFF, pvBrcIfHandle));

        // Set Const Data IN
        uint8_t *data_const_in = (uint8_t *)m_osInterface->pfnLockResource(
            m_osInterface, &m_brcBuffers.resBrcConstantDataBuffer[0], &lpReadOnly);
        CODECHAL_ENCODE_CHK_NULL_RETURN(data_const_in);
        CODECHAL_ENCODE_CHK_STATUS_RETURN(pfnSetBuffer(data_const_in, eVp9CONSTANT_DATA_BUFF, pvBrcIfHandle));

        // Set SLBB OUT
        uint8_t *data_slbb_out = (uint8_t *)m_osInterface->pfnLockResource(
            m_osInterface, &m_resVdencPictureState2NdLevelBatchBufferWrite[m_vdencPictureState2ndLevelBBIndex], &lpWriteOnly);
        CODECHAL_ENCODE_CHK_NULL_RETURN(data_slbb_out);
        CODECHAL_ENCODE_CHK_STATUS_RETURN(pfnSetBuffer(data_slbb_out, eVp9OUTPUT_SLBB_BUFF, pvBrcIfHandle));

        // PAK MMIO IN
        uint8_t *data_mmio_in = (uint8_t *)m_osInterface->pfnLockResource(
            m_osInterface, &m_brcBuffers.resBrcBitstreamSizeBuffer, &lpReadOnly);
        CODECHAL_ENCODE_CHK_NULL_RETURN(data_mmio_in);
        CODECHAL_ENCODE_CHK_STATUS_RETURN(pfnSetBuffer(data_mmio_in, eVp9PAKMMIO_BUFF, pvBrcIfHandle));

        // AUX Buffer IN/OUT (DLL extension buffer)
        HUC_AUX_BUFFER auxBuffer = { 0 };
        CODECHAL_ENCODE_CHK_STATUS_RETURN(pfnSetBuffer((uint8_t *)&auxBuffer, eVp9AUX_BUFF, pvBrcIfHandle));

        // Execute update firmware
        pfnProcess(pvBrcIfHandle, BRCUpdate);

        m_osInterface->pfnUnlockResource(m_osInterface, &m_resVdencBrcUpdateDmemBuffer[m_currPass][m_currRecycledBufIdx]);
        m_osInterface->pfnUnlockResource(m_osInterface, &m_brcBuffers.resBrcHistoryBuffer);
        m_osInterface->pfnUnlockResource(m_osInterface, &m_resVdencBrcStatsBuffer);
        m_osInterface->pfnUnlockResource(m_osInterface, &m_resFrameStatStreamOutBuffer);
        m_osInterface->pfnUnlockResource(m_osInterface, &m_resVdencPictureState2NdLevelBatchBufferRead[m_currPass][m_vdencPictureState2ndLevelBBIndex]);
        m_osInterface->pfnUnlockResource(m_osInterface, &m_brcBuffers.resBrcHucDataBuffer);
        m_osInterface->pfnUnlockResource(m_osInterface, &m_brcBuffers.resBrcConstantDataBuffer[0]);
        m_osInterface->pfnUnlockResource(m_osInterface, &m_resVdencPictureState2NdLevelBatchBufferWrite[m_vdencPictureState2ndLevelBBIndex]);
        m_osInterface->pfnUnlockResource(m_osInterface, &m_brcBuffers.resBrcBitstreamSizeBuffer);
    }

    pfnReleaseInstance(pvBrcIfHandle);

    return eStatus;
}
#endif

uint32_t CodechalVdencVp9State::CalculateBufferOffset(
    uint32_t idx,
    uint32_t width,
    uint32_t blockSize,
    uint32_t bufferPitch)
{
    uint32_t y = idx / (MOS_ALIGN_CEIL(width, CODEC_VP9_SUPER_BLOCK_WIDTH) / 32);
    uint32_t x = idx % (MOS_ALIGN_CEIL(width, CODEC_VP9_SUPER_BLOCK_WIDTH)/ 32);

    switch (blockSize)
    {
        case 0: // 16x16
            x *= 2;
            y *= 2;
            break;
        case 1: // 32x32 (no multiplier since streamin chunks are for 32x32)
            break;
        case 2: // 64x64
            x /= 2;
            y /= 2;
            break;
        case 3: // 8x8
            x *= 4;
            y *= 4;
            break;
    }

    uint32_t addr = y * bufferPitch;
    addr += x;

    return addr;
}

bool CodechalVdencVp9State::IsToBeCompressed(bool isDownScaledSurface)
{
    CODECHAL_ENCODE_FUNCTION_ENTER;
    // For regular encoding, we always compress this surface regardless of downscaling
    return m_mmcState ? m_mmcState->IsMmcEnabled() : false;
}

MOS_STATUS CodechalVdencVp9State::DysRefFrames()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    if (m_dysRefFrameFlags == DYS_REF_NONE)
    {
        return eStatus;
    }

    // allocate dynamic scaled surfaces if needed
    uint8_t idx = 0, refIdx = 0, numDysRefFrames = 0;
    if (m_dysRefFrameFlags & DYS_REF_LAST)
    {
        idx    = m_vp9PicParams->RefFrameList[m_vp9PicParams->RefFlags.fields.LastRefIdx].FrameIdx;
        refIdx = 1;
        numDysRefFrames++;
    }

    if (m_dysRefFrameFlags & DYS_REF_GOLDEN)
    {
        idx    = m_vp9PicParams->RefFrameList[m_vp9PicParams->RefFlags.fields.GoldenRefIdx].FrameIdx;
        refIdx = 2;
        numDysRefFrames++;
    }

    if (m_dysRefFrameFlags & DYS_REF_ALT)
    {
        idx    = m_vp9PicParams->RefFrameList[m_vp9PicParams->RefFlags.fields.AltRefIdx].FrameIdx;
        refIdx = 3;
        numDysRefFrames++;
    }

    if (numDysRefFrames > 1)
    {
        // for performance reason, we can only support single reference for dynamic scaling
        CODECHAL_ENCODE_ASSERTMESSAGE("Only single reference is supported for dynamic scaling!");
        return MOS_STATUS_INVALID_PARAMETER;
    }

    MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer;
    MOS_ZeroMemory(&allocParamsForBuffer, sizeof(MOS_ALLOC_GFXRES_PARAMS));
    allocParamsForBuffer.Type = MOS_GFXRES_2D;
    allocParamsForBuffer.TileType = MOS_TILE_Y;
    allocParamsForBuffer.Format = m_reconSurface.Format;
    allocParamsForBuffer.bIsCompressible = IsToBeCompressed(true);

    PCODEC_REF_LIST *refList = &m_refList[0];
    if (Mos_ResourceIsNull(&refList[idx]->sDysSurface.OsResource) ||
        (refList[idx]->sDysSurface.dwWidth != m_reconSurface.dwWidth) || (refList[idx]->sDysSurface.dwHeight != m_reconSurface.dwHeight))
    {
        // free existing resource first if resolution changes
        if (!Mos_ResourceIsNull(&refList[idx]->sDysSurface.OsResource))
        {
            m_osInterface->pfnFreeResource(
                m_osInterface,
                &refList[idx]->sDysSurface.OsResource);
        }

        allocParamsForBuffer.dwWidth = MOS_ALIGN_CEIL(m_reconSurface.dwWidth, CODEC_VP9_SUPER_BLOCK_WIDTH);
        allocParamsForBuffer.dwHeight = MOS_ALIGN_CEIL(m_reconSurface.dwHeight, CODEC_VP9_SUPER_BLOCK_HEIGHT);
        allocParamsForBuffer.pBufName = "Dynamic Scaled Surface for VP9";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBuffer,
            &refList[idx]->sDysSurface.OsResource));

        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(
            m_osInterface,
            &refList[idx]->sDysSurface));
    }

    refList[idx]->sDysSurface.dwWidth = m_oriFrameWidth;
    refList[idx]->sDysSurface.dwHeight = m_oriFrameHeight;

    // We use PAK to perform dynamic scaling for reference frame, basically if every CU is inter and skipped, the reconstructed picture will be
    // the down scaled copy of reference frame.
    // Here driver needs to prepare pak obj and cu record, since PAK has a limitation that input picture needs to be CU boundary aligned,
    // and to simplify handling the boundary condition, we set each CU with size 8x8, inter and zero MV.
    // Segment skip needs to be turned on also.

    auto oriFrameHeight = MOS_ALIGN_CEIL(m_oriFrameHeight, CODEC_VP9_MIN_BLOCK_HEIGHT);
    auto oriFrameWidth  = MOS_ALIGN_CEIL(m_oriFrameWidth, CODEC_VP9_MIN_BLOCK_WIDTH);

    uint32_t numCuLastSbCol = (oriFrameWidth / CODEC_VP9_MIN_BLOCK_WIDTH) - (m_picWidthInSb - 1) * (CODEC_VP9_SUPER_BLOCK_WIDTH / CODEC_VP9_MIN_BLOCK_WIDTH);
    uint32_t numCuLastSbRow = (oriFrameHeight / CODEC_VP9_MIN_BLOCK_HEIGHT) - (m_picHeightInSb - 1) * (CODEC_VP9_SUPER_BLOCK_HEIGHT / CODEC_VP9_MIN_BLOCK_HEIGHT);

    MOS_LOCK_PARAMS lockFlags;
    MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
    lockFlags.WriteOnly = 1;
    uint8_t* data = (uint8_t*)m_osInterface->pfnLockResource(
        m_osInterface, &m_resMbCodeSurface, &lockFlags);
    CODECHAL_ENCODE_CHK_NULL_RETURN(data);

    HcpPakObject* pakObjData = (HcpPakObject*)data;
    CU_DATA* cuDataPtr = (CU_DATA*)(data + m_mvOffset);

    // fill pak object
    HcpPakObject pakObj;
    MOS_ZeroMemory(&pakObj, sizeof(pakObj));
    pakObj.DW0.Type         = 0x03;
    pakObj.DW0.Opcode       = 0x27;
    pakObj.DW0.SubOp        = 0x35;
    pakObj.DW0.DwordLength  = 1;   //Total 4 DW. But only 3 DW are actual fields //DW 0,1 excluded from this field as per Spec definition

    pakObj.DW1.Split_flag_level0 = 1;
    pakObj.DW1.Split_flag_level1 = 0xF;
    pakObj.DW1.Split_flag_level2_level1part0 = 0xF;
    pakObj.DW1.Split_flag_level2_level1part1 = 0xF;
    pakObj.DW1.Split_flag_level2_level1part2 = 0xF;
    pakObj.DW1.Split_flag_level2_level1part3 = 0xF;

    // fill cu data
    CU_DATA cuData;
    MOS_ZeroMemory(&cuData, sizeof(cuData));
    cuData.cu_size = 0;  // 8x8
    cuData.cu_pred_mode0 = cuData.cu_pred_mode1 = 1;  // Inter
    cuData.refframe_part0_l0 = cuData.refframe_part1_l0 = refIdx;

    for (uint32_t j = 0; j < m_picHeightInSb; j++)
    {
        for (uint32_t  i = 0; i < m_picWidthInSb; i++)
        {
            if ((j == m_picHeightInSb - 1) && (i == m_picWidthInSb - 1))
            {
                pakObj.DW1.CU_count_minus1 = numCuLastSbCol * numCuLastSbRow - 1;
                pakObj.DW1.IsLastSBFrameflag = pakObj.DW1.IsLastSBTileflag = 1;
                pakObj.Reserved_DW03 = 0x05000000; // add batch buffer end flag
            }
            else if (i == m_picWidthInSb - 1)
            {
                pakObj.DW1.CU_count_minus1 = numCuLastSbCol * 8 - 1;
            }
            else if (j == m_picHeightInSb - 1)
            {
                pakObj.DW1.CU_count_minus1 = numCuLastSbRow * 8 - 1;
            }
            else
            {
                pakObj.DW1.CU_count_minus1 = 63;
            }

            pakObj.DW2.Current_SB_X_Addr = i;
            pakObj.DW2.Current_SB_Y_Addr = j;

            *pakObjData++ = pakObj;

            for (unsigned int cuIdx = 0; cuIdx < 64; cuIdx++)
            {
                *cuDataPtr++ = cuData;
            }
        }
    }

    m_osInterface->pfnUnlockResource(m_osInterface, &m_resMbCodeSurface);

    // save current state
    // we only need to run PAK to get the recon picture, so disable HuC and VDENC here
    m_vdencEnabled = false;
    m_dysHucEnabled = m_hucEnabled;
    m_hucEnabled = false;
    bool origWaitForENC = m_waitForEnc;
    m_waitForEnc = false;
    MOS_SURFACE origReconSurface = m_reconSurface;
    // Set the downscaled surface as the recon output surface
    m_reconSurface = refList[idx]->sDysSurface;
    // save the ucNumPasses and set the ucNumPasses = ucCurrPass + 1. otherwise SliceLevel will mistakenly treat current pass as last pass
    uint8_t origNumPasses = m_numPasses;
    m_numPasses = m_currPass + 1;

    bool origSegmentSkip[CODEC_VP9_MAX_SEGMENTS] = {false};
    for (auto i = 0; i < CODEC_VP9_MAX_SEGMENTS; i++)
    {
        origSegmentSkip[i]                                                = m_vp9SegmentParams->SegData[i].SegmentFlags.fields.SegmentSkipped;
        m_vp9SegmentParams->SegData[i].SegmentFlags.fields.SegmentSkipped = true;
    }

    CODECHAL_ENCODE_CHK_STATUS_RETURN(ExecuteDysPictureLevel());
    CODECHAL_ENCODE_CHK_STATUS_RETURN(ExecuteDysSliceLevel());

    CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
        &refList[idx]->sDysSurface,
        CodechalDbgAttr::attrReferenceSurfaces,
        (refIdx == 1) ? "DysLastScaledSurf" : (refIdx == 2) ? "DysGoldenScaledSurf" : "DysAltScaledSurf")));
    // recover state
    m_vdencEnabled = true;
    m_waitForEnc = origWaitForENC;
    m_reconSurface = origReconSurface;
    m_numPasses = origNumPasses;
    m_hucEnabled = (m_dysHucEnabled && !m_dysVdencMultiPassEnabled);
    for (auto i = 0; i < CODEC_VP9_MAX_SEGMENTS; i++)
    {
        m_vp9SegmentParams->SegData[i].SegmentFlags.fields.SegmentSkipped = origSegmentSkip[i];
    }

    return eStatus;
}

//------------------------------------------------------------------------------
//| Purpose:    Setup Sampler State for VP9 DYS Kernels
//| Return:     N/A
//------------------------------------------------------------------------------
MOS_STATUS CodechalVdencVp9State::SetSamplerStateDys(
    DysSamplerStateParams* params)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

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

    MHW_SAMPLER_STATE_PARAM samplerParams;
    MOS_ZeroMemory(&samplerParams, sizeof(samplerParams));

    samplerParams.bInUse = true;
    samplerParams.SamplerType = MHW_SAMPLER_TYPE_AVS;
    samplerParams.Avs.bEnableAVS = true;
    samplerParams.Avs.wR3cCoefficient = 15;
    samplerParams.Avs.wR3xCoefficient = 6;
    samplerParams.Avs.StrongEdgeThr = 8;
    samplerParams.Avs.WeakEdgeThr = 1;
    samplerParams.Avs.GainFactor = 32;
    samplerParams.Avs.bHdcDwEnable = 1;

    samplerParams.Avs.wR5cCoefficient = 3;
    samplerParams.Avs.wR5cxCoefficient = 8;
    samplerParams.Avs.wR5xCoefficient = 9;
    samplerParams.Avs.StrongEdgeWght = 6;
    samplerParams.Avs.RegularWght = 3;
    samplerParams.Avs.NonEdgeWght = 2;
    samplerParams.Avs.GlobalNoiseEstm = 255;

    samplerParams.Avs.AdditionalOverridesUsed = 1;
    samplerParams.Avs.YSlope2 = 24;
    samplerParams.Avs.S0L = 1792;
    samplerParams.Avs.YSlope1 = 24;
    samplerParams.Avs.S2U = 1792;
    samplerParams.Avs.S1U = 0;

    MHW_SAMPLER_AVS_TABLE_PARAM samplerTableParams;
    MOS_ZeroMemory(&samplerTableParams, sizeof(samplerTableParams));
    samplerParams.Avs.pMhwSamplerAvsTableParam = &samplerTableParams;

    MOS_SecureMemcpy(samplerTableParams.paMhwAvsCoeffParam,
        sizeof(samplerTableParams.paMhwAvsCoeffParam),
        m_samplerFilterCoeffs,
        MHW_NUM_HW_POLYPHASE_TABLES * 6 * sizeof(uint32_t));

    MOS_SecureMemcpy(samplerTableParams.paMhwAvsCoeffParamExtra,
        sizeof(samplerTableParams.paMhwAvsCoeffParamExtra),
        &m_samplerFilterCoeffs[MHW_NUM_HW_POLYPHASE_TABLES][0],
        MHW_NUM_HW_POLYPHASE_EXTRA_TABLES_G9 * 6 * sizeof(uint32_t));

    samplerTableParams.byteDefaultSharpnessLevel = 255;
    samplerTableParams.byteMaxDerivative4Pixels = 7;
    samplerTableParams.byteMaxDerivative8Pixels = 20;
    samplerTableParams.byteTransitionArea4Pixels = 4;
    samplerTableParams.byteTransitionArea8Pixels = 5;

    samplerTableParams.bBypassXAdaptiveFiltering = 1;
    samplerTableParams.bBypassYAdaptiveFiltering = 1;
    samplerTableParams.bAdaptiveFilterAllChannels = 0;

    MHW_RENDER_STATE_SIZES* hwSizes = m_stateHeapInterface->pStateHeapInterface->GetHwSizesPointer();
    CODECHAL_ENCODE_CHK_NULL_RETURN(hwSizes);
    uint8_t* sampler = (uint8_t*)MOS_AllocAndZeroMemory(hwSizes->dwSizeSamplerStateAvs);
    CODECHAL_ENCODE_CHK_NULL_RETURN(sampler);

    eStatus = m_stateHeapInterface->pfnSetSamplerState(m_stateHeapInterface, sampler, &samplerParams);
    if (eStatus != MOS_STATUS_SUCCESS)
    {
        MOS_FreeMemory(sampler);
        return eStatus;
    }

    eStatus = params->pKernelState->m_dshRegion.AddData(
        sampler,
        params->pKernelState->dwSamplerOffset,
        hwSizes->dwSizeSamplerStateAvs);

        MOS_FreeMemory(sampler);
        return eStatus;
}

//------------------------------------------------------------------------------
//| Purpose:    Setup Curbe for VP9 DYS Kernels
//| Return:     N/A
//------------------------------------------------------------------------------
MOS_STATUS CodechalVdencVp9State::SetCurbeDys(
    DysCurbeParams* params)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

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

    DysStaticData cmd;
    MOS_ZeroMemory(&cmd, sizeof(DysStaticData));

    cmd.DW0.InputFrameWidth         = params->dwInputWidth;;
    cmd.DW0.InputFrameHeight        = params->dwInputHeight;

    cmd.DW1.OutputFrameWidth        = params->dwOutputWidth;
    cmd.DW1.OutputFrameHeight       = params->dwOutputHeight;

    cmd.DW2.DeltaU                  = 1.0f / params->dwOutputWidth;
    cmd.DW3.DeltaV                  = 1.0f / params->dwOutputHeight;

    cmd.DW16.InputFrameNV12SurfBTI  = 0; //Surface 0
    cmd.DW17.OutputFrameYSurfBTI    = 1; //surface 1
    cmd.DW18.AVSSampleIdx           = 0;

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

    return eStatus;
}

// ------------------------------------------------------------------------------
// Send surfaces for the VP9 DYS kernel
//------------------------------------------------------------------------------------
MOS_STATUS CodechalVdencVp9State::SendDysSurfaces(
    PMOS_COMMAND_BUFFER cmdBuffer,
    DysSurfaceParams* 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->kernelState);
    CODECHAL_ENCODE_CHK_NULL_RETURN(params->dysBindingTable);

    DysBindingTable* dysBindingTable = (DysBindingTable*)params->dysBindingTable;

    CODECHAL_SURFACE_CODEC_PARAMS surfaceCodecParams;
    MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
    surfaceCodecParams.bUseAdvState         = true;
    surfaceCodecParams.psSurface            = params->inputFrameSurface;
    surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_CURR_ENCODE].Value;
    surfaceCodecParams.ucVDirection         = g_cMhw_VDirection[MHW_FRAME];
    surfaceCodecParams.dwBindingTableOffset = dysBindingTable->dysInputFrameNv12;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceCodecParams,
        params->kernelState));

    MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS));
    surfaceCodecParams.bIs2DSurface                 = true;
    surfaceCodecParams.bMediaBlockRW                = true;
    surfaceCodecParams.bUseUVPlane                  = true;
    surfaceCodecParams.psSurface                    = params->outputFrameSurface;
    surfaceCodecParams.dwCacheabilityControl        = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_CURR_ENCODE].Value;
    surfaceCodecParams.dwBindingTableOffset         = dysBindingTable->dysOutputFrameY;
    surfaceCodecParams.dwUVBindingTableOffset       = dysBindingTable->dysOutputFrameUV;
    surfaceCodecParams.dwVerticalLineStride         = params->verticalLineStride;
    surfaceCodecParams.dwVerticalLineStrideOffset   = params->verticalLineStrideOffset;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceCodecParams,
        params->kernelState));

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::DysKernel(
    DysKernelParams* dysKernelParams)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(dysKernelParams);

    PerfTagSetting perfTag;
    CODECHAL_ENCODE_SET_PERFTAG_INFO(perfTag, CODECHAL_ENCODE_PERFTAG_CALL_SCALING_KERNEL);

    MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferNV12;
    MOS_ZeroMemory(&allocParamsForBufferNV12, sizeof(MOS_ALLOC_GFXRES_PARAMS));
    allocParamsForBufferNV12.Type = MOS_GFXRES_2D;
    allocParamsForBufferNV12.TileType = MOS_TILE_Y;
    allocParamsForBufferNV12.Format = Format_NV12;

    PMHW_KERNEL_STATE kernelState = &m_dysKernelState;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnRequestSshSpaceForCmdBuf(
        m_stateHeapInterface,
        kernelState->KernelParams.iBTCount));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->AssignDshAndSshSpace(
        m_stateHeapInterface,
        kernelState,
        false,
        m_dysDshSize,
        false,
        m_storeData));

    DysSamplerStateParams dysSamplerStateParams;
    MOS_ZeroMemory(&dysSamplerStateParams, sizeof(dysSamplerStateParams));
    dysSamplerStateParams.pKernelState = kernelState;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(SetSamplerStateDys(&dysSamplerStateParams));

    DysCurbeParams dysCurbeParams;
    MOS_ZeroMemory(&dysCurbeParams, sizeof(dysCurbeParams));
    dysCurbeParams.dwInputWidth = dysKernelParams->dwInputWidth;
    dysCurbeParams.dwInputHeight = dysKernelParams->dwInputHeight;
    dysCurbeParams.dwOutputWidth = dysKernelParams->dwOutputWidth;
    dysCurbeParams.dwOutputHeight = dysKernelParams->dwOutputHeight;
    dysCurbeParams.pKernelState = kernelState;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(SetCurbeDys(&dysCurbeParams));

    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));

    CODECHAL_MEDIA_STATE_TYPE encFunctionType = CODECHAL_MEDIA_STATE_VP9_DYS;
    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));
    )

    m_vmeStatesSize = m_hwInterface->GetKernelLoadCommandSize(kernelState->KernelParams.iBTCount);
    CODECHAL_ENCODE_CHK_STATUS_RETURN(VerifyCommandBufferSize());

    MOS_COMMAND_BUFFER cmdBuffer;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(GetCommandBuffer(&cmdBuffer));

    SendKernelCmdsParams sendKernelCmdsParams = SendKernelCmdsParams();
    sendKernelCmdsParams.EncFunctionType = encFunctionType;
    sendKernelCmdsParams.pKernelState = kernelState;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(SendGenericKernelCmds(&cmdBuffer, &sendKernelCmdsParams));

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

    // allocate dynamic scaled surfaces if needed
    if (Mos_ResourceIsNull(&dysKernelParams->psOutputSurface->OsResource) ||
        (dysKernelParams->psOutputSurface->dwWidth != dysKernelParams->dwOutputWidth) || (dysKernelParams->psOutputSurface->dwHeight != dysKernelParams->dwOutputHeight))
    {
        // free existing resource first if resolution changes
        if (!Mos_ResourceIsNull(&dysKernelParams->psOutputSurface->OsResource))
        {
            m_osInterface->pfnFreeResource(
                m_osInterface,
                &dysKernelParams->psOutputSurface->OsResource);
        }

        allocParamsForBufferNV12.dwWidth = MOS_ALIGN_CEIL(dysKernelParams->dwOutputWidth, 64);
        allocParamsForBufferNV12.dwHeight = MOS_ALIGN_CEIL(dysKernelParams->dwOutputHeight, 64);
        allocParamsForBufferNV12.pBufName = "Dynamic Scaled Surface for VP9";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferNV12,
            &dysKernelParams->psOutputSurface->OsResource));

        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(
            m_osInterface,
            dysKernelParams->psOutputSurface));

        dysKernelParams->psOutputSurface->dwWidth = dysKernelParams->dwOutputWidth;
        dysKernelParams->psOutputSurface->dwHeight = dysKernelParams->dwOutputHeight;
    }

    // Add surface states
    DysSurfaceParams dysSurfaceParams;
    MOS_ZeroMemory(&dysSurfaceParams, sizeof(DysSurfaceParams));
    dysSurfaceParams.inputFrameSurface = dysKernelParams->psInputSurface;
    dysSurfaceParams.outputFrameSurface = dysKernelParams->psOutputSurface;
    dysSurfaceParams.verticalLineStride = m_verticalLineStride;
    dysSurfaceParams.verticalLineStrideOffset = m_verticalLineStrideOffset;
    dysSurfaceParams.kernelState = kernelState;
    dysSurfaceParams.dysBindingTable = &m_dysBindingTable;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(SendDysSurfaces(&cmdBuffer, &dysSurfaceParams));

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

    if (m_hwWalker)
    {
        uint32_t resolutionX = (uint32_t)m_picWidthInMb;
        uint32_t resolutionY = (uint32_t)m_frameFieldHeightInMb;

        CODECHAL_WALKER_CODEC_PARAMS walkerCodecParams;
        MOS_ZeroMemory(&walkerCodecParams, sizeof(walkerCodecParams));
        walkerCodecParams.WalkerMode = m_walkerMode;
        walkerCodecParams.dwResolutionX = resolutionX;
        walkerCodecParams.dwResolutionY = resolutionY;
        walkerCodecParams.bNoDependency = true;

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

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetRenderInterface()->AddMediaObjectWalkerCmd(
            &cmdBuffer,
            &walkerParams));
    }

    CODECHAL_ENCODE_CHK_STATUS_RETURN(EndStatusReport(&cmdBuffer, encFunctionType));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnUpdateGlobalCmdBufId(
        m_stateHeapInterface));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetMiInterface()->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));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(ReturnCommandBuffer(&cmdBuffer));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(SubmitCommandBuffer(&cmdBuffer, m_renderContextUsesNullHw));

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::InitMEState(
    VdencVmeState* state)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(state);
    MOS_ZeroMemory(state, sizeof(VdencVmeState));
    // Frame settings
    state->QpY                          = m_vp9PicParams->LumaACQIndex;
    state->CurrOriginalPic              = m_vp9PicParams->CurrOriginalPic;
    state->TargetUsage                  = m_vp9SeqParams->TargetUsage;
    state->GopRefDist                   = (uint8_t)m_vp9SeqParams->GopPicSize;  // -1 ??
    state->num_ref_idx_l0_active_minus1 = m_numRefFrames - 1;
    state->num_ref_idx_l1_active_minus1 = 0;

    // Constant values
    state->Level                        = 51;
    state->direct_spatial_mv_pred_flag  = true;
    state->dwBiWeight                   = 32;
    state->CurrOriginalPic.PicFlags     = PICTURE_FRAME;

    // Buffers
    state->s4xMeMvDataBuffer     = m_4xMeMvDataBuffer;
    state->s16xMeMvDataBuffer    = m_16xMeMvDataBuffer;
    state->s4xMeDistortionBuffer = m_4xMeDistortionBuffer;

    // Reference lookups
    // Use max of HEVC num surfaces because this is shared functionality between HEVC and VP9 and HEVC has less
    for (auto i = 0; i < CODECHAL_NUM_UNCOMPRESSED_SURFACE_HEVC ; ++i)
    {
        state->pRefList[i] = m_refList[i];
    }

    for (auto i = 0 ; i < CODEC_VP9_NUM_REF_FRAMES ; ++i)
    {
        state->PicIdx[i] = m_picIdx[i];
    }

    // Add references
    CODEC_PICTURE codecPicture;
    MOS_ZeroMemory(&codecPicture, sizeof(codecPicture));
    codecPicture.PicFlags = PICTURE_FRAME;
    uint8_t picCount = 0;
    if (m_lastRefPic)
    {
        codecPicture.FrameIdx               = m_vp9PicParams->RefFlags.fields.LastRefIdx;
        state->RefPicList[LIST_0][picCount] = codecPicture;
        picCount++;
    }

    if (m_goldenRefPic)
    {
        codecPicture.FrameIdx               = m_vp9PicParams->RefFlags.fields.GoldenRefIdx;
        state->RefPicList[LIST_0][picCount] = codecPicture;
        picCount++;
    }

    if (m_altRefPic)
    {
        codecPicture.FrameIdx               = m_vp9PicParams->RefFlags.fields.AltRefIdx;
        state->RefPicList[LIST_0][picCount] = codecPicture;
        picCount++;
    }

    // Mark L1[0] as INVALID so it's not added later, L1 refs should never be added for VP9, L1[0] should
    // always be marked as invalid and num_ref_idx_l1_active_minus1 should always == 0
    state->RefPicList[LIST_1][0].PicFlags = PICTURE_INVALID;

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::VdencSetCurbeHmeKernel(
    VdencVmeState* state)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

     CODECHAL_ENCODE_CHK_NULL_RETURN(state);

    bool isFramePicture  = CodecHal_PictureIsFrame(state->CurrOriginalPic);
    char qpPrimeY       = (state->QpY) + state->slice_qp_delta;

    VdencMeCurbe curbe;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(
        &curbe,
        sizeof(VdencMeCurbe),
        m_vdencMeCurbeInit,
        sizeof(VdencMeCurbe)));

    uint8_t mvShiftFactor = 0, prevMvReadPosFactor = 0;
    bool useMvFromPrevStep = false, writeDistortions = false;
    uint32_t scaleFactor = 0;
    PMHW_KERNEL_STATE kernelState;
    if (state->b16xMeInUse)
    {
        kernelState             = &m_vdencMeKernelState;
        useMvFromPrevStep       = false;
        writeDistortions        = false;
        scaleFactor            = SCALE_FACTOR_16x;
        mvShiftFactor          = 2;
        prevMvReadPosFactor    = 1;
    }
    else
    {
        kernelState             = &m_vdencStreaminKernelState;
        useMvFromPrevStep       = true;
        writeDistortions        = true;
        scaleFactor            = SCALE_FACTOR_4x;
        mvShiftFactor          = 2;
        prevMvReadPosFactor    = 0;
    }

    curbe.DW3.SubPelMode = 3;

    if (m_fieldScalingOutputInterleaved)
    {
        curbe.DW3.SrcAccess =
            curbe.DW3.RefAccess        = CodecHal_PictureIsField(state->CurrOriginalPic) ? 1 : 0;
        curbe.DW7.SrcFieldPolarity = CodecHal_PictureIsBottomField(state->CurrOriginalPic) ? 1 : 0;
    }

    curbe.DW4.PictureHeightMinus1    = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameFieldHeight / scaleFactor) - 1;
    curbe.DW4.PictureWidth           = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameWidth / scaleFactor);
    curbe.DW5.QpPrimeY               = qpPrimeY;
    curbe.DW6.WriteDistortions       = writeDistortions;
    curbe.DW6.UseMvFromPrevStep      = useMvFromPrevStep;
    curbe.DW6.SuperCombineDist       = 5;
    curbe.DW6.MaxVmvR                = m_maxMvLen;

    if (m_pictureCodingType == B_TYPE)
    {
        // This field is irrelevant since we are not using the bi-direct search.
        curbe.DW1.BiWeight              = state->dwBiWeight;
        curbe.DW13.NumRefIdxL1MinusOne  = state->num_ref_idx_l1_active_minus1;
    }

    if (m_pictureCodingType == P_TYPE ||  m_pictureCodingType == B_TYPE)
    {
        curbe.DW13.NumRefIdxL0MinusOne = state->num_ref_idx_l0_active_minus1;
    }

    curbe.DW30.ActualMBHeight   = (MOS_ALIGN_CEIL(m_frameHeight, CODEC_VP9_SUPER_BLOCK_HEIGHT ) / 32);
    curbe.DW30.ActualMBWidth    = (MOS_ALIGN_CEIL(m_frameWidth, CODEC_VP9_SUPER_BLOCK_WIDTH) / 32);
    curbe.DW13.RefStreaminCost  = 0;
    // This flag is to indicate the ROI source type instead of indicating ROI is enabled or not
    curbe.DW13.ROIEnable        = 0;

    uint8_t targetUsage = state->TargetUsage;
    uint8_t meMethod = 0;
    if (m_pictureCodingType == B_TYPE)
    {
        meMethod = m_bMeMethodGeneric[targetUsage];
    }
    else
    {
        meMethod = m_meMethodGeneric[targetUsage];
    }

    uint8_t tableIdx = (m_pictureCodingType == B_TYPE) ? 1 : 0;
    eStatus = MOS_SecureMemcpy(&(curbe.SPDelta), 14 * sizeof(uint32_t), m_encodeSearchPath[tableIdx][meMethod], 14 * sizeof(uint32_t));
    if (eStatus != MOS_STATUS_SUCCESS)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory.");
        return eStatus;
    }

    if (state->b4xMeInUse)
    {
        //StreamIn CURBE
        curbe.DW6.LCUSize                 = 1;//Only LCU64 supported by the VDEnc HW
        curbe.DW6.InputStreamInEn         = state->segmapProvided;
        curbe.DW31.NumImePredictors       = CODECHAL_VDENC_NUMIMEPREDICTORS;
        curbe.DW31.MaxCuSize              = 3;
        curbe.DW31.MaxTuSize              = 3;
        switch (state->TargetUsage)
        {
        case 1:
        case 4:
            curbe.DW36.NumMergeCandCu64x64 = 4;
            curbe.DW36.NumMergeCandCu32x32 = 3;
            curbe.DW36.NumMergeCandCu16x16 = 2;
            curbe.DW36.NumMergeCandCu8x8 = 1;
            break;
        case 7:
            curbe.DW36.NumMergeCandCu64x64 = 2;
            curbe.DW36.NumMergeCandCu32x32 = 2;
            curbe.DW36.NumMergeCandCu16x16 = 2;
            curbe.DW36.NumMergeCandCu8x8 = 0;
            break;
        }
    }

    curbe.DW40._4xMeMvOutputDataSurfIndex        = HmeMvDataSurfaceCm;
    curbe.DW41._16xOr32xMeMvInputDataSurfIndex   = Hme16xMeMvDataSurfaceCm;
    curbe.DW42._4xMeOutputDistSurfIndex          = HmeDistortionSurfaceCm;
    curbe.DW43._4xMeOutputBrcDistSurfIndex       = HmeBrcDistortionCm;
    curbe.DW44.VMEFwdInterPredictionSurfIndex    = HmeCurrForFwdRefCm;
    curbe.DW45.VMEBwdInterPredictionSurfIndex    = HmeCurrForBwdRefCm;
    curbe.DW46.VDEncStreamInOutputSurfIndex      = HmeVdencStreaminOutputCm;
    curbe.DW47.VDEncStreamInInputSurfIndex       = HmeVdencStreaminInputCm;

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

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::VdencSendHmeSurfaces(
    VdencVmeState* state,
    PMOS_COMMAND_BUFFER cmdBuffer)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(state);

    bool isCurrFieldPicture       = CodecHal_PictureIsField(m_currOriginalPic) ? true : false;
    bool isCurrBottomField        = CodecHal_PictureIsBottomField(m_currOriginalPic) ? true : false;
    uint8_t currVDirection        = (!isCurrFieldPicture) ? CODECHAL_VDIRECTION_FRAME :
        ((isCurrBottomField) ? CODECHAL_VDIRECTION_BOT_FIELD : CODECHAL_VDIRECTION_TOP_FIELD);

    PMHW_KERNEL_STATE kernelState = nullptr;
    PCODECHAL_ENCODE_BINDING_TABLE_GENERIC bindingTable = nullptr;
    PMOS_SURFACE currScaledSurface = nullptr, meMvDataBuffer = nullptr;
    uint32_t meMvBottomFieldOffset = 0, currScaledBottomFieldOffset = 0;
    uint32_t downscaledWidthInMb = 0, downscaledHeightInMb = 0;
    if (state->b16xMeInUse)
    {
        CODECHAL_ENCODE_CHK_NULL_RETURN(&state->s16xMeMvDataBuffer);
        kernelState                   = &m_vdencMeKernelState;
        bindingTable                  = &m_vdencMeKernelBindingTable;
        currScaledSurface            = m_trackedBuf->Get16xDsSurface(CODEC_CURR_TRACKED_BUFFER);
        meMvDataBuffer               = &state->s16xMeMvDataBuffer;
        meMvBottomFieldOffset        = 0;
        currScaledBottomFieldOffset  = m_scaled16xBottomFieldOffset;
        downscaledWidthInMb          = m_downscaledWidthInMb16x;
        downscaledHeightInMb         = m_downscaledHeightInMb16x;
    }
    else
    {
        CODECHAL_ENCODE_CHK_NULL_RETURN(&state->s4xMeMvDataBuffer);
        CODECHAL_ENCODE_CHK_NULL_RETURN(&m_resVdencStreamInBuffer[m_currRecycledBufIdx]);
        kernelState                  = &m_vdencStreaminKernelState;
        bindingTable                 = &m_vdencStreaminKernelBindingTable;
        currScaledSurface           = m_trackedBuf->Get4xDsSurface(CODEC_CURR_TRACKED_BUFFER);
        meMvDataBuffer              = &state->s4xMeMvDataBuffer;
        meMvBottomFieldOffset       = 0;
        currScaledBottomFieldOffset = m_scaledBottomFieldOffset;
        downscaledWidthInMb         = m_downscaledWidthInMb4x;
        downscaledHeightInMb        = m_downscaledHeightInMb4x;
    }

    uint32_t width  = MOS_ALIGN_CEIL(downscaledWidthInMb * 32, 64);
    uint32_t height = downscaledHeightInMb * 4 * 10;

    // Force the values
    meMvDataBuffer->dwWidth   = width;
    meMvDataBuffer->dwHeight  = height;
    meMvDataBuffer->dwPitch   = width;

    CODECHAL_SURFACE_CODEC_PARAMS surfaceCodecParams;
    MOS_ZeroMemory(&surfaceCodecParams, sizeof(surfaceCodecParams));
    surfaceCodecParams.bIs2DSurface    = true;
    surfaceCodecParams.bMediaBlockRW   = true;
    surfaceCodecParams.psSurface       = meMvDataBuffer;
    surfaceCodecParams.dwOffset        = meMvBottomFieldOffset;
    surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_MV_DATA_ENCODE].Value;
    surfaceCodecParams.dwBindingTableOffset  = bindingTable->dwBindingTableEntries[HmeMvDataSurfaceCm];
    surfaceCodecParams.bIsWritable   = true;
    surfaceCodecParams.bRenderTarget = true;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
        m_hwInterface,
        cmdBuffer,
        &surfaceCodecParams,
        kernelState));

    if (state->b4xMeInUse)
    {
        // Pass 16x MV to 4x ME operation
        MOS_ZeroMemory(&surfaceCodecParams, sizeof(surfaceCodecParams));
        surfaceCodecParams.bIs2DSurface             = true;
        surfaceCodecParams.bMediaBlockRW            = true;
        surfaceCodecParams.psSurface                = &state->s16xMeMvDataBuffer;
        surfaceCodecParams.dwOffset                 = 0;
        surfaceCodecParams.dwCacheabilityControl    = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_MV_DATA_ENCODE].Value;
        surfaceCodecParams.dwBindingTableOffset     = bindingTable->dwBindingTableEntries[Hme16xMeMvDataSurfaceCm];
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));

        MOS_ZeroMemory(&surfaceCodecParams, sizeof(surfaceCodecParams));
        surfaceCodecParams.bIs2DSurface          = true;
        surfaceCodecParams.bMediaBlockRW         = true;
        surfaceCodecParams.psSurface             = &state->s4xMeDistortionBuffer;
        surfaceCodecParams.dwOffset              = 0;
        surfaceCodecParams.dwBindingTableOffset  = bindingTable->dwBindingTableEntries[HmeDistortionSurfaceCm];
        surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_ME_DISTORTION_ENCODE].Value;
        surfaceCodecParams.bIsWritable           = true;
        surfaceCodecParams.bRenderTarget         = true;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }

    // Setup references 1...n
    // LIST 0 references
    MOS_SURFACE refScaledSurface = *currScaledSurface;
    for (uint8_t refIdx = 0; refIdx <= state->num_ref_idx_l0_active_minus1; refIdx++)
    {
        CODEC_PICTURE refPic = state->RefPicList[LIST_0][refIdx];

        if (!CodecHal_PictureIsInvalid(refPic))
        {
            if (refIdx == 0)
            {
                // Current Picture Y - VME
                MOS_ZeroMemory(&surfaceCodecParams, sizeof(surfaceCodecParams));
                surfaceCodecParams.bUseAdvState             = true;
                surfaceCodecParams.psSurface                = currScaledSurface;
                surfaceCodecParams.dwOffset                 = isCurrBottomField ? currScaledBottomFieldOffset : 0;
                surfaceCodecParams.dwCacheabilityControl    = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_CURR_ENCODE].Value;
                surfaceCodecParams.dwBindingTableOffset     = bindingTable->dwBindingTableEntries[HmeCurrForFwdRefCm];
                surfaceCodecParams.ucVDirection             = currVDirection;
                CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
                    m_hwInterface,
                    cmdBuffer,
                    &surfaceCodecParams,
                    kernelState));
            }

            bool isRefFieldPicture = CodecHal_PictureIsField(refPic) ? 1 : 0;
            bool isRefBottomField = (CodecHal_PictureIsBottomField(refPic)) ? 1 : 0;
            uint8_t refPicIdx    = state->PicIdx[refPic.FrameIdx].ucPicIdx;
            uint8_t scaledIdx    = state->pRefList[refPicIdx]->ucScalingIdx;
            if (state->b16xMeInUse)
            {
                MOS_SURFACE* p16xSurface = m_trackedBuf->Get16xDsSurface(scaledIdx);
                if (p16xSurface != nullptr)
                {
                    refScaledSurface.OsResource = p16xSurface->OsResource;
                }
                else
                {
                    CODECHAL_ENCODE_ASSERTMESSAGE("NULL pointer of DsSurface");
                }
            }
            else
            {
                MOS_SURFACE* p4xSurface = m_trackedBuf->Get4xDsSurface(scaledIdx);
                if (p4xSurface != nullptr)
                {
                    refScaledSurface.OsResource = p4xSurface->OsResource;
                }
                else
                {
                    CODECHAL_ENCODE_ASSERTMESSAGE("NULL pointer of DsSurface");
                }
            }
            uint32_t refScaledBottomFieldOffset = isRefBottomField ? currScaledBottomFieldOffset : 0;

            // L0 Reference Picture Y - VME
            MOS_ZeroMemory(&surfaceCodecParams, sizeof(surfaceCodecParams));
            surfaceCodecParams.bUseAdvState             = true;
            surfaceCodecParams.psSurface                = &refScaledSurface;
            surfaceCodecParams.dwOffset                 = isRefBottomField ? refScaledBottomFieldOffset : 0;
            surfaceCodecParams.dwCacheabilityControl    = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_REF_ENCODE].Value;
            surfaceCodecParams.dwBindingTableOffset     = bindingTable->dwBindingTableEntries[HmeFwdRefIdx0Cm + (refIdx * 2)];
            surfaceCodecParams.ucVDirection = !isCurrFieldPicture ? CODECHAL_VDIRECTION_FRAME :
                ((isRefBottomField) ? CODECHAL_VDIRECTION_BOT_FIELD : CODECHAL_VDIRECTION_TOP_FIELD);
            CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
                m_hwInterface,
                cmdBuffer,
                &surfaceCodecParams,
                kernelState));
        }
    }

    //List1
    for (uint8_t refIdx = 0; refIdx <= state->num_ref_idx_l1_active_minus1; refIdx++)
    {
        CODEC_PICTURE refPic = state->RefPicList[LIST_1][refIdx];

        if (!CodecHal_PictureIsInvalid(refPic))
        {
            if (refIdx == 0)
            {
                // Current Picture Y - VME
                MOS_ZeroMemory(&surfaceCodecParams, sizeof(surfaceCodecParams));
                surfaceCodecParams.bUseAdvState             = true;
                surfaceCodecParams.psSurface                = currScaledSurface;
                surfaceCodecParams.dwOffset                 = isCurrBottomField ? currScaledBottomFieldOffset : 0;
                surfaceCodecParams.dwCacheabilityControl    = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_CURR_ENCODE].Value;
                surfaceCodecParams.dwBindingTableOffset     = bindingTable->dwBindingTableEntries[HmeCurrForBwdRefCm];
                surfaceCodecParams.ucVDirection             = currVDirection;
                CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
                    m_hwInterface,
                    cmdBuffer,
                    &surfaceCodecParams,
                    kernelState));
            }

            bool isRefFieldPicture             = CodecHal_PictureIsField(refPic) ? 1 : 0;
            bool isRefBottomField              = (CodecHal_PictureIsBottomField(refPic)) ? 1 : 0;
            uint8_t refPicIdx                  = state->PicIdx[refPic.FrameIdx].ucPicIdx;
            uint8_t scaledIdx                  = state->pRefList[refPicIdx]->ucScalingIdx;
            if (state->b16xMeInUse)
            {
                MOS_SURFACE* p16xSurface = m_trackedBuf->Get16xDsSurface(scaledIdx);
                if (p16xSurface != nullptr)
                {
                    refScaledSurface.OsResource = p16xSurface->OsResource;
                }
                else
                {
                    CODECHAL_ENCODE_ASSERTMESSAGE("NULL pointer of DsSurface");
                }
            }
            else
            {
                MOS_SURFACE* p4xSurface = m_trackedBuf->Get4xDsSurface(scaledIdx);
                if (p4xSurface != nullptr)
                {
                    refScaledSurface.OsResource = p4xSurface->OsResource;
                }
                else
                {
                    CODECHAL_ENCODE_ASSERTMESSAGE("NULL pointer of DsSurface");
                }
            }
            
            uint32_t refScaledBottomFieldOffset = isRefBottomField ? currScaledBottomFieldOffset : 0;

            // L1 Reference Picture Y - VME
            MOS_ZeroMemory(&surfaceCodecParams, sizeof(surfaceCodecParams));
            surfaceCodecParams.bUseAdvState             = true;
            surfaceCodecParams.psSurface                = &refScaledSurface;
            surfaceCodecParams.dwOffset                 = isRefBottomField ? refScaledBottomFieldOffset : 0;
            surfaceCodecParams.dwCacheabilityControl    = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_REF_ENCODE].Value;
            surfaceCodecParams.dwBindingTableOffset     = bindingTable->dwBindingTableEntries[HmeBwdRefIdx0Cm + (refIdx * 2)];
            surfaceCodecParams.ucVDirection = !isCurrFieldPicture ? CODECHAL_VDIRECTION_FRAME :
                ((isRefBottomField) ? CODECHAL_VDIRECTION_BOT_FIELD : CODECHAL_VDIRECTION_TOP_FIELD);
            CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
                m_hwInterface,
                cmdBuffer,
                &surfaceCodecParams,
                kernelState));
        }
    }

    if (state->b4xMeInUse)
    {
        MOS_ZeroMemory(&surfaceCodecParams, sizeof(surfaceCodecParams));
        surfaceCodecParams.dwSize                   = MOS_BYTES_TO_DWORDS(MOS_ALIGN_CEIL(m_frameWidth, CODEC_VP9_SUPER_BLOCK_WIDTH) / 32 * MOS_ALIGN_CEIL(m_frameHeight, CODEC_VP9_SUPER_BLOCK_HEIGHT) / 32 * CODECHAL_CACHELINE_SIZE);
        surfaceCodecParams.bIs2DSurface             = false;
        surfaceCodecParams.presBuffer               = &m_resVdencStreamInBuffer[m_currRecycledBufIdx];
        surfaceCodecParams.dwBindingTableOffset     = bindingTable->dwBindingTableEntries[HmeVdencStreaminOutputCm];
        surfaceCodecParams.dwCacheabilityControl    = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_BRC_ME_DISTORTION_ENCODE].Value;
        surfaceCodecParams.bIsWritable              = true;
        surfaceCodecParams.bRenderTarget            = true;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState(
            m_hwInterface,
            cmdBuffer,
            &surfaceCodecParams,
            kernelState));
    }

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::VdencHmeKernel(
    VdencVmeState* state)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(state);

    PMHW_KERNEL_STATE kernelState = nullptr;
    CODECHAL_MEDIA_STATE_TYPE encFunctionType;
    if (state->b16xMeInUse)
    {
        kernelState    = &m_vdencMeKernelState;
        encFunctionType = CODECHAL_MEDIA_STATE_16X_ME;
    }
    else
    {
        kernelState    = &m_vdencStreaminKernelState;
        encFunctionType = CODECHAL_MEDIA_STATE_4X_ME;
    }

    // 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());
    }

    // Set up the DSH/SSH as normal
    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));

    //Setup curbe for StreamIn Kernel
    CODECHAL_ENCODE_CHK_STATUS_RETURN(VdencSetCurbeHmeKernel(
        state));

    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));
    )

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

    SendKernelCmdsParams sendKernelCmdsParams = SendKernelCmdsParams();
    sendKernelCmdsParams.EncFunctionType = encFunctionType;
    sendKernelCmdsParams.pKernelState = kernelState;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(SendGenericKernelCmds(&cmdBuffer, &sendKernelCmdsParams));

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

    uint32_t scalingFactor = (state->b16xMeInUse) ? SCALE_FACTOR_16x : SCALE_FACTOR_4x;

    VdencSendHmeSurfaces(state, &cmdBuffer);

    // Dump SSH for ME kernel
    CODECHAL_DEBUG_TOOL(
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion(
            encFunctionType,
            MHW_SSH_TYPE,
            kernelState)));

    uint32_t resolutionX = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth / scalingFactor);
    uint32_t resolutionY = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameFieldHeight / scalingFactor);

    CODECHAL_WALKER_CODEC_PARAMS walkerCodecParams;
    MOS_ZeroMemory(&walkerCodecParams, sizeof(walkerCodecParams));
    walkerCodecParams.WalkerMode                 = m_walkerMode;
    walkerCodecParams.dwResolutionX              = resolutionX;
    walkerCodecParams.dwResolutionY              = resolutionY;
    walkerCodecParams.bNoDependency              = true;
    walkerCodecParams.bMbaff                     = state->bMbaff ? true : false;
    walkerCodecParams.bGroupIdSelectSupported    = m_groupIdSelectSupported;
    walkerCodecParams.ucGroupId                  = m_groupId;

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

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

    CODECHAL_ENCODE_CHK_STATUS_RETURN(EndStatusReport(&cmdBuffer, encFunctionType));

    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)));

    m_hwInterface->UpdateSSEuForCmdBuffer(&cmdBuffer, m_singleTaskPhaseSupported, m_lastTaskInPhase);

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

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

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::ConstructPakInsertObjBatchBuf(
    PMOS_RESOURCE pakInsertObjBuffer)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    if (!pakInsertObjBuffer)
    {
        return MOS_STATUS_INVALID_PARAMETER;
    }

    CODECHAL_ENCODE_ASSERT(m_numNalUnit == 1);

    uint32_t nalUnitSize = m_nalUnitParams[0]->uiSize;
    uint32_t nalUnitOffset = m_nalUnitParams[0]->uiOffset;
    CODECHAL_ENCODE_ASSERT(nalUnitSize > 0 && nalUnitSize < CODECHAL_ENCODE_VP9_PAK_INSERT_UNCOMPRESSED_HEADER);

    MOS_LOCK_PARAMS lockFlagsWriteOnly;
    MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
    lockFlagsWriteOnly.WriteOnly = 1;
    uint8_t* data = (uint8_t*)m_osInterface->pfnLockResource(m_osInterface, pakInsertObjBuffer, &lockFlagsWriteOnly);
    CODECHAL_ENCODE_CHK_NULL_RETURN(data);

    MHW_VDBOX_PAK_INSERT_PARAMS pakInsertObjectParams;
    MOS_ZeroMemory(&pakInsertObjectParams, sizeof(pakInsertObjectParams));
    pakInsertObjectParams.bEmulationByteBitsInsert = false;
    pakInsertObjectParams.uiSkipEmulationCheckCount = m_nalUnitParams[0]->uiSkipEmulationCheckCount;
    pakInsertObjectParams.pBsBuffer = &m_bsBuffer;
    pakInsertObjectParams.dwBitSize = nalUnitSize * 8;
    pakInsertObjectParams.dwOffset = nalUnitOffset;
    pakInsertObjectParams.bEndOfSlice               = false;
    pakInsertObjectParams.bLastHeader               = true;

    MOS_COMMAND_BUFFER constructedCmdBuf;
    MOS_ZeroMemory(&constructedCmdBuf, sizeof(constructedCmdBuf));
    constructedCmdBuf.pCmdBase = (uint32_t *)data;
    constructedCmdBuf.pCmdPtr = (uint32_t *)data;
    constructedCmdBuf.iOffset = 0;
    constructedCmdBuf.iRemaining = CODECHAL_ENCODE_VP9_PAK_INSERT_UNCOMPRESSED_HEADER;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpPakInsertObject(&constructedCmdBuf, &pakInsertObjectParams));
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&constructedCmdBuf, nullptr));

    if (data)
    {
        m_osInterface->pfnUnlockResource(
            m_osInterface,
            pakInsertObjBuffer);
    }
    return eStatus;
}

void CodechalVdencVp9State::PutDataForCompressedHdr(
    CompressedHeader* compressedHdr,
    uint32_t bit,
    uint32_t prob,
    uint32_t binIdx)
{
    compressedHdr[binIdx].fields.valid = 1;
    compressedHdr[binIdx].fields.bin_probdiff = 1;
    compressedHdr[binIdx].fields.bin = bit;
    compressedHdr[binIdx].fields.prob = (prob == 128) ? 0 : 1;
}

// This function is NOT needed when HUC kernel is enabled.
// It only uses the default probablity and can NOT handle probability update!
MOS_STATUS CodechalVdencVp9State::RefreshFrameInternalBuffers()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_ASSERT(m_vp9PicParams->PicFlags.fields.refresh_frame_context == 0);

    MOS_LOCK_PARAMS lockFlagsWriteOnly;
    MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
    lockFlagsWriteOnly.WriteOnly = 1;

    bool keyFrame  = !m_vp9PicParams->PicFlags.fields.frame_type;
    bool isScaling = (m_oriFrameWidth == m_prevFrameInfo.FrameWidth) &&
                             (m_oriFrameHeight == m_prevFrameInfo.FrameHeight)
                         ? false
                         : true;
    bool resetSegIdBuf = keyFrame || isScaling ||
                         m_vp9PicParams->PicFlags.fields.error_resilient_mode ||
                         m_vp9PicParams->PicFlags.fields.intra_only;

    if (resetSegIdBuf)
    {
        uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(
            m_osInterface,
            &m_resSegmentIdBuffer,
            &lockFlagsWriteOnly);

        CODECHAL_ENCODE_CHK_NULL_RETURN(data);

        MOS_ZeroMemory(data, m_picSizeInSb * CODECHAL_CACHELINE_SIZE);

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
            m_osInterface,
            &m_resSegmentIdBuffer));
    }

    //refresh inter probs in needed frame context buffers
    bool clearAll = (keyFrame || m_vp9PicParams->PicFlags.fields.error_resilient_mode ||
                     (m_vp9PicParams->PicFlags.fields.reset_frame_context == 3 && m_vp9PicParams->PicFlags.fields.intra_only));

    bool clearSpecified = (m_vp9PicParams->PicFlags.fields.reset_frame_context == 2 &&
                           m_vp9PicParams->PicFlags.fields.intra_only);

    MOS_STATUS status1 = MOS_STATUS_SUCCESS;
    for (auto i = 0; i < CODEC_VP9_NUM_CONTEXTS; i++)
    {
        if (clearAll || (clearSpecified && i == m_vp9PicParams->PicFlags.fields.frame_context_idx))
        {
            uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(
                m_osInterface,
                &m_resProbBuffer[i],
                &lockFlagsWriteOnly);
            CODECHAL_ENCODE_CHK_NULL_RETURN(data);

            status1 = ContextBufferInit(data, keyFrame || m_vp9PicParams->PicFlags.fields.intra_only);

            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
                m_osInterface,
                &m_resProbBuffer[i]));
            CODECHAL_ENCODE_CHK_STATUS_RETURN(status1);

            m_clearAllToKey[i] = keyFrame || m_vp9PicParams->PicFlags.fields.intra_only;
            if (i == 0)  //reset this flag when Ctx buffer 0 is cleared.
            {
                m_isPreCtx0InterProbSaved = false;
            }
        }
        else if (m_clearAllToKey[i]) // this buffer is inside inter frame, but its interProb has not been init to default inter type data.
        {
            uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(
                m_osInterface,
                &m_resProbBuffer[i],
                &lockFlagsWriteOnly);
            CODECHAL_ENCODE_CHK_NULL_RETURN(data);

            if (m_vp9PicParams->PicFlags.fields.intra_only && i == 0)  // this buffer is used as intra_only context, do not need to set interprob to be inter type.
            {
                status1 = CtxBufDiffInit(data, true);
            }
            else // set interprob to be inter type.
            {
                status1 = CtxBufDiffInit(data, false);
                m_clearAllToKey[i] = false;
            }

            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
                m_osInterface,
                &m_resProbBuffer[i]));
            CODECHAL_ENCODE_CHK_STATUS_RETURN(status1);
        }
        else if (i == 0) // this buffer do not need to clear in current frame, also it has not been cleared to key type in previous frame.
        {                // in this case, only context buffer 0 will be temporally overwritten.
            if (m_vp9PicParams->PicFlags.fields.intra_only)
            {
                uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(
                    m_osInterface,
                    &m_resProbBuffer[i],
                    &lockFlagsWriteOnly);
                CODECHAL_ENCODE_CHK_NULL_RETURN(data);

                if (!m_isPreCtx0InterProbSaved)  // only when non intra-only -> intra-only need save InterProb, otherwise leave saved InterProb unchanged.
                {
                    //save current interprob
                    CODECHAL_ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(m_preCtx0InterProbSaved, CODECHAL_VP9_INTER_PROB_SIZE, data + CODEC_VP9_INTER_PROB_OFFSET, CODECHAL_VP9_INTER_PROB_SIZE));
                    m_isPreCtx0InterProbSaved = true;
                }
                status1 = CtxBufDiffInit(data, true);
                CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
                    m_osInterface,
                    &m_resProbBuffer[i]));
                CODECHAL_ENCODE_CHK_STATUS_RETURN(status1);
            }
            else if (m_isPreCtx0InterProbSaved)
            {
                uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(
                    m_osInterface,
                    &m_resProbBuffer[i],
                    &lockFlagsWriteOnly);
                CODECHAL_ENCODE_CHK_NULL_RETURN(data);
                //reload former interprob
                CODECHAL_ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(data + CODEC_VP9_INTER_PROB_OFFSET, CODECHAL_VP9_INTER_PROB_SIZE, m_preCtx0InterProbSaved, CODECHAL_VP9_INTER_PROB_SIZE));

                CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
                    m_osInterface,
                    &m_resProbBuffer[i]));

                m_isPreCtx0InterProbSaved = false;
            }
        }
    }

    // compressed header
    uint32_t index = 0;
    CompressedHeader* compressedHdr = (CompressedHeader*)MOS_AllocAndZeroMemory(sizeof(CompressedHeader)* (PAK_COMPRESSED_HDR_SYNTAX_ELEMS + 1));
    CODECHAL_ENCODE_CHK_NULL_RETURN(compressedHdr);

    if (!m_vp9PicParams->PicFlags.fields.LosslessFlag)
    {
        if (m_txMode == CODEC_VP9_TX_SELECTABLE)
        {
            PutDataForCompressedHdr(compressedHdr, 1, 128, PAK_TX_MODE_IDX);
            PutDataForCompressedHdr(compressedHdr, 1, 128, PAK_TX_MODE_IDX + 1);
            PutDataForCompressedHdr(compressedHdr, 1, 128, PAK_TX_MODE_SELECT_IDX);
        }
        else if (m_txMode == CODEC_VP9_TX_32X32)
        {
            PutDataForCompressedHdr(compressedHdr, 1, 128, PAK_TX_MODE_IDX);
            PutDataForCompressedHdr(compressedHdr, 1, 128, PAK_TX_MODE_IDX + 1);
            PutDataForCompressedHdr(compressedHdr, 0, 128, PAK_TX_MODE_SELECT_IDX);
        }
        else
        {
            PutDataForCompressedHdr(compressedHdr, (m_txMode & 0x02) >> 1, 128, PAK_TX_MODE_IDX);
            PutDataForCompressedHdr(compressedHdr, (m_txMode & 0x01), 128, PAK_TX_MODE_IDX + 1);
        }

        if (m_txMode == CODEC_VP9_TX_SELECTABLE)
        {
            index = PAK_TX_8x8_PROB_IDX;
            for (auto i = 0; i < 2; i++)
            {
                PutDataForCompressedHdr(compressedHdr, 0, 252, index);
                index += 2;
            }

            index = PAK_TX_16x16_PROB_IDX;
            for (auto i = 0; i < 2; i++)
            {
                for (auto j = 0; j < 2; j++)
                {
                    PutDataForCompressedHdr(compressedHdr, 0, 252, index);
                    index += 2;
                }
            }

            index = PAK_TX_32x32_PROB_IDX;
            for (auto i = 0; i < 2; i++)
            {
                for (auto j = 0; j < 3; j++)
                {
                    PutDataForCompressedHdr(compressedHdr, 0, 252, index);
                    index += 2;
                }
            }
        }
    }

    for (auto coeffSize = 0; coeffSize < 4; coeffSize++)
    {
        if (coeffSize > m_txMode)
        {
            continue;
        }

        switch (coeffSize)
        {
        case 0: index = PAK_TX_4x4_COEFF_PROB_IDX;
            break;
        case 1: index = PAK_TX_8x8_COEFF_PROB_IDX;
            break;
        case 2: index = PAK_TX_16x16_COEFF_PROB_IDX;
            break;
        case 3: index = PAK_TX_32x32_COEFF_PROB_IDX;
            break;
        }

        PutDataForCompressedHdr(compressedHdr, 0, 128, index);
    }

    PutDataForCompressedHdr(compressedHdr, 0, 252, PAK_SKIP_CONTEXT_IDX);
    PutDataForCompressedHdr(compressedHdr, 0, 252, PAK_SKIP_CONTEXT_IDX + 2);
    PutDataForCompressedHdr(compressedHdr, 0, 252, PAK_SKIP_CONTEXT_IDX + 4);

    if (m_vp9PicParams->PicFlags.fields.frame_type != 0 && !m_vp9PicParams->PicFlags.fields.intra_only)
    {
        index = PAK_INTER_MODE_CTX_IDX;
        for (auto i = 0; i < 7; i++)
        {
            for (auto j = 0; j < 3; j++)
            {
                PutDataForCompressedHdr(compressedHdr, 0, 252, index);
                index += 2;
            }
        }

        if (m_vp9PicParams->PicFlags.fields.mcomp_filter_type == CODEC_VP9_SWITCHABLE_FILTERS)
        {
            index = PAK_SWITCHABLE_FILTER_CTX_IDX;
            for (auto i = 0; i < 4; i++)
            {
                for (auto j = 0; j < 2; j++)
                {
                    PutDataForCompressedHdr(compressedHdr, 0, 252, index);
                    index += 2;
                }
            }
        }

        index = PAK_INTRA_INTER_CTX_IDX;
        for (auto i = 0; i < 4; i++)
        {
            PutDataForCompressedHdr(compressedHdr, 0, 252, index);
            index += 2;
        }

        bool allowComp = !(
            (m_vp9PicParams->RefFlags.fields.LastRefSignBias && m_vp9PicParams->RefFlags.fields.GoldenRefSignBias && m_vp9PicParams->RefFlags.fields.AltRefSignBias) ||
            (!m_vp9PicParams->RefFlags.fields.LastRefSignBias && !m_vp9PicParams->RefFlags.fields.GoldenRefSignBias && !m_vp9PicParams->RefFlags.fields.AltRefSignBias));

        if (allowComp)
        {
            if (m_vp9PicParams->PicFlags.fields.comp_prediction_mode == PRED_MODE_HYBRID)
            {
                PutDataForCompressedHdr(compressedHdr, 1, 128, PAK_COMPOUND_PRED_MODE_IDX);
                PutDataForCompressedHdr(compressedHdr, 1, 128, PAK_COMPOUND_PRED_MODE_IDX + 1);
                index = PAK_HYBRID_PRED_CTX_IDX;
                for (auto i = 0; i < 5; i++)
                {
                    PutDataForCompressedHdr(compressedHdr, 0, 252, index);
                    index += 2;
                }
            }
            else if (m_vp9PicParams->PicFlags.fields.comp_prediction_mode == PRED_MODE_COMPOUND)
            {
                PutDataForCompressedHdr(compressedHdr, 1, 128, PAK_COMPOUND_PRED_MODE_IDX);
                PutDataForCompressedHdr(compressedHdr, 0, 128, PAK_COMPOUND_PRED_MODE_IDX + 1);
            }
            else
            {
                PutDataForCompressedHdr(compressedHdr, 0, 128, PAK_COMPOUND_PRED_MODE_IDX);
            }
        }

        if (m_vp9PicParams->PicFlags.fields.comp_prediction_mode != PRED_MODE_COMPOUND)
        {
            index = PAK_SINGLE_REF_PRED_CTX_IDX;
            for (auto i = 0; i < 5; i++)
            {
                for (auto j = 0; j < 2; j++)
                {
                    PutDataForCompressedHdr(compressedHdr, 0, 252, index);
                    index += 2;
                }
            }
        }

        if (m_vp9PicParams->PicFlags.fields.comp_prediction_mode != PRED_MODE_SINGLE)
        {
            index = PAK_CMPUND_PRED_CTX_IDX;
            for (auto i = 0; i < 5; i++)
            {
                PutDataForCompressedHdr(compressedHdr, 0, 252, index);
                index += 2;
            }
        }

        index = PAK_INTRA_MODE_PROB_CTX_IDX;
        for (auto i = 0; i < 4; i++)
        {
            for (auto j = 0; j < 9; j++)
            {
                PutDataForCompressedHdr(compressedHdr, 0, 252, index);
                index += 2;
            }
        }

        index = PAK_PARTITION_PROB_IDX;
        for (auto i = 0; i < 16; i++)
        {
            for (auto j = 0; j < 3; j++)
            {
                PutDataForCompressedHdr(compressedHdr, 0, 252, index);
                index += 2;
            }
        }

        index = PAK_MVJOINTS_PROB_IDX;
        for (auto i = 0; i < 3; i++)
        {
            PutDataForCompressedHdr(compressedHdr, 0, 252, index);
            index += 8;
        }

        for (auto d = 0; d < 2; d++)
        {
            index = (d == 0) ? PAK_MVCOMP0_IDX : PAK_MVCOMP1_IDX;
            PutDataForCompressedHdr(compressedHdr, 0, 252, index);
            index += 8;
            for (auto i = 0; i < 10; i++)
            {
                PutDataForCompressedHdr(compressedHdr, 0, 252, index);
                index += 8;
            }
            PutDataForCompressedHdr(compressedHdr, 0, 252, index);
            index += 8;
            for (auto i = 0; i < 10; i++)
            {
                PutDataForCompressedHdr(compressedHdr, 0, 252, index);
                index += 8;
            }
        }

        for (auto d = 0; d < 2; d++)
        {
            index = (d == 0) ? PAK_MVFRAC_COMP0_IDX : PAK_MVFRAC_COMP1_IDX;
            for (auto i = 0; i < 3; i++)
            {
                PutDataForCompressedHdr(compressedHdr, 0, 252, index);
                index += 8;
            }
            for (auto i = 0; i < 3; i++)
            {
                PutDataForCompressedHdr(compressedHdr, 0, 252, index);
                index += 8;
            }
            for (auto i = 0; i < 3; i++)
            {
                PutDataForCompressedHdr(compressedHdr, 0, 252, index);
                index += 8;
            }
        }

        if (m_vp9PicParams->PicFlags.fields.allow_high_precision_mv)
        {
            for (auto d = 0; d < 2; d++)
            {
                index = (d == 0) ? PAK_MVHP_COMP0_IDX : PAK_MVHP_COMP1_IDX;
                PutDataForCompressedHdr(compressedHdr, 0, 252, index);
                index += 8;
                PutDataForCompressedHdr(compressedHdr, 0, 252, index);
            }
        }
    }

    uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(
        m_osInterface,
        &m_resCompressedHeaderBuffer,
        &lockFlagsWriteOnly);
    if(data == nullptr)
    {
        MOS_FreeMemory(compressedHdr);
        CODECHAL_ENCODE_CHK_NULL_RETURN(nullptr);
    }

    for (uint32_t i = 0; i < PAK_COMPRESSED_HDR_SYNTAX_ELEMS; i += 2)
    {
        data[i>>1] = (compressedHdr[i + 1].value << 0x04) | (compressedHdr[i].value);
    }

    eStatus = (MOS_STATUS) m_osInterface->pfnUnlockResource(
        m_osInterface,
        &m_resCompressedHeaderBuffer);
    if (eStatus != MOS_STATUS_SUCCESS)
    {
        MOS_FreeMemory(compressedHdr);
        CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
    }

    MOS_FreeMemory(compressedHdr);
    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::ExecutePictureLevel()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    // resize CommandBuffer Size for every BRC pass
    if (!m_singleTaskPhaseSupported)
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(VerifySpaceAvailable());
    }

    PerfTagSetting perfTag;
    CODECHAL_ENCODE_SET_PERFTAG_INFO(perfTag, CODECHAL_ENCODE_PERFTAG_CALL_PAK_ENGINE);

    if (m_currPass == 0)
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(ConstructPakInsertObjBatchBuf(&m_resHucPakInsertUncompressedHeaderReadBuffer[m_currRecycledBufIdx]));
    }

    // For VDENC dynamic scaling, here are the steps we need to process
    //   Pass 0. VDENC + PAK Pass
    //     a. If this is Dys + BRC case, then run BRC Pass 0
    //     b. Ref frame scaling
    //    c. VDENC + PAK pass to stream out PakObjCmd
    //   Pass 1 -> Reset to Pass 0 so as to run HPU Pass 0
    //     a. If this is Dys + BRC case, then run BRC Pass 1
    //     b. Run HPU Pass 0
    //     c. Lite Pass (Pak only multi pass enabled) to stream in
    //        PakObjCmd from previous pass
    //   Pass 1 -> Only run HPU Pass 1 to update the probabilities for
    //   next frame. Repak is disabled for performance reasons
    if ( m_dysRefFrameFlags != DYS_REF_NONE)
    {
        if (m_currPass == 0)
        {
            if (m_dysVdencMultiPassEnabled)
            {
                if (Mos_ResourceIsNull(&m_resVdencDysPictureState2NdLevelBatchBuffer))
                {
                    MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;

                    MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
                    allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
                    allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
                    allocParamsForBufferLinear.Format = Format_Buffer;
                    allocParamsForBufferLinear.dwBytes = m_vdencPicStateSecondLevelBatchBufferSize;
                    allocParamsForBufferLinear.pBufName = "VDEnc DYS Picture Second Level Batch Buffer";

                    eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
                        m_osInterface,
                        &allocParamsForBufferLinear,
                        &m_resVdencDysPictureState2NdLevelBatchBuffer);

                    if (eStatus != MOS_STATUS_SUCCESS)
                    {
                        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate VDEnc DYS Picture Second Level Batch Buffer.");
                        return eStatus;
                    }
                }

                CODECHAL_ENCODE_CHK_STATUS_RETURN(VerifySpaceAvailable());
            }
        }
        else if (m_currPass == 1)
        {
            m_hucEnabled = m_dysHucEnabled; // recover huc state
            m_vdencPakonlyMultipassEnabled = true;
            m_dysRefFrameFlags = DYS_REF_NONE;
            m_currPass = 0; // reset ucCurrPass = 0 to run the Huc
            m_lastTaskInPhase = false;
        }
    }
    else
    {
        if (IsFirstPass() && m_vdencBrcEnabled)
        {
            m_vdencPakObjCmdStreamOutEnabled = true;
            m_resVdencPakObjCmdStreamOutBuffer = &m_resMbCodeSurface;
        }
        else
        {
            m_vdencPakObjCmdStreamOutEnabled = false;
        }
    }

    if ((m_dysRefFrameFlags != DYS_REF_NONE) && m_dysVdencMultiPassEnabled)
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(ConstructPicStateBatchBuf(&m_resVdencDysPictureState2NdLevelBatchBuffer));
    }
    else
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(ConstructPicStateBatchBuf(&m_resVdencPictureState2NdLevelBatchBufferRead[m_currPass][m_vdencPictureState2ndLevelBBIndex]));
    }

    if (m_vdencBrcEnabled)
    {
        // Invoke BRC init/reset FW
        if (m_brcInit || m_brcReset)
        {
            if (!m_singleTaskPhaseSupported)
            {
                //Reset earlier set PAK perf tag
                m_osInterface->pfnResetPerfBufferID(m_osInterface);
                CODECHAL_ENCODE_SET_PERFTAG_INFO(perfTag, CODECHAL_ENCODE_PERFTAG_CALL_BRC_INIT_RESET);
            }
            CODECHAL_ENCODE_CHK_STATUS_RETURN(HuCBrcInitReset());
            m_brcInit = m_brcReset = false;
        }
        // For multipass and singlepass+RePAK we call BRC update for all passes except last pass (RePAK)
        // For single pass w/o RePAK (1 total pass) we call BRC update on one and only pass
        if ((m_currPass < m_numPasses) || (m_currPass == 0 && m_numPasses == 0))
        {
            bool origSingleTaskPhase = m_singleTaskPhaseSupported;
            // If this is the case of Dynamic Scaling + BRC Pass 0'  VDENC + Pak  pass
            // As a WA, Disable SingleTaskPhase before running 1st BRC update
            // To run HPU0 on the next pass i.e Pak only pass, we make Pass 1 as Pass 0 in which case the
            // BRC dmem buffer( resVdencBrcUpdateDmemBuffer[0] ) will get overridden if we do not submit BRC command now.
            if (m_dysBrc && m_dysRefFrameFlags != DYS_REF_NONE)
            {
                m_singleTaskPhaseSupported = false;
            }
            if (!m_singleTaskPhaseSupported)
            {
                //Reset performance buffer used for BRC init
                m_osInterface->pfnResetPerfBufferID(m_osInterface);
                CODECHAL_ENCODE_SET_PERFTAG_INFO(perfTag, CODECHAL_ENCODE_PERFTAG_CALL_BRC_UPDATE);
            }
            CODECHAL_ENCODE_CHK_STATUS_RETURN(HuCBrcUpdate());

            //Restore the original state of SingleTaskPhaseSupported flag
            m_singleTaskPhaseSupported = origSingleTaskPhase;
        }
    }

    // run HuC_VP9Prob first pass (it runs in parallel with ENC)
    if (m_hucEnabled)
    {
        if ((m_currPass == 0) || (m_currPass == m_numPasses))  // Before the first PAK pass and for RePak pass
        {
            if (!m_singleTaskPhaseSupported)
            {
                //Reset earlier set PAK perf tag
                m_osInterface->pfnResetPerfBufferID(m_osInterface);
                // Add Hpu tag here after added
            }
            CODECHAL_ENCODE_CHK_STATUS_RETURN(HuCVp9Prob());
        }
    }
    else
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(RefreshFrameInternalBuffers());
    }

    //Ref frame scaling
    if (m_dysRefFrameFlags != DYS_REF_NONE && m_currPass == 0)
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(DysRefFrames());

        if (m_dysVdencMultiPassEnabled)
        {
            m_singleTaskPhaseSupported = true;
            m_firstTaskInPhase = true;
            m_vdencPakObjCmdStreamOutEnabled = true;
            m_resVdencPakObjCmdStreamOutBuffer = &m_resMbCodeSurface;
        }
        else
        {
            m_hucEnabled = m_dysHucEnabled; // recover huc state
        }
    }

    // set HCP_SURFACE_STATE values
    MHW_VDBOX_SURFACE_PARAMS surfaceParams[CODECHAL_HCP_ALTREF_SURFACE_ID + 1];
    for (uint8_t i = 0; i <= CODECHAL_HCP_ALTREF_SURFACE_ID; i++)
    {
        MOS_ZeroMemory(&surfaceParams[i], sizeof(surfaceParams[i]));
        surfaceParams[i].Mode = m_mode;
        surfaceParams[i].ucSurfaceStateId = i;
        surfaceParams[i].ChromaType = m_outputChromaFormat;
        surfaceParams[i].bSrc8Pak10Mode   = (m_vp9SeqParams->SeqFlags.fields.EncodedBitDepth) && (!m_vp9SeqParams->SeqFlags.fields.SourceBitDepth);

        switch (m_vp9SeqParams->SeqFlags.fields.EncodedBitDepth)
        {
            case VP9_ENCODED_BIT_DEPTH_10: //10 bit encoding
            {
                surfaceParams[i].ucBitDepthChromaMinus8 = 2;
                surfaceParams[i].ucBitDepthLumaMinus8 = 2;
                break;
            }
            default:
            {
                surfaceParams[i].ucBitDepthChromaMinus8 = 0;
                surfaceParams[i].ucBitDepthLumaMinus8 = 0;
                break;
            }
        }
    }

    // For PAK engine, we do NOT use scaled reference images even if dynamic scaling is enabled
    PMOS_SURFACE refSurface[3], refSurfaceNonScaled[3], dsRefSurface4x[3], dsRefSurface8x[3];
    for (auto i = 0; i < 3; i++)
    {
        refSurface[i] = refSurfaceNonScaled[i] = dsRefSurface4x[i] = dsRefSurface8x[i] = nullptr;
    }
    CODECHAL_ENCODE_CHK_STATUS_RETURN(SetHcpSrcSurfaceParams(surfaceParams, refSurface, refSurfaceNonScaled, dsRefSurface4x, dsRefSurface8x));

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

    if (!m_singleTaskPhaseSupported)
    {
        CODECHAL_ENCODE_SET_PERFTAG_INFO(perfTag, CODECHAL_ENCODE_PERFTAG_CALL_PAK_ENGINE);
    }

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

    // Repak conditional batch buffer end based on repak flag written by Huc to HUC_STATUS regster
    if (m_hucEnabled && (m_numPasses > 0)  && (m_currPass == m_numPasses))
    {
        // Insert conditional batch buffer end
        // Success = bit 30 set to 1, Do RePAK = bit 31 set to 1, value is always 0; if 0 < memory, continue
        MHW_MI_CONDITIONAL_BATCH_BUFFER_END_PARAMS miConditionalBatchBufferEndParams;
        MOS_ZeroMemory(
            &miConditionalBatchBufferEndParams,
            sizeof(MHW_MI_CONDITIONAL_BATCH_BUFFER_END_PARAMS));

        miConditionalBatchBufferEndParams.presSemaphoreBuffer =
            &m_resHucPakMmioBuffer;
        // Make the DisableCompareMask 0, so that the HW will do AND operation on DW0 with Mask DW1, refer to HuCVp9Prob() for the settings
        // and compare the result against the Semaphore data which in our case dwValue = 0.
        // If result > dwValue then continue execution otherwise terminate the batch buffer
        miConditionalBatchBufferEndParams.bDisableCompareMask = false;

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

    CODECHAL_ENCODE_CHK_STATUS_RETURN(StartStatusReport(&cmdBuffer, CODECHAL_NUM_MEDIA_STATES));

    PMHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams = nullptr;
    // set HCP_PIPE_MODE_SELECT values
    pipeModeSelectParams = m_vdencInterface->CreateMhwVdboxPipeModeSelectParams();
    CODECHAL_ENCODE_CHK_NULL_RETURN(pipeModeSelectParams);

    auto release_func = [&]()
    {
        m_vdencInterface->ReleaseMhwVdboxPipeModeSelectParams(pipeModeSelectParams);
        pipeModeSelectParams = nullptr;
    };

    SetHcpPipeModeSelectParams(*pipeModeSelectParams);
    CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_hcpInterface->AddHcpPipeModeSelectCmd(&cmdBuffer, pipeModeSelectParams), release_func);

    // This wait cmd is needed to make sure copy command is done as suggested by HW folk
    CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_miInterface->AddMfxWaitCmd(&cmdBuffer, nullptr, false), release_func);

    // Decoded picture
    CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_hcpInterface->AddHcpSurfaceCmd(&cmdBuffer, &surfaceParams[CODECHAL_HCP_DECODED_SURFACE_ID]), release_func);

    // Source input
    CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_hcpInterface->AddHcpSurfaceCmd(&cmdBuffer, &surfaceParams[CODECHAL_HCP_SRC_SURFACE_ID]), release_func);

    // Last reference picture
    if (refSurface[0])
    {
        CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_hcpInterface->AddHcpSurfaceCmd(&cmdBuffer, &surfaceParams[CODECHAL_HCP_LAST_SURFACE_ID]), release_func);
    }

    // Golden reference picture
    if (refSurface[1])
    {
        CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_hcpInterface->AddHcpSurfaceCmd(&cmdBuffer, &surfaceParams[CODECHAL_HCP_GOLDEN_SURFACE_ID]), release_func);
    }

    // Alt reference picture
    if (refSurface[2])
    {
        CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_hcpInterface->AddHcpSurfaceCmd(&cmdBuffer, &surfaceParams[CODECHAL_HCP_ALTREF_SURFACE_ID]), release_func);
    }

    // set HCP_PIPE_BUF_ADDR_STATE values
    PMHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams = nullptr;
    pipeBufAddrParams = CreateHcpPipeBufAddrParams(pipeBufAddrParams);

    auto release_func2 = [&]()
    {
        m_vdencInterface->ReleaseMhwVdboxPipeModeSelectParams(pipeModeSelectParams);
        pipeModeSelectParams = nullptr;

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

    if (pipeBufAddrParams)
    {
        CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(SetHcpPipeBufAddrParams(*pipeBufAddrParams, refSurface, refSurfaceNonScaled, dsRefSurface4x, dsRefSurface8x), release_func2);
        CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(SetPipeBufAddr(pipeBufAddrParams, refSurface, &cmdBuffer), release_func2);
        CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_hcpInterface->AddHcpPipeBufAddrCmd(&cmdBuffer, pipeBufAddrParams), release_func2);
    }

    // set HCP_IND_OBJ_BASE_ADDR_STATE values
    MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS indObjBaseAddrParams;
    SetHcpIndObjBaseAddrParams(indObjBaseAddrParams);
    CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_hcpInterface->AddHcpIndObjBaseAddrCmd(&cmdBuffer, &indObjBaseAddrParams), release_func2);

    CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_vdencInterface->AddVdencPipeModeSelectCmd(&cmdBuffer, pipeModeSelectParams), release_func2);

    m_vdencInterface->ReleaseMhwVdboxPipeModeSelectParams(pipeModeSelectParams);

    CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_vdencInterface->AddVdencSrcSurfaceStateCmd(&cmdBuffer, &surfaceParams[CODECHAL_HCP_SRC_SURFACE_ID]), release_func2);
    if (m_pictureCodingType == I_TYPE)
    {
        CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_vdencInterface->AddVdencRefSurfaceStateCmd(&cmdBuffer, &surfaceParams[CODECHAL_HCP_DECODED_SURFACE_ID]), release_func2);
    }
    else
    {
        CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_vdencInterface->AddVdencRefSurfaceStateCmd(&cmdBuffer, &surfaceParams[CODECHAL_HCP_LAST_SURFACE_ID]), release_func2);
        if ((m_dysRefFrameFlags != DYS_REF_NONE) && !m_dysVdencMultiPassEnabled)
        {
            if (m_refFrameFlags & 0x02)
            {
                CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_vdencInterface->AddVdencRefSurfaceStateCmd(&cmdBuffer, &surfaceParams[CODECHAL_HCP_GOLDEN_SURFACE_ID]), release_func2);
            }
            if (m_refFrameFlags & 0x04)
            {
                CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_vdencInterface->AddVdencRefSurfaceStateCmd(&cmdBuffer, &surfaceParams[CODECHAL_HCP_ALTREF_SURFACE_ID]), release_func2);
            }
        }
    }

    MHW_VDBOX_SURFACE_PARAMS dsSurfaceParams[2];     // 8x and 4x DS surfaces
    SetHcpDsSurfaceParams(&dsSurfaceParams[0]);
    CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_vdencInterface->AddVdencDsRefSurfaceStateCmd(&cmdBuffer, &dsSurfaceParams[0], 2), release_func2);

    if (pipeBufAddrParams)
    {
        CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_vdencInterface->AddVdencPipeBufAddrCmd(&cmdBuffer, pipeBufAddrParams), release_func2);
        MOS_Delete(pipeBufAddrParams);
        pipeBufAddrParams = nullptr;
    }

    MHW_BATCH_BUFFER secondLevelBatchBuffer;
    MOS_ZeroMemory(&secondLevelBatchBuffer, sizeof(secondLevelBatchBuffer));
    secondLevelBatchBuffer.dwOffset = 0;
    secondLevelBatchBuffer.bSecondLevel = true;
    if (m_hucEnabled)
    {
        secondLevelBatchBuffer.OsResource = m_resVdencPictureState2NdLevelBatchBufferWrite[m_vdencPictureState2ndLevelBBIndex];
    }
    else
    {
        if (m_dysRefFrameFlags != DYS_REF_NONE && m_dysVdencMultiPassEnabled)
        {
            // For DyS + BRC case, we run BRC on Pass 0, so although we dont run HPU on Pass 0
            // (VDENC + PAK pass) we will still use the write buffer here
            if (m_dysBrc)
            {
                secondLevelBatchBuffer.OsResource = m_resVdencPictureState2NdLevelBatchBufferWrite[m_vdencPictureState2ndLevelBBIndex];
            }
            else //CQP case for Pass 0 , HPU has not run yet.. so use this buffer
            {
                secondLevelBatchBuffer.OsResource = m_resVdencDysPictureState2NdLevelBatchBuffer;
            }
        }
        else
        {
            secondLevelBatchBuffer.OsResource = m_resVdencPictureState2NdLevelBatchBufferRead[m_currPass][m_vdencPictureState2ndLevelBBIndex];
        }
    }

    CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_miInterface->AddMiBatchBufferStartCmd(
        &cmdBuffer,
        &secondLevelBatchBuffer), release_func);

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

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::Resize4x8xforDS(uint8_t bufIdx)
{
    CODECHAL_ENCODE_FUNCTION_ENTER;

    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
    
    // calculate the expected 4x dimensions
    uint32_t downscaledSurfaceWidth4x  = m_downscaledWidthInMb4x * CODECHAL_MACROBLOCK_WIDTH;
    uint32_t downscaledSurfaceHeight4x = ((m_downscaledHeightInMb4x + 1) >> 1) * CODECHAL_MACROBLOCK_HEIGHT;
    downscaledSurfaceHeight4x          = MOS_ALIGN_CEIL(downscaledSurfaceHeight4x, MOS_YTILE_H_ALIGNMENT) << 1;

    // calculate the expected 8x dimensions
    uint32_t downscaledSurfaceWidth8x  = downscaledSurfaceWidth4x >> 1;
    uint32_t downscaledSurfaceHeight8x = downscaledSurfaceHeight4x >> 1;

    CODECHAL_ENCODE_CHK_NULL_RETURN(m_trackedBuf);

    // get the 8x and 4x ds downscaled surfaces from tracked buffers
    auto m_trackedBuf8xDsReconSurface = m_trackedBuf->Get8xDsReconSurface(bufIdx);
    auto m_trackedBuf4xDsReconSurface = m_trackedBuf->Get4xDsReconSurface(bufIdx);

    CODECHAL_ENCODE_CHK_NULL_RETURN(m_trackedBuf8xDsReconSurface);
    CODECHAL_ENCODE_CHK_NULL_RETURN(m_trackedBuf4xDsReconSurface);

    // If any dimension of allocated surface is smaller, realloc needed
    if (m_trackedBuf8xDsReconSurface->dwWidth < downscaledSurfaceWidth8x || m_trackedBuf8xDsReconSurface->dwHeight < downscaledSurfaceHeight8x) {
        
        // Get the previously assigned dimensions to make sure we do not lower any dimension
        auto previous8xWidth = m_trackedBuf8xDsReconSurface->dwWidth;
        auto previous8xHeight = m_trackedBuf8xDsReconSurface->dwHeight;

        auto new8xWidth = MOS_MAX(previous8xWidth, downscaledSurfaceWidth8x);
        auto new8xHeight = MOS_MAX(previous8xHeight, downscaledSurfaceHeight8x);
        
        // Release the smaller resource
        m_allocator->ReleaseResource(m_standard, ds8xRecon, bufIdx);

        // Re alloc larger resource
        CODECHAL_ENCODE_CHK_NULL_RETURN(
            m_trackedBuf8xDsReconSurface = (MOS_SURFACE*)m_allocator->AllocateResource(
                m_standard, new8xWidth, new8xHeight, ds8xRecon, "ds8xRecon", bufIdx, false, Format_NV12, MOS_TILE_Y));

        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, m_trackedBuf8xDsReconSurface));
    }

    if (m_trackedBuf4xDsReconSurface->dwWidth < downscaledSurfaceWidth4x || m_trackedBuf4xDsReconSurface->dwHeight < downscaledSurfaceHeight4x) {
        
        // Get the previously assigned dimensions to make sure we do not lower any dimension
        auto previous4xWidth = m_trackedBuf4xDsReconSurface->dwWidth;
        auto previous4xHeight = m_trackedBuf4xDsReconSurface->dwHeight;

        auto new4xWidth = MOS_MAX(previous4xWidth, downscaledSurfaceWidth4x);
        auto new4xHeight = MOS_MAX(previous4xHeight, downscaledSurfaceHeight4x);

        // Release the smaller resource
        m_allocator->ReleaseResource(m_standard, ds4xRecon, bufIdx);

        // Re alloc larger resource
        CODECHAL_ENCODE_CHK_NULL_RETURN(
            m_trackedBuf4xDsReconSurface = (MOS_SURFACE*)m_allocator->AllocateResource(
                m_standard, new4xWidth, new4xHeight, ds4xRecon, "ds4xRecon", bufIdx, false, Format_NV12, MOS_TILE_Y));

        CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, m_trackedBuf4xDsReconSurface));
    }
    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::SetHcpSrcSurfaceParams(MHW_VDBOX_SURFACE_PARAMS* surfaceParams,
    PMOS_SURFACE* refSurface,
    PMOS_SURFACE* refSurfaceNonScaled,
    PMOS_SURFACE* dsRefSurface4x,
    PMOS_SURFACE* dsRefSurface8x)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    if (m_pictureCodingType != I_TYPE)
    {
        uint8_t refPicIndex = 0, scalingIdx = 0;
        if (m_refFrameFlags & 0x01)
        {
            refPicIndex = m_vp9PicParams->RefFlags.fields.LastRefIdx;

            CODECHAL_ENCODE_ASSERT((refPicIndex < CODEC_VP9_NUM_REF_FRAMES) && (!CodecHal_PictureIsInvalid(m_vp9PicParams->RefFrameList[refPicIndex])));
            refSurfaceNonScaled[0] = &(m_refList[m_vp9PicParams->RefFrameList[refPicIndex].FrameIdx]->sRefBuffer);
            refSurface[0]          = (m_dysRefFrameFlags & DYS_REF_LAST) ? &(m_refList[m_vp9PicParams->RefFrameList[refPicIndex].FrameIdx]->sDysSurface) : refSurfaceNonScaled[0];

            scalingIdx        = m_refList[m_vp9PicParams->RefFrameList[refPicIndex].FrameIdx]->ucScalingIdx;
            CODECHAL_ENCODE_CHK_STATUS_RETURN(Resize4x8xforDS(scalingIdx));

            CODECHAL_ENCODE_CHK_NULL_RETURN(m_trackedBuf);
            dsRefSurface4x[0] = m_trackedBuf->Get4xDsReconSurface(scalingIdx);
            CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, dsRefSurface4x[0]));
            dsRefSurface8x[0] = m_trackedBuf->Get8xDsReconSurface(scalingIdx);
            CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, dsRefSurface8x[0]));
        }

        if (m_refFrameFlags & 0x02)
        {
            refPicIndex = m_vp9PicParams->RefFlags.fields.GoldenRefIdx;

            CODECHAL_ENCODE_ASSERT((refPicIndex < CODEC_VP9_NUM_REF_FRAMES) && (!CodecHal_PictureIsInvalid(m_vp9PicParams->RefFrameList[refPicIndex])));
            refSurfaceNonScaled[1] = &(m_refList[m_vp9PicParams->RefFrameList[refPicIndex].FrameIdx]->sRefBuffer);
            refSurface[1]          = (m_dysRefFrameFlags & DYS_REF_GOLDEN) ? &(m_refList[m_vp9PicParams->RefFrameList[refPicIndex].FrameIdx]->sDysSurface) : refSurfaceNonScaled[1];

            scalingIdx        = m_refList[m_vp9PicParams->RefFrameList[refPicIndex].FrameIdx]->ucScalingIdx;
            CODECHAL_ENCODE_CHK_STATUS_RETURN(Resize4x8xforDS(scalingIdx));

            CODECHAL_ENCODE_CHK_NULL_RETURN(m_trackedBuf);
            dsRefSurface4x[1] = m_trackedBuf->Get4xDsReconSurface(scalingIdx);
            CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, dsRefSurface4x[1]));
            dsRefSurface8x[1] = m_trackedBuf->Get8xDsReconSurface(scalingIdx);
            CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, dsRefSurface8x[1]));
        }

        if (m_refFrameFlags & 0x04)
        {
            refPicIndex = m_vp9PicParams->RefFlags.fields.AltRefIdx;

            CODECHAL_ENCODE_ASSERT((refPicIndex < CODEC_VP9_NUM_REF_FRAMES) && (!CodecHal_PictureIsInvalid(m_vp9PicParams->RefFrameList[refPicIndex])));
            refSurfaceNonScaled[2] = &(m_refList[m_vp9PicParams->RefFrameList[refPicIndex].FrameIdx]->sRefBuffer);
            refSurface[2]          = (m_dysRefFrameFlags & DYS_REF_ALT) ? &(m_refList[m_vp9PicParams->RefFrameList[refPicIndex].FrameIdx]->sDysSurface) : refSurfaceNonScaled[2];

            scalingIdx        = m_refList[m_vp9PicParams->RefFrameList[refPicIndex].FrameIdx]->ucScalingIdx;
            CODECHAL_ENCODE_CHK_STATUS_RETURN(Resize4x8xforDS(scalingIdx));

            CODECHAL_ENCODE_CHK_NULL_RETURN(m_trackedBuf);
            dsRefSurface4x[2] = m_trackedBuf->Get4xDsReconSurface(scalingIdx);
            CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, dsRefSurface4x[2]));
            dsRefSurface8x[2] = m_trackedBuf->Get8xDsReconSurface(scalingIdx);
            CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, dsRefSurface8x[2]));
        }

        if (!refSurface[0])
        {
            refSurface[0] = (refSurface[1]) ? refSurface[1] : refSurface[2];
            refSurfaceNonScaled[0] = (refSurfaceNonScaled[1]) ? refSurfaceNonScaled[1] : refSurfaceNonScaled[2];
            dsRefSurface4x[0] = (dsRefSurface4x[1]) ? dsRefSurface4x[1] : dsRefSurface4x[2];
            dsRefSurface8x[0] = (dsRefSurface8x[1]) ? dsRefSurface8x[1] : dsRefSurface8x[2];
        }

        if (!refSurface[1])
        {
            refSurface[1] = (refSurface[0]) ? refSurface[0] : refSurface[2];
            refSurfaceNonScaled[1] = (refSurfaceNonScaled[0]) ? refSurfaceNonScaled[0] : refSurfaceNonScaled[2];
            dsRefSurface4x[1] = (dsRefSurface4x[0]) ? dsRefSurface4x[0] : dsRefSurface4x[2];
            dsRefSurface8x[1] = (dsRefSurface8x[0]) ? dsRefSurface8x[0] : dsRefSurface8x[2];
        }

        if (!refSurface[2])
        {
            refSurface[2] = (refSurface[0]) ? refSurface[0] : refSurface[1];
            refSurfaceNonScaled[2] = (refSurfaceNonScaled[0]) ? refSurfaceNonScaled[0] : refSurfaceNonScaled[1];
            dsRefSurface4x[2] = (dsRefSurface4x[0]) ? dsRefSurface4x[0] : dsRefSurface4x[1];
            dsRefSurface8x[2] = (dsRefSurface8x[0]) ? dsRefSurface8x[0] : dsRefSurface8x[1];
        }

        // Program Surface params for Reference surfaces
        if ((m_dysRefFrameFlags != DYS_REF_NONE) && !m_dysVdencMultiPassEnabled)
        {
            surfaceParams[CODECHAL_HCP_LAST_SURFACE_ID].psSurface               = refSurfaceNonScaled[0];
            surfaceParams[CODECHAL_HCP_LAST_SURFACE_ID].bVdencDynamicScaling    = true;

            surfaceParams[CODECHAL_HCP_GOLDEN_SURFACE_ID].psSurface             = refSurfaceNonScaled[1];
            surfaceParams[CODECHAL_HCP_GOLDEN_SURFACE_ID].bVdencDynamicScaling  = true;

            surfaceParams[CODECHAL_HCP_ALTREF_SURFACE_ID].psSurface             = refSurfaceNonScaled[2];
            surfaceParams[CODECHAL_HCP_ALTREF_SURFACE_ID].bVdencDynamicScaling = true;
        }
        else
        {
            surfaceParams[CODECHAL_HCP_LAST_SURFACE_ID].psSurface               = refSurface[0];
            surfaceParams[CODECHAL_HCP_GOLDEN_SURFACE_ID].psSurface             = refSurface[1];
            surfaceParams[CODECHAL_HCP_ALTREF_SURFACE_ID].psSurface             = refSurface[2];
        }

        if (m_dysCurrFrameFlag)
        {
            if (m_dysVdencMultiPassEnabled)
            {
                surfaceParams[CODECHAL_HCP_LAST_SURFACE_ID].dwReconSurfHeight   = MOS_ALIGN_CEIL((refSurface[0] ? refSurface[0]->dwHeight : 0), CODEC_VP9_MIN_BLOCK_WIDTH);
                surfaceParams[CODECHAL_HCP_GOLDEN_SURFACE_ID].dwReconSurfHeight = MOS_ALIGN_CEIL((refSurface[1] ? refSurface[1]->dwHeight : 0), CODEC_VP9_MIN_BLOCK_WIDTH);
                surfaceParams[CODECHAL_HCP_ALTREF_SURFACE_ID].dwReconSurfHeight = MOS_ALIGN_CEIL((refSurface[2] ? refSurface[2]->dwHeight : 0), CODEC_VP9_MIN_BLOCK_WIDTH);
            }
            else
            {
                surfaceParams[CODECHAL_HCP_LAST_SURFACE_ID].dwReconSurfHeight   = MOS_ALIGN_CEIL((refSurfaceNonScaled[0] ? refSurfaceNonScaled[0]->dwHeight : 0), CODEC_VP9_MIN_BLOCK_WIDTH);
                surfaceParams[CODECHAL_HCP_GOLDEN_SURFACE_ID].dwReconSurfHeight = MOS_ALIGN_CEIL((refSurfaceNonScaled[1] ? refSurfaceNonScaled[1]->dwHeight : 0), CODEC_VP9_MIN_BLOCK_WIDTH);
                surfaceParams[CODECHAL_HCP_ALTREF_SURFACE_ID].dwReconSurfHeight = MOS_ALIGN_CEIL((refSurfaceNonScaled[2] ? refSurfaceNonScaled[2]->dwHeight : 0), CODEC_VP9_MIN_BLOCK_WIDTH);
            }
        }
        else
        {
            surfaceParams[CODECHAL_HCP_LAST_SURFACE_ID].dwReconSurfHeight =
            surfaceParams[CODECHAL_HCP_GOLDEN_SURFACE_ID].dwReconSurfHeight =
            surfaceParams[CODECHAL_HCP_ALTREF_SURFACE_ID].dwReconSurfHeight = m_rawSurfaceToPak->dwHeight;
        }
    }

    // Program Surface params for reconstructed surface
    surfaceParams[CODECHAL_HCP_DECODED_SURFACE_ID].psSurface            = &m_reconSurface;
    surfaceParams[CODECHAL_HCP_DECODED_SURFACE_ID].dwReconSurfHeight    = m_rawSurfaceToPak->dwHeight;

    // Program Surface params for source surface
    surfaceParams[CODECHAL_HCP_SRC_SURFACE_ID].psSurface                = m_rawSurfaceToPak;
    surfaceParams[CODECHAL_HCP_SRC_SURFACE_ID].bDisplayFormatSwizzle    = m_vp9SeqParams->SeqFlags.fields.DisplayFormatSwizzle;
    surfaceParams[CODECHAL_HCP_SRC_SURFACE_ID].dwActualWidth            = MOS_ALIGN_CEIL(m_oriFrameWidth, CODEC_VP9_MIN_BLOCK_WIDTH);
    surfaceParams[CODECHAL_HCP_SRC_SURFACE_ID].dwActualHeight           = MOS_ALIGN_CEIL(m_oriFrameHeight, CODEC_VP9_MIN_BLOCK_WIDTH);

    return eStatus;
}

void CodechalVdencVp9State::SetHcpPipeModeSelectParams(MHW_VDBOX_PIPE_MODE_SELECT_PARAMS& pipeModeSelectParams)
{
    pipeModeSelectParams = {};
    pipeModeSelectParams.Mode = m_mode;
    pipeModeSelectParams.bStreamOutEnabled = m_vdencBrcEnabled;
    pipeModeSelectParams.bVdencEnabled = true;
    pipeModeSelectParams.bVdencPakObjCmdStreamOutEnable = m_vdencPakObjCmdStreamOutEnabled;
    pipeModeSelectParams.bTlbPrefetchEnable = true;
    pipeModeSelectParams.isIFrame = (m_vp9PicParams->PicFlags.fields.frame_type == 0);

    // Add 1 to compensate for VdencPipeModeSelect params values
    pipeModeSelectParams.ChromaType = m_vp9SeqParams->SeqFlags.fields.EncodedFormat + 1;
    switch (m_vp9SeqParams->SeqFlags.fields.EncodedBitDepth)
    {
        case VP9_ENCODED_BIT_DEPTH_10:
        {
            pipeModeSelectParams.ucVdencBitDepthMinus8 = 2;
            break;
        }
        default:
        {
            pipeModeSelectParams.ucVdencBitDepthMinus8 = 0;
            break;
        }
    }
}

PMHW_VDBOX_PIPE_BUF_ADDR_PARAMS CodechalVdencVp9State::CreateHcpPipeBufAddrParams(PMHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams)
{
    pipeBufAddrParams = MOS_New(MHW_VDBOX_PIPE_BUF_ADDR_PARAMS);

    return pipeBufAddrParams;
}

MOS_STATUS CodechalVdencVp9State::SetPipeBufAddr(
    PMHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams,
    PMOS_SURFACE refSurface[3],
    PMOS_COMMAND_BUFFER cmdBuffer)
{
    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(m_mmcState);
    return m_mmcState->SetPipeBufAddr(pipeBufAddrParams, cmdBuffer);
}

MOS_STATUS CodechalVdencVp9State::SetHcpPipeBufAddrParams(MHW_VDBOX_PIPE_BUF_ADDR_PARAMS& pipeBufAddrParams,
    PMOS_SURFACE* refSurface,
    PMOS_SURFACE* refSurfaceNonScaled,
    PMOS_SURFACE* dsRefSurface4x,
    PMOS_SURFACE* dsRefSurface8x)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    pipeBufAddrParams = {};
    pipeBufAddrParams.Mode = m_mode;
    pipeBufAddrParams.psPreDeblockSurface = &m_reconSurface;
    pipeBufAddrParams.psPostDeblockSurface = &m_reconSurface;
    pipeBufAddrParams.psRawSurface = m_rawSurfaceToPak;

    pipeBufAddrParams.presMfdDeblockingFilterRowStoreScratchBuffer =
        &m_resDeblockingFilterLineBuffer;

    pipeBufAddrParams.presDeblockingFilterTileRowStoreScratchBuffer =
        &m_resDeblockingFilterTileLineBuffer;

    pipeBufAddrParams.presDeblockingFilterColumnRowStoreScratchBuffer =
        &m_resDeblockingFilterTileColumnBuffer;

    pipeBufAddrParams.presMetadataLineBuffer       = &m_resMetadataLineBuffer;
    pipeBufAddrParams.presMetadataTileLineBuffer   = &m_resMetadataTileLineBuffer;
    pipeBufAddrParams.presMetadataTileColumnBuffer = &m_resMetadataTileColumnBuffer;
    pipeBufAddrParams.presCurMvTempBuffer = m_trackedBuf->GetMvTemporalBuffer(m_currMvTemporalBufferIndex);

    // Huc first pass doesn't write probabilities to output prob region but only updates to the input region. HuC run before repak writes to the ouput region.
    uint8_t frameCtxIdx = 0;
    if (m_hucEnabled && m_currPass == m_numPasses)
    {
        pipeBufAddrParams.presVp9ProbBuffer = &m_resHucProbOutputBuffer;
    }
    else
    {
        frameCtxIdx = m_vp9PicParams->PicFlags.fields.frame_context_idx;
        CODECHAL_ENCODE_ASSERT(frameCtxIdx < CODEC_VP9_NUM_CONTEXTS);
        pipeBufAddrParams.presVp9ProbBuffer = &m_resProbBuffer[frameCtxIdx];
    }

    pipeBufAddrParams.presVp9SegmentIdBuffer              = &m_resSegmentIdBuffer;
    pipeBufAddrParams.presHvdTileRowStoreBuffer           = &m_resHvcTileRowstoreBuffer;
    pipeBufAddrParams.ps4xDsSurface = m_trackedBuf->Get4xDsReconSurface(CODEC_CURR_TRACKED_BUFFER);
    pipeBufAddrParams.ps8xDsSurface = m_trackedBuf->Get8xDsReconSurface(CODEC_CURR_TRACKED_BUFFER);
    pipeBufAddrParams.presVdencIntraRowStoreScratchBuffer = &m_resVdencIntraRowStoreScratchBuffer;
    pipeBufAddrParams.dwNumRefIdxL0ActiveMinus1           = (m_vp9PicParams->PicFlags.fields.frame_type) ? m_numRefFrames - 1 : 0;
    pipeBufAddrParams.presVdencStreamOutBuffer            = &m_resVdencBrcStatsBuffer;
    pipeBufAddrParams.presStreamOutBuffer = nullptr;
    pipeBufAddrParams.presFrameStatStreamOutBuffer        = &m_resFrameStatStreamOutBuffer;
    pipeBufAddrParams.presSseSrcPixelRowStoreBuffer       = &m_resSseSrcPixelRowStoreBuffer;
    pipeBufAddrParams.presVdencStreamInBuffer = &m_resVdencStreamInBuffer[m_currRecycledBufIdx];
    pipeBufAddrParams.presSegmentMapStreamOut             = &m_resVdencSegmentMapStreamOut;
    pipeBufAddrParams.presPakCuLevelStreamoutBuffer =
        Mos_ResourceIsNull(&m_resPakcuLevelStreamoutData.sResource) ? nullptr : &m_resPakcuLevelStreamoutData.sResource;
    if (m_dysRefFrameFlags != DYS_REF_NONE)
    {
        pipeBufAddrParams.presVdencPakObjCmdStreamOutBuffer =
            (m_vdencPakObjCmdStreamOutEnabled) ? m_resVdencPakObjCmdStreamOutBuffer : nullptr;
    }
    else
    {
        pipeBufAddrParams.presVdencPakObjCmdStreamOutBuffer = m_resVdencPakObjCmdStreamOutBuffer = &m_resMbCodeSurface;
    }

    if (m_pictureCodingType != I_TYPE)
    {
        for (auto i = 0; i < 3; i++)
        {
            CODECHAL_ENCODE_CHK_NULL_RETURN(refSurface[i]);
            CODECHAL_ENCODE_CHK_NULL_RETURN(dsRefSurface4x[i]);
            CODECHAL_ENCODE_CHK_NULL_RETURN(dsRefSurface8x[i]);

            pipeBufAddrParams.presReferences[i]         = &refSurface[i]->OsResource;
            pipeBufAddrParams.presVdencReferences[i]    = &refSurface[i]->OsResource;
            pipeBufAddrParams.presVdenc4xDsSurface[i]   = &dsRefSurface4x[i]->OsResource;
            pipeBufAddrParams.presVdenc8xDsSurface[i]   = &dsRefSurface8x[i]->OsResource;

            if ((m_dysRefFrameFlags != DYS_REF_NONE) && !m_dysVdencMultiPassEnabled)
            {
                pipeBufAddrParams.presReferences[i + 4] = &refSurfaceNonScaled[i]->OsResource;
            }
        }

        pipeBufAddrParams.presColMvTempBuffer[0] = m_trackedBuf->GetMvTemporalBuffer(m_currMvTemporalBufferIndex ^ 0x01);
    }

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::VerifyCommandBufferSize()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(VerifySpaceAvailable());
    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::GetCommandBuffer(
    PMOS_COMMAND_BUFFER cmdBuffer)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, cmdBuffer, 0));
    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::ReturnCommandBuffer(
    PMOS_COMMAND_BUFFER cmdBuffer)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
    
    m_osInterface->pfnReturnCommandBuffer(m_osInterface, cmdBuffer, 0);
 
    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::SubmitCommandBuffer(
    PMOS_COMMAND_BUFFER cmdBuffer,
    bool bNullRendering)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
   
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, cmdBuffer, bNullRendering));

    return eStatus;
}

void CodechalVdencVp9State::SetHcpIndObjBaseAddrParams(MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS& indObjBaseAddrParams)
{
    MOS_ZeroMemory(&indObjBaseAddrParams, sizeof(indObjBaseAddrParams));
    indObjBaseAddrParams.Mode = m_mode;
    indObjBaseAddrParams.presPakBaseObjectBuffer = &m_resBitstreamBuffer;
    indObjBaseAddrParams.dwPakBaseObjectSize = m_bitstreamUpperBound;
    indObjBaseAddrParams.presProbabilityDeltaBuffer   = &m_resProbabilityDeltaBuffer;
    indObjBaseAddrParams.dwProbabilityDeltaSize = 29 * CODECHAL_CACHELINE_SIZE;
    indObjBaseAddrParams.presCompressedHeaderBuffer   = &m_resCompressedHeaderBuffer;
    indObjBaseAddrParams.dwCompressedHeaderSize = 32 * CODECHAL_CACHELINE_SIZE;
    indObjBaseAddrParams.presProbabilityCounterBuffer = &m_resProbabilityCounterBuffer;
    indObjBaseAddrParams.dwProbabilityCounterOffset = 0;
    indObjBaseAddrParams.dwProbabilityCounterSize = 193 * CODECHAL_CACHELINE_SIZE;
    indObjBaseAddrParams.presTileRecordBuffer         = &m_resTileRecordStrmOutBuffer;
    indObjBaseAddrParams.dwTileRecordSize = m_picSizeInSb * CODECHAL_CACHELINE_SIZE;
    indObjBaseAddrParams.presCuStatsBuffer            = &m_resCuStatsStrmOutBuffer;
    indObjBaseAddrParams.dwCuStatsSize = MOS_ALIGN_CEIL(m_picSizeInSb * 64 * 8, CODECHAL_CACHELINE_SIZE);
}

void CodechalVdencVp9State::SetHcpDsSurfaceParams(MHW_VDBOX_SURFACE_PARAMS* dsSurfaceParams)
{
    // 8xDS surface
    MOS_ZeroMemory(&dsSurfaceParams[0], sizeof(MHW_VDBOX_SURFACE_PARAMS));
    dsSurfaceParams[0].Mode = m_mode;
    dsSurfaceParams[0].ucSurfaceStateId = CODECHAL_MFX_DSRECON_SURFACE_ID;
    dsSurfaceParams[0].psSurface = m_trackedBuf->Get8xDsReconSurface(CODEC_CURR_TRACKED_BUFFER);
    // 4xDS Surface
    MOS_ZeroMemory(&dsSurfaceParams[1], sizeof(MHW_VDBOX_SURFACE_PARAMS));
    dsSurfaceParams[1].Mode = m_mode;
    dsSurfaceParams[1].ucSurfaceStateId = CODECHAL_MFX_DSRECON_SURFACE_ID;
    dsSurfaceParams[1].psSurface = m_trackedBuf->Get4xDsReconSurface(CODEC_CURR_TRACKED_BUFFER);
}

MOS_STATUS CodechalVdencVp9State::GetStatusReport(
    EncodeStatus*       encodeStatus,
    EncodeStatusReport* encodeStatusReport)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(encodeStatus);
    CODECHAL_ENCODE_CHK_NULL_RETURN(encodeStatusReport);

    encodeStatusReport->CodecStatus = CODECHAL_STATUS_SUCCESSFUL;
    encodeStatusReport->bitstreamSize =
        encodeStatus->dwMFCBitstreamByteCountPerFrame + encodeStatus->dwHeaderBytesInserted;

    encodeStatusReport->QpY          = m_vp9PicParams->LumaACQIndex;
    encodeStatusReport->NumberPasses = (uint8_t)encodeStatus->dwNumberPasses;

    if (m_brcEnabled)
    {
        MOS_LOCK_PARAMS lockFlagsReadOnly;
        MOS_ZeroMemory(&lockFlagsReadOnly, sizeof(MOS_LOCK_PARAMS));
        lockFlagsReadOnly.ReadOnly = 1;

        uint8_t* data = (uint8_t*)m_osInterface->pfnLockResource(m_osInterface, &m_brcBuffers.resBrcHucDataBuffer, &lockFlagsReadOnly);
        CODECHAL_ENCODE_CHK_NULL_RETURN(data);

        HucBrcDataBuffer* hucData = (HucBrcDataBuffer*)data;

        encodeStatusReport->NextFrameWidthMinus1  = (uint16_t) hucData->DW5.NextFrameWidth - 1;
        encodeStatusReport->NextFrameHeightMinus1 = (uint16_t) hucData->DW5.NextFrameHeight - 1;

        m_osInterface->pfnUnlockResource(m_osInterface, &m_brcBuffers.resBrcHucDataBuffer);
    }

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::ExecuteSliceLevel()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

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

    MHW_BATCH_BUFFER secondLevelBatchBuffer;
    MOS_ZeroMemory(&secondLevelBatchBuffer, sizeof(secondLevelBatchBuffer));
    secondLevelBatchBuffer.dwOffset = 0;
    secondLevelBatchBuffer.bSecondLevel = true;
    if (!m_hucEnabled)
    {
        secondLevelBatchBuffer.OsResource = m_resHucPakInsertUncompressedHeaderReadBuffer[m_currRecycledBufIdx];
    }
    else
    {
        secondLevelBatchBuffer.OsResource = m_resHucPakInsertUncompressedHeaderWriteBuffer;
    }
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(
        &cmdBuffer,
        &secondLevelBatchBuffer));

    MHW_VDBOX_VDENC_WEIGHT_OFFSET_PARAMS vdencWeightOffsetParams;
    MOS_ZeroMemory(&vdencWeightOffsetParams, sizeof(vdencWeightOffsetParams));
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_vdencInterface->AddVdencWeightsOffsetsStateCmd(&cmdBuffer, nullptr, &vdencWeightOffsetParams));

    MHW_VDBOX_VDENC_WALKER_STATE_PARAMS vdencWalkerStateParams;
    vdencWalkerStateParams.Mode = CODECHAL_ENCODE_MODE_VP9;
    vdencWalkerStateParams.pVp9EncPicParams = m_vp9PicParams;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_vdencInterface->AddVdencWalkerStateCmd(&cmdBuffer, &vdencWalkerStateParams));

    MHW_VDBOX_VD_PIPE_FLUSH_PARAMS vdPipelineFlushParams;
    MOS_ZeroMemory(&vdPipelineFlushParams, sizeof(vdPipelineFlushParams));
    // MFXPipeDone should not be set for tail insertion
    vdPipelineFlushParams.Flags.bWaitDoneMFX = 1;
    vdPipelineFlushParams.Flags.bWaitDoneHEVC = 1;
    vdPipelineFlushParams.Flags.bFlushHEVC = 1;
    vdPipelineFlushParams.Flags.bWaitDoneVDCmdMsgParser = 1;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_vdencInterface->AddVdPipelineFlushCmd(&cmdBuffer, &vdPipelineFlushParams));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(EndStatusReport(&cmdBuffer, CODECHAL_NUM_MEDIA_STATES));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(ReadHcpStatus(&cmdBuffer));

    uint32_t offset =
        (m_encodeStatusBuf.wCurrIndex * m_encodeStatusBuf.dwReportSize)  +
        m_encodeStatusBuf.dwNumPassesOffset                                      +
        sizeof(uint32_t) * 2; // encode status doesn't start until 3rd DW

    MHW_MI_STORE_DATA_PARAMS storeDataParams;
    storeDataParams.pOsResource         = &m_encodeStatusBuf.resStatusBuffer;
    storeDataParams.dwResourceOffset    = offset;
    storeDataParams.dwValue             = m_currPass + 1;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(&cmdBuffer, &storeDataParams));

    MHW_MI_FLUSH_DW_PARAMS flushDwParams;
    MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(&cmdBuffer, &flushDwParams));

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

    std::string pakPassName = "PAK_PASS" + std::to_string(static_cast<uint32_t>(m_currPass));
    CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer(
        &cmdBuffer,
        CODECHAL_NUM_MEDIA_STATES,
        pakPassName.data())));

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

    if (!m_singleTaskPhaseSupported || m_lastTaskInPhase)
    {
        bool renderFlags;

        if (m_waitForEnc &&
            !Mos_ResourceIsNull(&m_resSyncObjectRenderContextInUse))
        {
            MOS_SYNC_PARAMS syncParams;
            syncParams = g_cInitSyncParams;
            syncParams.GpuContext = m_videoContext;
            syncParams.presSyncResource = &m_resSyncObjectRenderContextInUse;

            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
            m_waitForEnc = false;
        }

        renderFlags = m_videoContextUsesNullHw;

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, renderFlags));
        m_lastTaskInPhase = false;

        CODECHAL_DEBUG_TOOL(
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer(
                m_resVdencPakObjCmdStreamOutBuffer,
                CodechalDbgAttr::attrPakObjStreamout,
                pakPassName.data(),
                m_mbCodeSize + 8 * CODECHAL_CACHELINE_SIZE,
                0,
                CODECHAL_NUM_MEDIA_STATES));

            if (m_vp9PicParams->PicFlags.fields.segmentation_enabled) {
                ; //CodecHal_DbgDumpEncodeVp9SegmentStreamout(m_debugInterface, m_encoder);
            } if (m_mmcState) {
                m_mmcState->UpdateUserFeatureKey(&m_reconSurface);
            });
    }

    // Reset parameters for next PAK execution
    if (m_currPass == m_numPasses)
    {
        if (m_vp9PicParams->PicFlags.fields.super_frame && m_tsEnabled)
        {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(ConstructSuperFrame());
        }

        if (m_signalEnc &&
            !Mos_ResourceIsNull(&m_resSyncObjectVideoContextInUse))
        {
            // Check if the signal obj count exceeds max value
            MOS_SYNC_PARAMS syncParams;
            if (m_semaphoreObjCount == MOS_MIN(m_semaphoreMaxCount, MOS_MAX_OBJECT_SIGNALED))
            {
                syncParams = g_cInitSyncParams;
                syncParams.GpuContext = m_renderContext;
                syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse;

                CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
                m_semaphoreObjCount--;
            }

            // signal semaphore
            syncParams = g_cInitSyncParams;
            syncParams.GpuContext = m_videoContext;
            syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse;

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

        m_prevFrameInfo.KeyFrame    = !m_vp9PicParams->PicFlags.fields.frame_type;
        m_prevFrameInfo.IntraOnly   = (m_vp9PicParams->PicFlags.fields.frame_type == CODEC_VP9_KEY_FRAME) || m_vp9PicParams->PicFlags.fields.intra_only;
        m_prevFrameInfo.ShowFrame   = m_vp9PicParams->PicFlags.fields.show_frame;
        m_prevFrameInfo.FrameWidth  = m_oriFrameWidth;
        m_prevFrameInfo.FrameHeight = m_oriFrameHeight;
        m_currMvTemporalBufferIndex ^= 0x01;
        m_contextFrameTypes[m_vp9PicParams->PicFlags.fields.frame_context_idx] = m_vp9PicParams->PicFlags.fields.frame_type;
        m_prevFrameSegEnabled                                                  = m_vp9PicParams->PicFlags.fields.segmentation_enabled;

        if (!m_singleTaskPhaseSupported)
        {
            m_osInterface->pfnResetPerfBufferID(m_osInterface);
        }

        m_newPpsHeader = 0;
        m_newSeqHeader = 0;
        m_frameNum++;
    }

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::PakConstructPicStateBatchBuf(
    PMOS_RESOURCE picStateBuffer)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(picStateBuffer);

    MOS_LOCK_PARAMS lockFlagsWriteOnly;
    MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
    lockFlagsWriteOnly.WriteOnly = 1;
    uint8_t* data = (uint8_t*)m_osInterface->pfnLockResource(m_osInterface, picStateBuffer, &lockFlagsWriteOnly);
    CODECHAL_ENCODE_CHK_NULL_RETURN(data);

    // HCP_VP9_PIC_STATE
    MHW_VDBOX_VP9_ENCODE_PIC_STATE picState;
    MOS_ZeroMemory(&picState, sizeof(picState));
    picState.pVp9PicParams                    = m_vp9PicParams;
    picState.pVp9SeqParams                    = m_vp9SeqParams;
    picState.ppVp9RefList                     = &(m_refList[0]);
    picState.PrevFrameParams.fields.KeyFrame  = m_prevFrameInfo.KeyFrame;
    picState.PrevFrameParams.fields.IntraOnly = m_prevFrameInfo.IntraOnly;
    picState.PrevFrameParams.fields.Display   = m_prevFrameInfo.ShowFrame;
    picState.dwPrevFrmWidth                   = m_prevFrameInfo.FrameWidth;
    picState.dwPrevFrmHeight                  = m_prevFrameInfo.FrameHeight;
    picState.ucTxMode = m_txMode;

    for (auto i = 0; i < CODECHAL_ENCODE_VP9_BRC_MAX_NUM_OF_PASSES; i++)
    {
        picState.bNonFirstPassFlag = (i != 0) ? true : false;

        MOS_COMMAND_BUFFER constructedCmdBuf;

        constructedCmdBuf.pCmdBase   = (uint32_t *)data;
        constructedCmdBuf.pCmdPtr    = (uint32_t *)(data + i * CODECHAL_ENCODE_VP9_PIC_STATE_BUFFER_SIZE_PER_PASS);
        constructedCmdBuf.iOffset    = 0;
        constructedCmdBuf.iRemaining = CODECHAL_ENCODE_VP9_PIC_STATE_BUFFER_SIZE_PER_PASS;

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpVp9PicStateEncCmd(&constructedCmdBuf, nullptr, &picState));

        // After adding pic State cmds in above function, pCmdPtr is not at the end of the picState Buffer, so adjusting it.
        constructedCmdBuf.pCmdPtr    = (uint32_t *)(data + (i+1) * CODECHAL_ENCODE_VP9_PIC_STATE_BUFFER_SIZE_PER_PASS) - 1;  //-1 to go back one uint32_t where BB end will be added

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&constructedCmdBuf, nullptr));
    }

    if (data)
    {
        m_osInterface->pfnUnlockResource(
            m_osInterface,
            picStateBuffer);
    }
    return eStatus;
}

// This is used only for DynamicScaling
MOS_STATUS CodechalVdencVp9State::ExecuteDysPictureLevel()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_COND_RETURN((m_vdboxIndex > m_hwInterface->GetMfxInterface()->GetMaxVdboxIndex()),"ERROR - vdbox index exceed the maximum");
    auto mmioRegisters = m_hcpInterface->GetMmioRegisters(m_vdboxIndex);
    CODECHAL_ENCODE_CHK_NULL_RETURN(mmioRegisters);
    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);

    // We only need to update Huc PAK insert object and picture state for the first pass
    if (m_currPass == 0)
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(ConstructPakInsertObjBatchBuf(&m_resHucPakInsertUncompressedHeaderReadBuffer[m_currRecycledBufIdx]));
        CODECHAL_ENCODE_CHK_STATUS_RETURN(PakConstructPicStateBatchBuf(
            &m_brcBuffers.resPicStateBrcWriteHucReadBuffer));

    }

    MOS_COMMAND_BUFFER cmdBuffer;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(GetCommandBuffer(&cmdBuffer));

    if (!m_singleTaskPhaseSupported || m_firstTaskInPhase)
    {
        bool requestFrameTracking = false;

        // 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));
    }

    // Making sure ImgStatusCtrl is zeroed out before first PAK pass. HW supposedly does this before start of each frame. Remove this after confirming.
    if (m_currPass == 0)
    {
        MHW_MI_LOAD_REGISTER_IMM_PARAMS miLoadRegImmParams;
        MOS_ZeroMemory(&miLoadRegImmParams, sizeof(miLoadRegImmParams));
        miLoadRegImmParams.dwData     = 0;
        miLoadRegImmParams.dwRegister = mmioRegisters->hcpVp9EncImageStatusCtrlRegOffset;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetMiInterface()->AddMiLoadRegisterImmCmd(&cmdBuffer, &miLoadRegImmParams));
    }

    // Read Image status before running PAK, to get correct cumulative delta applied for final pass.
    if (m_currPass != m_numPasses)        // Don't read it for Repak
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(ReadImageStatus(&cmdBuffer));
    }

    //updating the numberofpakpasses in encode staus buffer. should not update for repak.
    if (m_currPass < m_numPasses)
    {
        uint32_t offset =
            (m_encodeStatusBuf.wCurrIndex * m_encodeStatusBuf.dwReportSize) +
            m_encodeStatusBuf.dwNumPassesOffset +
            sizeof(uint32_t)* 2; // encode status doesn't start until 3rd DW

        MHW_MI_STORE_DATA_PARAMS storeDataParams;
        MOS_ZeroMemory(&storeDataParams, sizeof(storeDataParams));
        storeDataParams.pOsResource = &m_encodeStatusBuf.resStatusBuffer;
        storeDataParams.dwResourceOffset = offset;
        storeDataParams.dwValue = m_currPass + 1;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(&cmdBuffer, &storeDataParams));
    }

    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.
        PMOS_RESOURCE globalGpuContextSyncTagBuffer = nullptr;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetGpuStatusBufferResource(
            m_osInterface,
            globalGpuContextSyncTagBuffer));
        CODECHAL_ENCODE_CHK_NULL_RETURN(globalGpuContextSyncTagBuffer);

        uint32_t value = m_osInterface->pfnGetGpuStatusTag(m_osInterface, m_osInterface->CurrentGpuContextOrdinal);
        MHW_MI_STORE_DATA_PARAMS params;
        params.pOsResource = globalGpuContextSyncTagBuffer;
        params.dwResourceOffset = m_osInterface->pfnGetGpuStatusTagOffset(m_osInterface, m_osInterface->CurrentGpuContextOrdinal);
        params.dwValue = (value > 0) ? (value - 1) : 0;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetMiInterface()->AddMiStoreDataImmCmd(&cmdBuffer, &params));
    }

    CODECHAL_ENCODE_CHK_STATUS_RETURN(StartStatusReport(&cmdBuffer, CODECHAL_NUM_MEDIA_STATES));

    // set HCP_PIPE_MODE_SELECT values
    PMHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams = nullptr;
    pipeModeSelectParams = m_vdencInterface->CreateMhwVdboxPipeModeSelectParams();
    if (pipeModeSelectParams)
    {
        pipeModeSelectParams->Mode = m_mode;
        pipeModeSelectParams->bStreamOutEnabled  = false;
        pipeModeSelectParams->bVdencEnabled      = false;
        pipeModeSelectParams->ChromaType         = m_vp9SeqParams->SeqFlags.fields.EncodedFormat;

        eStatus = m_hcpInterface->AddHcpPipeModeSelectCmd(&cmdBuffer, pipeModeSelectParams);
        m_vdencInterface->ReleaseMhwVdboxPipeModeSelectParams(pipeModeSelectParams);
        CODECHAL_ENCODE_CHK_STATUS_RETURN(eStatus);
    }

    // set HCP_SURFACE_STATE values
    MHW_VDBOX_SURFACE_PARAMS surfaceParams[CODECHAL_HCP_ALTREF_SURFACE_ID + 1];
    for (uint8_t i = 0; i <= CODECHAL_HCP_ALTREF_SURFACE_ID; i++)
    {
        MOS_ZeroMemory(&surfaceParams[i], sizeof(surfaceParams[i]));
        surfaceParams[i].Mode = m_mode;
        surfaceParams[i].ucSurfaceStateId = i;
        surfaceParams[i].ChromaType = m_outputChromaFormat;

        switch (m_vp9SeqParams->SeqFlags.fields.EncodedBitDepth)
        {
        case VP9_ENCODED_BIT_DEPTH_10: //10 bit encoding
        {
            surfaceParams[i].ucBitDepthChromaMinus8 = 2;
            surfaceParams[i].ucBitDepthLumaMinus8 = 2;
            break;
        }
        default:
        {
            surfaceParams[i].ucBitDepthChromaMinus8 = 0;
            surfaceParams[i].ucBitDepthLumaMinus8 = 0;
            break;
        }
        }
    }

    // For PAK engine, we do NOT use scaled reference images even if dynamic scaling is enabled
    PMOS_SURFACE refSurface[3];
    for (auto i = 0; i < 3; i++)
    {
        refSurface[i] = nullptr;
    }

    if (m_pictureCodingType != I_TYPE)
    {
        uint8_t refPicIndex;
        if (m_refFrameFlags & 0x01)
        {
            refPicIndex = m_vp9PicParams->RefFlags.fields.LastRefIdx;

            CODECHAL_ENCODE_ASSERT((refPicIndex < CODEC_VP9_NUM_REF_FRAMES) && (!CodecHal_PictureIsInvalid(m_vp9PicParams->RefFrameList[refPicIndex])));
            refSurface[0] = &(m_refList[m_vp9PicParams->RefFrameList[refPicIndex].FrameIdx]->sRefBuffer);
        }

        if (m_refFrameFlags & 0x02)
        {
            refPicIndex = m_vp9PicParams->RefFlags.fields.GoldenRefIdx;

            CODECHAL_ENCODE_ASSERT((refPicIndex < CODEC_VP9_NUM_REF_FRAMES) && (!CodecHal_PictureIsInvalid(m_vp9PicParams->RefFrameList[refPicIndex])));
            refSurface[1] = &(m_refList[m_vp9PicParams->RefFrameList[refPicIndex].FrameIdx]->sRefBuffer);
        }

        if (m_refFrameFlags & 0x04)
        {
            refPicIndex = m_vp9PicParams->RefFlags.fields.AltRefIdx;

            CODECHAL_ENCODE_ASSERT((refPicIndex < CODEC_VP9_NUM_REF_FRAMES) && (!CodecHal_PictureIsInvalid(m_vp9PicParams->RefFrameList[refPicIndex])))
            refSurface[2] = &(m_refList[m_vp9PicParams->RefFrameList[refPicIndex].FrameIdx]->sRefBuffer);
        }

        if (!refSurface[0])
        {
            refSurface[0] = (refSurface[1]) ? refSurface[1] : refSurface[2];
        }

        if (!refSurface[1])
        {
            refSurface[1] = (refSurface[0]) ? refSurface[0] : refSurface[2];
        }

        if (!refSurface[2])
        {
            refSurface[2] = (refSurface[0]) ? refSurface[0] : refSurface[1];
        }

        // Program Surface params for Last/Golen/Alt Reference surface
        surfaceParams[CODECHAL_HCP_LAST_SURFACE_ID].psSurface               = refSurface[0];
        surfaceParams[CODECHAL_HCP_GOLDEN_SURFACE_ID].psSurface             = refSurface[1];
        surfaceParams[CODECHAL_HCP_ALTREF_SURFACE_ID].psSurface             = refSurface[2];

        surfaceParams[CODECHAL_HCP_LAST_SURFACE_ID].dwReconSurfHeight   = MOS_ALIGN_CEIL((refSurface[0] ? refSurface[0]->dwHeight : 0), CODEC_VP9_MIN_BLOCK_WIDTH);
        surfaceParams[CODECHAL_HCP_GOLDEN_SURFACE_ID].dwReconSurfHeight = MOS_ALIGN_CEIL((refSurface[1] ? refSurface[1]->dwHeight : 0), CODEC_VP9_MIN_BLOCK_WIDTH);
        surfaceParams[CODECHAL_HCP_ALTREF_SURFACE_ID].dwReconSurfHeight = MOS_ALIGN_CEIL((refSurface[2] ? refSurface[2]->dwHeight : 0), CODEC_VP9_MIN_BLOCK_WIDTH);
    }

    // recon
    surfaceParams[CODECHAL_HCP_DECODED_SURFACE_ID].psSurface            = &m_reconSurface;
    surfaceParams[CODECHAL_HCP_DECODED_SURFACE_ID].dwReconSurfHeight    = m_rawSurfaceToPak->dwHeight;

    // raw
    surfaceParams[CODECHAL_HCP_SRC_SURFACE_ID].psSurface                = m_rawSurfaceToPak;
    surfaceParams[CODECHAL_HCP_SRC_SURFACE_ID].bDisplayFormatSwizzle    = m_vp9SeqParams->SeqFlags.fields.DisplayFormatSwizzle;
    surfaceParams[CODECHAL_HCP_SRC_SURFACE_ID].dwActualWidth            = MOS_ALIGN_CEIL(m_oriFrameWidth, CODEC_VP9_MIN_BLOCK_WIDTH);
    surfaceParams[CODECHAL_HCP_SRC_SURFACE_ID].dwActualHeight           = MOS_ALIGN_CEIL(m_oriFrameHeight, CODEC_VP9_MIN_BLOCK_WIDTH);

    // Decodec picture
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpSurfaceCmd(&cmdBuffer, &surfaceParams[CODECHAL_HCP_DECODED_SURFACE_ID]));

    // Source input
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpSurfaceCmd(&cmdBuffer, &surfaceParams[CODECHAL_HCP_SRC_SURFACE_ID]));

    // Last reference picture
    if (refSurface[0])
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpSurfaceCmd(&cmdBuffer, &surfaceParams[CODECHAL_HCP_LAST_SURFACE_ID]));
    }

    // Golden reference picture
    if (refSurface[1])
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpSurfaceCmd(&cmdBuffer, &surfaceParams[CODECHAL_HCP_GOLDEN_SURFACE_ID]));
    }

    // Alt reference picture
    if (refSurface[2])
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpSurfaceCmd(&cmdBuffer, &surfaceParams[CODECHAL_HCP_ALTREF_SURFACE_ID]));
    }

    // set HCP_PIPE_BUF_ADDR_STATE values
    PMHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams = nullptr;
    pipeBufAddrParams = CreateHcpPipeBufAddrParams(pipeBufAddrParams);
    if (pipeBufAddrParams)
    {
        auto delete_func = [&]()
        {
            MOS_Delete(pipeBufAddrParams);
            pipeBufAddrParams = nullptr;
        };

        pipeBufAddrParams->Mode = m_mode;
        pipeBufAddrParams->psPreDeblockSurface = &m_reconSurface;
        pipeBufAddrParams->psPostDeblockSurface = &m_reconSurface;
        pipeBufAddrParams->psRawSurface = m_rawSurfaceToPak;

        pipeBufAddrParams->presStreamOutBuffer = nullptr;
        pipeBufAddrParams->presMfdDeblockingFilterRowStoreScratchBuffer =
            &m_resDeblockingFilterLineBuffer;

        pipeBufAddrParams->presDeblockingFilterTileRowStoreScratchBuffer =
            &m_resDeblockingFilterTileLineBuffer;

        pipeBufAddrParams->presDeblockingFilterColumnRowStoreScratchBuffer =
            &m_resDeblockingFilterTileColumnBuffer;

        pipeBufAddrParams->presMetadataLineBuffer       = &m_resMetadataLineBuffer;
        pipeBufAddrParams->presMetadataTileLineBuffer   = &m_resMetadataTileLineBuffer;
        pipeBufAddrParams->presMetadataTileColumnBuffer = &m_resMetadataTileColumnBuffer;
        pipeBufAddrParams->presCurMvTempBuffer = m_trackedBuf->GetMvTemporalBuffer(m_currMvTemporalBufferIndex);
        if (m_pictureCodingType != I_TYPE)
        {
            for (auto i = 0; i < 3; i++)
            {
                CODECHAL_ENCODE_CHK_NULL_WITH_DESTROY_RETURN(refSurface[i], delete_func);
                pipeBufAddrParams->presReferences[i] = &refSurface[i]->OsResource;
            }
        }


        pipeBufAddrParams->pRawSurfParam      = &surfaceParams[CODECHAL_HCP_SRC_SURFACE_ID];
        pipeBufAddrParams->pDecodedReconParam = &surfaceParams[CODECHAL_HCP_DECODED_SURFACE_ID];
        CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(SetPipeBufAddr(pipeBufAddrParams, refSurface, &cmdBuffer), delete_func);

        //Huc is disabled for ref frame scaling, use input region
        uint8_t frameCtxIdx = m_vp9PicParams->PicFlags.fields.frame_context_idx;
        CODECHAL_ENCODE_ASSERT(frameCtxIdx < CODEC_VP9_NUM_CONTEXTS);
        pipeBufAddrParams->presVp9ProbBuffer      = &m_resProbBuffer[frameCtxIdx];
        pipeBufAddrParams->presVp9SegmentIdBuffer = &m_resSegmentIdBuffer;

        if (m_pictureCodingType != I_TYPE)
        {
            pipeBufAddrParams->presColMvTempBuffer[0] = m_trackedBuf->GetMvTemporalBuffer(m_currMvTemporalBufferIndex ^ 0x01);
        }
        CODECHAL_ENCODE_CHK_STATUS_WITH_DESTROY_RETURN(m_hcpInterface->AddHcpPipeBufAddrCmd(&cmdBuffer, pipeBufAddrParams), delete_func);

        MOS_Delete(pipeBufAddrParams);
    }

    // set HCP_IND_OBJ_BASE_ADDR_STATE values
    MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS indObjBaseAddrParams;
    MOS_ZeroMemory(&indObjBaseAddrParams, sizeof(indObjBaseAddrParams));
    indObjBaseAddrParams.Mode                           = m_mode;
    indObjBaseAddrParams.presMvObjectBuffer             = &m_resMbCodeSurface;
    indObjBaseAddrParams.dwMvObjectOffset               = m_mvOffset;
    indObjBaseAddrParams.dwMvObjectSize                 = m_mbCodeSize - m_mvOffset;
    indObjBaseAddrParams.presPakBaseObjectBuffer        = &m_resBitstreamBuffer;
    indObjBaseAddrParams.dwPakBaseObjectSize            = m_bitstreamUpperBound;
    indObjBaseAddrParams.presProbabilityDeltaBuffer     = &m_resProbabilityDeltaBuffer;
    indObjBaseAddrParams.dwProbabilityDeltaSize         = 29 * CODECHAL_CACHELINE_SIZE;
    indObjBaseAddrParams.presCompressedHeaderBuffer     = &m_resCompressedHeaderBuffer;
    indObjBaseAddrParams.dwCompressedHeaderSize         = 32 * CODECHAL_CACHELINE_SIZE;
    indObjBaseAddrParams.presProbabilityCounterBuffer   = &m_resProbabilityCounterBuffer;
    indObjBaseAddrParams.dwProbabilityCounterSize       = 193 * CODECHAL_CACHELINE_SIZE;
    indObjBaseAddrParams.presTileRecordBuffer           = &m_resTileRecordStrmOutBuffer;
    indObjBaseAddrParams.dwTileRecordSize               = m_picSizeInSb * CODECHAL_CACHELINE_SIZE;
    indObjBaseAddrParams.presCuStatsBuffer              = &m_resCuStatsStrmOutBuffer;
    indObjBaseAddrParams.dwCuStatsSize                  = MOS_ALIGN_CEIL(m_picSizeInSb * 64 * 8, CODECHAL_CACHELINE_SIZE);
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpIndObjBaseAddrCmd(&cmdBuffer, &indObjBaseAddrParams));

    // Using picstate zero with updated QP and LF deltas by HuC for repak, irrespective of how many Pak passes were run in multi-pass mode.
    MHW_BATCH_BUFFER secondLevelBatchBuffer;
    MOS_ZeroMemory(&secondLevelBatchBuffer, sizeof(secondLevelBatchBuffer));
    secondLevelBatchBuffer.dwOffset = (m_numPasses > 0) ? CODECHAL_ENCODE_VP9_PIC_STATE_BUFFER_SIZE_PER_PASS * (m_currPass % m_numPasses) : 0;
    secondLevelBatchBuffer.bSecondLevel = true;
    //As Huc is disabled for Ref frame scaling, use the ReadBuffer
    secondLevelBatchBuffer.OsResource = m_brcBuffers.resPicStateBrcWriteHucReadBuffer;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(
        &cmdBuffer,
        &secondLevelBatchBuffer));

    // HCP_VP9_SEGMENT_STATE
    uint8_t segmentCount = (m_vp9PicParams->PicFlags.fields.segmentation_enabled) ? CODEC_VP9_MAX_SEGMENTS : 1;

    MHW_VDBOX_VP9_SEGMENT_STATE segmentState;
    MOS_ZeroMemory(&segmentState, sizeof(segmentState));
    segmentState.Mode                        = m_mode;
    segmentState.pVp9EncodeSegmentParams     = m_vp9SegmentParams;
    segmentState.ucQPIndexLumaAC             = m_vp9PicParams->LumaACQIndex;

    // For BRC with segmentation, seg state commands for PAK are copied from BRC seg state buffer
    // For CQP or BRC with no segmentation, PAK still needs seg state commands and driver prepares those commands.
    segmentState.pbSegStateBufferPtr = nullptr; // Set this to nullptr, for commands to be prepared by driver
    segmentState.pcucLfQpLookup          = &LF_VALUE_QP_LOOKUP[0];
    for (uint8_t i = 0; i < segmentCount; i++)
    {
        segmentState.ucCurrentSegmentId  = i;
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hcpInterface->AddHcpVp9SegmentStateCmd(&cmdBuffer, nullptr, &segmentState));
    }

    CODECHAL_ENCODE_CHK_STATUS_RETURN(ReturnCommandBuffer(&cmdBuffer));

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::ExecuteDysSliceLevel()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(m_nalUnitParams);

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

    MHW_BATCH_BUFFER secondLevelBatchBuffer;
    MOS_ZeroMemory(&secondLevelBatchBuffer, sizeof(secondLevelBatchBuffer));
    secondLevelBatchBuffer.dwOffset = 0;
    secondLevelBatchBuffer.bSecondLevel = true;
    // This function is called only for Reference frame scaling for Dynamic Scaling feature
    // Huc is disabled for ref frame scaling so we use on the ReadBuffer
    secondLevelBatchBuffer.OsResource = m_resHucPakInsertUncompressedHeaderReadBuffer[m_currRecycledBufIdx];

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(
        &cmdBuffer,
        &secondLevelBatchBuffer));

    MOS_ZeroMemory(&secondLevelBatchBuffer, sizeof(MHW_BATCH_BUFFER));
    secondLevelBatchBuffer.OsResource = m_resMbCodeSurface;
    secondLevelBatchBuffer.dwOffset = 0;
    secondLevelBatchBuffer.bSecondLevel = true;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(&cmdBuffer, &secondLevelBatchBuffer));

    MHW_VDBOX_VD_PIPE_FLUSH_PARAMS vdPipelineFlushParams;
    MOS_ZeroMemory(&vdPipelineFlushParams, sizeof(vdPipelineFlushParams));
    // MFXPipeDone should not be set for tail insertion
    vdPipelineFlushParams.Flags.bWaitDoneMFX =
        (m_lastPicInStream || m_lastPicInSeq) ? 0 : 1;
    vdPipelineFlushParams.Flags.bWaitDoneHEVC = 1;
    vdPipelineFlushParams.Flags.bFlushHEVC = 1;
    vdPipelineFlushParams.Flags.bWaitDoneVDCmdMsgParser = 1;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_vdencInterface->AddVdPipelineFlushCmd(&cmdBuffer, &vdPipelineFlushParams));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(ReadMfcStatus(&cmdBuffer));

    MHW_MI_FLUSH_DW_PARAMS flushDwParams;
    MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(&cmdBuffer, &flushDwParams));

    CODECHAL_ENCODE_CHK_STATUS_RETURN(EndStatusReport(&cmdBuffer, CODECHAL_NUM_MEDIA_STATES));

    if (m_currPass >= (m_numPasses - 1))    // Last pass and the one before last
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr));
    }

    std::string pakPassName = "PAK_PASS" + std::to_string(static_cast<uint32_t>(m_currPass));
    CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer(
        &cmdBuffer,
        CODECHAL_NUM_MEDIA_STATES,
        pakPassName.data())));

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

    if (m_waitForEnc &&
        !Mos_ResourceIsNull(&m_resSyncObjectRenderContextInUse))
    {
        MOS_SYNC_PARAMS syncParams = g_cInitSyncParams;
        syncParams.GpuContext = m_videoContext;
        syncParams.presSyncResource = &m_resSyncObjectRenderContextInUse;

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
        m_waitForEnc = false;
    }

    if (m_currPass >= (m_numPasses - 1))    // Last pass and the one before last
    {
        bool renderFlags;

        renderFlags = m_videoContextUsesNullHw;

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, renderFlags));
    }

    CODECHAL_DEBUG_TOOL(
        if (m_vp9PicParams->PicFlags.fields.segmentation_enabled) {
            ; //CodecHal_DbgDumpEncodeVp9SegmentStreamout(m_debugInterface, m_encoder);
        } if (m_mmcState) {
            m_mmcState->UpdateUserFeatureKey(&m_reconSurface);
        });

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::AllocateMbBrcSegMapSurface()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    //MBBRC segment map surface needs to be allocated when mbbrc is enabled as segment map will not be
    //passed from APP when MBBRC is enabled
    uint32_t picWidthInMb = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_maxPicWidth);
    uint32_t picHeightInMb = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_maxPicHeight);

    m_mbSegmentMapSurface.TileType      = MOS_TILE_LINEAR;
    m_mbSegmentMapSurface.bArraySpacing = true;
    m_mbSegmentMapSurface.Format        = Format_Buffer_2D;
    m_mbSegmentMapSurface.dwWidth       = MOS_ALIGN_CEIL(picWidthInMb, 4);
    m_mbSegmentMapSurface.dwHeight      = picHeightInMb;
    m_mbSegmentMapSurface.dwPitch       = MOS_ALIGN_CEIL(picWidthInMb, 64);

    MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
    MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS));

    allocParamsForBuffer2D.Type = MOS_GFXRES_2D;
    allocParamsForBuffer2D.TileType = MOS_TILE_LINEAR;
    allocParamsForBuffer2D.Format = Format_Buffer_2D;
    allocParamsForBuffer2D.dwWidth  = m_mbSegmentMapSurface.dwPitch;
    allocParamsForBuffer2D.dwHeight = picHeightInMb;
    allocParamsForBuffer2D.pBufName = "MBBRC driver Segment Map Surface";

    uint32_t size = allocParamsForBuffer2D.dwWidth * allocParamsForBuffer2D.dwHeight;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
        m_osInterface,
        &allocParamsForBuffer2D,
        &m_mbSegmentMapSurface.OsResource));

    MOS_LOCK_PARAMS lockFlagsWriteOnly;
    MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
    lockFlagsWriteOnly.WriteOnly = 1;

    uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(
        m_osInterface,
        &(m_mbSegmentMapSurface.OsResource),
        &lockFlagsWriteOnly);

    if (data == nullptr)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to Lock MBBRC driver segment map resource.");
        return MOS_STATUS_UNKNOWN;
    }

    MOS_ZeroMemory(data, size);
    m_osInterface->pfnUnlockResource(m_osInterface, &m_mbSegmentMapSurface.OsResource);

    m_segmentMapAllocated = true;

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::SetSequenceStructs()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    if (m_osInterface->osCpInterface->IsHMEnabled())
    {
        m_advancedDshInUse = true;
    }

    m_numPasses = m_hucEnabled ? CODECHAL_ENCODE_VP9_CQP_NUM_OF_PASSES - 1 : 0;
    m_brcEnabled = CodecHalIsRateControlBrc(m_vp9SeqParams->RateControlMethod, CODECHAL_VP9);
    if (m_brcEnabled)
    {
        m_brcReset        = m_vp9SeqParams->SeqFlags.fields.bResetBRC;
        m_vdencBrcEnabled = true;
        m_numPasses = m_multipassBrcSupported ? CODECHAL_ENCODE_VP9_BRC_DEFAULT_NUM_OF_PASSES : CODECHAL_ENCODE_VP9_BRC_DEFAULT_NUM_OF_PASSES - 1;
    }

    if (m_adaptiveRepakSupported)
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(CalculateRePakThresholds());
    }

    m_tsEnabled = (m_vp9SeqParams->NumTemporalLayersMinus1 > 0) ? true : false;

    if (m_tsEnabled && m_brcEnabled)
    {
        // check base layer properties
        CODECHAL_ENCODE_ASSERT(m_vp9SeqParams->FrameRate[0].uiNumerator > 0 && m_vp9SeqParams->FrameRate[0].uiDenominator > 0);
        CODECHAL_ENCODE_ASSERT(m_vp9SeqParams->TargetBitRate[0] > 0);

        for (auto i = 1; i < m_vp9SeqParams->NumTemporalLayersMinus1 + 1; i += 1)
        {
            // check current layer properties
            CODECHAL_ENCODE_ASSERT(m_vp9SeqParams->FrameRate[i].uiNumerator > 0 && m_vp9SeqParams->FrameRate[i].uiDenominator > 0);
            CODECHAL_ENCODE_ASSERT(m_vp9SeqParams->TargetBitRate[i] > 0);

            // check current layer properties are bigger than previous layer (since current includes previous layer properties)
            CODECHAL_ENCODE_ASSERT(m_vp9SeqParams->FrameRate[i].uiNumerator / m_vp9SeqParams->FrameRate[i].uiDenominator >
                                   m_vp9SeqParams->FrameRate[i - 1].uiNumerator / m_vp9SeqParams->FrameRate[i - 1].uiDenominator);
            CODECHAL_ENCODE_ASSERT(m_vp9SeqParams->TargetBitRate[i] > m_vp9SeqParams->TargetBitRate[i - 1]);
        }
    }

    if ((m_vp9SeqParams->SeqFlags.fields.MBBRC == MBBRC_ENABLED) || (m_vp9SeqParams->SeqFlags.fields.MBBRC == MBBRC_ENABLED_TU_DEPENDENCY))
    {
        if (!m_segmentMapAllocated)
        {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateMbBrcSegMapSurface());
        }
    }
    else
    {
        //Allocated Driver MbBrc Segment map resource needs to be deallocated when MBBRC is disabled. The reason being
        //same segmnet map surface (sMbSegmentMapSurface) will be used in the driver referencing both the Application passed
        //as well as Driver allocated resource for segmentmap depending on mbbrc disabled or enabled.
        if (!Mos_ResourceIsNull(&m_mbSegmentMapSurface.OsResource) && m_segmentMapAllocated)
        {
            m_osInterface->pfnFreeResource(
                m_osInterface,
                &m_mbSegmentMapSurface.OsResource);
        }

        m_segmentMapAllocated = false;
    }

    // if GOP structure is I-frame only, we use 3 non-ref slots for tracked buffer
    m_gopIsIdrFrameOnly = (m_vp9SeqParams->GopPicSize == 1);

    // check output Chroma format
    if (VP9_ENCODED_CHROMA_FORMAT_YUV420 == m_vp9SeqParams->SeqFlags.fields.EncodedFormat)
    {
        m_outputChromaFormat = HCP_CHROMA_FORMAT_YUV420;
    }
    else if (VP9_ENCODED_CHROMA_FORMAT_YUV422 == m_vp9SeqParams->SeqFlags.fields.EncodedFormat)
    {
        m_outputChromaFormat = HCP_CHROMA_FORMAT_YUV422;
    }
    else if (VP9_ENCODED_CHROMA_FORMAT_YUV444 == m_vp9SeqParams->SeqFlags.fields.EncodedFormat)
    {
        m_outputChromaFormat = HCP_CHROMA_FORMAT_YUV444;
    }
    else
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Invalid output chromat format in VP9 Seq param!");
        return MOS_STATUS_INVALID_PARAMETER;
    }

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::SetPictureStructs()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    //Enable only for TU1
    if (m_vp9SeqParams->TargetUsage != TU_QUALITY)
    {
        m_hmeEnabled = m_16xMeSupported = m_32xMeSupported = false;
        m_16xMeEnabled = false;
    }

    // setup internal parameters
    // dwOriFrameWidth and dwOriFrameHeight are encoded resolutions which might be different from source resoultions if dynamic scaling is enabled
    m_oriFrameWidth  = m_vp9PicParams->SrcFrameWidthMinus1 + 1;
    m_oriFrameHeight = m_vp9PicParams->SrcFrameHeightMinus1 + 1;

    if (m_oriFrameWidth == 0 || m_oriFrameWidth > m_maxPicWidth ||
        m_oriFrameHeight == 0 || m_oriFrameHeight > m_maxPicHeight)
    {
        return MOS_STATUS_INVALID_PARAMETER;
    }

    m_picWidthInSb = MOS_ROUNDUP_DIVIDE(m_oriFrameWidth, CODEC_VP9_SUPER_BLOCK_WIDTH);
    m_picHeightInSb = MOS_ROUNDUP_DIVIDE(m_oriFrameHeight, CODEC_VP9_SUPER_BLOCK_HEIGHT);
    m_picSizeInSb = m_picWidthInSb * m_picHeightInSb;

    m_picWidthInMb  = (uint16_t)CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_oriFrameWidth);
    m_picHeightInMb = (uint16_t)CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_oriFrameHeight);
    m_frameWidth  = m_picWidthInMb * CODECHAL_MACROBLOCK_WIDTH;
    m_frameHeight = m_picHeightInMb * CODECHAL_MACROBLOCK_HEIGHT;

    // HME Scaling WxH
    m_downscaledWidthInMb4x  = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth / SCALE_FACTOR_4x);
    m_downscaledHeightInMb4x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameHeight / SCALE_FACTOR_4x);
    m_downscaledWidth4x = m_downscaledWidthInMb4x * CODECHAL_MACROBLOCK_WIDTH;
    m_downscaledHeight4x = m_downscaledHeightInMb4x * CODECHAL_MACROBLOCK_HEIGHT;

    // SuperHME Scaling WxH
    m_downscaledWidthInMb16x  = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth / SCALE_FACTOR_16x);
    m_downscaledHeightInMb16x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameHeight / SCALE_FACTOR_16x);
    m_downscaledWidth16x = m_downscaledWidthInMb16x * CODECHAL_MACROBLOCK_WIDTH;
    m_downscaledHeight16x = m_downscaledHeightInMb16x * CODECHAL_MACROBLOCK_HEIGHT;

    m_frameFieldHeight = m_frameHeight;
    m_frameFieldHeightInMb = m_picHeightInMb;
    m_downscaledFrameFieldHeightInMb4x = m_downscaledHeightInMb4x;
    m_downscaledFrameFieldHeightInMb16x = m_downscaledHeightInMb16x;

    MotionEstimationDisableCheck();

    if (m_vp9SeqParams->SeqFlags.fields.EnableDynamicScaling)
    {
            m_rawSurface.dwWidth  = MOS_ALIGN_CEIL(m_vp9PicParams->SrcFrameWidthMinus1 + 1, CODEC_VP9_MIN_BLOCK_WIDTH);
            m_rawSurface.dwHeight = MOS_ALIGN_CEIL(m_vp9PicParams->SrcFrameHeightMinus1 + 1, CODEC_VP9_MIN_BLOCK_HEIGHT);
    }

    if (Mos_ResourceIsNull(&m_reconSurface.OsResource) &&
        (!m_vp9SeqParams->SeqFlags.fields.bUseRawReconRef || m_codecFunction != CODECHAL_FUNCTION_ENC))
    {
        return MOS_STATUS_INVALID_PARAMETER;
    }

    // Sync initialize
    m_waitForEnc = false;
    if ((m_firstFrame) ||
        (!m_brcEnabled && m_vp9SeqParams->SeqFlags.fields.bUseRawReconRef) ||
        (!m_brcEnabled && (m_vp9PicParams->PicFlags.fields.frame_type == 0 || m_vp9PicParams->PicFlags.fields.intra_only)))
    {
        m_waitForPak = false;
    }
    else
    {
        m_waitForPak = true;
    }

    m_signalEnc = false;

    uint8_t currRefIdx = m_vp9PicParams->CurrReconstructedPic.FrameIdx;

    m_dysRefFrameFlags = DYS_REF_NONE;
    m_dysBrc = false;
    m_dysCqp = false;

    // m_refFrameFlags is to indicate which frames to be used as reference
    // m_refFrameFlags & 0x01 != 0: Last ref frames used as reference
    // m_refFrameFlags & 0x02 != 0: Golden ref frames used as reference
    // m_refFrameFlags & 0x04 != 0: Alternate ref frames used as reference
    m_refFrameFlags = 0;
    m_numRefFrames = 0;
    m_lastRefPic = 0;
    m_goldenRefPic = 0;
    m_altRefPic = 0;

    uint8_t index = 0;
    PCODEC_REF_LIST *refList = &m_refList[0];
    if (m_vp9PicParams->PicFlags.fields.frame_type != 0 && !m_vp9PicParams->PicFlags.fields.intra_only)
    {
        m_refFrameFlags = m_vp9PicParams->RefFlags.fields.ref_frame_ctrl_l0 | m_vp9PicParams->RefFlags.fields.ref_frame_ctrl_l1;

        if (CodecHal_PictureIsInvalid(m_vp9PicParams->RefFrameList[m_vp9PicParams->RefFlags.fields.LastRefIdx]))
        {
            m_refFrameFlags &= ~0x1;
        }
        if (CodecHal_PictureIsInvalid(m_vp9PicParams->RefFrameList[m_vp9PicParams->RefFlags.fields.GoldenRefIdx]))
        {
            m_refFrameFlags &= ~0x2;
        }
        if (CodecHal_PictureIsInvalid(m_vp9PicParams->RefFrameList[m_vp9PicParams->RefFlags.fields.AltRefIdx]))
        {
            m_refFrameFlags &= ~0x4;
        }

        //consilidate the reference flag, becasue two reference frame may have the same index
        if ((m_refFrameFlags & 0x01) &&
            (m_vp9PicParams->RefFrameList[m_vp9PicParams->RefFlags.fields.LastRefIdx].FrameIdx == m_vp9PicParams->RefFrameList[m_vp9PicParams->RefFlags.fields.GoldenRefIdx].FrameIdx))
        {
            m_refFrameFlags &= ~0x2;  //skip golden frame
        }
        if ((m_refFrameFlags & 0x01) &&
            (m_vp9PicParams->RefFrameList[m_vp9PicParams->RefFlags.fields.LastRefIdx].FrameIdx == m_vp9PicParams->RefFrameList[m_vp9PicParams->RefFlags.fields.AltRefIdx].FrameIdx))
        {
            m_refFrameFlags &= ~0x4;  //skip alt frame
        }
        if ((m_refFrameFlags & 0x02) &&
            (m_vp9PicParams->RefFrameList[m_vp9PicParams->RefFlags.fields.GoldenRefIdx].FrameIdx == m_vp9PicParams->RefFrameList[m_vp9PicParams->RefFlags.fields.AltRefIdx].FrameIdx))
        {
            m_refFrameFlags &= ~0x4;  //skip alt frame
        }

        if (m_refFrameFlags == 7 && !m_16xMeSupported)
        {
            // can support max 2 reference frames when SHME disabled, so ignore alt frame
            m_refFrameFlags &= ~0x4;
        }

        // MaxNum_Reference is 1 for TU7
        if (m_refFrameFlags != 1 && m_vp9SeqParams->TargetUsage == TU_PERFORMANCE)
        {
            m_refFrameFlags = 1;
        }

        if (m_refFrameFlags == 0)
        {
            CODECHAL_ENCODE_ASSERTMESSAGE("Ref list is empty!.");
            return MOS_STATUS_INVALID_PARAMETER;
        }

        if (m_refFrameFlags & 0x01)
        {
            index = m_vp9PicParams->RefFrameList[m_vp9PicParams->RefFlags.fields.LastRefIdx].FrameIdx;
            refList[index]->sRefBuffer =
                m_vp9SeqParams->SeqFlags.fields.bUseRawReconRef ? refList[index]->sRefRawBuffer : refList[index]->sRefReconBuffer;

            m_lastRefPic = &refList[index]->sRefBuffer;
            CodecHalGetResourceInfo(m_osInterface, m_lastRefPic);
            m_lastRefPic->dwWidth = refList[index]->dwFrameWidth;
            m_lastRefPic->dwHeight = refList[index]->dwFrameHeight;
            m_numRefFrames++;

            if (m_vp9SeqParams->SeqFlags.fields.EnableDynamicScaling &&
                (refList[index]->dwFrameWidth != m_oriFrameWidth || refList[index]->dwFrameHeight != m_oriFrameHeight))
            {
                m_dysRefFrameFlags |= DYS_REF_LAST;
            }
        }

        if (m_refFrameFlags & 0x02)
        {
            index = m_vp9PicParams->RefFrameList[m_vp9PicParams->RefFlags.fields.GoldenRefIdx].FrameIdx;
            refList[index]->sRefBuffer =
                m_vp9SeqParams->SeqFlags.fields.bUseRawReconRef ? refList[index]->sRefRawBuffer : refList[index]->sRefReconBuffer;

            m_goldenRefPic = &refList[index]->sRefBuffer;
            CodecHalGetResourceInfo(m_osInterface, m_goldenRefPic);
            m_goldenRefPic->dwWidth = refList[index]->dwFrameWidth;
            m_goldenRefPic->dwHeight = refList[index]->dwFrameHeight;
            m_numRefFrames++;

            if (m_vp9SeqParams->SeqFlags.fields.EnableDynamicScaling &&
                (refList[index]->dwFrameWidth != m_oriFrameWidth || refList[index]->dwFrameHeight != m_oriFrameHeight))
            {
                m_dysRefFrameFlags |= DYS_REF_GOLDEN;
            }
        }

        if (m_refFrameFlags & 0x04)
        {
            index = m_vp9PicParams->RefFrameList[m_vp9PicParams->RefFlags.fields.AltRefIdx].FrameIdx;
            refList[index]->sRefBuffer =
                m_vp9SeqParams->SeqFlags.fields.bUseRawReconRef ? refList[index]->sRefRawBuffer : refList[index]->sRefReconBuffer;

            m_altRefPic = &refList[index]->sRefBuffer;
            CodecHalGetResourceInfo(m_osInterface, m_altRefPic);
            m_altRefPic->dwWidth = refList[index]->dwFrameWidth;
            m_altRefPic->dwHeight = refList[index]->dwFrameHeight;
            m_numRefFrames++;

            if (m_vp9SeqParams->SeqFlags.fields.EnableDynamicScaling &&
                (refList[index]->dwFrameWidth != m_oriFrameWidth || refList[index]->dwFrameHeight != m_oriFrameHeight))
            {
                m_dysRefFrameFlags |= DYS_REF_ALT;
            }
        }
    }
    m_dysCurrFrameFlag = m_dysRefFrameFlags;

    refList[currRefIdx]->sRefReconBuffer = m_reconSurface;
    refList[currRefIdx]->sRefRawBuffer = m_rawSurface;
    refList[currRefIdx]->RefPic             = m_vp9PicParams->CurrOriginalPic;
    refList[currRefIdx]->bUsedAsRef = true;
    refList[currRefIdx]->resBitstreamBuffer = m_resBitstreamBuffer;
    refList[currRefIdx]->dwFrameWidth = m_oriFrameWidth;
    refList[currRefIdx]->dwFrameHeight = m_oriFrameHeight;

    m_currOriginalPic            = m_vp9PicParams->CurrOriginalPic;
    m_currReconstructedPic       = m_vp9PicParams->CurrReconstructedPic;
    m_statusReportFeedbackNumber = m_vp9PicParams->StatusReportFeedbackNumber;
    m_pictureCodingType          = m_vp9PicParams->PicFlags.fields.frame_type == 0 ? I_TYPE : P_TYPE;

    PCODEC_PIC_ID picIdx = &m_picIdx[0];
    for (auto i = 0; i < CODEC_VP9_NUM_REF_FRAMES; i++)
    {
        picIdx[i].bValid = false;
    }
    if (m_vp9PicParams->PicFlags.fields.frame_type != 0 && !m_vp9PicParams->PicFlags.fields.intra_only)
    {
        for (auto i = 0; i < CODEC_VP9_NUM_REF_FRAMES; i++)
        {
            if (m_vp9PicParams->RefFrameList[i].PicFlags != PICTURE_INVALID)
            {
                index              = m_vp9PicParams->RefFrameList[i].FrameIdx;
                bool duplicatedIdx = false;
                for (auto ii = 0; ii < i; ii++)
                {
                    if (picIdx[ii].bValid && index == m_vp9PicParams->RefFrameList[ii].FrameIdx)
                    {
                        // we find the same FrameIdx in the ref_frame_list. Multiple reference frames are the same.
                        duplicatedIdx = true;
                        break;
                    }
                }
                if (duplicatedIdx)
                {
                    continue;
                }

                // this reference frame in unique. Save it into the full reference list with 127 items
                refList[index]->RefPic.PicFlags =
                    CodecHal_CombinePictureFlags(refList[index]->RefPic, m_vp9PicParams->RefFrameList[i]);

                picIdx[i].bValid = true;
                picIdx[i].ucPicIdx = index;
            }
        }
    }

    // Save the current RefList
    uint8_t ii = 0;
    for (auto i = 0; i < CODEC_VP9_NUM_REF_FRAMES; i++)
    {
        if (picIdx[i].bValid)
        {
            refList[currRefIdx]->RefList[ii] = m_vp9PicParams->RefFrameList[i];
            ii++;
        }
    }
    refList[currRefIdx]->ucNumRef = ii;
    m_currRefList             = refList[currRefIdx];

    // the actual MbCode/MvData surface to be allocated later
    m_trackedBuf->SetAllocationFlag(true);

    m_vdencPakonlyMultipassEnabled = false;
    m_vdencPakObjCmdStreamOutEnabled = false;

    // In case there is overflow
    if ((m_vp9PicParams->LumaACQIndex + m_vp9PicParams->LumaDCQIndexDelta) < 0)
    {
        m_vp9PicParams->LumaACQIndex = MOS_ABS(m_vp9PicParams->LumaDCQIndexDelta) + 1;
    }
    refList[currRefIdx]->ucQPValue[0] = m_vp9PicParams->LumaACQIndex + m_vp9PicParams->LumaDCQIndexDelta;

    m_txMode = CODEC_VP9_TX_SELECTABLE;

    // For VDEnc disable HME if HME hasn't been disabled by reg key AND TU != TU1
    m_hmeSupported   = m_hmeSupported && (m_vp9SeqParams->TargetUsage == TU_QUALITY);
    m_16xMeSupported = m_16xMeSupported && m_hmeSupported;

    // Enable HME/SHME for frame
    m_hmeEnabled   = m_hmeSupported && m_pictureCodingType != I_TYPE && !m_vp9PicParams->PicFlags.fields.intra_only;
    m_16xMeEnabled = m_16xMeSupported && m_hmeEnabled;

    if (m_dysRefFrameFlags != DYS_REF_NONE && m_dysVdencMultiPassEnabled )
    {
        if (!m_hucEnabled)
        {
            m_numPasses = m_dysRefFrameFlags != DYS_REF_NONE;
        }
        if (m_vdencBrcEnabled)
        {
            m_dysBrc = true;
            //Reduce the total passes by 1, as m_currPass == 1 becomes m_currPass = 0 for Huc to run
            m_numPasses = (m_numPasses > 0 ) ? m_numPasses - 1 : m_numPasses;
        }
        else
        {
            m_dysCqp = true;
        }
    }

    // We cannot use refresh_frame_context if HuC isn't enabled to update probs
    if (m_vp9PicParams->PicFlags.fields.refresh_frame_context && !m_hucEnabled)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Refresh_frame_context cannot be enabled while HuC is disabled.  HuC is needed for refresh_frame_context to be enabled.");
        return MOS_STATUS_INVALID_PARAMETER;
    }

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::SetRowstoreCachingOffsets()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
    if (m_vdencEnabled &&
        m_hwInterface->GetHcpInterface()->IsRowStoreCachingSupported())
    {
        MHW_VDBOX_ROWSTORE_PARAMS rowStoreParams;
        rowStoreParams.Mode             = m_mode;
        rowStoreParams.dwPicWidth       = m_frameWidth;
        rowStoreParams.ucChromaFormat   = m_chromaFormat;
        rowStoreParams.ucBitDepthMinus8 = m_bitDepth * 2;  // 0(8bit) -> 0, 1(10bit)->2, 2(12bit)->4
        m_hwInterface->SetRowstoreCachingOffsets(&rowStoreParams);
    }
    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::InitializePicture(const EncoderParams& params)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    m_vp9SeqParams  = (PCODEC_VP9_ENCODE_SEQUENCE_PARAMS)(params.pSeqParams);
    m_vp9PicParams  = (PCODEC_VP9_ENCODE_PIC_PARAMS)(params.pPicParams);
    m_nalUnitParams = params.ppNALUnitParams;
    m_numNalUnit    = params.uiNumNalUnits;

    CODECHAL_ENCODE_CHK_NULL_RETURN(m_vp9SeqParams);
    CODECHAL_ENCODE_CHK_NULL_RETURN(m_vp9PicParams);
    CODECHAL_ENCODE_CHK_NULL_RETURN(m_nalUnitParams);

    m_segmentMapProvided = params.bSegmentMapProvided && m_vp9PicParams->PicFlags.fields.segmentation_enabled;
    // In MBBRC case, without a SegMap provided by the app, we need to set the SegMapUpdate ON
    // as the Segmap is generated by HuC and it can be different for every frame
    if (m_vp9PicParams->PicFlags.fields.segmentation_enabled && !params.bSegmentMapProvided)
    {
        m_vp9PicParams->PicFlags.fields.segmentation_update_map = 1;
    }

    // For dynamic scaling, the SingleTaskPhaseSupported is set to true and it does not get restored
    // to the original value after encoding of the frame. So need to restore to the original state
    m_singleTaskPhaseSupported = m_storeSingleTaskPhaseSupported;

    m_mbBrcEnabled = false;
    m_vp9SeqParams->SeqFlags.fields.MBBRC = MBBRC_DISABLED;

    // Filter level is decided by driver in VDEnc, app value is ignored
    // Uncomment when PSNR thresholds are set properly
    //pVp9PicParams->filter_level = CODECHAL_ENCODE_VP9_LF_VALUE_QP_LOOKUP[pVp9PicParams->LumaACQIndex];

    // We do not support segmentation w/o seg map in CQP case, only support segmentation w/ seg map in CQP
    // BRC/ACQP supports segmentation both w/ and w/o seg map
    if (m_vp9PicParams->PicFlags.fields.segmentation_enabled && !params.bSegmentMapProvided &&
        m_vp9SeqParams->RateControlMethod == RATECONTROL_CQP)
    {
        return MOS_STATUS_INVALID_PARAMETER;
    }

    // Need to index properly when more than one temporal layer is present.
    CODECHAL_ENCODE_ASSERT(m_vp9SeqParams->FrameRate[0].uiDenominator > 0);

    CODECHAL_ENCODE_CHK_COND_RETURN(m_vp9SeqParams->FrameRate[0].uiDenominator == 0, "uiDenominator cannot be zero.");
    uint32_t frameRate = m_vp9SeqParams->FrameRate[0].uiNumerator / m_vp9SeqParams->FrameRate[0].uiDenominator;
    m_vp9SegmentParams = (PCODEC_VP9_ENCODE_SEGMENT_PARAMS)(params.pSegmentParams);

    CODECHAL_ENCODE_CHK_NULL_RETURN(m_vp9SegmentParams);

    CODECHAL_ENCODE_CHK_STATUS_RETURN(PlatformCapabilityCheck());

    if (m_newSeq)
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(SetSequenceStructs());
    }

    //when MBBRC is enabled App will not pass segment map.
    if (!m_mbBrcEnabled)
    {
        m_mbStatsEnabled = false;
        if (m_segmentMapProvided)
        {
            m_mbSegmentMapSurface = *(params.psMbSegmentMapSurface);
            CodecHalGetResourceInfo(m_osInterface, &(m_mbSegmentMapSurface));
        }
    }
    else
    {
        //Kernel C model fixed Qindex delta's when MBBRC is enabled
        int16_t segmentQIndexDelta[CODEC_VP9_MAX_SEGMENTS] = { 0, -8, -6, -4, -2, 2, 4, 6 };

        for (uint8_t i = 0; i < CODEC_VP9_MAX_SEGMENTS; i++)
        {
            m_vp9SegmentParams->SegData[i].SegmentFlags.value  = 0;
            m_vp9SegmentParams->SegData[i].SegmentLFLevelDelta = 0;
            m_vp9SegmentParams->SegData[i].SegmentQIndexDelta  = segmentQIndexDelta[i];
        }
        m_mbStatsEnabled = true;
    }

    CODECHAL_ENCODE_CHK_STATUS_RETURN(SetPictureStructs());

    CODECHAL_ENCODE_CHK_STATUS_RETURN(SetRowstoreCachingOffsets());

    m_pictureStatesSize = m_defaultPictureStatesSize;
    m_picturePatchListSize = m_defaultPicturePatchListSize;

    m_hucCommandsSize = m_defaultHucCmdsSize;

    // Scaling occurs when HME is enabled
    m_scalingEnabled = m_hmeSupported;
    m_useRawForRef   = m_vp9SeqParams->SeqFlags.fields.bUseRawReconRef;

    if (m_currReconstructedPic.FrameIdx >= m_numUncompressedSurface)
    {
        return MOS_STATUS_INVALID_PARAMETER;
    }
        CODECHAL_ENCODE_CHK_STATUS_RETURN(SetStatusReportParams(m_refList[m_currReconstructedPic.FrameIdx]));
   
    CODECHAL_DEBUG_TOOL(
        m_debugInterface->m_currPic            = m_vp9PicParams->CurrOriginalPic;
        m_debugInterface->m_bufferDumpFrameNum = m_storeData;
        m_debugInterface->m_frameType          = m_pictureCodingType;

        if (m_newSeq) {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpSeqParams(
                m_vp9SeqParams));
        }

        CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpPicParams(
            m_vp9PicParams));

        CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpSegmentParams(
            m_vp9SegmentParams));)

    CODECHAL_DEBUG_TOOL(
        m_resVdencStatsBuffer = &(m_resVdencBrcStatsBuffer);)

    m_bitstreamUpperBound = params.dwBitstreamSize;

    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::AllocateResourcesBrc()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    // initiate allocation paramters and lock flags
    MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
    MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
    allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
    allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
    allocParamsForBufferLinear.Format = Format_Buffer;

    MOS_LOCK_PARAMS lockFlagsWriteOnly;
    MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
    lockFlagsWriteOnly.WriteOnly = 1;

    // BRC history buffer
    uint32_t size = m_brcHistoryBufferSize;
    allocParamsForBufferLinear.dwBytes = m_vdencEnabled ? MOS_ALIGN_CEIL(size, CODECHAL_PAGE_SIZE) : size;
    allocParamsForBufferLinear.pBufName = "BRC History Buffer";

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
        m_osInterface,
        &allocParamsForBufferLinear,
        &m_brcBuffers.resBrcHistoryBuffer));

    // BRC Constant Data Buffer
    allocParamsForBufferLinear.dwBytes = m_vdencEnabled ? MOS_ALIGN_CEIL(m_brcConstantSurfaceSize, CODECHAL_PAGE_SIZE) : CODECHAL_ENCODE_VP9_BRC_CONSTANTSURFACE_SIZE;
    allocParamsForBufferLinear.pBufName = "BRC Constant Data Buffer";
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
        m_osInterface,
        &allocParamsForBufferLinear,
        &m_brcBuffers.resBrcConstantDataBuffer[0]));
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
        m_osInterface,
        &allocParamsForBufferLinear,
        &m_brcBuffers.resBrcConstantDataBuffer[1]));

    // PicState Brc read buffer
    size = CODECHAL_ENCODE_VP9_PIC_STATE_BUFFER_SIZE_PER_PASS * m_brcMaxNumPasses;
    allocParamsForBufferLinear.dwBytes = size;
    allocParamsForBufferLinear.pBufName = "BRC Pic State Read Buffer";

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
        m_osInterface,
        &allocParamsForBufferLinear,
        &m_brcBuffers.resPicStateBrcReadBuffer));

    uint8_t* data = (uint8_t*)m_osInterface->pfnLockResource(
        m_osInterface,
        &m_brcBuffers.resPicStateBrcReadBuffer,
        &lockFlagsWriteOnly);

    if (data == nullptr)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to Lock BRC Pic State Read Buffer.");
        return MOS_STATUS_UNKNOWN;
    }

    MOS_ZeroMemory(data, size);
    m_osInterface->pfnUnlockResource(
        m_osInterface,
        &m_brcBuffers.resPicStateBrcReadBuffer);

    // PicState Brc Write and Huc Read buffer
    allocParamsForBufferLinear.dwBytes = size;
    allocParamsForBufferLinear.pBufName = "BRC Pic State Write Buffer";

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
        m_osInterface,
        &allocParamsForBufferLinear,
        &m_brcBuffers.resPicStateBrcWriteHucReadBuffer));

    data = (uint8_t*)m_osInterface->pfnLockResource(
        m_osInterface,
        &m_brcBuffers.resPicStateBrcWriteHucReadBuffer,
        &lockFlagsWriteOnly);

    if (data == nullptr)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to Lock BRC Pic State Write Buffer.");
        return MOS_STATUS_UNKNOWN;
    }

    MOS_ZeroMemory(data, size);
    m_osInterface->pfnUnlockResource(
        m_osInterface,
        &m_brcBuffers.resPicStateBrcWriteHucReadBuffer);

    // PicState HuC Write buffer
    allocParamsForBufferLinear.dwBytes = CODECHAL_ENCODE_VP9_PIC_STATE_BUFFER_SIZE_PER_PASS * m_brcMaxNumPasses;
    allocParamsForBufferLinear.pBufName = "BRC Huc Pic State Write Buffer";

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
        m_osInterface,
        &allocParamsForBufferLinear,
        &m_brcBuffers.resPicStateHucWriteBuffer));

    // SegmentState Brc Read buffer
    allocParamsForBufferLinear.dwBytes  = CODECHAL_ENCODE_VP9_SEGMENT_STATE_BUFFER_SIZE;
    allocParamsForBufferLinear.pBufName = "BRC Segment State Read Buffer";

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
        m_osInterface,
        &allocParamsForBufferLinear,
        &m_brcBuffers.resSegmentStateBrcReadBuffer));

    // SegmentState Brc Write buffer
    allocParamsForBufferLinear.dwBytes  = CODECHAL_ENCODE_VP9_SEGMENT_STATE_BUFFER_SIZE;
    allocParamsForBufferLinear.pBufName = "BRC Segment State Write Buffer";

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
        m_osInterface,
        &allocParamsForBufferLinear,
        &m_brcBuffers.resSegmentStateBrcWriteBuffer));

    // BRC Bitstream Size Data buffer
    allocParamsForBufferLinear.dwBytes = m_vdencEnabled ?
        MOS_ALIGN_CEIL(CODECHAL_ENCODE_VP9_BRC_BITSTREAM_SIZE_BUFFER_SIZE, CODECHAL_PAGE_SIZE) :
        CODECHAL_ENCODE_VP9_BRC_BITSTREAM_SIZE_BUFFER_SIZE;
    allocParamsForBufferLinear.pBufName = "BRC Bitstream Size Data buffer";

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
        m_osInterface,
        &allocParamsForBufferLinear,
        &m_brcBuffers.resBrcBitstreamSizeBuffer));

    // BRC HuC Data Buffer
    allocParamsForBufferLinear.dwBytes = m_vdencEnabled ?
        MOS_ALIGN_CEIL(CODECHAL_ENCODE_VP9_HUC_BRC_DATA_BUFFER_SIZE, CODECHAL_PAGE_SIZE) :
        CODECHAL_ENCODE_VP9_HUC_BRC_DATA_BUFFER_SIZE;
    allocParamsForBufferLinear.pBufName = "BRC HuC Data Buffer";

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
        m_osInterface,
        &allocParamsForBufferLinear,
        &m_brcBuffers.resBrcHucDataBuffer));

    allocParamsForBufferLinear.dwBytes = CODECHAL_ENCODE_VP9_BRC_MSDK_PAK_BUFFER_SIZE;
    allocParamsForBufferLinear.pBufName = "BRC MSDK Buffer";

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
        m_osInterface,
        &allocParamsForBufferLinear,
        &m_brcBuffers.resBrcMsdkPakBuffer));

    return eStatus;
}

void CodechalVdencVp9State::ReleaseResourcesBrc()
{
    CODECHAL_ENCODE_FUNCTION_ENTER;

    if (!Mos_ResourceIsNull(&m_brcBuffers.resBrcHistoryBuffer))
    {
        m_osInterface->pfnFreeResource(
            m_osInterface,
            &m_brcBuffers.resBrcHistoryBuffer);
    }

    if (!Mos_ResourceIsNull(&m_brcBuffers.resBrcConstantDataBuffer[0]))
    {
        m_osInterface->pfnFreeResource(
            m_osInterface,
            &m_brcBuffers.resBrcConstantDataBuffer[0]);
    }

    if (!Mos_ResourceIsNull(&m_brcBuffers.resBrcConstantDataBuffer[1]))
    {
        m_osInterface->pfnFreeResource(
            m_osInterface,
            &m_brcBuffers.resBrcConstantDataBuffer[1]);
    }

    if (!Mos_ResourceIsNull(&m_brcBuffers.resPicStateBrcReadBuffer))
    {
        m_osInterface->pfnFreeResource(
            m_osInterface,
            &m_brcBuffers.resPicStateBrcReadBuffer);
    }

    if (!Mos_ResourceIsNull(&m_brcBuffers.resPicStateBrcWriteHucReadBuffer))
    {
        m_osInterface->pfnFreeResource(
            m_osInterface,
            &m_brcBuffers.resPicStateBrcWriteHucReadBuffer);
    }

    if (!Mos_ResourceIsNull(&m_brcBuffers.resPicStateHucWriteBuffer))
    {
        m_osInterface->pfnFreeResource(
            m_osInterface,
            &m_brcBuffers.resPicStateHucWriteBuffer);
    }

    if (!Mos_ResourceIsNull(&m_brcBuffers.resSegmentStateBrcReadBuffer))
    {
        m_osInterface->pfnFreeResource(
            m_osInterface,
            &m_brcBuffers.resSegmentStateBrcReadBuffer);
    }

    if (!Mos_ResourceIsNull(&m_brcBuffers.resSegmentStateBrcWriteBuffer))
    {
        m_osInterface->pfnFreeResource(
            m_osInterface,
            &m_brcBuffers.resSegmentStateBrcWriteBuffer);
    }

    if (!Mos_ResourceIsNull(&m_brcBuffers.resBrcBitstreamSizeBuffer))
    {
        m_osInterface->pfnFreeResource(
            m_osInterface,
            &m_brcBuffers.resBrcBitstreamSizeBuffer);
    }

    if (!Mos_ResourceIsNull(&m_brcBuffers.resBrcHucDataBuffer))
    {
        m_osInterface->pfnFreeResource(
            m_osInterface,
            &m_brcBuffers.resBrcHucDataBuffer);
    }

    if (!Mos_ResourceIsNull(&m_brcBuffers.resBrcMsdkPakBuffer))
    {
        m_osInterface->pfnFreeResource(
            m_osInterface,
            &m_brcBuffers.resBrcMsdkPakBuffer);
    }

    return;
}

MOS_STATUS CodechalVdencVp9State::AllocateResources()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::AllocateResources());

    // Application needs to pass the maxinum frame width/height
    m_maxPicWidth = m_frameWidth;
    m_maxPicHeight = m_frameHeight;

    uint32_t maxPicWidthInSb = MOS_ROUNDUP_DIVIDE(m_maxPicWidth, CODEC_VP9_SUPER_BLOCK_WIDTH);
    uint32_t maxPicHeightInSb = MOS_ROUNDUP_DIVIDE(m_maxPicHeight, CODEC_VP9_SUPER_BLOCK_HEIGHT);
    uint32_t maxPicSizeInSb = maxPicWidthInSb * maxPicHeightInSb;
    uint32_t maxNumCuRecords = maxPicSizeInSb * 64;

    // initiate allocation paramters and lock flags
    MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
    MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
    allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
    allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
    allocParamsForBufferLinear.Format = Format_Buffer;

    MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
    MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS));
    allocParamsForBuffer2D.Type = MOS_GFXRES_2D;
    allocParamsForBuffer2D.TileType = MOS_TILE_LINEAR;
    allocParamsForBuffer2D.Format = Format_Buffer_2D;

    MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferNV12;
    MOS_ZeroMemory(&allocParamsForBufferNV12, sizeof(MOS_ALLOC_GFXRES_PARAMS));
    allocParamsForBufferNV12.Type     = MOS_GFXRES_2D;
    allocParamsForBufferNV12.TileType = MOS_TILE_Y;
    allocParamsForBufferNV12.Format   = Format_NV12;

    MOS_LOCK_PARAMS lockFlagsWriteOnly;
    MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS));
    lockFlagsWriteOnly.WriteOnly = 1;

    // Allocate Ref Lists
    CodecHalAllocateDataList(
        m_refList,
        m_numUncompressedSurface);

    if (m_pakEnabled)
    {
        // m_mvoffset looks not correct here, and corresponding setting of buffer offset in HCP_IND_OBJ, need to check with HW team.
        // keep current logic unchanged but increase the buffer size for now in case regression before we know how to correctly program these.
        m_mvOffset = MOS_ALIGN_CEIL((maxPicSizeInSb * 4 * sizeof(uint32_t)), CODECHAL_PAGE_SIZE); // 3 uint32_t for HCP_PAK_OBJECT and 1 uint32_t for padding zero in kernel

        // we need additional buffer for (1) 1 CL for size info at the beginning of each tile column (max of 4 vdbox in scalability mode)
        // (2) CL alignment at end of every tile column for every SB of width
        // as a result, increase the height by 1 for allocation purposes
        uint32_t numOfLCU = maxPicSizeInSb + maxPicWidthInSb;

        //the following code used to calculate ulMBCodeSize:
        //pakObjCmdStreamOutDataSize = 2*BYTES_PER_DWORD*(numOfLcu*NUM_PAK_DWS_PER_LCU + numOfLcu*maxNumOfCUperLCU*NUM_DWS_PER_CU); // Multiply by 2 for sideband
        //const uint32_t maxNumOfCUperLCU = (64/8)*(64/8);
        // NUM_PAK_DWS_PER_LCU 5
        // NUM_DWS_PER_CU 8
        m_mbCodeSize = MOS_ALIGN_CEIL(2 * sizeof(uint32_t) * numOfLCU * (5 + 64 * 8), CODECHAL_PAGE_SIZE);

        uint32_t formatMultiFactor = (m_chromaFormat == VP9_ENCODED_CHROMA_FORMAT_YUV444) ? 3 : 2;
        formatMultiFactor *= (m_bitDepth == VP9_ENCODED_BIT_DEPTH_8) ? 1 : 2;
        uint32_t size = (18 * formatMultiFactor) / 2;
        // Deblocking filter line buffer
        size = maxPicWidthInSb * size * CODECHAL_CACHELINE_SIZE;
        allocParamsForBufferLinear.dwBytes = size;
        allocParamsForBufferLinear.pBufName = "DeblockingFilterLineBuffer";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resDeblockingFilterLineBuffer));

        // Deblocking filter tile line buffer
        allocParamsForBufferLinear.dwBytes = size;
        allocParamsForBufferLinear.pBufName = "DeblockingFilterTileLineBuffer";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resDeblockingFilterTileLineBuffer));

        formatMultiFactor = m_chromaFormat == VP9_ENCODED_CHROMA_FORMAT_YUV444 ? 25 : 17;
        size = formatMultiFactor * ((m_bitDepth == VP9_ENCODED_BIT_DEPTH_8) ? 1 : 2);
        // Deblocking filter tile column buffer
        size = maxPicHeightInSb * size * CODECHAL_CACHELINE_SIZE;
        allocParamsForBufferLinear.dwBytes = size;
        allocParamsForBufferLinear.pBufName = "DeblockingFilterTileColumnBuffer";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resDeblockingFilterTileColumnBuffer));

        // Metadata Line buffer
        size = maxPicWidthInSb * 5 * CODECHAL_CACHELINE_SIZE;
        allocParamsForBufferLinear.dwBytes = size;
        allocParamsForBufferLinear.pBufName = "MetadataLineBuffer";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resMetadataLineBuffer));

        // Metadata Tile Line buffer
        size = maxPicWidthInSb * 5 * CODECHAL_CACHELINE_SIZE;
        allocParamsForBufferLinear.dwBytes = size;
        allocParamsForBufferLinear.pBufName = "MetadataTileLineBuffer";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resMetadataTileLineBuffer));

        // Metadata Tile Column buffer
        size = maxPicHeightInSb * 5 * CODECHAL_CACHELINE_SIZE;
        allocParamsForBufferLinear.dwBytes = size;
        allocParamsForBufferLinear.pBufName = "MetadataTileColumnBuffer";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resMetadataTileColumnBuffer));

        // Current MV temporal buffer
        size = maxPicSizeInSb * 9 * CODECHAL_CACHELINE_SIZE;
        CODECHAL_ENCODE_CHK_NULL_RETURN(m_allocator->AllocateResource(m_standard, size, 1, mvTemporalBuffer, "mvTemporalBuffer", 0));
        CODECHAL_ENCODE_CHK_NULL_RETURN(m_allocator->AllocateResource(m_standard, size, 1, mvTemporalBuffer, "mvTemporalBuffer", 1));

        // Probability buffer
        size = 32 * CODECHAL_CACHELINE_SIZE;
        allocParamsForBufferLinear.dwBytes = size;
        allocParamsForBufferLinear.pBufName = "ProbabilityBuffer";

        for (auto i = 0; i < CODEC_VP9_NUM_CONTEXTS; i++)
        {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
                m_osInterface,
                &allocParamsForBufferLinear,
                &m_resProbBuffer[i]));
        }

        // Segment ID buffer
        size = maxPicSizeInSb * CODECHAL_CACHELINE_SIZE;
        allocParamsForBufferLinear.dwBytes = size;
        allocParamsForBufferLinear.pBufName = "SegmentIdBuffer";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resSegmentIdBuffer));

        uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(
            m_osInterface,
            &m_resSegmentIdBuffer,
            &lockFlagsWriteOnly);
        CODECHAL_ENCODE_CHK_NULL_RETURN(data);

        MOS_ZeroMemory(data, size);
        m_osInterface->pfnUnlockResource(m_osInterface, &m_resSegmentIdBuffer);

        // Probability delta buffer
        size = 29 * CODECHAL_CACHELINE_SIZE;
        allocParamsForBufferLinear.dwBytes = size;
        allocParamsForBufferLinear.pBufName = "ProbabilityDeltaBuffer";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resProbabilityDeltaBuffer));

        // Compressed header buffer
        size = 32 * CODECHAL_CACHELINE_SIZE;
        allocParamsForBufferLinear.dwBytes = size;
        allocParamsForBufferLinear.pBufName = "CompressedHeaderBuffer";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resCompressedHeaderBuffer));

        // Probability counter buffer
        allocParamsForBufferLinear.dwBytes = m_probabilityCounterBufferSize * m_maxTileNumber;
        allocParamsForBufferLinear.pBufName = "ProbabilityCounterBuffer";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resProbabilityCounterBuffer));

        // Tile record stream out buffer
        size = maxPicSizeInSb * CODECHAL_CACHELINE_SIZE; // worst case: each SB is a tile
        allocParamsForBufferLinear.dwBytes = size;
        allocParamsForBufferLinear.pBufName = "TileRecordStrmOutBuffer";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resTileRecordStrmOutBuffer));

        // CU statistics stream out buffer
        size = MOS_ALIGN_CEIL(maxPicSizeInSb * 64 * 8, CODECHAL_CACHELINE_SIZE);
        allocParamsForBufferLinear.dwBytes = size;
        allocParamsForBufferLinear.pBufName = "CuStatsStrmOutBuffer";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resCuStatsStrmOutBuffer));

        // HUC Prob DMEM buffer
        allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(MOS_MAX(sizeof(HucProbDmem), sizeof(HucProbDmem)), CODECHAL_CACHELINE_SIZE);
        allocParamsForBufferLinear.pBufName = "HucProbDmemBuffer";
        for (auto j = 0; j < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; ++j)
        {
            for (auto i = 0; i < 3; i++)
            {
                CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
                                                      m_osInterface,
                                                      &allocParamsForBufferLinear,
                                                      &m_resHucProbDmemBuffer[i][j]));
            }
        }
        // Huc default prob buffer
        allocParamsForBufferLinear.dwBytes = sizeof(Keyframe_Default_Probs)+sizeof(Inter_Default_Probs);
        allocParamsForBufferLinear.pBufName = "HucDefaultProbBuffer";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resHucDefaultProbBuffer));

        data = (uint8_t *)m_osInterface->pfnLockResource(
            m_osInterface,
            &m_resHucDefaultProbBuffer,
            &lockFlagsWriteOnly);
        CODECHAL_ENCODE_CHK_NULL_RETURN(data);

        MOS_SecureMemcpy(data, sizeof(Keyframe_Default_Probs),
            Keyframe_Default_Probs, sizeof(Keyframe_Default_Probs));
        MOS_SecureMemcpy(data + sizeof(Keyframe_Default_Probs), sizeof(Inter_Default_Probs),
            Inter_Default_Probs, sizeof(Inter_Default_Probs));

        m_osInterface->pfnUnlockResource(m_osInterface, &m_resHucDefaultProbBuffer);

        // Huc probability output buffer
        allocParamsForBufferLinear.dwBytes = 32 * CODECHAL_CACHELINE_SIZE;
        allocParamsForBufferLinear.pBufName = "HucProbabilityOutputBuffer";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resHucProbOutputBuffer));

        // Huc VP9 pak insert uncompressed header
        allocParamsForBufferLinear.dwBytes = CODECHAL_ENCODE_VP9_PAK_INSERT_UNCOMPRESSED_HEADER;
        allocParamsForBufferLinear.pBufName = "HucPakInsertUncompressedHeaderReadBuffer";

        for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
        {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
                                                  m_osInterface,
                                                  &allocParamsForBufferLinear,
                                                  &m_resHucPakInsertUncompressedHeaderReadBuffer[i]));
        }
        allocParamsForBufferLinear.dwBytes = CODECHAL_ENCODE_VP9_PAK_INSERT_UNCOMPRESSED_HEADER;
        allocParamsForBufferLinear.pBufName = "HucPakInsertUncompressedHeaderWriteBuffer";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resHucPakInsertUncompressedHeaderWriteBuffer));

        // Huc VP9 pak mmio buffer
        allocParamsForBufferLinear.dwBytes = 4 * sizeof(uint32_t);
        allocParamsForBufferLinear.pBufName = "HucPakMmioBuffer";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resHucPakMmioBuffer));

        // Huc debug output buffer
        allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(1024 * sizeof(uint32_t), CODECHAL_PAGE_SIZE);
        allocParamsForBufferLinear.pBufName = "HucDebugOutputBuffer";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resHucDebugOutputBuffer));
    }

    if (m_encEnabled)
    {
        CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateResourcesBrc());

        if (m_hmeSupported)
        {
            MOS_ZeroMemory(&m_4xMeMvDataBuffer, sizeof(MOS_SURFACE));
            m_4xMeMvDataBuffer.TileType = MOS_TILE_LINEAR;
            m_4xMeMvDataBuffer.bArraySpacing = true;
            m_4xMeMvDataBuffer.Format = Format_Buffer_2D;
            m_4xMeMvDataBuffer.dwWidth = m_downscaledWidthInMb4x * 32;
            m_4xMeMvDataBuffer.dwHeight = m_downscaledHeightInMb4x * 4 * 10;
            m_4xMeMvDataBuffer.dwPitch = MOS_ALIGN_CEIL(m_4xMeMvDataBuffer.dwWidth, 128);

            allocParamsForBuffer2D.dwWidth = m_4xMeMvDataBuffer.dwWidth;
            allocParamsForBuffer2D.dwHeight = m_4xMeMvDataBuffer.dwHeight;
            allocParamsForBuffer2D.pBufName = "4xME MV Data Buffer";
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
                m_osInterface,
                &allocParamsForBuffer2D,
                &m_4xMeMvDataBuffer.OsResource));

            MOS_ZeroMemory(&m_4xMeDistortionBuffer, sizeof(MOS_SURFACE));
            m_4xMeDistortionBuffer.TileType = MOS_TILE_LINEAR;
            m_4xMeDistortionBuffer.bArraySpacing = true;
            m_4xMeDistortionBuffer.Format = Format_Buffer_2D;
            m_4xMeDistortionBuffer.dwWidth = m_downscaledWidthInMb4x * 8;
            m_4xMeDistortionBuffer.dwHeight = m_downscaledHeightInMb4x * 4 * 10;
            m_4xMeDistortionBuffer.dwPitch = MOS_ALIGN_CEIL(m_4xMeDistortionBuffer.dwWidth, 128);

            allocParamsForBuffer2D.dwWidth = m_4xMeDistortionBuffer.dwWidth;
            allocParamsForBuffer2D.dwHeight = m_4xMeDistortionBuffer.dwHeight;
            allocParamsForBuffer2D.pBufName = "4xME Distortion Buffer";
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
                m_osInterface,
                &allocParamsForBuffer2D,
                &m_4xMeDistortionBuffer.OsResource));
        }

        if (m_16xMeSupported)
        {
            MOS_ZeroMemory(&m_16xMeMvDataBuffer, sizeof(MOS_SURFACE));
            m_16xMeMvDataBuffer.TileType = MOS_TILE_LINEAR;
            m_16xMeMvDataBuffer.bArraySpacing = true;
            m_16xMeMvDataBuffer.Format = Format_Buffer_2D;

            m_16xMeMvDataBuffer.dwWidth = MOS_ALIGN_CEIL((m_downscaledWidthInMb16x * 32), 64);
            m_16xMeMvDataBuffer.dwHeight = m_downscaledHeightInMb16x * 4 * 10;
            m_16xMeMvDataBuffer.dwPitch = MOS_ALIGN_CEIL(m_16xMeMvDataBuffer.dwWidth, 128);

            allocParamsForBuffer2D.dwWidth = m_4xMeMvDataBuffer.dwWidth;
            allocParamsForBuffer2D.dwHeight = m_4xMeMvDataBuffer.dwHeight;
            allocParamsForBuffer2D.pBufName = "16xME MV Data Buffer";
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
                m_osInterface,
                &allocParamsForBuffer2D,
                &m_16xMeMvDataBuffer.OsResource));
        }

        // intermediate surface to be used by the P kernel to help reduce number of SIC calls
        MOS_ZeroMemory(&m_output16X16InterModes, sizeof(MOS_SURFACE));
        m_output16X16InterModes.TileType      = MOS_TILE_LINEAR;
        m_output16X16InterModes.bArraySpacing = true;
        m_output16X16InterModes.Format        = Format_Buffer_2D;
        m_output16X16InterModes.dwWidth       = 16 * m_picWidthInMb;
        m_output16X16InterModes.dwHeight      = 8 * m_picHeightInMb;
        m_output16X16InterModes.dwPitch       = MOS_ALIGN_CEIL(m_output16X16InterModes.dwWidth, 64);

        allocParamsForBuffer2D.dwWidth  = m_output16X16InterModes.dwWidth;
        allocParamsForBuffer2D.dwHeight = m_output16X16InterModes.dwHeight;
        allocParamsForBuffer2D.pBufName = "Intermediate surface";

        CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBuffer2D,
            &m_output16X16InterModes.OsResource));

        uint32_t picSizeInMb                = m_picWidthInMb * m_picHeightInMb;
        uint32_t size                       = 16 * picSizeInMb * sizeof(uint32_t);
        allocParamsForBufferLinear.dwBytes  = size;
        allocParamsForBufferLinear.pBufName = "Mode Decision Buffer";

        for (auto i = 0; i < 2; i++)
        {
            CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
                m_osInterface,
                &allocParamsForBufferLinear,
                &m_resModeDecision[i]));
        }
    }

    // VDENC Intra Row Store Scratch buffer
    allocParamsForBufferLinear.dwBytes = m_picWidthInMb * CODECHAL_CACHELINE_SIZE;
    allocParamsForBufferLinear.pBufName = "VDENC Intra Row Store Scratch Buffer";

    eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
        m_osInterface,
        &allocParamsForBufferLinear,
        &m_resVdencIntraRowStoreScratchBuffer);

    if (eStatus != MOS_STATUS_SUCCESS)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate VDENC Intra Row Store Scratch Buffer.");
        return eStatus;
    }

    // VDENC BRC Statistics buffer
    allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(m_maxTileNumber * m_vdencBrcStatsBufferSize, CODECHAL_PAGE_SIZE);
    allocParamsForBufferLinear.pBufName = "VDENC BRC Statistics Buffer";

    eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
        m_osInterface,
        &allocParamsForBufferLinear,
        &m_resVdencBrcStatsBuffer);

    if (eStatus != MOS_STATUS_SUCCESS)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("%s: Failed to allocate VDENC BRC Statistics Buffer\n", __FUNCTION__);
        return eStatus;
    }

    // HVC Tile Row Store Buffer
    allocParamsForBufferLinear.dwBytes = CODECHAL_CACHELINE_SIZE * maxPicWidthInSb;
    allocParamsForBufferLinear.pBufName = "HvcTileRowStoreBuffer";

    eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
        m_osInterface,
        &allocParamsForBufferLinear,
        &m_resHvcTileRowstoreBuffer);

    if (eStatus != MOS_STATUS_SUCCESS)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate HVC Tile Row Store Buffer.");
        return eStatus;
    }

    // VDENC picture second level batch buffer
    allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(m_vdencPicStateSecondLevelBatchBufferSize, CODECHAL_PAGE_SIZE);
    allocParamsForBufferLinear.pBufName = "VDEnc Picture Second Level Batch Buffer Read";

    for (auto i = 0; i < CODECHAL_VP9_ENCODE_RECYCLED_BUFFER_NUM; i++)
    {
        for (auto j = 0; j < 3; j++)
        {
            eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
                m_osInterface,
                &allocParamsForBufferLinear,
                &m_resVdencPictureState2NdLevelBatchBufferRead[j][i]);
        }
    }

    if (eStatus != MOS_STATUS_SUCCESS)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate VDEnc Picture Second Level Batch Buffer Read.");
        return eStatus;
    }

    allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(m_vdencPicStateSecondLevelBatchBufferSize, CODECHAL_PAGE_SIZE);
    allocParamsForBufferLinear.pBufName = "VDEnc Picture Second Level Batch Buffer Write";

    for (auto i = 0; i < CODECHAL_VP9_ENCODE_RECYCLED_BUFFER_NUM; i++)
    {
        eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
            m_osInterface,
            &allocParamsForBufferLinear,
            &m_resVdencPictureState2NdLevelBatchBufferWrite[i]);
    }

    if (eStatus != MOS_STATUS_SUCCESS)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate VDEnc Picture Second Level Batch Buffer Write.");
        return eStatus;
    }

    // BRC init/reset DMEM
    allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(sizeof(HucBrcInitDmem), CODECHAL_CACHELINE_SIZE);
    allocParamsForBufferLinear.pBufName = "VDENC BrcInit DmemBuffer";
    eStatus                             = (MOS_STATUS)m_osInterface->pfnAllocateResource(
        m_osInterface,
        &allocParamsForBufferLinear,
        &m_resVdencBrcInitDmemBuffer);

    if (eStatus != MOS_STATUS_SUCCESS)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate VDENC BRC Init DMEM Buffer\n");
        return eStatus;
    }

    // BRC update DMEM
    for (auto i = 0; i < 3; i++)
    {
        for (auto ib = 0; ib < CODECHAL_VP9_ENCODE_RECYCLED_BUFFER_NUM; ib++)
        {
            // BRC update DMEM
            allocParamsForBufferLinear.dwBytes  = MOS_ALIGN_CEIL(sizeof(HucBrcUpdateDmem), CODECHAL_CACHELINE_SIZE);
            allocParamsForBufferLinear.pBufName = "VDENC BrcUpdate DmemBuffer";
            eStatus                             = (MOS_STATUS)m_osInterface->pfnAllocateResource(
                m_osInterface,
                &allocParamsForBufferLinear,
                &m_resVdencBrcUpdateDmemBuffer[i][ib]);
        }
    }

    if (eStatus != MOS_STATUS_SUCCESS)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate VDENC BRC Update DMEM Buffer\n");
        return eStatus;
    }

    // This stream out/stream in buffer may need to be a separate buffer on HW, in which case
    // we'll create 2 and ping-pong back and forth per-frame.  For now, though, on simulation/SW,
    // they can be the same buffer.
    allocParamsForBufferLinear.dwBytes = CODECHAL_CACHELINE_SIZE * maxPicSizeInSb;
    allocParamsForBufferLinear.pBufName = "VDEnc Segment Map Stream Out";

    eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource(
        m_osInterface,
        &allocParamsForBufferLinear,
        &m_resVdencSegmentMapStreamOut);

    if (eStatus != MOS_STATUS_SUCCESS)
    {
        CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate VDEnc Segment Map Stream Out Buffer.");
        return eStatus;
    }

    // Allocate Frame Statistics Streamout Data Destination Buffer
    uint32_t size = MOS_ALIGN_CEIL(m_vdencBrcPakStatsBufferSize, CODECHAL_PAGE_SIZE); // Align to page is HuC requirement
    allocParamsForBufferLinear.dwBytes  = size * m_maxTileNumber;
    allocParamsForBufferLinear.pBufName = "FrameStatStreamOutBuffer";

    CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource(
                                                  m_osInterface,
                                                  &allocParamsForBufferLinear,
                                                  &m_resFrameStatStreamOutBuffer),
        "Failed to allocate VP9 FrameStatStreamOutBuffer");

    uint8_t* data = nullptr;
    CODECHAL_ENCODE_CHK_NULL_RETURN(
        data = (uint8_t *)m_osInterface->pfnLockResource(
            m_osInterface,
            &m_resFrameStatStreamOutBuffer,
            &lockFlagsWriteOnly));

    MOS_ZeroMemory(data, allocParamsForBufferLinear.dwBytes);

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
        m_osInterface,
        &m_resFrameStatStreamOutBuffer));

    // Allocate SSE Source Pixel Row Store Buffer
    m_sizeOfSseSrcPixelRowStoreBufferPerLcu = ((maxPicWidthInSb + 2) << 5) * CODECHAL_CACHELINE_SIZE;
    size = m_sizeOfSseSrcPixelRowStoreBufferPerLcu * m_maxTileNumber;
    allocParamsForBufferLinear.dwBytes = size;
    allocParamsForBufferLinear.pBufName = "SseSrcPixelRowStoreBuffer";

    CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource(
                                                  m_osInterface,
                                                  &allocParamsForBufferLinear,
                                                  &m_resSseSrcPixelRowStoreBuffer),
        "Failed to allocate VP9 SseSrcPixelRowStoreBuffer");

    CODECHAL_ENCODE_CHK_NULL_RETURN(
        data = (uint8_t *)m_osInterface->pfnLockResource(
            m_osInterface,
            &m_resSseSrcPixelRowStoreBuffer,
            &lockFlagsWriteOnly));

    MOS_ZeroMemory(data, size);

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
        m_osInterface,
        &m_resSseSrcPixelRowStoreBuffer));

    // Allocate data extension buffer
    size = CODECHAL_ENCODE_VP9_VDENC_DATA_EXTENSION_SIZE;
    allocParamsForBufferLinear.dwBytes = size;
    allocParamsForBufferLinear.pBufName = "DataExtensionBuffer";

    CODECHAL_ENCODE_CHK_STATUS_MESSAGE_RETURN(m_osInterface->pfnAllocateResource(
                                                  m_osInterface,
                                                  &allocParamsForBufferLinear,
                                                  &m_resVdencDataExtensionBuffer),
        "Failed to allocate VP9 HuC data extension buffer");

    CODECHAL_ENCODE_CHK_NULL_RETURN(
        data = (uint8_t *)m_osInterface->pfnLockResource(
            m_osInterface,
            &m_resVdencDataExtensionBuffer,
            &lockFlagsWriteOnly));

    MOS_ZeroMemory(data, size);

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnUnlockResource(
        m_osInterface,
        &m_resVdencDataExtensionBuffer));

    if (m_hucCmdInitializer)
    {
        m_hucCmdInitializer->CmdInitializerAllocateResources(m_hwInterface);
    }

    return eStatus;
}

void CodechalVdencVp9State::FreeResources()
{
    CODECHAL_ENCODE_FUNCTION_ENTER;

    CodechalEncoderState::FreeResources();

    PCODEC_REF_LIST *refList = &m_refList[0];

    // Release Ref Lists
    for (uint32_t i = 0; i < m_numUncompressedSurface; i++)
    {
        if (!Mos_ResourceIsNull(&refList[i]->sDysSurface.OsResource))
        {
            m_osInterface->pfnFreeResource(
                m_osInterface,
                &refList[i]->sDysSurface.OsResource);
        }

        if (!Mos_ResourceIsNull(&refList[i]->sDys4xScaledSurface.OsResource))
        {
            m_osInterface->pfnFreeResource(
                m_osInterface,
                &refList[i]->sDys4xScaledSurface.OsResource);
        }

        if (!Mos_ResourceIsNull(&refList[i]->sDys16xScaledSurface.OsResource))
        {
            m_osInterface->pfnFreeResource(
                m_osInterface,
                &refList[i]->sDys16xScaledSurface.OsResource);
        }
    }

    CodecHalFreeDataList(m_refList, m_numUncompressedSurface);

    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resDeblockingFilterLineBuffer);

    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resDeblockingFilterTileLineBuffer);

    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resDeblockingFilterTileColumnBuffer);

    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resMetadataLineBuffer);

    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resMetadataTileLineBuffer);

    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resMetadataTileColumnBuffer);

    for (auto i = 0; i < CODEC_VP9_NUM_CONTEXTS; i++)
    {
        m_osInterface->pfnFreeResource(
            m_osInterface,
            &m_resProbBuffer[i]);
    }

    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resSegmentIdBuffer);

    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resProbabilityDeltaBuffer);

    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resCompressedHeaderBuffer);

    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resProbabilityCounterBuffer);

    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resTileRecordStrmOutBuffer);

    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resCuStatsStrmOutBuffer);

    for (auto j = 0; j < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; ++j)
    {
        for (auto i = 0; i < 3; i++)
        {
            m_osInterface->pfnFreeResource(
                m_osInterface,
                &m_resHucProbDmemBuffer[i][j]);
        }
    }
    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resHucPakMmioBuffer);

    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resHucDefaultProbBuffer);

    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resHucProbOutputBuffer);
    for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; ++i)
    {
        m_osInterface->pfnFreeResource(
            m_osInterface,
            &m_resHucPakInsertUncompressedHeaderReadBuffer[i]);
    }
    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resHucPakInsertUncompressedHeaderWriteBuffer);

    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resHucDebugOutputBuffer);

    m_osInterface->pfnFreeResource(
        m_osInterface,
        &m_resVdencDataExtensionBuffer);

    if (m_encEnabled)
    {
        ReleaseResourcesBrc();
        for (auto i = 0; i < 2; i++)
        {
            if (!Mos_ResourceIsNull(&m_resModeDecision[i]))
            {
                m_osInterface->pfnFreeResource(
                    m_osInterface,
                    &m_resModeDecision[i]);
            }
        }

        if (!Mos_ResourceIsNull(&m_output16X16InterModes.OsResource))
        {
            m_osInterface->pfnFreeResource(
                m_osInterface,
                &m_output16X16InterModes.OsResource);
        }

        if (!Mos_ResourceIsNull(&m_4xMeMvDataBuffer.OsResource))
        {
            m_osInterface->pfnFreeResource(
                m_osInterface,
                &m_4xMeMvDataBuffer.OsResource);
        }

        if (!Mos_ResourceIsNull(&m_4xMeDistortionBuffer.OsResource))
        {
            m_osInterface->pfnFreeResource(
                m_osInterface,
                &m_4xMeDistortionBuffer.OsResource);
        }

        if (!Mos_ResourceIsNull(&m_16xMeMvDataBuffer.OsResource))
        {
            m_osInterface->pfnFreeResource(
                m_osInterface,
                &m_16xMeMvDataBuffer.OsResource);
        }

        if (!Mos_ResourceIsNull(&m_mbSegmentMapSurface.OsResource) && m_segmentMapAllocated)
        {
            m_osInterface->pfnFreeResource(
                m_osInterface,
                &m_mbSegmentMapSurface.OsResource);
        }
    }

    m_osInterface->pfnFreeResource(m_osInterface, &m_resVdencIntraRowStoreScratchBuffer);
    m_osInterface->pfnFreeResource(m_osInterface, &m_resVdencBrcStatsBuffer);
    m_osInterface->pfnFreeResource(m_osInterface, &m_resHvcTileRowstoreBuffer);

    m_osInterface->pfnFreeResource(m_osInterface, &m_resVdencDysPictureState2NdLevelBatchBuffer);
    m_osInterface->pfnFreeResource(m_osInterface, &m_resVdencSegmentMapStreamOut);
    m_osInterface->pfnFreeResource(m_osInterface, &m_resVdencBrcInitDmemBuffer);
    for (auto i = 0; i < 3; i++)
    {
        for (auto ib = 0; ib < CODECHAL_VP9_ENCODE_RECYCLED_BUFFER_NUM; ib++)
        {
            m_osInterface->pfnFreeResource(m_osInterface, &m_resVdencBrcUpdateDmemBuffer[i][ib]);
        }
    }
    m_osInterface->pfnFreeResource(m_osInterface, &m_resFrameStatStreamOutBuffer);
    m_osInterface->pfnFreeResource(m_osInterface, &m_resSseSrcPixelRowStoreBuffer);
    MOS_FreeMemory(m_mapBuffer);

    for (auto i = 0; i < CODECHAL_VP9_ENCODE_RECYCLED_BUFFER_NUM; i++)
    {
        for (auto j = 0; j < 3; j++)
        {
            m_osInterface->pfnFreeResource(
                m_osInterface,
                &m_resVdencPictureState2NdLevelBatchBufferRead[j][i]);
        }
        m_osInterface->pfnFreeResource(
            m_osInterface,
            &m_resVdencPictureState2NdLevelBatchBufferWrite[i]);
    }
    if (m_hucCmdInitializer)
    {
        m_hucCmdInitializer->CmdInitializerFreeResources();
        MOS_Delete(m_hucCmdInitializer);
        m_hucCmdInitializer = nullptr;
    }

#if (_DEBUG || _RELEASE_INTERNAL)
    if (m_swBrcMode != nullptr)
    {
        bool result = MosUtilities::MosFreeLibrary(m_swBrcMode) ? true : false;
        CODECHAL_ENCODE_ASSERT(result == true);
        m_swBrcMode = nullptr;
    }
#endif

    return;
}

MOS_STATUS CodechalVdencVp9State::CalculateVdencPictureStateCommandSize()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    MHW_VDBOX_STATE_CMDSIZE_PARAMS stateCmdSizeParams;
    uint32_t vdencPictureStatesSize = 0, vdencPicturePatchListSize = 0;
    stateCmdSizeParams.bHucDummyStream = true;
    m_hwInterface->GetHxxStateCommandSize(
        CODECHAL_ENCODE_MODE_VP9,
        &vdencPictureStatesSize,
        &vdencPicturePatchListSize,
        &stateCmdSizeParams);

    m_defaultPictureStatesSize += vdencPictureStatesSize;
    m_defaultPicturePatchListSize += vdencPicturePatchListSize;

    m_hwInterface->GetVdencStateCommandsDataSize(
        CODECHAL_ENCODE_MODE_VP9,
        &vdencPictureStatesSize,
        &vdencPicturePatchListSize);

    m_defaultPictureStatesSize += vdencPictureStatesSize;
    m_defaultPicturePatchListSize += vdencPicturePatchListSize;

    //Set to max huc commands
    uint32_t vdencHucStatesSize = 0, hucPatchListSize = 0;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetHucInterface()->GetHucStateCommandSize(
        CODECHAL_ENCODE_MODE_VP9, (uint32_t*)&vdencHucStatesSize, (uint32_t*)&hucPatchListSize, &stateCmdSizeParams));
    m_defaultHucCmdsSize += m_defaultHucCmdsSize;
    m_defaultHucPatchListSize += hucPatchListSize;
    return eStatus;
}

MOS_STATUS CodechalVdencVp9State::Initialize(CodechalSetting * settings)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;
#ifndef _FULL_OPEN_SOURCE
    if (m_cscDsState)
    {
        // support non-aligned and csc ds copy usages
        m_cscDsState->EnableCopy();
        m_cscDsState->EnableColor();

        // Temp WA until cscDs Codec/Platform LUT is completed
        m_cscDsState->DisableCsc();
    }
#endif
    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::Initialize(settings));
#ifdef _MMC_SUPPORTED
    CODECHAL_ENCODE_CHK_STATUS_RETURN(InitMmcState());
#endif
    m_bitDepth     = (settings->lumaChromaDepth & CODECHAL_LUMA_CHROMA_DEPTH_10_BITS) ? VP9_ENCODED_BIT_DEPTH_10 : VP9_ENCODED_BIT_DEPTH_8;
    m_chromaFormat = settings->chromaFormat;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(CalculateVdencPictureStateCommandSize());

    // Slice Level Commands
    CODECHAL_ENCODE_CHK_STATUS_RETURN(
        m_hwInterface->GetHxxPrimitiveCommandSize(
            CODECHAL_ENCODE_MODE_VP9,
            &m_sliceStatesSize,
            &m_slicePatchListSize,
            false));

    m_hwInterface->GetVdencPictureSecondLevelCommandsSize(
        CODECHAL_ENCODE_MODE_VP9,
        &m_vdencPicStateSecondLevelBatchBufferSize);

    return eStatus;
}

//------------------------------------------------------------------------------
//| Purpose:    Reports user feature keys used for VP9 encoding
//| Return:     N/A
//------------------------------------------------------------------------------
MOS_STATUS CodechalVdencVp9State::UserFeatureKeyReport()
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::UserFeatureKeyReport())

    CodecHalEncodeWriteKey(__MEDIA_USER_FEATURE_VALUE_ENCODE_BRC_IN_USE_ID, m_brcEnabled, m_osInterface->pOsContext);
    CodecHalEncodeWriteKey(__MEDIA_USER_FEATURE_VALUE_VP9_ENCODE_MULTIPASS_BRC_IN_USE_ID, m_multipassBrcSupported, m_osInterface->pOsContext);
    CodecHalEncodeWriteKey(__MEDIA_USER_FEATURE_VALUE_VP9_ENCODE_ADAPTIVE_REPAK_IN_USE_ID, m_adaptiveRepakSupported, m_osInterface->pOsContext);
    CodecHalEncodeWriteKey(__MEDIA_USER_FEATURE_VALUE_VP9_ENCODE_ME_ENABLE_ID, m_hmeSupported, m_osInterface->pOsContext);
    CodecHalEncodeWriteKey(__MEDIA_USER_FEATURE_VALUE_VP9_ENCODE_16xME_ENABLE_ID, m_16xMeSupported, m_osInterface->pOsContext);
    CodecHalEncodeWriteKey(__MEDIA_USER_FEATURE_VALUE_VP9_ENCODE_HUC_ENABLE_ID, m_hucEnabled, m_osInterface->pOsContext);

#if (_DEBUG || _RELEASE_INTERNAL)
    CodecHalEncodeWriteKey(__MEDIA_USER_FEATURE_VALUE_VDENC_IN_USE_ID, m_vdencEnabled, m_osInterface->pOsContext);
#endif

    return eStatus;
}

//------------------------------------------------------------------------------
//| Purpose:    Retrieves the HCP registers and stores them in the status report
//| Return:     N/A
//------------------------------------------------------------------------------
MOS_STATUS CodechalVdencVp9State::ReadHcpStatus(
    PMOS_COMMAND_BUFFER cmdBuffer)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    CODECHAL_ENCODE_FUNCTION_ENTER;

    CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);

    CODECHAL_ENCODE_CHK_COND_RETURN((m_vdboxIndex > m_hwInterface->GetMfxInterface()->GetMaxVdboxIndex()),"ERROR - vdbox index exceed the maximum");

    EncodeStatusBuffer* encodeStatusBuf   = &m_encodeStatusBuf;
    uint32_t baseOffset =
        (encodeStatusBuf->wCurrIndex * m_encodeStatusBuf.dwReportSize) +
        sizeof(uint32_t)* 2;  // encodeStatus is offset by 2 DWs in the resource

    MHW_MI_FLUSH_DW_PARAMS flushDwParams;
    MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(cmdBuffer, &flushDwParams));

    auto mmioRegisters = m_hcpInterface->GetMmioRegisters(m_vdboxIndex);
    CODECHAL_ENCODE_CHK_NULL_RETURN(mmioRegisters);
    MHW_MI_STORE_REGISTER_MEM_PARAMS miStoreRegMemParams;
    MOS_ZeroMemory(&miStoreRegMemParams, sizeof(miStoreRegMemParams));
    miStoreRegMemParams.presStoreBuffer = &encodeStatusBuf->resStatusBuffer;
    miStoreRegMemParams.dwOffset        = baseOffset + encodeStatusBuf->dwBSByteCountOffset;
    miStoreRegMemParams.dwRegister      = mmioRegisters->hcpVp9EncBitstreamBytecountFrameRegOffset;
    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreRegisterMemCmd(cmdBuffer, &miStoreRegMemParams));

    MHW_MI_COPY_MEM_MEM_PARAMS copyMemMemParams;
    MOS_ZeroMemory(&copyMemMemParams , sizeof(copyMemMemParams));

    copyMemMemParams.presSrc        = &encodeStatusBuf->resStatusBuffer;
    copyMemMemParams.dwSrcOffset    = baseOffset + encodeStatusBuf->dwBSByteCountOffset;
    copyMemMemParams.presDst        = &m_brcBuffers.resBrcBitstreamSizeBuffer;
    copyMemMemParams.dwDstOffset    = CODECHAL_OFFSETOF(BRC_BITSTREAM_SIZE_BUFFER, dwHcpBitstreamByteCountFrame);

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiCopyMemMemCmd(
        cmdBuffer,
        &copyMemMemParams));

    MOS_ZeroMemory(&copyMemMemParams, sizeof(copyMemMemParams));

    // write frame size directly to huc second pass dmem buffer
    // it is needed for correct pipeline synchronization and dmem initialization
    copyMemMemParams.presSrc = &encodeStatusBuf->resStatusBuffer;
    copyMemMemParams.dwSrcOffset = baseOffset + encodeStatusBuf->dwBSByteCountOffset;
    // For BRC cases, do not overwrite the HPU probability in huc Dmen buffer in the last pass
    copyMemMemParams.presDst = &m_resHucProbDmemBuffer[m_vdencBrcEnabled ? 2 : 1][m_currRecycledBufIdx];
    copyMemMemParams.dwDstOffset = CODECHAL_OFFSETOF(HucProbDmem, FrameSize);

    CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiCopyMemMemCmd(
        cmdBuffer,
        &copyMemMemParams));

    return eStatus;
}

CodechalVdencVp9State::CodechalVdencVp9State(
    CodechalHwInterface* hwInterface,
    CodechalDebugInterface* debugInterface,
    PCODECHAL_STANDARD_INFO standardInfo)
    :CodechalEncoderState(hwInterface, debugInterface, standardInfo)
{
    m_32xMeSupported = false;

    // VP9 uses a CM based down scale kernel
    m_useCmScalingKernel      = true;
    m_interlacedFieldDisabled = true;
    m_firstField              = true; // each frame is treated as the first field

    // No field pictures in VP9
    m_verticalLineStride = CODECHAL_VLINESTRIDE_FRAME;
    m_verticalLineStrideOffset = CODECHAL_VLINESTRIDEOFFSET_TOP_FIELD;

    // enable codec specific user feature key reporting
    m_userFeatureKeyReport = true;

    m_codecGetStatusReportDefined = true;       // Codec specific GetStatusReport is implemented.

    m_brcInit = true;

    MOS_ZeroMemory(&m_resDeblockingFilterLineBuffer, sizeof(m_resDeblockingFilterLineBuffer));
    MOS_ZeroMemory(&m_resDeblockingFilterTileLineBuffer, sizeof(m_resDeblockingFilterTileLineBuffer));
    MOS_ZeroMemory(&m_resDeblockingFilterTileColumnBuffer, sizeof(m_resDeblockingFilterTileColumnBuffer));
    MOS_ZeroMemory(&m_resMetadataLineBuffer, sizeof(m_resMetadataLineBuffer));
    MOS_ZeroMemory(&m_resMetadataTileLineBuffer, sizeof(m_resMetadataTileLineBuffer));
    MOS_ZeroMemory(&m_resMetadataTileColumnBuffer, sizeof(m_resMetadataTileColumnBuffer));

    for (auto i = 0; i < CODEC_VP9_NUM_CONTEXTS; i++)
    {
        MOS_ZeroMemory(&m_resProbBuffer[i], sizeof(m_resProbBuffer[i]));
    }
    MOS_ZeroMemory(&m_resSegmentIdBuffer, sizeof(m_resSegmentIdBuffer));
    MOS_ZeroMemory(&m_resHvcLineRowstoreBuffer, sizeof(m_resHvcLineRowstoreBuffer));  // Handle of HVC Line Row Store surface
    MOS_ZeroMemory(&m_resHvcTileRowstoreBuffer, sizeof(m_resHvcTileRowstoreBuffer));  // Handle of HVC Tile Row Store surface
    MOS_ZeroMemory(&m_resProbabilityDeltaBuffer, sizeof(m_resProbabilityDeltaBuffer));
    MOS_ZeroMemory(&m_resTileRecordStrmOutBuffer, sizeof(m_resTileRecordStrmOutBuffer));
    MOS_ZeroMemory(&m_resCuStatsStrmOutBuffer, sizeof(m_resCuStatsStrmOutBuffer));
    MOS_ZeroMemory(&m_resCompressedHeaderBuffer, sizeof(m_resCompressedHeaderBuffer));
    MOS_ZeroMemory(&m_resProbabilityCounterBuffer, sizeof(m_resProbabilityCounterBuffer));
    for (auto i = 0; i < 2; i++)
    {
        MOS_ZeroMemory(&m_resModeDecision[i], sizeof(m_resModeDecision[i]));
    }
    MOS_ZeroMemory(&m_resFrameStatStreamOutBuffer, sizeof(m_resFrameStatStreamOutBuffer));
    MOS_ZeroMemory(&m_resSseSrcPixelRowStoreBuffer, sizeof(m_resSseSrcPixelRowStoreBuffer));

    MOS_ZeroMemory(&m_prevFrameInfo, sizeof(m_prevFrameInfo));

    for (auto j = 0; j < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; ++j)
    {
        for (auto i = 0; i < 3; i++)
        {
            MOS_ZeroMemory(&m_resHucProbDmemBuffer[i][j], sizeof(m_resHucProbDmemBuffer[i][j]));
        }
    }
    MOS_ZeroMemory(&m_resHucDefaultProbBuffer, sizeof(m_resHucDefaultProbBuffer));
    MOS_ZeroMemory(&m_resHucProbOutputBuffer, sizeof(m_resHucProbOutputBuffer));
    for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++)
    {
        MOS_ZeroMemory(&m_resHucPakInsertUncompressedHeaderReadBuffer[i], sizeof(m_resHucPakInsertUncompressedHeaderReadBuffer[i]));
    }
    MOS_ZeroMemory(&m_resHucPakInsertUncompressedHeaderWriteBuffer, sizeof(m_resHucPakInsertUncompressedHeaderWriteBuffer));
    MOS_ZeroMemory(&m_resHucPakMmioBuffer, sizeof(m_resHucPakMmioBuffer));
    MOS_ZeroMemory(&m_resHucDebugOutputBuffer, sizeof(m_resHucDebugOutputBuffer));
    MOS_ZeroMemory(&m_mbSegmentMapSurface, sizeof(m_mbSegmentMapSurface));
    MOS_ZeroMemory(&m_output16X16InterModes, sizeof(m_output16X16InterModes));

    MOS_ZeroMemory(&m_4xMeMvDataBuffer, sizeof(m_4xMeMvDataBuffer));
    MOS_ZeroMemory(&m_16xMeMvDataBuffer, sizeof(m_16xMeMvDataBuffer));
    MOS_ZeroMemory(&m_4xMeDistortionBuffer, sizeof(m_4xMeDistortionBuffer));

    MOS_ZeroMemory(&m_resVdencIntraRowStoreScratchBuffer, sizeof(m_resVdencIntraRowStoreScratchBuffer));  // Handle of intra row store surface
    MOS_ZeroMemory(&m_resVdencBrcStatsBuffer, sizeof(m_resVdencBrcStatsBuffer));
    MOS_ZeroMemory(&m_resVdencSegmentMapStreamOut, sizeof(m_resVdencSegmentMapStreamOut));

    for (auto i = 0; i < CODECHAL_VP9_ENCODE_RECYCLED_BUFFER_NUM; i++)
    {
        for (auto j = 0; j < 3; j++)
        {
            MOS_ZeroMemory(&m_resVdencPictureState2NdLevelBatchBufferRead[j][i], sizeof(m_resVdencPictureState2NdLevelBatchBufferRead[j][i]));
        }

        MOS_ZeroMemory(&m_resVdencPictureState2NdLevelBatchBufferWrite[i], sizeof(m_resVdencPictureState2NdLevelBatchBufferWrite[i]));
    }

    MOS_ZeroMemory(&m_resVdencDysPictureState2NdLevelBatchBuffer, sizeof(m_resVdencDysPictureState2NdLevelBatchBuffer));
    MOS_ZeroMemory(&m_resVdencBrcInitDmemBuffer, sizeof(m_resVdencBrcInitDmemBuffer));
    for (auto i = 0; i < 3; i++)
    {
        for (auto ib = 0; ib < CODECHAL_VP9_ENCODE_RECYCLED_BUFFER_NUM; ib++)
        {
            MOS_ZeroMemory(&m_resVdencBrcUpdateDmemBuffer[i][ib], sizeof(m_resVdencBrcUpdateDmemBuffer[i][ib]));
        }
    }
    MOS_ZeroMemory(&m_resVdencDataExtensionBuffer, sizeof(m_resVdencDataExtensionBuffer));

    MOS_ZeroMemory(&m_dysKernelState, sizeof(m_dysKernelState));

    m_vdboxOneDefaultUsed = true;
}

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

MOS_STATUS CodechalVdencVp9State::CtxBufDiffInit(
    uint8_t *ctxBuffer,
    bool setToKey)
{
    int32_t i, j;
    uint32_t byteCnt = CODEC_VP9_INTER_PROB_OFFSET;
    //inter mode probs. have to be zeros for Key frame
    for (i = 0; i < CODEC_VP9_INTER_MODE_CONTEXTS; i++)
    {
        for (j = 0; j < CODEC_VP9_INTER_MODES - 1; j++)
        {
            if (!setToKey)
            {
                ctxBuffer[byteCnt++] = DefaultInterModeProbs[i][j];
            }
            else
            {
                //zeros for key frame
                byteCnt++;
            }
        }
    }
    //switchable interprediction probs
    for (i = 0; i < CODEC_VP9_SWITCHABLE_FILTERS + 1; i++)
    {
        for (j = 0; j < CODEC_VP9_SWITCHABLE_FILTERS - 1; j++)
        {
            if (!setToKey)
            {
                ctxBuffer[byteCnt++] = DefaultSwitchableInterpProb[i][j];
            }
            else
            {
                //zeros for key frame
                byteCnt++;
            }
        }
    }
    //intra inter probs
    for (i = 0; i < CODEC_VP9_INTRA_INTER_CONTEXTS; i++)
    {
        if (!setToKey)
        {
            ctxBuffer[byteCnt++] = DefaultIntraInterProb[i];
        }
        else
        {
            //zeros for key frame
            byteCnt++;
        }
    }
    //comp inter probs
    for (i = 0; i < CODEC_VP9_COMP_INTER_CONTEXTS; i++)
    {
        if (!setToKey)
        {
            ctxBuffer[byteCnt++] = DefaultCompInterProb[i];
        }
        else
        {
            //zeros for key frame
            byteCnt++;
        }
    }
    //single ref probs
    for (i = 0; i < CODEC_VP9_REF_CONTEXTS; i++)
    {
        for (j = 0; j < 2; j++)
        {
            if (!setToKey)
            {
                ctxBuffer[byteCnt++] = DefaultSingleRefProb[i][j];
            }
            else
            {
                //zeros for key frame
                byteCnt++;
            }
        }
    }
    //comp ref probs
    for (i = 0; i < CODEC_VP9_REF_CONTEXTS; i++)
    {
        if (!setToKey)
        {
            ctxBuffer[byteCnt++] = DefaultCompRefProb[i];
        }
        else
        {
            //zeros for key frame
            byteCnt++;
        }
    }
    //y mode probs
    for (i = 0; i < CODEC_VP9_BLOCK_SIZE_GROUPS; i++)
    {
        for (j = 0; j < CODEC_VP9_INTRA_MODES - 1; j++)
        {
            if (!setToKey)
            {
                ctxBuffer[byteCnt++] = DefaultIFYProb[i][j];
            }
            else
            {
                //zeros for key frame, since HW will not use this buffer, but default right buffer.
                byteCnt++;
            }
        }
    }
    //partition probs, key & intra-only frames use key type, other inter frames use inter type
    for (i = 0; i < CODECHAL_VP9_PARTITION_CONTEXTS; i++)
    {
        for (j = 0; j < CODEC_VP9_PARTITION_TYPES - 1; j++)
        {
            if (setToKey)
            {
                ctxBuffer[byteCnt++] = DefaultKFPartitionProb[i][j];
            }
            else
            {
                ctxBuffer[byteCnt++] = DefaultPartitionProb[i][j];
            }
        }
    }
    //nmvc joints
    for (i = 0; i < (CODEC_VP9_MV_JOINTS - 1); i++)
    {
        if (!setToKey)
        {
            ctxBuffer[byteCnt++] = DefaultNmvContext.joints[i];
        }
        else
        {
            //zeros for key frame
            byteCnt++;
        }
    }
    //nmvc comps
    for (i = 0; i < 2; i++)
    {
        if (!setToKey)
        {
            ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].sign;
            for (j = 0; j < (CODEC_VP9_MV_CLASSES - 1); j++)
            {
                ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].classes[j];
            }
            for (j = 0; j < (CODECHAL_VP9_CLASS0_SIZE - 1); j++)
            {
                ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].class0[j];
            }
            for (j = 0; j < CODECHAL_VP9_MV_OFFSET_BITS; j++)
            {
                ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].bits[j];
            }
        }
        else
        {
            byteCnt += 1;
            byteCnt += (CODEC_VP9_MV_CLASSES - 1);
            byteCnt += (CODECHAL_VP9_CLASS0_SIZE - 1);
            byteCnt += (CODECHAL_VP9_MV_OFFSET_BITS);
        }
    }
    for (i = 0; i < 2; i++)
    {
        if (!setToKey)
        {
            for (j = 0; j < CODECHAL_VP9_CLASS0_SIZE; j++)
            {
                for (int32_t k = 0; k < (CODEC_VP9_MV_FP_SIZE - 1); k++)
                {
                    ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].class0_fp[j][k];
                }
            }
            for (j = 0; j < (CODEC_VP9_MV_FP_SIZE - 1); j++)
            {
                ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].fp[j];
            }
        }
        else
        {
            byteCnt += (CODECHAL_VP9_CLASS0_SIZE * (CODEC_VP9_MV_FP_SIZE - 1));
            byteCnt += (CODEC_VP9_MV_FP_SIZE - 1);
        }
    }
    for (i = 0; i < 2; i++)
    {
        if (!setToKey)
        {
            ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].class0_hp;
            ctxBuffer[byteCnt++] = DefaultNmvContext.comps[i].hp;
        }
        else
        {
            byteCnt += 2;
        }
    }

    //47 bytes of zeros
    byteCnt += 47;

    //uv mode probs
    for (i = 0; i < CODEC_VP9_INTRA_MODES; i++)
    {
        for (j = 0; j < CODEC_VP9_INTRA_MODES - 1; j++)
        {
            if (setToKey)
            {
                ctxBuffer[byteCnt++] = DefaultKFUVModeProb[i][j];
            }
            else
            {
                ctxBuffer[byteCnt++] = DefaultIFUVProbs[i][j];
            }
        }
    }

    return MOS_STATUS_SUCCESS;
}

MOS_STATUS CodechalVdencVp9State::ContextBufferInit(
    uint8_t *ctxBuffer,
    bool setToKey)
{

    MOS_ZeroMemory(ctxBuffer, CODEC_VP9_SEG_PROB_OFFSET);

    int32_t i, j;
    uint32_t byteCnt = 0;
    //TX probs
    for (i = 0; i < CODEC_VP9_TX_SIZE_CONTEXTS; i++)
    {
        for (j = 0; j < CODEC_VP9_TX_SIZES - 3; j++)
        {
            ctxBuffer[byteCnt++] = DefaultTxProbs.p8x8[i][j];
        }
    }
    for (i = 0; i < CODEC_VP9_TX_SIZE_CONTEXTS; i++)
    {
        for (j = 0; j < CODEC_VP9_TX_SIZES - 2; j++)
        {
            ctxBuffer[byteCnt++] = DefaultTxProbs.p16x16[i][j];
        }
    }
    for (i = 0; i < CODEC_VP9_TX_SIZE_CONTEXTS; i++)
    {
        for (j = 0; j < CODEC_VP9_TX_SIZES - 1; j++)
        {
            ctxBuffer[byteCnt++] = DefaultTxProbs.p32x32[i][j];
        }
    }

    //52 bytes of zeros
    byteCnt += 52;

    uint8_t blocktype = 0;
    uint8_t reftype = 0;
    uint8_t coeffbands = 0;
    uint8_t unConstrainedNodes = 0;
    uint8_t prevCoefCtx = 0;
    //coeff probs
    for (blocktype = 0; blocktype < CODEC_VP9_BLOCK_TYPES; blocktype++)
    {
        for (reftype = 0; reftype < CODEC_VP9_REF_TYPES; reftype++)
        {
            for (coeffbands = 0; coeffbands < CODEC_VP9_COEF_BANDS; coeffbands++)
            {
                uint8_t numPrevCoeffCtxts = (coeffbands == 0) ? 3 : CODEC_VP9_PREV_COEF_CONTEXTS;
                for (prevCoefCtx = 0; prevCoefCtx < numPrevCoeffCtxts; prevCoefCtx++)
                {
                    for (unConstrainedNodes = 0; unConstrainedNodes < CODEC_VP9_UNCONSTRAINED_NODES; unConstrainedNodes++)
                    {
                        ctxBuffer[byteCnt++] = DefaultCoefProbs4x4[blocktype][reftype][coeffbands][prevCoefCtx][unConstrainedNodes];
                    }
                }
            }
        }
    }

    for (blocktype = 0; blocktype < CODEC_VP9_BLOCK_TYPES; blocktype++)
    {
        for (reftype = 0; reftype < CODEC_VP9_REF_TYPES; reftype++)
        {
            for (coeffbands = 0; coeffbands < CODEC_VP9_COEF_BANDS; coeffbands++)
            {
                uint8_t numPrevCoeffCtxts = (coeffbands == 0) ? 3 : CODEC_VP9_PREV_COEF_CONTEXTS;
                for (prevCoefCtx = 0; prevCoefCtx < numPrevCoeffCtxts; prevCoefCtx++)
                {
                    for (unConstrainedNodes = 0; unConstrainedNodes < CODEC_VP9_UNCONSTRAINED_NODES; unConstrainedNodes++)
                    {
                        ctxBuffer[byteCnt++] = DefaultCoefPprobs8x8[blocktype][reftype][coeffbands][prevCoefCtx][unConstrainedNodes];
                    }
                }
            }
        }
    }

    for (blocktype = 0; blocktype < CODEC_VP9_BLOCK_TYPES; blocktype++)
    {
        for (reftype = 0; reftype < CODEC_VP9_REF_TYPES; reftype++)
        {
            for (coeffbands = 0; coeffbands < CODEC_VP9_COEF_BANDS; coeffbands++)
            {
                uint8_t numPrevCoeffCtxts = (coeffbands == 0) ? 3 : CODEC_VP9_PREV_COEF_CONTEXTS;
                for (prevCoefCtx = 0; prevCoefCtx < numPrevCoeffCtxts; prevCoefCtx++)
                {
                    for (unConstrainedNodes = 0; unConstrainedNodes < CODEC_VP9_UNCONSTRAINED_NODES; unConstrainedNodes++)
                    {
                        ctxBuffer[byteCnt++] = DefaultCoefProbs16x16[blocktype][reftype][coeffbands][prevCoefCtx][unConstrainedNodes];
                    }
                }
            }
        }
    }

    for (blocktype = 0; blocktype < CODEC_VP9_BLOCK_TYPES; blocktype++)
    {
        for (reftype = 0; reftype < CODEC_VP9_REF_TYPES; reftype++)
        {
            for (coeffbands = 0; coeffbands < CODEC_VP9_COEF_BANDS; coeffbands++)
            {
                uint8_t numPrevCoeffCtxts = (coeffbands == 0) ? 3 : CODEC_VP9_PREV_COEF_CONTEXTS;
                for (prevCoefCtx = 0; prevCoefCtx < numPrevCoeffCtxts; prevCoefCtx++)
                {
                    for (unConstrainedNodes = 0; unConstrainedNodes < CODEC_VP9_UNCONSTRAINED_NODES; unConstrainedNodes++)
                    {
                        ctxBuffer[byteCnt++] = DefaultCoefProbs32x32[blocktype][reftype][coeffbands][prevCoefCtx][unConstrainedNodes];
                    }
                }
            }
        }
    }

    //16 bytes of zeros
    byteCnt += 16;

    // mb skip probs
    for (i = 0; i < CODEC_VP9_MBSKIP_CONTEXTS; i++)
    {
        ctxBuffer[byteCnt++] = DefaultMbskipProbs[i];
    }

    // populate prob values which are different between Key and Non-Key frame
    CtxBufDiffInit(ctxBuffer, setToKey);

    //skip Seg tree/pred probs, updating not done in this function.
    byteCnt = CODEC_VP9_SEG_PROB_OFFSET;
    byteCnt += 7;
    byteCnt += 3;

    //28 bytes of zeros
    for (i = 0; i < 28; i++)
    {
        ctxBuffer[byteCnt++] = 0;
    }

    //Just a check.
    if (byteCnt > CODEC_VP9_PROB_MAX_NUM_ELEM)
    {
        CODECHAL_PUBLIC_ASSERTMESSAGE("Error: FrameContext array out-of-bounds, byteCnt = %d!\n", byteCnt);
        return MOS_STATUS_NO_SPACE;
    }
    else
    {
        return MOS_STATUS_SUCCESS;
    }
}

#if USE_CODECHAL_DEBUG_TOOL
MOS_STATUS CodechalVdencVp9State::DumpSeqParams(
    PCODEC_VP9_ENCODE_SEQUENCE_PARAMS seqParams)
{
    CODECHAL_DEBUG_FUNCTION_ENTER;

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

    CODECHAL_DEBUG_CHK_NULL(seqParams);

    std::ostringstream oss;
    oss.setf(std::ios::showbase | std::ios::uppercase);

    oss << "# DDI Parameters:" << std::endl;
    oss << "MaxFrameWidth = " << std::dec << +seqParams->wMaxFrameWidth << std::endl;
    oss << "MaxFrameHeight = " << std::dec << +seqParams->wMaxFrameHeight << std::endl;
    oss << "GopPicSize = " << std::dec << +seqParams->GopPicSize << std::endl;
    oss << "TargetUsage = " << std::dec << +seqParams->TargetUsage << std::endl;
    oss << "RateControlMethod = " << std::dec << +seqParams->RateControlMethod << std::endl;

    for (uint8_t i = 0; i < 8; i++)
    {
        oss << "TargetBitRate[" << +i << "] = " << std::dec << +seqParams->TargetBitRate[i] << std::endl;
    }
    oss << "MaxBitRate = " << std::dec << +seqParams->MaxBitRate << std::endl;
    oss << "MinBitRate = " << std::dec << +seqParams->MinBitRate << std::endl;
    oss << "InitVBVBufferFullnessInBit = " << +seqParams->InitVBVBufferFullnessInBit << std::endl;
    oss << "VBVBufferSizeInBit = " << std::dec << +seqParams->VBVBufferSizeInBit << std::endl;
    oss << "OptimalVBVBufferLevelInBit = " << std::dec << +seqParams->OptimalVBVBufferLevelInBit << std::endl;
    oss << "UpperVBVBufferLevelThresholdInBit = " << std::dec << +seqParams->UpperVBVBufferLevelThresholdInBit << std::endl;
    oss << "LowerVBVBufferLevelThresholdInBit = " << std::dec << +seqParams->LowerVBVBufferLevelThresholdInBit << std::endl;
    oss << "DisplayFormatSwizzle = " << std::dec << +seqParams->SeqFlags.fields.DisplayFormatSwizzle << std::endl;
    // begining of union/struct
    oss << "# bResetBRC = " << std::dec << +seqParams->SeqFlags.fields.bResetBRC << std::endl;
    oss << "# bNoFrameHeaderInsertion = " << std::dec << +seqParams->SeqFlags.fields.bNoFrameHeaderInsertion << std::endl;
    // Next 5 fields not currently implemented.  nullptr output
    oss << "# UseRawReconRef = " << std::dec << +seqParams->SeqFlags.fields.bUseRawReconRef << std::endl;
    oss << "# MBBRC = " << std::dec << +seqParams->SeqFlags.fields.MBBRC << std::endl;
    oss << "EnableDynamicScaling = " << std::dec << +seqParams->SeqFlags.fields.EnableDynamicScaling << std::endl;
    oss << "SourceFormat = " << std::dec << +seqParams->SeqFlags.fields.SourceFormat << std::endl;
    oss << "SourceBitDepth = " << std::dec << +seqParams->SeqFlags.fields.SourceBitDepth << std::endl;
    oss << "EncodedFormat = " << std::dec << +seqParams->SeqFlags.fields.EncodedFormat << std::endl;
    oss << "EncodedBitDepth = " << std::dec << +seqParams->SeqFlags.fields.EncodedBitDepth << std::endl;
    oss << "DisplayFormatSwizzle = " << std::dec << +seqParams->SeqFlags.fields.DisplayFormatSwizzle << std::endl;
    // end of union/struct

    oss << "UserMaxFrameSize = " << std::dec << +seqParams->UserMaxFrameSize << std::endl;
    for (uint8_t i = 0; i < 8; i++)
    {
        oss << "FrameRateNumerator[" << +i << "] = " << std::dec << +seqParams->FrameRate[i].uiNumerator << std::endl;
        oss << "FrameRateDenominator[" << +i << "] = " << std::dec << +seqParams->FrameRate[i].uiDenominator << std::endl;
    }

    oss << "NumTemporalLayersMinus1 = " << std::dec << +seqParams->NumTemporalLayersMinus1 << std::endl;

    const char *fileName = m_debugInterface->CreateFileName(
        "_DDIEnc",
        CodechalDbgBufferType::bufSeqParams,
        CodechalDbgExtType::txt);

    std::ofstream ofs(fileName, std::ios::out);
    ofs << oss.str();
    ofs.close();

    if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDriverUltDump))
    {
        if (!m_debugInterface->m_ddiFileName.empty())
        {
            std::ofstream ofs(m_debugInterface->m_ddiFileName, std::ios::app);
            ofs << "SeqParamFile"
                << " = \"" << m_debugInterface->m_fileName << "\"" << std::endl;
            ofs.close();
        }
    }

    return MOS_STATUS_SUCCESS;
}

MOS_STATUS CodechalVdencVp9State::DumpPicParams(
    PCODEC_VP9_ENCODE_PIC_PARAMS picParams)
{
    CODECHAL_DEBUG_FUNCTION_ENTER;

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

    CODECHAL_DEBUG_CHK_NULL(picParams);

    std::ostringstream oss;
    oss.setf(std::ios::showbase | std::ios::uppercase);

    oss << "# DDI Parameters:" << std::endl;
    oss << "SrcFrameHeightMinus1 = " << std::dec << +picParams->SrcFrameHeightMinus1 << std::endl;
    oss << "SrcFrameWidthMinus1 = " << std::dec << +picParams->SrcFrameWidthMinus1 << std::endl;
    oss << "CurrOriginalPic = " << std::dec << +picParams->CurrOriginalPic.FrameIdx << std::endl;
    oss << "CurrReconstructedPic = " << std::dec << +picParams->CurrReconstructedPic.FrameIdx << std::endl;

    for (uint16_t i = 0; i < CODEC_VP9_NUM_REF_FRAMES; ++i)
    {
        oss << "RefFrameList[" << +i << "] = " << std::dec << +picParams->RefFrameList[i].FrameIdx << std::endl;
    }
    oss << "frame_type = " << std::dec << +picParams->PicFlags.fields.frame_type << std::endl;
    oss << "show_frame = " << std::dec << +picParams->PicFlags.fields.show_frame << std::endl;
    oss << "error_resilient_mode = " << std::dec << +picParams->PicFlags.fields.error_resilient_mode << std::endl;
    oss << "intra_only = " << std::dec << +picParams->PicFlags.fields.intra_only << std::endl;
    oss << "allow_high_precision_mv = " << std::dec << +picParams->PicFlags.fields.allow_high_precision_mv << std::endl;
    oss << "mcomp_filter_type = " << std::dec << +picParams->PicFlags.fields.mcomp_filter_type << std::endl;
    oss << "frame_parallel_decoding_mode = " << std::dec << +picParams->PicFlags.fields.frame_parallel_decoding_mode << std::endl;
    oss << "segmentation_enabled = " << std::dec << +picParams->PicFlags.fields.segmentation_enabled << std::endl;
    oss << "segmentation_temporal_update = " << std::dec << +picParams->PicFlags.fields.segmentation_temporal_update << std::endl;
    oss << "segmentation_update_map = " << std::dec << +picParams->PicFlags.fields.segmentation_update_map << std::endl;
    oss << "reset_frame_context = " << std::dec << +picParams->PicFlags.fields.reset_frame_context << std::endl;
    oss << "refresh_frame_context = " << std::dec << +picParams->PicFlags.fields.refresh_frame_context << std::endl;
    oss << "frame_context_idx = " << std::dec << +picParams->PicFlags.fields.frame_context_idx << std::endl;
    oss << "LosslessFlag = " << std::dec << +picParams->PicFlags.fields.LosslessFlag << std::endl;
    oss << "comp_prediction_mode = " << std::dec << +picParams->PicFlags.fields.comp_prediction_mode << std::endl;
    oss << "super_frame = " << std::dec << +picParams->PicFlags.fields.super_frame << std::endl;
    oss << "seg_id_block_size = " << std::dec << +picParams->PicFlags.fields.seg_id_block_size << std::endl;
    oss << "seg_update_data = " << std::dec << +picParams->PicFlags.fields.seg_update_data << std::endl;
    oss << "LastRefIdx = " << std::dec << +picParams->RefFlags.fields.LastRefIdx << std::endl;
    oss << "LastRefSignBias = " << std::dec << +picParams->RefFlags.fields.LastRefSignBias << std::endl;
    oss << "GoldenRefIdx = " << std::dec << +picParams->RefFlags.fields.GoldenRefIdx << std::endl;
    oss << "GoldenRefSignBias = " << std::dec << +picParams->RefFlags.fields.GoldenRefSignBias << std::endl;
    oss << "AltRefIdx = " << std::dec << +picParams->RefFlags.fields.AltRefIdx << std::endl;
    oss << "AltRefSignBias = " << std::dec << +picParams->RefFlags.fields.AltRefSignBias << std::endl;
    oss << "ref_frame_ctrl_l0 = " << std::dec << +picParams->RefFlags.fields.ref_frame_ctrl_l0 << std::endl;
    oss << "ref_frame_ctrl_l1 = " << std::dec << +picParams->RefFlags.fields.ref_frame_ctrl_l1 << std::endl;
    oss << "refresh_frame_flags = " << std::dec << +picParams->RefFlags.fields.refresh_frame_flags << std::endl;
    oss << "LumaACQIndex = " << std::dec << +picParams->LumaACQIndex << std::endl;
    oss << "LumaDCQIndexDelta = " << std::dec << +picParams->LumaDCQIndexDelta << std::endl;
    oss << "ChromaACQIndexDelta = " << std::dec << +picParams->ChromaACQIndexDelta << std::endl;
    oss << "ChromaDCQIndexDelta = " << std::dec << +picParams->ChromaDCQIndexDelta << std::endl;
    oss << "filter_level = " << std::dec << +picParams->filter_level << std::endl;
    oss << "sharpness_level = " << std::dec << +picParams->sharpness_level << std::endl;

    for (uint8_t i = 0; i < 4; ++i)
    {
        oss << "LFRefDelta[" << +i << "] = " << std::dec << +picParams->LFRefDelta[i] << std::endl;
    }

    for (uint8_t i = 0; i < 2; ++i)
    {
        oss << "LFModeDelta[" << +i << "] = " << std::dec << +picParams->LFModeDelta[i] << std::endl;
    }

    oss << "BitOffsetForLFRefDelta = " << std::dec << +picParams->BitOffsetForLFRefDelta << std::endl;
    oss << "BitOffsetForLFModeDelta = " << std::dec << +picParams->BitOffsetForLFModeDelta << std::endl;
    oss << "BitOffsetForLFLevel = " << std::dec << +picParams->BitOffsetForLFLevel << std::endl;
    oss << "BitOffsetForQIndex = " << std::dec << +picParams->BitOffsetForQIndex << std::endl;
    oss << "BitOffsetForFirstPartitionSize = " << std::dec << +picParams->BitOffsetForFirstPartitionSize << std::endl;
    oss << "BitOffsetForSegmentation = " << std::dec << +picParams->BitOffsetForSegmentation << std::endl;
    oss << "BitSizeForSegmentation = " << std::dec << +picParams->BitSizeForSegmentation << std::endl;
    oss << "log2_tile_rows = " << std::dec << +picParams->log2_tile_rows << std::endl;
    oss << "log2_tile_columns = " << std::dec << +picParams->log2_tile_columns << std::endl;
    oss << "temporal_id = " << std::dec << +picParams->temporal_id << std::endl;
    oss << "StatusReportFeedbackNumber = " << std::dec << +picParams->StatusReportFeedbackNumber << std::endl;
    oss << "SkipFrameFlag = " << std::dec << +picParams->SkipFrameFlag << std::endl;
    oss << "NumSkipFrames = " << std::dec << +picParams->NumSkipFrames << std::endl;
    oss << "SizeSkipFrames = " << std::dec << +picParams->SizeSkipFrames << std::endl;

    const char *fileName = m_debugInterface->CreateFileName(
        "_DDIEnc",
        CodechalDbgBufferType::bufPicParams,
        CodechalDbgExtType::txt);

    std::ofstream ofs(fileName, std::ios::out);
    ofs << oss.str();
    ofs.close();

    if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDriverUltDump))
    {
        if (!m_debugInterface->m_ddiFileName.empty())
        {
            std::ofstream ofs(m_debugInterface->m_ddiFileName, std::ios::app);
            ofs << "PicNum"
                << " = " << m_debugInterface->m_bufferDumpFrameNum << std::endl;
            ofs << "PicParamFile"
                << " = \"" << m_debugInterface->m_fileName << "\"" << std::endl;
            ofs.close();
        }
    }

    return MOS_STATUS_SUCCESS;
}

MOS_STATUS CodechalVdencVp9State::DumpSegmentParams(
    PCODEC_VP9_ENCODE_SEGMENT_PARAMS segmentParams)
{
    CODECHAL_DEBUG_FUNCTION_ENTER;

    if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSegmentParams))
    {
        return MOS_STATUS_SUCCESS;
    }
    CODECHAL_DEBUG_CHK_NULL(segmentParams);

    std::ostringstream oss;
    oss.setf(std::ios::showbase | std::ios::uppercase);

    for (uint8_t i = 0; i < 8; ++i)
    {
        oss << "Segment_id = " << std::dec << +i << std::endl;
        oss << "SegmentReferenceEnabled = " << std::dec << +segmentParams->SegData[i].SegmentFlags.fields.SegmentReferenceEnabled << std::endl;
        oss << "SegmentReference = " << std::dec << +segmentParams->SegData[i].SegmentFlags.fields.SegmentReference << std::endl;
        oss << "SegmentSkipped = " << std::dec << +segmentParams->SegData[i].SegmentFlags.fields.SegmentSkipped << std::endl;
        oss << "SegmentLFLevelDelta = " << std::dec << +segmentParams->SegData[i].SegmentLFLevelDelta << std::endl;
        oss << "SegmentQIndexDelta = " << std::dec << +segmentParams->SegData[i].SegmentQIndexDelta << std::endl;
    }

    if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDriverUltDump))
    {
        if (!m_debugInterface->m_ddiFileName.empty())
        {
            std::ofstream ofs(m_debugInterface->m_ddiFileName, std::ios::app);
            ofs << "SegmentParamFileParamFile"
                << " = \"" << m_debugInterface->m_fileName << "\"" << std::endl;
            ofs.close();
        }
    }

    const char *fileName = m_debugInterface->CreateFileName(
        "_DDIEnc",
        CodechalDbgBufferType::bufSegmentParams,
        CodechalDbgExtType::txt);

    std::ofstream ofs(fileName, std::ios::out);
    ofs << oss.str();
    ofs.close();

    return MOS_STATUS_SUCCESS;
}
#endif

void CodechalVdencVp9State::fill_pad_with_value(PMOS_SURFACE psSurface, uint32_t real_height, uint32_t aligned_height)
{
    CODECHAL_ENCODE_CHK_NULL_NO_STATUS_RETURN(psSurface);

    // unaligned surfaces only
    if (aligned_height <= real_height || aligned_height > psSurface->dwHeight)
    {
        return;
    }

    // avoid DYS frames cases
    if (m_dysRefFrameFlags != DYS_REF_NONE && m_dysVdencMultiPassEnabled)
    {
        return;
    }

    if (psSurface->OsResource.TileType == MOS_TILE_INVALID)
    {
        return;
    }

    if (psSurface->Format == Format_NV12 || psSurface->Format == Format_P010)
    {
        uint32_t pitch         = psSurface->dwPitch;
        uint32_t UVPlaneOffset = psSurface->UPlaneOffset.iSurfaceOffset;
        uint32_t YPlaneOffset  = psSurface->dwOffset;
        uint32_t pad_rows = aligned_height - real_height;
        uint32_t y_plane_size   = pitch * real_height;
        uint32_t uv_plane_size   = pitch * real_height / 2;

        MOS_LOCK_PARAMS lockFlags;
        MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
        lockFlags.WriteOnly = 1;

        // padding for the linear format buffer.
        if (psSurface->OsResource.TileType == MOS_TILE_LINEAR)
        {
            uint8_t *src_data = (uint8_t *)m_osInterface->pfnLockResource(m_osInterface, &(psSurface->OsResource), &lockFlags);
            CODECHAL_ENCODE_CHK_NULL_NO_STATUS_RETURN(src_data);

            uint8_t *src_data_y     = src_data + YPlaneOffset;
            uint8_t *src_data_y_end = src_data_y + y_plane_size;
            for (uint32_t i = 0; i < pad_rows; i++)
            {
                MOS_SecureMemcpy(src_data_y_end + i * pitch, pitch, src_data_y_end - pitch, pitch);
            }

            uint8_t *src_data_uv     = src_data + UVPlaneOffset;
            uint8_t *src_data_uv_end = src_data_uv + uv_plane_size;
            for (uint32_t i = 0; i < pad_rows / 2; i++)
            {
                MOS_SecureMemcpy(src_data_uv_end + i * pitch, pitch, src_data_uv_end - pitch, pitch);
            }

            m_osInterface->pfnUnlockResource(m_osInterface, &(psSurface->OsResource));
        }
        else
        {
            // we don't copy out the whole tiled buffer to linear and padding on the tiled buffer directly.
            lockFlags.TiledAsTiled = 1;

            uint8_t *src_data   = (uint8_t *)m_osInterface->pfnLockResource(m_osInterface, &(psSurface->OsResource), &lockFlags);
            CODECHAL_ENCODE_CHK_NULL_NO_STATUS_RETURN(src_data);

            uint8_t* padding_data = (uint8_t *)MOS_AllocMemory(pitch * pad_rows);
            CODECHAL_ENCODE_CHK_NULL_NO_STATUS_RETURN(padding_data);

            // Copy last Y row data to linear padding data.
            GMM_RES_COPY_BLT    gmmResCopyBlt  = {0};
            gmmResCopyBlt.Gpu.pData      = src_data;
            gmmResCopyBlt.Gpu.OffsetX    = 0;
            gmmResCopyBlt.Gpu.OffsetY    = (YPlaneOffset + y_plane_size - pitch) / pitch;
            gmmResCopyBlt.Sys.pData      = padding_data;
            gmmResCopyBlt.Sys.RowPitch   = pitch;
            gmmResCopyBlt.Sys.BufferSize = pitch * pad_rows;
            gmmResCopyBlt.Sys.SlicePitch = pitch;
            gmmResCopyBlt.Blt.Slices     = 1;
            gmmResCopyBlt.Blt.Upload     = false;
            gmmResCopyBlt.Blt.Width      = psSurface->dwWidth;
            gmmResCopyBlt.Blt.Height     = 1;
            psSurface->OsResource.pGmmResInfo->CpuBlt(&gmmResCopyBlt);
            // Fill the remain padding lines with last Y row data.
            for (uint32_t i = 1; i < pad_rows; i++)
            {
                MOS_SecureMemcpy(padding_data + i * pitch, pitch, padding_data, pitch);
            }
            // Filling the padding for Y.
            gmmResCopyBlt.Gpu.pData      = src_data;
            gmmResCopyBlt.Gpu.OffsetX    = 0;
            gmmResCopyBlt.Gpu.OffsetY    = (YPlaneOffset + y_plane_size) / pitch;
            gmmResCopyBlt.Sys.pData      = padding_data;
            gmmResCopyBlt.Sys.RowPitch   = pitch;
            gmmResCopyBlt.Sys.BufferSize = pitch * pad_rows;
            gmmResCopyBlt.Sys.SlicePitch = pitch;
            gmmResCopyBlt.Blt.Slices     = 1;
            gmmResCopyBlt.Blt.Upload     = true;
            gmmResCopyBlt.Blt.Width      = psSurface->dwWidth;
            gmmResCopyBlt.Blt.Height     = pad_rows;
            psSurface->OsResource.pGmmResInfo->CpuBlt(&gmmResCopyBlt);

            // Copy last UV row data to linear padding data.
            gmmResCopyBlt.Gpu.pData      = src_data;
            gmmResCopyBlt.Gpu.OffsetX    = 0;
            gmmResCopyBlt.Gpu.OffsetY    = (UVPlaneOffset + uv_plane_size - pitch) / pitch;
            gmmResCopyBlt.Sys.pData      = padding_data;
            gmmResCopyBlt.Sys.RowPitch   = pitch;
            gmmResCopyBlt.Sys.BufferSize = pitch * pad_rows / 2;
            gmmResCopyBlt.Sys.SlicePitch = pitch;
            gmmResCopyBlt.Blt.Slices     = 1;
            gmmResCopyBlt.Blt.Upload     = false;
            gmmResCopyBlt.Blt.Width      = psSurface->dwWidth;
            gmmResCopyBlt.Blt.Height     = 1;
            psSurface->OsResource.pGmmResInfo->CpuBlt(&gmmResCopyBlt);
            // Fill the remain padding lines with last UV row data.
            for (uint32_t i = 1; i < pad_rows / 2; i++)
            {
                MOS_SecureMemcpy(padding_data + i * pitch, pitch, padding_data, pitch);
            }
            // Filling the padding for UV.
            gmmResCopyBlt.Gpu.pData      = src_data;
            gmmResCopyBlt.Gpu.OffsetX    = 0;
            gmmResCopyBlt.Gpu.OffsetY    = (UVPlaneOffset + uv_plane_size) / pitch;
            gmmResCopyBlt.Sys.pData      = padding_data;
            gmmResCopyBlt.Sys.RowPitch   = pitch;
            gmmResCopyBlt.Sys.BufferSize = pitch * pad_rows / 2;
            gmmResCopyBlt.Sys.SlicePitch = pitch;
            gmmResCopyBlt.Blt.Slices     = 1;
            gmmResCopyBlt.Blt.Upload     = true;
            gmmResCopyBlt.Blt.Width      = psSurface->dwWidth;
            gmmResCopyBlt.Blt.Height     = pad_rows / 2;
            psSurface->OsResource.pGmmResInfo->CpuBlt(&gmmResCopyBlt);

            MOS_FreeMemory(padding_data);
            padding_data = nullptr;
            m_osInterface->pfnUnlockResource(m_osInterface, &(psSurface->OsResource));
        }
    }
}
