1 /*
2 * Copyright (c) 2020-2023, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     encode_avc_brc.cpp
24 //! \brief    Defines the common interface for avc brc features
25 //!
26 
27 #include "encode_avc_brc.h"
28 #include "encode_avc_vdenc_feature_manager.h"
29 #include "encode_avc_vdenc_const_settings.h"
30 #include "encode_avc_huc_brc_init_packet.h"
31 #include "encode_avc_huc_brc_update_packet.h"
32 #include "encode_avc_basic_feature.h"
33 
34 namespace encode
35 {
36 
37 #define ENCODE_AVC_BRC_MIN_QP                      1
38 #define VDENC_AVC_BRC_MIN_QP                       10
39 #define VDENC_AVC_BPS_RATIO_LOW                    0.1
40 #define VDENC_AVC_BPS_RATIO_HIGH                   3.5
41 #define ENCODE_AVC_VDENC_MIN_ICQ_QUALITYFACTOR     11
42 
43 //dynamic deviation thresholds calculation
44 #define VDENC_AVC_POS_MULT_I                       50
45 #define VDENC_AVC_NEG_MULT_I                       -50
46 #define VDENC_AVC_POS_MULT_PB                      50
47 #define VDENC_AVC_NEG_MULT_PB                      -50
48 #define VDENC_AVC_POS_MULT_VBR                     100
49 #define VDENC_AVC_NEG_MULT_VBR                     -50
50 
51 #define VDENC_AVC_BRC_TOPQPDELTATHRFORADAPT2PASS   2
52 #define VDENC_AVC_BRC_BOTQPDELTATHRFORADAPT2PASS   1
53 #define VDENC_AVC_BRC_TOPFRMSZTHRFORADAPT2PASS     32
54 #define VDENC_AVC_BRC_BOTFRMSZTHRFORADAPT2PASS     24
55 
56 #define VDENC_AVC_AVBR_TOPQPDELTATHRFORADAPT2PASS  2
57 #define VDENC_AVC_AVBR_BOTQPDELTATHRFORADAPT2PASS  2
58 #define VDENC_AVC_AVBR_TOPFRMSZTHRFORADAPT2PASS    48
59 #define VDENC_AVC_AVBR_BOTFRMSZTHRFORADAPT2PASS    32
60 
61 #define VDENC_AVC_BRC_TOPQPDELTATHRFORADAPT2PASS_4K 5
62 #define VDENC_AVC_BRC_BOTQPDELTATHRFORADAPT2PASS_4K 5
63 #define VDENC_AVC_BRC_TOPFRMSZTHRFORADAPT2PASS_4K   80
64 #define VDENC_AVC_BRC_BOTFRMSZTHRFORADAPT2PASS_4K   80
65 
66 // VDEnc BRC Flag in BRC Init Kernel
67 typedef enum _BRCFLAG
68 {
69     BRCFLAG_ISICQ                        = 0x0000,
70     BRCFLAG_ISCBR                        = 0x0010,
71     BRCFLAG_ISVBR                        = 0x0020,
72     BRCFLAG_ISVCM                        = 0x0040,
73     BRCFLAG_ISLOWDELAY                   = 0x0080
74 } BRCFLAG;
75 
AvcEncodeBRC(MediaFeatureManager * featureManager,EncodeAllocator * allocator,CodechalHwInterfaceNext * hwInterface,void * constSettings)76 AvcEncodeBRC::AvcEncodeBRC(
77     MediaFeatureManager *featureManager,
78     EncodeAllocator *allocator,
79     CodechalHwInterfaceNext *hwInterface,
80     void *constSettings) :
81     MediaFeature(constSettings, hwInterface ? hwInterface->GetOsInterface() : nullptr),
82     m_hwInterface(hwInterface),
83     m_allocator(allocator)
84 {
85     m_featureManager = featureManager;
86     //TODO: can be optimized after move encode parameter to feature manager.
87     auto encFeatureManager = dynamic_cast<EncodeAvcVdencFeatureManager*>(featureManager);
88     ENCODE_CHK_NULL_NO_STATUS_RETURN(encFeatureManager);
89 
90     m_basicFeature = dynamic_cast<AvcBasicFeature *>(encFeatureManager->GetFeature(FeatureIDs::basicFeature));
91     ENCODE_CHK_NULL_NO_STATUS_RETURN(m_basicFeature);
92 
93     ENCODE_CHK_NULL_NO_STATUS_RETURN(m_hwInterface);
94     m_vdencItf = std::static_pointer_cast<mhw::vdbox::vdenc::Itf>(m_hwInterface->GetVdencInterfaceNext());
95     m_mfxItf   = std::static_pointer_cast<mhw::vdbox::mfx::Itf>(m_hwInterface->GetMfxInterfaceNext());
96     m_miItf    = std::static_pointer_cast<mhw::mi::Itf>(m_hwInterface->GetMiInterfaceNext());
97 }
98 
~AvcEncodeBRC()99 AvcEncodeBRC::~AvcEncodeBRC()
100 {
101     FreeBrcResources();
102 }
103 
Init(void * setting)104 MOS_STATUS AvcEncodeBRC::Init(void *setting)
105 {
106     ENCODE_FUNC_CALL();
107 
108     MediaUserSetting::Value outValue;
109     ReadUserSetting(
110         m_userSettingPtr,
111         outValue,
112         "AVC Encode MB BRC",
113         MediaUserSetting::Group::Sequence);
114 
115     int32_t val                  = outValue.Get<int32_t>();
116     if ((val == 0) || (val == 1))
117     {
118         m_mbBrcUserFeatureKeyControl = true;
119         m_mbBrcEnabled               =  val ? true : false;
120     }
121 
122     outValue = 0;
123 
124     ReadUserSetting(
125         m_userSettingPtr,
126         outValue,
127         "VDEnc Single Pass Enable",
128         MediaUserSetting::Group::Sequence);
129 
130     m_vdencSinglePassEnable = outValue.Get<int32_t>() == 1;
131 
132 #if (_DEBUG || _RELEASE_INTERNAL)
133     auto statusKey = ReadUserSettingForDebug(
134         m_userSettingPtr,
135         outValue,
136         "Lpla TargetBufferFulness Data Address",
137         MediaUserSetting::Group::Sequence);
138     const char             *path_buffer = outValue.ConstString().c_str();
139 
140     if (statusKey == MOS_STATUS_SUCCESS && strcmp(path_buffer, "") != 0)
141         m_useBufferFulnessData = true;
142 
143     if (m_useBufferFulnessData)
144     {
145         std::ifstream fp(path_buffer);
146         if (!fp.is_open())
147         {
148             m_useBufferFulnessData = false;
149             ENCODE_ASSERTMESSAGE("lpla targetBufferFulness data load failed!");
150         }
151         int         cnt  = 0;
152         std::string line = "";
153         while (getline(fp, line))
154         {
155             m_bufferFulnessData_csv[cnt++] = atoi(line.c_str());
156         }
157     }
158 #endif
159 
160     ENCODE_CHK_STATUS_RETURN(AllocateResources());
161 
162     return MOS_STATUS_SUCCESS;
163 }
164 
Update(void * params)165 MOS_STATUS AvcEncodeBRC::Update(void *params)
166 {
167     ENCODE_FUNC_CALL();
168     ENCODE_CHK_NULL_RETURN(params);
169 
170     EncoderParams *encodeParams = (EncoderParams *)params;
171 
172     ENCODE_CHK_STATUS_RETURN(SetSequenceStructs());
173 
174     if (m_basicFeature->m_seqParam->RateControlMethod == RATECONTROL_VCM && m_basicFeature->m_pictureCodingType == B_TYPE)
175     {
176         ENCODE_ASSERTMESSAGE("VCM BRC mode does not support B-frames\n");
177         return MOS_STATUS_INVALID_PARAMETER;
178     }
179 
180     if (m_basicFeature->m_seqParam->RateControlMethod == RATECONTROL_VCM &&
181         (m_basicFeature->m_picParam->FieldCodingFlag || m_basicFeature->m_picParam->FieldFrameCodingFlag))
182     {
183         ENCODE_ASSERTMESSAGE("VCM BRC mode does not support interlaced\n");
184         return MOS_STATUS_INVALID_PARAMETER;
185     }
186 
187 #if (_DEBUG || _RELEASE_INTERNAL)
188     ReportUserSettingForDebug(
189         m_userSettingPtr,
190         "Encode RateControl Method",
191         m_rcMode,
192         MediaUserSetting::Group::Sequence);
193 #endif
194     return MOS_STATUS_SUCCESS;
195 }
196 
AllocateResources()197 MOS_STATUS AvcEncodeBRC::AllocateResources()
198 {
199     ENCODE_FUNC_CALL();
200 
201     ENCODE_CHK_NULL_RETURN(m_allocator);
202     ENCODE_CHK_NULL_RETURN(m_basicFeature);
203     ENCODE_CHK_NULL_RETURN(m_basicFeature->m_recycleBuf);
204     ENCODE_CHK_NULL_RETURN(m_hwInterface);
205     ENCODE_CHK_NULL_RETURN(m_hwInterface->GetOsInterface());
206 
207     auto setting = static_cast<AvcVdencFeatureSettings *>(m_constSettings);
208     ENCODE_CHK_NULL_RETURN(setting);
209 
210     auto brcSettings = setting->brcSettings;
211 
212     MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
213     MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
214     allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
215     allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
216     allocParamsForBufferLinear.Format = Format_Buffer;
217 
218     // VDENC Statistics buffer
219     allocParamsForBufferLinear.dwBytes  = MOS_ALIGN_CEIL(brcSettings.vdencBrcStatsBufferSize, CODECHAL_PAGE_SIZE);
220     allocParamsForBufferLinear.pBufName = "VDENC BRC Statistics Buffer";
221     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_WRITE;
222     ENCODE_CHK_STATUS_RETURN(m_basicFeature->m_recycleBuf->RegisterResource(VdencStatsBuffer, allocParamsForBufferLinear, 1));
223 
224     // VDENC BRC PAK MMIO buffer
225     allocParamsForBufferLinear.dwBytes = sizeof(VdencBrcPakMmio);
226     allocParamsForBufferLinear.pBufName = "VDENC BRC PAK MMIO Buffer";
227     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
228     ENCODE_CHK_STATUS_RETURN(m_basicFeature->m_recycleBuf->RegisterResource(VdencBrcPakMmioBuffer, allocParamsForBufferLinear, 1));
229 
230     // Debug buffer
231     allocParamsForBufferLinear.dwBytes  = MOS_ALIGN_CEIL(brcSettings.vdencBrcDbgBufferSize, CODECHAL_PAGE_SIZE);
232     allocParamsForBufferLinear.pBufName = "VDENC BRC Debug Buffer";
233     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
234     ENCODE_CHK_STATUS_RETURN(m_basicFeature->m_recycleBuf->RegisterResource(VdencBrcDebugBuffer, allocParamsForBufferLinear, 1));
235 
236     // BRC history buffer
237     allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(brcSettings.vdencBrcHistoryBufferSize, CODECHAL_PAGE_SIZE);
238     allocParamsForBufferLinear.pBufName = "VDENC BRC History Buffer";
239     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
240     ENCODE_CHK_STATUS_RETURN(m_basicFeature->m_recycleBuf->RegisterResource(VdencBRCHistoryBuffer, allocParamsForBufferLinear, 1));
241 
242     // VDENC uses second level batch buffer for image state cmds
243     MOS_ZeroMemory(&m_batchBufferForVdencImgStat, sizeof(MHW_BATCH_BUFFER));
244     m_batchBufferForVdencImgStat.bSecondLevel = true;
245     ENCODE_CHK_STATUS_RETURN(Mhw_AllocateBb(
246         m_hwInterface->GetOsInterface(),
247         &m_batchBufferForVdencImgStat,
248         nullptr,
249         GetVdencBRCImgStateBufferSize()));
250 
251     return MOS_STATUS_SUCCESS;
252 }
253 
SetDmemForInit(void * params)254 MOS_STATUS AvcEncodeBRC::SetDmemForInit(void *params)
255 {
256     ENCODE_FUNC_CALL();
257 
258     ENCODE_CHK_NULL_RETURN(params);
259     auto hucVdencBrcInitDmem =(VdencAvcHucBrcInitDmem*)params;
260     static_assert(sizeof(VdencAvcHucBrcInitDmem) == 192, "VdencAvcHucBrcInitDmem size MUST be equal to 192");
261 
262     auto setting = static_cast<AvcVdencFeatureSettings *>(m_constSettings);
263     ENCODE_CHK_NULL_RETURN(setting);
264 
265     auto brcSettings  = setting->brcSettings;
266     auto avcSeqParams = m_basicFeature->m_seqParam;
267     auto avcPicParams = m_basicFeature->m_picParam;
268 
269     if (avcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_EXTREMELY_LOW) // Low Delay Mode
270     {
271         avcSeqParams->MaxBitRate = avcSeqParams->TargetBitRate;
272     }
273 
274     m_dBrcInitResetInputBitsPerFrame     = avcSeqParams->MaxBitRate * 100.0 / avcSeqParams->FramesPer100Sec;
275     m_dBrcInitCurrentTargetBufFullInBits = m_dBrcInitResetInputBitsPerFrame;
276     m_dBrcTargetSize                     = avcSeqParams->InitVBVBufferFullnessInBit;
277 
278     hucVdencBrcInitDmem->BRCFunc_U8 = m_brcInit ? 0 : 2;  // 0 for init, 2 for reset
279 
280     hucVdencBrcInitDmem->INIT_FrameWidth_U16  = (uint16_t)m_basicFeature->m_frameWidth;
281     hucVdencBrcInitDmem->INIT_FrameHeight_U16 = (uint16_t)m_basicFeature->m_frameHeight;
282 
283     hucVdencBrcInitDmem->INIT_TargetBitrate_U32 = avcSeqParams->TargetBitRate;
284     hucVdencBrcInitDmem->INIT_MinRate_U32 = avcSeqParams->MinBitRate;
285     hucVdencBrcInitDmem->INIT_MaxRate_U32 = avcSeqParams->MaxBitRate;
286     hucVdencBrcInitDmem->INIT_BufSize_U32 = avcSeqParams->VBVBufferSizeInBit;
287     hucVdencBrcInitDmem->INIT_InitBufFull_U32 = avcSeqParams->InitVBVBufferFullnessInBit;
288 
289     if (hucVdencBrcInitDmem->INIT_InitBufFull_U32 > avcSeqParams->VBVBufferSizeInBit)
290         hucVdencBrcInitDmem->INIT_InitBufFull_U32 = avcSeqParams->VBVBufferSizeInBit;
291 
292     switch (avcSeqParams->RateControlMethod)
293     {
294     case RATECONTROL_CBR:
295         hucVdencBrcInitDmem->INIT_BRCFlag_U16 |= BRCFLAG_ISCBR;
296         break;
297     case RATECONTROL_VBR:
298         hucVdencBrcInitDmem->INIT_BRCFlag_U16 |= BRCFLAG_ISVBR;
299         break;
300     case RATECONTROL_QVBR:
301         // QVBR will use VBR BRCFlag, triggered when ICQQualityFactor > 10
302         hucVdencBrcInitDmem->INIT_BRCFlag_U16 |= BRCFLAG_ISVBR;
303         break;
304         // Temp solution using AVBR for low delay case, before the BRC flag is added to DDI
305     case RATECONTROL_AVBR:
306         hucVdencBrcInitDmem->INIT_BRCFlag_U16 |= BRCFLAG_ISLOWDELAY;
307         break;
308     case RATECONTROL_ICQ:
309         hucVdencBrcInitDmem->INIT_BRCFlag_U16 |= BRCFLAG_ISICQ;
310         break;
311     case RATECONTROL_VCM:
312         hucVdencBrcInitDmem->INIT_BRCFlag_U16 |= BRCFLAG_ISVCM;
313         break;
314     default:
315         break;
316     }
317 
318     if (avcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_EXTREMELY_LOW) // Low Delay Mode
319     {
320         hucVdencBrcInitDmem->INIT_BRCFlag_U16 = BRCFLAG_ISLOWDELAY;
321         hucVdencBrcInitDmem->INIT_LowDelayGoldenFrameBoost_U8 = 0; //get from ?
322     }
323 
324     hucVdencBrcInitDmem->INIT_FrameRateM_U32 = avcSeqParams->FramesPer100Sec;
325     hucVdencBrcInitDmem->INIT_FrameRateD_U32 = 100;
326 
327     hucVdencBrcInitDmem->INIT_ProfileLevelMaxFrame_U32 = m_basicFeature->GetProfileLevelMaxFrameSize();
328 
329     if (avcSeqParams->GopRefDist && (avcSeqParams->GopPicSize > 0))
330     {
331         uint16_t intraPeriod               = avcSeqParams->GopPicSize - 1;
332         if (intraPeriod % avcSeqParams->GopRefDist != 0)
333         {
334             // Implement original cmodel behavior: use only complete Gop (for intraPeriod=6, GopRefDist=4 => intraPeriod must be 4)
335             intraPeriod -= intraPeriod % avcSeqParams->GopRefDist;
336         }
337 
338         hucVdencBrcInitDmem->INIT_GopP_U16 = intraPeriod / avcSeqParams->GopRefDist;
339         hucVdencBrcInitDmem->INIT_GopB_U16 = (avcSeqParams->GopRefDist - 1) * hucVdencBrcInitDmem->INIT_GopP_U16;
340 
341         if (avcSeqParams->GopRefDist >= avcSeqParams->GopPicSize && avcSeqParams->GopPicSize > 1)
342         {
343             hucVdencBrcInitDmem->INIT_ExtGopP_U16 = 1;
344             hucVdencBrcInitDmem->INIT_ExtGopB_U16 = avcSeqParams->GopPicSize - 2;
345         }
346         else if (IsBPyramidWithGoldenBGOP()) // For now AVC support only GOP4 and GOP8 golden gops
347         {
348             auto    dmem     = hucVdencBrcInitDmem;
349             uint8_t BGopSize = (uint8_t)avcSeqParams->GopRefDist;
350 
351             dmem->INIT_ExtGopP_U16 = (uint16_t)(intraPeriod / BGopSize);
352             dmem->INIT_ExtGopB_U16 = BGopSize > 1 ? (uint16_t)dmem->INIT_ExtGopP_U16 : 0;
353 
354             uint16_t gopB1Multiplicator = (BGopSize > 2 ? 1 : 0) +
355                                           (BGopSize == 4 || BGopSize > 5 ? 1 : 0);
356             uint16_t gopB2Multiplicator = (BGopSize > 3 ? 1 : 0);
357 
358             dmem->INIT_ExtGopB1_U16      = dmem->INIT_ExtGopP_U16 * gopB1Multiplicator;
359             dmem->INIT_ExtGopB2_U16      = (intraPeriod - dmem->INIT_ExtGopP_U16 - dmem->INIT_ExtGopB_U16 - dmem->INIT_ExtGopB1_U16) * gopB2Multiplicator;
360             dmem->INIT_ExtMaxBrcLevel_U8 = dmem->INIT_ExtGopB1_U16 == 0 ? 2 :
361                                           (dmem->INIT_ExtGopB2_U16 == 0 ? AvcBrcFrameType::B1_FRAME : AvcBrcFrameType::B2_FRAME);
362             ENCODE_CHK_COND_RETURN(BGopSize != (1 << (dmem->INIT_ExtMaxBrcLevel_U8 - 1)),
363                 "'BGopSize' (GopRefDist) must be equal '1 << (dmem->INIT_MaxBrcLevel_U16 - 1)'");
364         }
365         else
366         {
367             hucVdencBrcInitDmem->INIT_ExtGopP_U16 = hucVdencBrcInitDmem->INIT_GopP_U16;
368             hucVdencBrcInitDmem->INIT_ExtGopB_U16 = hucVdencBrcInitDmem->INIT_GopB_U16;
369 
370             hucVdencBrcInitDmem->INIT_ExtGopB1_U16 = hucVdencBrcInitDmem->INIT_ExtGopB2_U16 = hucVdencBrcInitDmem->INIT_ExtMaxBrcLevel_U8 = 0;
371         }
372     }
373 
374     if (m_basicFeature->m_minMaxQpControlEnabled)
375     {
376         hucVdencBrcInitDmem->INIT_MinQP_U16 = m_basicFeature->m_iMinQp;
377         hucVdencBrcInitDmem->INIT_MaxQP_U16 = m_basicFeature->m_iMaxQp;
378     }
379     else
380     {
381         hucVdencBrcInitDmem->INIT_MinQP_U16 = VDENC_AVC_BRC_MIN_QP;     // Setting values from arch spec
382         hucVdencBrcInitDmem->INIT_MaxQP_U16 = CODECHAL_ENCODE_AVC_MAX_SLICE_QP;  // Setting values from arch spec
383     }
384 
385                                                                              //dynamic deviation thresholds
386     double inputBitsPerFrame = avcSeqParams->MaxBitRate * 100.0 / avcSeqParams->FramesPer100Sec;
387     double bps_ratio = inputBitsPerFrame / (avcSeqParams->VBVBufferSizeInBit * 100.0 / avcSeqParams->FramesPer100Sec/*DEV_STD_FPS*/);
388     if (bps_ratio < VDENC_AVC_BPS_RATIO_LOW) bps_ratio = VDENC_AVC_BPS_RATIO_LOW;
389     if (bps_ratio > VDENC_AVC_BPS_RATIO_HIGH) bps_ratio = VDENC_AVC_BPS_RATIO_HIGH;
390 
391     if (avcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_EXTREMELY_LOW) // Low Delay Mode
392     {
393         MOS_SecureMemcpy(hucVdencBrcInitDmem->INIT_DevThreshPB0_S8, 8 * sizeof(int8_t),
394                          brcSettings.BRC_LowDelay_DevThreshPB0_S8, 8 * sizeof(int8_t));
395         MOS_SecureMemcpy(hucVdencBrcInitDmem->INIT_DevThreshI0_S8, 8 * sizeof(int8_t),
396                          brcSettings.BRC_LowDelay_DevThreshI0_S8, 8 * sizeof(int8_t));
397         MOS_SecureMemcpy(hucVdencBrcInitDmem->INIT_DevThreshVBR0_S8, 8 * sizeof(int8_t),
398                          brcSettings.BRC_LowDelay_DevThreshVBR0_S8, 8 * sizeof(int8_t));
399     }
400     else
401     {
402         //dynamic deviation thresholds
403         for (int i = 0; i < AvcVdencBrcConstSettings::m_numDevThreshlds / 2; i++)
404         {
405             hucVdencBrcInitDmem->INIT_DevThreshPB0_S8[i] =
406                 (int8_t)(VDENC_AVC_NEG_MULT_PB * pow(brcSettings.BRC_DevThreshPB0_FP_NEG[i], bps_ratio));
407             hucVdencBrcInitDmem->INIT_DevThreshPB0_S8[i + AvcVdencBrcConstSettings::m_numDevThreshlds / 2] =
408                 (int8_t)(VDENC_AVC_POS_MULT_PB * pow(brcSettings.BRC_DevThreshPB0_FP_POS[i], bps_ratio));
409 
410             hucVdencBrcInitDmem->INIT_DevThreshI0_S8[i] =
411                 (int8_t)(VDENC_AVC_NEG_MULT_I * pow(brcSettings.BRC_DevThreshI0_FP_NEG[i], bps_ratio));
412             hucVdencBrcInitDmem->INIT_DevThreshI0_S8[i + AvcVdencBrcConstSettings::m_numDevThreshlds / 2] =
413                 (int8_t)(VDENC_AVC_POS_MULT_I * pow(brcSettings.BRC_DevThreshI0_FP_POS[i], bps_ratio));
414 
415             hucVdencBrcInitDmem->INIT_DevThreshVBR0_S8[i] =
416                 (int8_t)(VDENC_AVC_NEG_MULT_VBR * pow(brcSettings.BRC_DevThreshVBR0_NEG[i], bps_ratio));
417             hucVdencBrcInitDmem->INIT_DevThreshVBR0_S8[i + AvcVdencBrcConstSettings::m_numDevThreshlds / 2] =
418                 (int8_t)(VDENC_AVC_POS_MULT_VBR * pow(brcSettings.BRC_DevThreshVBR0_POS[i], bps_ratio));
419         }
420     }
421 
422     hucVdencBrcInitDmem->INIT_InitQPIP = (uint8_t)ComputeBRCInitQP();
423 
424     // MBBRC control
425     if (m_mbBrcEnabled)
426     {
427         hucVdencBrcInitDmem->INIT_MbQpCtrl_U8 = 1;
428         MOS_SecureMemcpy(hucVdencBrcInitDmem->INIT_DistQPDelta_I8, 4 * sizeof(int8_t),
429                          brcSettings.BRC_INIT_DistQPDelta_I8, 4 * sizeof(int8_t));
430     }
431 
432     hucVdencBrcInitDmem->INIT_SliceSizeCtrlEn_U8 = avcSeqParams->EnableSliceLevelRateCtrl; // Enable slice size control
433 
434     hucVdencBrcInitDmem->INIT_OscillationQpDelta_U8 =
435         ((avcSeqParams->RateControlMethod == RATECONTROL_VCM) || (avcSeqParams->RateControlMethod == RATECONTROL_QVBR)) ? 16 : 0;
436     hucVdencBrcInitDmem->INIT_HRDConformanceCheckDisable_U8 =
437         ((avcSeqParams->RateControlMethod == RATECONTROL_VCM) || (avcSeqParams->RateControlMethod == RATECONTROL_AVBR)) ? 1 : 0;
438 
439     // Adaptive 2nd re-encode pass
440     if (m_basicFeature->m_picWidthInMb * m_basicFeature->m_picHeightInMb >= ((3840 * 2160) >> 8)) // >= 4K
441     {
442         hucVdencBrcInitDmem->INIT_TopQPDeltaThrForAdapt2Pass_U8 = VDENC_AVC_BRC_TOPQPDELTATHRFORADAPT2PASS_4K;
443         hucVdencBrcInitDmem->INIT_BotQPDeltaThrForAdapt2Pass_U8 = VDENC_AVC_BRC_BOTQPDELTATHRFORADAPT2PASS_4K;
444         hucVdencBrcInitDmem->INIT_TopFrmSzThrForAdapt2Pass_U8 = VDENC_AVC_BRC_TOPFRMSZTHRFORADAPT2PASS_4K;
445         hucVdencBrcInitDmem->INIT_BotFrmSzThrForAdapt2Pass_U8 = VDENC_AVC_BRC_BOTFRMSZTHRFORADAPT2PASS_4K;
446     }
447     else
448     {
449         if (avcSeqParams->RateControlMethod == RATECONTROL_AVBR)
450         {
451             hucVdencBrcInitDmem->INIT_TopQPDeltaThrForAdapt2Pass_U8 = VDENC_AVC_AVBR_TOPQPDELTATHRFORADAPT2PASS;
452             hucVdencBrcInitDmem->INIT_BotQPDeltaThrForAdapt2Pass_U8 = VDENC_AVC_AVBR_BOTQPDELTATHRFORADAPT2PASS;
453             hucVdencBrcInitDmem->INIT_TopFrmSzThrForAdapt2Pass_U8 = VDENC_AVC_AVBR_TOPFRMSZTHRFORADAPT2PASS;
454             hucVdencBrcInitDmem->INIT_BotFrmSzThrForAdapt2Pass_U8 = VDENC_AVC_AVBR_BOTFRMSZTHRFORADAPT2PASS;
455         }
456         else
457         {
458             hucVdencBrcInitDmem->INIT_TopQPDeltaThrForAdapt2Pass_U8 = VDENC_AVC_BRC_TOPQPDELTATHRFORADAPT2PASS;
459             hucVdencBrcInitDmem->INIT_BotQPDeltaThrForAdapt2Pass_U8 = VDENC_AVC_BRC_BOTQPDELTATHRFORADAPT2PASS;
460             hucVdencBrcInitDmem->INIT_TopFrmSzThrForAdapt2Pass_U8 = VDENC_AVC_BRC_TOPFRMSZTHRFORADAPT2PASS;
461             hucVdencBrcInitDmem->INIT_BotFrmSzThrForAdapt2Pass_U8 = VDENC_AVC_BRC_BOTFRMSZTHRFORADAPT2PASS;
462         }
463     }
464 
465     hucVdencBrcInitDmem->INIT_QPSelectForFirstPass_U8 = 1;
466     hucVdencBrcInitDmem->INIT_MBHeaderCompensation_U8 = 1;
467     hucVdencBrcInitDmem->INIT_DeltaQP_Adaptation_U8 = 1;
468     hucVdencBrcInitDmem->INIT_MaxCRFQualityFactor_U8 = CODECHAL_ENCODE_AVC_MAX_ICQ_QUALITYFACTOR + 1;
469 
470     if (RATECONTROL_QVBR == avcSeqParams->RateControlMethod || RATECONTROL_ICQ == avcSeqParams->RateControlMethod)
471     {
472         hucVdencBrcInitDmem->INIT_CRFQualityFactor_U8 = (uint8_t)avcSeqParams->ICQQualityFactor;
473         hucVdencBrcInitDmem->INIT_ScenarioInfo_U8 = (RATECONTROL_QVBR == avcSeqParams->RateControlMethod) ? 1 : 0;
474     }
475 
476     if (m_basicFeature->m_picParam->NumDirtyROI)
477     {
478         hucVdencBrcInitDmem->INIT_ScenarioInfo_U8 = 1; //DISPLAYREMOTING
479     }
480 
481     if (avcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_LOW) // Sliding Window BRC
482     {
483         hucVdencBrcInitDmem->INIT_SlidingWidowRCEnable_U8 = 1;
484         if (avcSeqParams->RateControlMethod == RATECONTROL_CBR && avcSeqParams->TargetBitRate != 0)
485         {
486             hucVdencBrcInitDmem->INIT_SlidingWindowSize_U8         = MOS_MIN((uint8_t)avcSeqParams->SlidingWindowSize, 60);
487             hucVdencBrcInitDmem->INIT_SlidingWindowMaxRateRatio_U8 = (uint8_t)((uint64_t)avcSeqParams->MaxBitRatePerSlidingWindow * 100 / avcSeqParams->TargetBitRate);
488         }
489         else
490         {
491             hucVdencBrcInitDmem->INIT_SlidingWindowSize_U8         = (uint8_t)(avcSeqParams->FramesPer100Sec / 100);
492             hucVdencBrcInitDmem->INIT_SlidingWindowMaxRateRatio_U8 = 120;
493         }
494     }
495 
496     MOS_SecureMemcpy(hucVdencBrcInitDmem->INIT_EstRateThreshP0_U8, 7 * sizeof(uint8_t),
497                      brcSettings.BRC_EstRateThreshP0_U8, 7 * sizeof(uint8_t));
498     MOS_SecureMemcpy(hucVdencBrcInitDmem->INIT_EstRateThreshI0_U8, 7 * sizeof(uint8_t),
499                      brcSettings.BRC_EstRateThreshI0_U8, 7 * sizeof(uint8_t));
500 
501     // fractional QP enable for extended rho domain
502     hucVdencBrcInitDmem->INIT_FracQPEnable_U8 = (uint8_t)m_vdencItf->IsRhoDomainStatsEnabled();
503 
504     // force enabling fractional QP and disabling HRD conformance for TCBRC
505     if ((avcPicParams->TargetFrameSize > 0) && (m_basicFeature->m_lookaheadDepth == 0))
506     {
507         hucVdencBrcInitDmem->INIT_FracQPEnable_U8 = 1;
508         hucVdencBrcInitDmem->INIT_HRDConformanceCheckDisable_U8 = 1;
509     }
510 
511     hucVdencBrcInitDmem->INIT_SinglePassOnly = (uint8_t)m_vdencSinglePassEnable;
512 
513     if (avcSeqParams->ScenarioInfo == ESCENARIO_GAMESTREAMING)
514     {
515         if (avcSeqParams->RateControlMethod == RATECONTROL_VBR)
516         {
517             avcSeqParams->MaxBitRate = avcSeqParams->TargetBitRate;
518         }
519 
520         // Disable delta QP adaption for non-VCM/ICQ/LowDelay until we have better algorithm
521         if ((avcSeqParams->RateControlMethod != RATECONTROL_VCM) &&
522             (avcSeqParams->RateControlMethod != RATECONTROL_ICQ) &&
523             (avcSeqParams->FrameSizeTolerance != EFRAMESIZETOL_EXTREMELY_LOW))
524         {
525             hucVdencBrcInitDmem->INIT_DeltaQP_Adaptation_U8 = 0;
526         }
527 
528         hucVdencBrcInitDmem->INIT_New_DeltaQP_Adaptation_U8 = 1;
529     }
530 
531     if (((avcSeqParams->TargetUsage & 0x07) == TARGETUSAGE_BEST_SPEED) &&
532         (avcSeqParams->FrameWidth >= setting->singlePassMinFrameWidth) &&
533         (avcSeqParams->FrameHeight >= setting->singlePassMinFrameHeight) &&
534         (avcSeqParams->FramesPer100Sec >= setting->singlePassMinFramePer100s))
535     {
536         hucVdencBrcInitDmem->INIT_SinglePassOnly = true;
537     }
538 
539     hucVdencBrcInitDmem->INIT_LookaheadDepth_U8 = m_basicFeature->m_lookaheadDepth;
540 
541     //Override the DistQPDelta setting
542     if (m_mbBrcEnabled)
543     {
544         if (avcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_EXTREMELY_LOW)
545         {
546             MOS_SecureMemcpy(hucVdencBrcInitDmem->INIT_DistQPDelta_I8, 4 * sizeof(int8_t),
547                              brcSettings.brcInitDistQpDeltaI8LowDelay, 4 * sizeof(int8_t));
548         }
549         else
550         {
551             MOS_SecureMemcpy(hucVdencBrcInitDmem->INIT_DistQPDelta_I8, 4 * sizeof(int8_t),
552                              brcSettings.brcInitDistQpDeltaI8, 4 * sizeof(int8_t));
553         }
554     }
555 
556     return MOS_STATUS_SUCCESS;
557 }
558 
SetDmemForUpdate(void * params,uint16_t currPass,bool bIsLastPass)559 MOS_STATUS AvcEncodeBRC::SetDmemForUpdate(void *params, uint16_t currPass, bool bIsLastPass)
560 {
561     ENCODE_FUNC_CALL();
562 
563     ENCODE_CHK_NULL_RETURN(params);
564     auto hucVdencBrcUpdateDmem =(VdencAvcHucBrcUpdateDmem*)params;
565     static_assert(sizeof(VdencAvcHucBrcUpdateDmem) == 448, "VdencAvcHucBrcUpdateDmem size MUST be equal to 448");
566 
567     auto setting = static_cast<AvcVdencFeatureSettings *>(m_constSettings);
568     ENCODE_CHK_NULL_RETURN(setting);
569 
570     auto brcSettings = setting->brcSettings;
571     auto avcSeqParams = m_basicFeature->m_seqParam;
572     auto avcPicParams = m_basicFeature->m_picParam;
573 
574     hucVdencBrcUpdateDmem->BRCFunc_U8 = 1;   // Update:1
575 
576     if (!m_brcInit && (currPass == 0))
577     {
578         m_brcInitPreviousTargetBufFullInBits = (uint32_t)(m_dBrcInitCurrentTargetBufFullInBits);
579         m_dBrcInitCurrentTargetBufFullInBits += m_dBrcInitResetInputBitsPerFrame;
580         m_dBrcTargetSize += m_dBrcInitResetInputBitsPerFrame;
581     }
582 
583     if (m_dBrcTargetSize > avcSeqParams->VBVBufferSizeInBit)
584     {
585         m_dBrcTargetSize -= avcSeqParams->VBVBufferSizeInBit;
586     }
587 
588     hucVdencBrcUpdateDmem->UPD_FRAMENUM_U32           = m_basicFeature->m_frameNum;
589     hucVdencBrcUpdateDmem->UPD_TARGETSIZE_U32         = (uint32_t)(m_dBrcTargetSize);
590     hucVdencBrcUpdateDmem->UPD_PeakTxBitsPerFrame_U32 = (uint32_t)(m_dBrcInitCurrentTargetBufFullInBits - m_brcInitPreviousTargetBufFullInBits);
591 
592     //Dynamic slice size control
593     if (avcSeqParams->EnableSliceLevelRateCtrl)
594     {
595         hucVdencBrcUpdateDmem->UPD_SLCSZ_TARGETSLCSZ_U16 = (uint16_t)avcPicParams->SliceSizeInBytes; // target slice size
596         hucVdencBrcUpdateDmem->UPD_TargetSliceSize_U16 = (uint16_t)avcPicParams->SliceSizeInBytes; // set max slice size to be same as target slice size
597         hucVdencBrcUpdateDmem->UPD_MaxNumSliceAllowed_U16 = (uint16_t)m_basicFeature->m_maxNumSlicesAllowed;
598 
599         for (uint8_t k = 0; k < 42; k++)
600         {
601             hucVdencBrcUpdateDmem->UPD_SLCSZ_UPD_THRDELTAI_U16[k] = MOS_MIN(avcPicParams->SliceSizeInBytes - 150, setting->SliceSizeThrsholdsI[k + 10]);
602             hucVdencBrcUpdateDmem->UPD_SLCSZ_UPD_THRDELTAP_U16[k] = MOS_MIN(avcPicParams->SliceSizeInBytes - 150, setting->SliceSizeThrsholdsP[k + 10]);
603         }
604     }
605     else
606     {
607         hucVdencBrcUpdateDmem->UPD_SLCSZ_TARGETSLCSZ_U16 = 0;
608         hucVdencBrcUpdateDmem->UPD_TargetSliceSize_U16 = 0;
609         hucVdencBrcUpdateDmem->UPD_MaxNumSliceAllowed_U16 = 0;
610 
611         for (uint8_t k = 0; k < 42; k++)
612         {
613             hucVdencBrcUpdateDmem->UPD_SLCSZ_UPD_THRDELTAI_U16[k] = 0;
614             hucVdencBrcUpdateDmem->UPD_SLCSZ_UPD_THRDELTAP_U16[k] = 0;
615         }
616     }
617 
618     if (avcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_LOW) // Sliding Window BRC
619     {
620         MOS_SecureMemcpy(hucVdencBrcUpdateDmem->UPD_gRateRatioThreshold_U8, 7 * sizeof(uint8_t),
621                          brcSettings.BRC_UPD_slwin_global_rate_ratio_threshold, 7 * sizeof(uint8_t));
622     }
623     else
624     {
625         MOS_SecureMemcpy(hucVdencBrcUpdateDmem->UPD_gRateRatioThreshold_U8, 7 * sizeof(uint8_t),
626                          brcSettings.BRC_UPD_global_rate_ratio_threshold, 7 * sizeof(uint8_t));
627     }
628 
629     SetFrameTypeForUpdate(hucVdencBrcUpdateDmem, currPass);
630 
631     MOS_SecureMemcpy(hucVdencBrcUpdateDmem->UPD_startGAdjFrame_U16, 4 * sizeof(uint16_t),
632                      brcSettings.BRC_UPD_start_global_adjust_frame, 4 * sizeof(uint16_t));
633     MOS_SecureMemcpy(hucVdencBrcUpdateDmem->UPD_startGAdjMult_U8, 5 * sizeof(uint8_t),
634                      brcSettings.BRC_UPD_start_global_adjust_mult, 5 * sizeof(uint8_t));
635     MOS_SecureMemcpy(hucVdencBrcUpdateDmem->UPD_startGAdjDiv_U8, 5 * sizeof(uint8_t),
636                      brcSettings.BRC_UPD_start_global_adjust_div, 5 * sizeof(uint8_t));
637     MOS_SecureMemcpy(hucVdencBrcUpdateDmem->UPD_gRateRatioThresholdQP_U8, 8 * sizeof(uint8_t),
638                      brcSettings.BRC_UPD_global_rate_ratio_threshold_qp, 8 * sizeof(uint8_t));
639 
640     hucVdencBrcUpdateDmem->UPD_PAKPassNum_U8 = (uint8_t)currPass;
641     hucVdencBrcUpdateDmem->UPD_MaxNumPass_U8 = m_featureManager->GetNumPass();
642 
643     uint32_t numP = 0;
644     if (avcSeqParams->GopRefDist && (avcSeqParams->GopPicSize > 0))
645     {
646         numP = (avcSeqParams->GopPicSize - 1) / avcSeqParams->GopRefDist;
647     }
648 
649     for (int32_t i = 0; i < 2; i++)
650     {
651         hucVdencBrcUpdateDmem->UPD_SceneChgWidth_U8[i] = (uint8_t)MOS_MIN((numP + 1) / 5, 6);
652     }
653 
654     hucVdencBrcUpdateDmem->UPD_SceneChgDetectEn_U8 = 1;
655     hucVdencBrcUpdateDmem->UPD_SceneChgPrevIntraPctThreshold_U8 = 0x60;
656     hucVdencBrcUpdateDmem->UPD_SceneChgCurIntraPctThreshold_U8 = 0xc0;
657 
658     hucVdencBrcUpdateDmem->UPD_IPAverageCoeff_U8 = (avcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_EXTREMELY_LOW) ? 0 : 0x80;
659 
660     hucVdencBrcUpdateDmem->UPD_CQP_FracQp_U8 = 0;
661 
662     if (avcSeqParams->RateControlMethod == RATECONTROL_ICQ)
663     {
664         hucVdencBrcUpdateDmem->UPD_CQP_QpValue_U8 = 18;   //Cmodel suggested a few values to try: 18,20,26,30
665     }
666     else
667     {
668         hucVdencBrcUpdateDmem->UPD_CQP_QpValue_U8 = 0;
669     }
670 
671     hucVdencBrcUpdateDmem->UPD_HMEDetectionEnable_U8 = 0;
672 
673     if (FRAME_SKIP_NORMAL == m_basicFeature->m_skipFrameFlag)
674     {
675         hucVdencBrcUpdateDmem->UPD_SkipFrameSize_U16      = (uint16_t)avcPicParams->SizeSkipFrames;
676         hucVdencBrcUpdateDmem->UPD_NumOfFramesSkipped_U16 = (uint16_t)avcPicParams->NumSkipFrames;
677     }
678     else
679     {
680         hucVdencBrcUpdateDmem->UPD_SkipFrameSize_U16      = 0;
681         hucVdencBrcUpdateDmem->UPD_NumOfFramesSkipped_U16 = 0;
682     }
683 
684     // HMECost enabled by default in CModel V11738+
685     hucVdencBrcUpdateDmem->UPD_HMECostEnable_U8 = 1;
686 
687     // ROI and static region pct parameters
688     // must be zero if they are not used
689     hucVdencBrcUpdateDmem->UPD_RoiQpViaForceQp_U8 = 0;
690     hucVdencBrcUpdateDmem->UPD_StaticRegionPct_U16 = 0;
691     hucVdencBrcUpdateDmem->UPD_ROISource_U8 = 0;
692     if (avcPicParams->NumROI)
693     {
694         ENCODE_CHK_COND_RETURN(avcPicParams->NumROIDistinctDeltaQp > sizeof(hucVdencBrcUpdateDmem->UPD_ROIQpDelta_I8) - 1, "Number of ROI is greater that dmem roi array size");
695 
696         hucVdencBrcUpdateDmem->UPD_RoiQpViaForceQp_U8 = avcPicParams->bNativeROI ? 0 : 1;
697         for (uint8_t i = 0; i < avcPicParams->NumROIDistinctDeltaQp; i++)
698         {
699             hucVdencBrcUpdateDmem->UPD_ROIQpDelta_I8[i + 1] = avcPicParams->ROIDistinctDeltaQp[i];
700         }
701     }
702     else if (avcPicParams->NumDirtyROI)
703     {
704         //hucVdencBrcUpdateDmem->UPD_StaticRegionPct_U16 = (uint16_t)m_vdencStaticRegionPct;
705         if (m_mbBrcEnabled)
706         {
707             hucVdencBrcUpdateDmem->UPD_ROISource_U8 = 2;
708         }
709     }
710 
711     hucVdencBrcUpdateDmem->UPD_SLBB_Size_U16 = (uint16_t)MOS_ALIGN_CEIL(m_hwInterface->m_vdencBrcImgStateBufferSize, CODECHAL_CACHELINE_SIZE);
712 
713     hucVdencBrcUpdateDmem->UPD_WidthInMB_U16  = m_basicFeature->m_picWidthInMb;
714     hucVdencBrcUpdateDmem->UPD_HeightInMB_U16 = m_basicFeature->m_picHeightInMb;
715 
716     hucVdencBrcUpdateDmem->MOTION_ADAPTIVE_G4 = (avcSeqParams->ScenarioInfo == ESCENARIO_GAMESTREAMING) || ((avcPicParams->TargetFrameSize > 0) && (m_basicFeature->m_lookaheadDepth == 0));  // GS or TCBRC
717     hucVdencBrcUpdateDmem->UPD_CQMEnabled_U8  = avcSeqParams->seq_scaling_matrix_present_flag || avcPicParams->pic_scaling_matrix_present_flag;
718 
719     hucVdencBrcUpdateDmem->UPD_LA_TargetSize_U32    = avcPicParams->TargetFrameSize << 3;
720     hucVdencBrcUpdateDmem->UPD_TCBRC_SCENARIO_U8    = 0;  // Temporal fix because of DDI flag deprication. Use Cloud Gaming mode by default
721     hucVdencBrcUpdateDmem->UPD_NumSlicesForRounding = GetAdaptiveRoundingNumSlices();
722     hucVdencBrcUpdateDmem->UPD_UserMaxFramePB       = avcSeqParams->UserMaxPBFrameSize;
723 
724     if (avcSeqParams->LookaheadDepth == 0 && avcPicParams->TargetFrameSize > 0 &&
725         (hucVdencBrcUpdateDmem->UPD_TCBRC_SCENARIO_U8 == 2 || avcSeqParams->UserMaxPBFrameSize <= avcPicParams->TargetFrameSize * 2))
726     {
727         if (avcSeqParams->UserMaxPBFrameSize == 0)
728         {
729             hucVdencBrcUpdateDmem->UPD_UserMaxFramePB = 2 * avcPicParams->TargetFrameSize;
730         }
731 
732         uint32_t inputbitsperframe = avcPicParams->TargetFrameSize << 3;
733 
734         if (avcPicParams->CodingType == I_TYPE)
735         {
736             hucVdencBrcUpdateDmem->UPD_LA_TargetSize_U32 = inputbitsperframe + inputbitsperframe / 8;
737         }
738         else if (abs((int)(8 * hucVdencBrcUpdateDmem->UPD_UserMaxFramePB - inputbitsperframe)) <= 8)
739         {
740             hucVdencBrcUpdateDmem->UPD_LA_TargetSize_U32 = inputbitsperframe * 9 / 10;
741         }
742         else
743         {
744             hucVdencBrcUpdateDmem->UPD_LA_TargetSize_U32 = inputbitsperframe;
745         }
746     }
747 
748     if (m_basicFeature->m_lookaheadDepth > 0)
749     {
750         DeltaQPUpdate(avcPicParams->QpModulationStrength, bIsLastPass);
751         hucVdencBrcUpdateDmem->EnableLookAhead          = 1;
752 #if (_DEBUG || _RELEASE_INTERNAL)
753         hucVdencBrcUpdateDmem->UPD_LA_TargetFulness_U32 = m_useBufferFulnessData ? m_bufferFulnessData_csv[m_basicFeature->m_frameNum % m_bufferFulnessDataSize] : m_basicFeature->m_targetBufferFulness;
754 #else
755         hucVdencBrcUpdateDmem->UPD_LA_TargetFulness_U32 = m_basicFeature->m_targetBufferFulness;
756 #endif
757         hucVdencBrcUpdateDmem->UPD_Delta_U8             = m_qpModulationStrength;
758     }
759 
760     return MOS_STATUS_SUCCESS;
761 }
762 
FillHucConstData(uint8_t * data,uint8_t pictureType)763 MOS_STATUS AvcEncodeBRC::FillHucConstData(uint8_t *data, uint8_t pictureType)
764 {
765     auto hucConstData = (VdencAvcHucBrcConstantData*)data;
766 
767     auto setting = static_cast<AvcVdencFeatureSettings *>(m_constSettings);
768     ENCODE_CHK_NULL_RETURN(setting);
769 
770     auto brcSettings = setting->brcSettings;
771     auto avcSeqParams = m_basicFeature->m_seqParam;
772 
773     MOS_SecureMemcpy(hucConstData->UPD_GlobalRateQPAdjTabI_U8, 64 * sizeof(uint8_t),
774                      brcSettings.BRC_UPD_GlobalRateQPAdjTabI_U8, 64 * sizeof(uint8_t));
775     if (avcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_LOW)  // Sliding Window BRC
776     {
777         MOS_SecureMemcpy(hucConstData->UPD_GlobalRateQPAdjTabP_U8, 64 * sizeof(uint8_t),
778                          brcSettings.BRC_UPD_SlWinGlobalRateQPAdjTabP_U8, 64 * sizeof(uint8_t));
779     }
780     else
781     {
782         MOS_SecureMemcpy(hucConstData->UPD_GlobalRateQPAdjTabP_U8, 64 * sizeof(uint8_t),
783                          brcSettings.BRC_UPD_GlobalRateQPAdjTabP_U8, 64 * sizeof(uint8_t));
784     }
785     MOS_SecureMemcpy(hucConstData->UPD_GlobalRateQPAdjTabB_U8, 64 * sizeof(uint8_t),
786                      brcSettings.BRC_UPD_GlobalRateQPAdjTabB_U8, 64 * sizeof(uint8_t));
787 
788     MOS_SecureMemcpy(hucConstData->UPD_DistThreshldI_U8, 10 * sizeof(uint8_t),
789                      brcSettings.BRC_UPD_DistThreshldI_U8, 10 * sizeof(uint8_t));
790     MOS_SecureMemcpy(hucConstData->UPD_DistThreshldP_U8, 10 * sizeof(uint8_t),
791                      brcSettings.BRC_UPD_DistThreshldP_U8, 10 * sizeof(uint8_t));
792     MOS_SecureMemcpy(hucConstData->UPD_DistThreshldB_U8, 10 * sizeof(uint8_t),
793                      brcSettings.BRC_UPD_DistThreshldB_U8, 10 * sizeof(uint8_t));
794 
795     if (avcSeqParams->RateControlMethod == RATECONTROL_CBR)
796     {
797         MOS_SecureMemcpy(hucConstData->UPD_DistQPAdjTabI_U8, 81 * sizeof(uint8_t),
798                          brcSettings.CBR_UPD_DistQPAdjTabI_U8, 81 * sizeof(int8_t));
799         MOS_SecureMemcpy(hucConstData->UPD_DistQPAdjTabP_U8, 81 * sizeof(uint8_t),
800                          brcSettings.CBR_UPD_DistQPAdjTabP_U8, 81 * sizeof(int8_t));
801         MOS_SecureMemcpy(hucConstData->UPD_DistQPAdjTabB_U8, 81 * sizeof(uint8_t),
802                          brcSettings.CBR_UPD_DistQPAdjTabB_U8, 81 * sizeof(int8_t));
803         MOS_SecureMemcpy(hucConstData->UPD_BufRateAdjTabI_S8, 72 * sizeof(uint8_t),
804                          brcSettings.CBR_UPD_FrmSzAdjTabI_S8, 72 * sizeof(int8_t));
805         MOS_SecureMemcpy(hucConstData->UPD_BufRateAdjTabP_S8, 72 * sizeof(uint8_t),
806                          brcSettings.CBR_UPD_FrmSzAdjTabP_S8, 72 * sizeof(int8_t));
807         MOS_SecureMemcpy(hucConstData->UPD_BufRateAdjTabB_S8, 72 * sizeof(uint8_t),
808                          brcSettings.CBR_UPD_FrmSzAdjTabB_S8, 72 * sizeof(int8_t));
809     }
810     else
811     {
812         MOS_SecureMemcpy(hucConstData->UPD_DistQPAdjTabI_U8, 81 * sizeof(uint8_t),
813                          brcSettings.VBR_UPD_DistQPAdjTabI_U8, 81 * sizeof(int8_t));
814         MOS_SecureMemcpy(hucConstData->UPD_DistQPAdjTabP_U8, 81 * sizeof(uint8_t),
815                          brcSettings.VBR_UPD_DistQPAdjTabP_U8, 81 * sizeof(int8_t));
816         MOS_SecureMemcpy(hucConstData->UPD_DistQPAdjTabB_U8, 81 * sizeof(uint8_t),
817                          brcSettings.VBR_UPD_DistQPAdjTabB_U8, 81 * sizeof(int8_t));
818 
819         if (avcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_EXTREMELY_LOW)  // Low Delay Mode
820         {
821             MOS_SecureMemcpy(hucConstData->UPD_BufRateAdjTabI_S8, 72 * sizeof(uint8_t),
822                              brcSettings.LOW_DELAY_UPD_FrmSzAdjTabI_S8, 72 * sizeof(int8_t));
823             MOS_SecureMemcpy(hucConstData->UPD_BufRateAdjTabP_S8, 72 * sizeof(uint8_t),
824                              brcSettings.LOW_DELAY_UPD_FrmSzAdjTabP_S8, 72 * sizeof(int8_t));
825             MOS_SecureMemcpy(hucConstData->UPD_BufRateAdjTabB_S8, 72 * sizeof(uint8_t),
826                              brcSettings.LOW_DELAY_UPD_FrmSzAdjTabB_S8, 72 * sizeof(int8_t));
827         }
828         else
829         {
830             MOS_SecureMemcpy(hucConstData->UPD_BufRateAdjTabI_S8, 72 * sizeof(uint8_t),
831                              brcSettings.VBR_UPD_FrmSzAdjTabI_S8, 72 * sizeof(int8_t));
832 
833             if (avcSeqParams->RateControlMethod == RATECONTROL_QVBR)
834             {
835                 MOS_SecureMemcpy(hucConstData->UPD_BufRateAdjTabP_S8, 72 * sizeof(uint8_t),
836                                  brcSettings.QVBR_UPD_FrmSzAdjTabP_S8, 72 * sizeof(int8_t));
837             }
838             else
839             {
840                 MOS_SecureMemcpy(hucConstData->UPD_BufRateAdjTabP_S8, 72 * sizeof(uint8_t),
841                                  brcSettings.VBR_UPD_FrmSzAdjTabP_S8, 72 * sizeof(int8_t));
842             }
843 
844             MOS_SecureMemcpy(hucConstData->UPD_BufRateAdjTabB_S8, 72 * sizeof(uint8_t),
845                              brcSettings.VBR_UPD_FrmSzAdjTabB_S8, 72 * sizeof(int8_t));
846         }
847     }
848 
849     MOS_SecureMemcpy(hucConstData->UPD_FrmSzMinTabP_U8, 9 * sizeof(uint8_t), brcSettings.BRC_UPD_FrmSzMinTabP_U8, 9 * sizeof(uint8_t));
850     MOS_SecureMemcpy(hucConstData->UPD_FrmSzMinTabI_U8, 9 * sizeof(uint8_t), brcSettings.BRC_UPD_FrmSzMinTabI_U8, 9 * sizeof(uint8_t));
851 
852     MOS_SecureMemcpy(hucConstData->UPD_FrmSzMaxTabP_U8, 9 * sizeof(uint8_t), brcSettings.BRC_UPD_FrmSzMaxTabP_U8, 9 * sizeof(uint8_t));
853     MOS_SecureMemcpy(hucConstData->UPD_FrmSzMaxTabI_U8, 9 * sizeof(uint8_t), brcSettings.BRC_UPD_FrmSzMaxTabI_U8, 9 * sizeof(uint8_t));
854 
855     MOS_SecureMemcpy(hucConstData->UPD_FrmSzSCGTabP_U8, 9 * sizeof(uint8_t), brcSettings.BRC_UPD_FrmSzSCGTabP_U8, 9 * sizeof(uint8_t));
856     MOS_SecureMemcpy(hucConstData->UPD_FrmSzSCGTabI_U8, 9 * sizeof(uint8_t), brcSettings.BRC_UPD_FrmSzSCGTabI_U8, 9 * sizeof(uint8_t));
857 
858     MOS_SecureMemcpy(hucConstData->UPD_I_IntraNonPred, 42 * sizeof(uint8_t), brcSettings.BRC_UPD_I_IntraNonPred, 42 * sizeof(uint8_t));
859     MOS_SecureMemcpy(hucConstData->UPD_I_Intra8x8, 42 * sizeof(uint8_t), brcSettings.BRC_UPD_I_Intra8x8, 42 * sizeof(uint8_t));
860     MOS_SecureMemcpy(hucConstData->UPD_I_Intra4x4, 42 * sizeof(uint8_t), brcSettings.BRC_UPD_I_Intra4x4, 42 * sizeof(uint8_t));
861 
862     MOS_SecureMemcpy(hucConstData->UPD_P_IntraNonPred, 42 * sizeof(uint8_t), brcSettings.BRC_UPD_P_IntraNonPred, 42 * sizeof(uint8_t));
863     MOS_SecureMemcpy(hucConstData->UPD_P_Intra16x16, 42 * sizeof(uint8_t), brcSettings.BRC_UPD_P_Intra16x16, 42 * sizeof(uint8_t));
864     MOS_SecureMemcpy(hucConstData->UPD_P_Intra8x8, 42 * sizeof(uint8_t), brcSettings.BRC_UPD_P_Intra8x8, 42 * sizeof(uint8_t));
865     MOS_SecureMemcpy(hucConstData->UPD_P_Intra4x4, 42 * sizeof(uint8_t), brcSettings.BRC_UPD_P_Intra4x4, 42 * sizeof(uint8_t));
866 
867     MOS_SecureMemcpy(hucConstData->UPD_P_Inter16x8, 42 * sizeof(uint8_t), brcSettings.BRC_UPD_P_Inter16x8, 42 * sizeof(uint8_t));
868     MOS_SecureMemcpy(hucConstData->UPD_P_Inter8x8, 42 * sizeof(uint8_t), brcSettings.BRC_UPD_P_Inter8x8, 42 * sizeof(uint8_t));
869     MOS_SecureMemcpy(hucConstData->UPD_P_Inter16x16, 42 * sizeof(uint8_t), brcSettings.BRC_UPD_P_Inter16x16, 42 * sizeof(uint8_t));
870     MOS_SecureMemcpy(hucConstData->UPD_P_RefId, 42 * sizeof(uint8_t), brcSettings.BRC_UPD_P_RefId, 42 * sizeof(uint8_t));
871 
872     ENCODE_CHK_STATUS_RETURN(LoadConstTable0(hucConstData->VdencAvcHucBrcConstantData_0));
873     ENCODE_CHK_STATUS_RETURN(LoadConstTable3(pictureType, hucConstData->VdencAvcHucBrcConstantData_1));
874     ENCODE_CHK_STATUS_RETURN(LoadConstTable5(pictureType, hucConstData->VdencAvcHucBrcConstantData_2));
875     ENCODE_CHK_STATUS_RETURN(LoadConstTable6(pictureType, hucConstData->VdencAvcHucBrcConstantData_3));
876     ENCODE_CHK_STATUS_RETURN(LoadConstTable7(pictureType, hucConstData->VdencAvcHucBrcConstantData_4));
877     ENCODE_CHK_STATUS_RETURN(LoadConstTable8(pictureType, hucConstData->VdencAvcHucBrcConstantData_5));
878 
879     return MOS_STATUS_SUCCESS;
880 }
881 
SaveBrcUpdateDmemBufferPtr(PMOS_RESOURCE vdencBrcUpdateDmemBuffer0,PMOS_RESOURCE vdencBrcUpdateDmemBuffer1)882 MOS_STATUS AvcEncodeBRC::SaveBrcUpdateDmemBufferPtr(
883     PMOS_RESOURCE vdencBrcUpdateDmemBuffer0,
884     PMOS_RESOURCE vdencBrcUpdateDmemBuffer1)
885 {
886     ENCODE_FUNC_CALL();
887 
888     m_vdencBrcUpdateDmemBufferPtr[0] = vdencBrcUpdateDmemBuffer0;
889     m_vdencBrcUpdateDmemBufferPtr[1] = vdencBrcUpdateDmemBuffer1;
890 
891     return MOS_STATUS_SUCCESS;
892 }
893 
SaveHucStatus2Buffer(PMOS_RESOURCE hucStatus2Buffer)894 MOS_STATUS AvcEncodeBRC::SaveHucStatus2Buffer(PMOS_RESOURCE hucStatus2Buffer)
895 {
896     ENCODE_FUNC_CALL();
897 
898     m_hucStatus2BufferPtr = hucStatus2Buffer;
899 
900     return MOS_STATUS_SUCCESS;
901 }
902 
SetMfcStatusParams(EncodeStatusReadParams & params)903 MOS_STATUS AvcEncodeBRC::SetMfcStatusParams(EncodeStatusReadParams &params)
904 {
905     ENCODE_FUNC_CALL();
906 
907     if (m_vdencBrcEnabled)
908     {
909         params.vdencBrcEnabled                = true;
910         params.vdencBrcNumOfSliceOffset       = CODECHAL_OFFSETOF(VdencAvcHucBrcUpdateDmem, NumOfSlice);
911         params.resVdencBrcUpdateDmemBufferPtr = m_vdencBrcUpdateDmemBufferPtr;
912     }
913 
914     return MOS_STATUS_SUCCESS;
915 }
916 
LoadConstTable0(uint8_t constTable[8][42])917 MOS_STATUS AvcEncodeBRC::LoadConstTable0(uint8_t constTable[8][42])
918 {
919     ENCODE_FUNC_CALL();
920 
921     auto settings = static_cast<AvcVdencFeatureSettings *>(m_featureManager->GetFeatureSettings()->GetConstSettings());
922     ENCODE_CHK_NULL_RETURN(settings);
923 
924     const auto &constTable1 = settings->vdencCMD3Table->AvcVdencCMD3ConstSettings_0;
925 
926     for (auto i = 0; i < 8; i++)
927     {
928         for (auto j = 0; j < 42; j++)
929         {
930             constTable[i][j] = constTable1[i][j + 10];
931         }
932     }
933 
934     return MOS_STATUS_SUCCESS;
935 }
936 
LoadConstTable3(uint8_t pictureType,uint8_t ConstTable3[42])937 MOS_STATUS AvcEncodeBRC::LoadConstTable3(uint8_t pictureType, uint8_t ConstTable3[42])
938 {
939     ENCODE_FUNC_CALL();
940 
941     auto settings = static_cast<AvcVdencFeatureSettings *>(m_featureManager->GetFeatureSettings()->GetConstSettings());
942     ENCODE_CHK_NULL_RETURN(settings);
943 
944     const auto &  table      = settings->vdencCMD3Table->AvcVdencCMD3ConstSettings_3;
945     const uint8_t codingType = pictureType + 1;
946 
947     for (auto i = 0; i < 42; i++)
948     {
949         if (codingType == I_TYPE || codingType == P_TYPE)
950         {
951             ConstTable3[i] = table[pictureType][i + 10];
952         }
953         else  // B and Ref B
954         {
955             ConstTable3[i] = 14;
956         }
957     }
958 
959     return MOS_STATUS_SUCCESS;
960 }
961 
LoadConstTable5(uint8_t pictureType,uint16_t ConstTable5[42])962 MOS_STATUS AvcEncodeBRC::LoadConstTable5(uint8_t pictureType, uint16_t ConstTable5[42])
963 {
964     ENCODE_FUNC_CALL();
965 
966     auto settings = static_cast<AvcVdencFeatureSettings *>(m_featureManager->GetFeatureSettings()->GetConstSettings());
967     ENCODE_CHK_NULL_RETURN(settings);
968 
969     const auto & table = settings->vdencCMD3Table->AvcVdencCMD3ConstSettings_5;
970     uint8_t    isIPGOP = m_basicFeature->m_seqParam->GopRefDist == 1 ? 1 : 0;
971     for (int8_t qp = 10; qp < 52; ++qp)
972     {
973         uint8_t idx        = uint8_t(qp > 12 ? qp - 12 : 0);
974         ConstTable5[qp-10] = table[pictureType][isIPGOP][idx];
975     }
976 
977     return MOS_STATUS_SUCCESS;
978 }
979 
LoadConstTable6(uint8_t pictureType,uint16_t ConstTable6[42])980 MOS_STATUS AvcEncodeBRC::LoadConstTable6(uint8_t pictureType, uint16_t ConstTable6[42])
981 {
982     ENCODE_FUNC_CALL();
983 
984     auto settings = static_cast<AvcVdencFeatureSettings *>(m_featureManager->GetFeatureSettings()->GetConstSettings());
985     ENCODE_CHK_NULL_RETURN(settings);
986 
987     const auto & table = settings->vdencCMD3Table->AvcVdencCMD3ConstSettings_6;
988     uint8_t    isIPGOP = m_basicFeature->m_seqParam->GopRefDist == 1 ? 1 : 0;
989     for (int8_t qp = 10; qp < 52; ++qp)
990     {
991         uint8_t idx        = uint8_t(qp > 12 ? qp - 12 : 0);
992         ConstTable6[qp-10] = table[pictureType][isIPGOP][idx];
993     }
994 
995     return MOS_STATUS_SUCCESS;
996 }
997 
LoadConstTable7(uint8_t pictureType,uint8_t ConstTable7[42])998 MOS_STATUS AvcEncodeBRC::LoadConstTable7(uint8_t pictureType, uint8_t ConstTable7[42])
999 {
1000     ENCODE_FUNC_CALL();
1001 
1002     const uint8_t codingType = pictureType + 1;
1003     if (codingType == I_TYPE)
1004         return MOS_STATUS_SUCCESS;
1005 
1006     auto settings = static_cast<AvcVdencFeatureSettings *>(m_featureManager->GetFeatureSettings()->GetConstSettings());
1007     ENCODE_CHK_NULL_RETURN(settings);
1008 
1009     uint8_t isIPGOP = m_basicFeature->m_seqParam->GopRefDist == 1;
1010     auto    index   = (codingType == P_TYPE) ? (isIPGOP ? 3 : 2) : (codingType == B_TYPE ? 0 : 1);
1011 
1012     const auto &table   = settings->AdaptiveInterRounding[index];
1013     for (int8_t qp = 10; qp < 52; ++qp)
1014     {
1015         ConstTable7[qp - 10] = table[qp];
1016     }
1017 
1018     return MOS_STATUS_SUCCESS;
1019 }
1020 
LoadConstTable8(uint8_t pictureType,uint8_t ConstTable8[42])1021 MOS_STATUS AvcEncodeBRC::LoadConstTable8(uint8_t pictureType, uint8_t ConstTable8[42])
1022 {
1023     ENCODE_FUNC_CALL();
1024 
1025     const uint8_t codingType = pictureType + 1;
1026     if (codingType == I_TYPE)
1027         return MOS_STATUS_SUCCESS;
1028 
1029     auto settings = static_cast<AvcVdencFeatureSettings *>(m_featureManager->GetFeatureSettings()->GetConstSettings());
1030     ENCODE_CHK_NULL_RETURN(settings);
1031 
1032     uint8_t isIPGOP = m_basicFeature->m_seqParam->GopRefDist == 1;
1033     auto    index   = (codingType == P_TYPE) ? (isIPGOP ? 3 : 2) : (codingType == B_TYPE ? 0 : 1);
1034 
1035     const auto &table = settings->AdaptiveIntraRounding[index];
1036     for (int8_t qp = 10; qp < 52; ++qp)
1037     {
1038         ConstTable8[qp - 10] = table[qp];
1039     }
1040 
1041     return MOS_STATUS_SUCCESS;
1042 }
1043 
1044 
SetSequenceStructs()1045 MOS_STATUS AvcEncodeBRC::SetSequenceStructs()
1046 {
1047     ENCODE_FUNC_CALL();
1048 
1049     auto seqParams = m_basicFeature->m_seqParam;
1050 
1051     m_brcInit         = m_basicFeature->m_resolutionChanged;
1052     m_vdencBrcEnabled = IsVdencBrcSupported(seqParams);
1053     m_rcMode          = m_vdencBrcEnabled ? seqParams->RateControlMethod : 0;
1054 
1055     if (IsRateControlBrc(seqParams->RateControlMethod) && m_vdencBrcEnabled == 0)
1056     {
1057         // Error propagation
1058         return MOS_STATUS_INVALID_PARAMETER;
1059     }
1060 
1061     // control MBBRC if the user feature key does not exist
1062     if (m_vdencBrcEnabled && !m_mbBrcUserFeatureKeyControl)
1063     {
1064         SetMbBrc();
1065     }
1066 
1067     // BRC Init or Reset
1068     if (seqParams->bInitBRC)
1069     {
1070         m_brcInit = seqParams->bInitBRC;
1071     }
1072     else
1073     {
1074         m_brcReset = seqParams->bResetBRC;
1075     }
1076 
1077     if (seqParams->RateControlMethod == RATECONTROL_ICQ || seqParams->RateControlMethod == RATECONTROL_QVBR)
1078     {
1079         if (seqParams->ICQQualityFactor < ENCODE_AVC_VDENC_MIN_ICQ_QUALITYFACTOR ||
1080             seqParams->ICQQualityFactor > CODECHAL_ENCODE_AVC_MAX_ICQ_QUALITYFACTOR)
1081         {
1082             ENCODE_ASSERTMESSAGE("Invalid ICQ Quality Factor input\n");
1083             seqParams->ICQQualityFactor = (uint16_t)CodecHal_Clip3(ENCODE_AVC_VDENC_MIN_ICQ_QUALITYFACTOR,
1084                 CODECHAL_ENCODE_AVC_MAX_ICQ_QUALITYFACTOR,
1085                 seqParams->ICQQualityFactor);
1086         }
1087     }
1088 
1089     return MOS_STATUS_SUCCESS;
1090 }
1091 
SetMbBrc()1092 void AvcEncodeBRC::SetMbBrc()
1093 {
1094     ENCODE_FUNC_CALL();
1095 
1096     auto seqParams = m_basicFeature->m_seqParam;
1097     if (seqParams->RateControlMethod == RATECONTROL_ICQ || seqParams->RateControlMethod == RATECONTROL_QVBR)
1098     {
1099         // If the rate control method is ICQ or QVBR then enable MBBRC by default for all TUs and ignore the app input
1100         m_mbBrcEnabled = true;
1101         ENCODE_NORMALMESSAGE("MBBRC enabled with rate control = %d", seqParams->RateControlMethod);
1102     }
1103     else if (seqParams->RateControlMethod == RATECONTROL_VCM)
1104     {
1105         // If the rate control method is VCM then disable MBBRC by default for all TUs and ignore the app input
1106         m_mbBrcEnabled = false;
1107     }
1108     else
1109     {
1110         switch (seqParams->MBBRC)
1111         {
1112         case mbBrcInternal:
1113             m_mbBrcEnabled = true;
1114             break;
1115         case mbBrcDisabled:
1116             m_mbBrcEnabled = false;
1117             break;
1118         case mbBrcEnabled:
1119             m_mbBrcEnabled = true;
1120             break;
1121         }
1122     }
1123 }
1124 
FreeBrcResources()1125 MOS_STATUS AvcEncodeBRC::FreeBrcResources()
1126 {
1127     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1128 
1129     ENCODE_FUNC_CALL();
1130     ENCODE_CHK_NULL_RETURN(m_hwInterface);
1131     ENCODE_CHK_NULL_RETURN(m_hwInterface->GetOsInterface());
1132 
1133     if (m_batchBufferForVdencImgStat.iSize)
1134     {
1135         ENCODE_CHK_STATUS_RETURN(Mhw_FreeBb(m_hwInterface->GetOsInterface(), &m_batchBufferForVdencImgStat, nullptr));
1136     }
1137 
1138     return eStatus;
1139 }
1140 
ComputeBRCInitQP()1141 int32_t AvcEncodeBRC::ComputeBRCInitQP()
1142 {
1143     ENCODE_FUNC_CALL();
1144 
1145     const float x0 = 0, y0 = 1.19f, x1 = 1.75f, y1 = 1.75f;
1146     uint32_t    frameSize;
1147     int32_t     QP, deltaQ;
1148 
1149     auto seqParams = m_basicFeature->m_seqParam;
1150 
1151     // InitQPIP calculation
1152     frameSize = ((m_basicFeature->m_frameWidth * m_basicFeature->m_frameHeight * 3) >> 1);
1153     QP        = (int32_t)(1. / 1.2 * pow(10.0, (log10(frameSize * 2. / 3. * ((float)seqParams->FramesPer100Sec) / ((float)(seqParams->TargetBitRate) * 100)) - x0) * (y1 - y0) / (x1 - x0) + y0) + 0.5);
1154     QP += 2;
1155     //add additional change based on buffer size. It is especially useful for low delay
1156     deltaQ = (int32_t)(9 - (seqParams->VBVBufferSizeInBit * ((float)seqParams->FramesPer100Sec) / ((float)(seqParams->TargetBitRate) * 100)));
1157     QP += deltaQ < 0 ? 0 : deltaQ;
1158     QP = CodecHal_Clip3(ENCODE_AVC_BRC_MIN_QP, CODECHAL_ENCODE_AVC_MAX_SLICE_QP, QP);
1159     QP--;
1160     if (QP < 0)
1161         QP = 1;
1162 
1163     return QP;
1164 }
1165 
DeltaQPUpdate(uint8_t qpModulationStrength,bool bIsLastPass)1166 MOS_STATUS AvcEncodeBRC::DeltaQPUpdate(uint8_t qpModulationStrength, bool bIsLastPass)
1167 {
1168     ENCODE_FUNC_CALL();
1169 
1170     uint8_t qpStrength = (uint8_t)(qpModulationStrength + (qpModulationStrength >> 1));
1171     if (!m_isFirstDeltaQPCalculation)
1172     {
1173         if (qpModulationStrength == 0)
1174         {
1175             m_qpModulationStrength = 0;
1176         }
1177         else
1178         {
1179             m_qpModulationStrength = (m_qpModulationStrength + qpStrength + 1) >> 1;
1180         }
1181     }
1182     else
1183     {
1184         m_qpModulationStrength = qpStrength;
1185         if (bIsLastPass)
1186         {
1187             m_isFirstDeltaQPCalculation = false;
1188         }
1189     }
1190 
1191     return MOS_STATUS_SUCCESS;
1192 }
1193 
SetFrameTypeForUpdate(VdencAvcHucBrcUpdateDmem * dmem,uint16_t currPass)1194 void AvcEncodeBRC::SetFrameTypeForUpdate(VdencAvcHucBrcUpdateDmem *dmem, uint16_t currPass)
1195 {
1196     dmem->UPD_CurrFrameType_U8 = (m_basicFeature->m_pictureCodingType + 1) % 3;  // I:2, P:0, B:1. Same values in AvcBrcFrameType
1197     if (dmem->UPD_CurrFrameType_U8 == 1 && m_basicFeature->m_picParam->RefPicFlag == 1)
1198     {
1199         dmem->UPD_CurrFrameType_U8 = 3;  // separated type for reference B for legacy BRC
1200     }
1201 
1202     if (m_basicFeature->m_pictureCodingType == I_TYPE || m_basicFeature->m_pictureCodingType == P_TYPE)
1203     {
1204         m_frameIdxInBGop = 0;
1205     }
1206     else if (currPass == 0)
1207     {
1208         ++m_frameIdxInBGop;
1209     }
1210 
1211     //
1212     // Calculate correct ExtCurrFrameType only for Golden GOPs
1213     //
1214     // Calculate B-frame type based on hierarchy level for B-pyramid
1215     if (IsBPyramidWithGoldenBGOP() && m_basicFeature->m_pictureCodingType == B_TYPE)
1216     {
1217         uint16_t curOrder = 0, curLvlInBGop = 0;
1218         CalculateCurLvlInBGop(m_frameIdxInBGop, 1, m_basicFeature->m_seqParam->GopRefDist, 0, curOrder, curLvlInBGop);
1219 
1220         dmem->UPD_ExtCurrFrameType = curLvlInBGop == 1 ? AvcBrcFrameType::B1_FRAME : (curLvlInBGop == 2 ? AvcBrcFrameType::B2_FRAME : AvcBrcFrameType::B_FRAME);
1221     }
1222 }
1223 
IsVdencBrcSupported(PCODEC_AVC_ENCODE_SEQUENCE_PARAMS avcSeqParams)1224 bool AvcEncodeBRC::IsVdencBrcSupported(
1225     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS avcSeqParams)
1226 {
1227     ENCODE_FUNC_CALL();
1228 
1229     bool vdencBrcSupported = false;
1230 
1231     // HuC based BRC should be used when 1) BRC is requested by App and 2) HuC FW is loaded and HuC is enabled for use.
1232     if (IsRateControlBrc(avcSeqParams->RateControlMethod))
1233     {
1234         if (!MEDIA_IS_SKU(m_hwInterface->GetSkuTable(), FtrEnableMediaKernels))
1235         {
1236             ENCODE_ASSERTMESSAGE("Failed to load HuC firmware!");
1237         }
1238 
1239         vdencBrcSupported = MEDIA_IS_SKU(m_hwInterface->GetSkuTable(), FtrEnableMediaKernels);
1240     }
1241 
1242     // Simple check for BRC parameters; if error, disable BRC and continue encoding
1243     if ((vdencBrcSupported) &&
1244         (avcSeqParams->RateControlMethod != RATECONTROL_ICQ) &&
1245         (((!avcSeqParams->InitVBVBufferFullnessInBit || !avcSeqParams->VBVBufferSizeInBit || !avcSeqParams->MaxBitRate) &&
1246            (avcSeqParams->RateControlMethod != RATECONTROL_AVBR)) ||
1247            !avcSeqParams->TargetBitRate ||
1248            !avcSeqParams->FramesPer100Sec))
1249     {
1250         ENCODE_ASSERTMESSAGE("Fatal error in AVC Encoding BRC parameters.");
1251         ENCODE_ASSERTMESSAGE("RateControlMethod = %d, InitVBVBufferFullnessInBit = %d, VBVBufferSizeInBit = %d, MaxBitRate = %d, TargetBitRate = %d, FramesPer100Sec = %d",
1252             avcSeqParams->RateControlMethod,
1253             avcSeqParams->InitVBVBufferFullnessInBit,
1254             avcSeqParams->VBVBufferSizeInBit,
1255             avcSeqParams->MaxBitRate,
1256             avcSeqParams->TargetBitRate,
1257             avcSeqParams->FramesPer100Sec);
1258         vdencBrcSupported = false;
1259     }
1260 
1261     return vdencBrcSupported;
1262 }
1263 
GetVdencBRCImgStateBufferSize()1264 uint32_t AvcEncodeBRC::GetVdencBRCImgStateBufferSize()
1265 {
1266     return MOS_ALIGN_CEIL(MOS_ALIGN_CEIL(m_hwInterface->m_vdencBrcImgStateBufferSize, CODECHAL_CACHELINE_SIZE) +
1267                               CODECHAL_ENCODE_AVC_MAX_SLICES_SUPPORTED * GetVdencOneSliceStateSize(),
1268         CODECHAL_PAGE_SIZE);
1269 }
1270 
GetVdencOneSliceStateSize()1271 uint32_t AvcEncodeBRC::GetVdencOneSliceStateSize()
1272 {
1273     return m_mfxItf->MHW_GETSIZE_F(MFX_AVC_SLICE_STATE)() +
1274            m_vdencItf->MHW_GETSIZE_F(VDENC_AVC_SLICE_STATE)() +
1275            m_miItf->MHW_GETSIZE_F(MI_BATCH_BUFFER_END)();
1276 }
1277 
IsBPyramidWithGoldenBGOP()1278 bool AvcEncodeBRC::IsBPyramidWithGoldenBGOP()
1279 {
1280     return
1281           // Add HierarchicalFlag to condition to not use hierarchy B-Frames when HierarchicalFlag==0
1282           // m_basicFeature->m_seqParam->HierarchicalFlag &&
1283             (m_basicFeature->m_seqParam->GopRefDist == 2 ||
1284              m_basicFeature->m_seqParam->GopRefDist == 4 ||
1285              m_basicFeature->m_seqParam->GopRefDist == 8);
1286 }
1287 
CalculateCurLvlInBGop(uint16_t curFrameIdxInBGop,uint16_t begin,uint16_t end,uint16_t curLvl,uint16_t & curOrder,uint16_t & retLvl)1288 void AvcEncodeBRC::CalculateCurLvlInBGop(uint16_t curFrameIdxInBGop, uint16_t begin, uint16_t end, uint16_t curLvl, uint16_t &curOrder, uint16_t &retLvl)
1289 {
1290     curOrder += 1;
1291     if (curOrder == curFrameIdxInBGop)
1292     {
1293         retLvl = curLvl;
1294         return;
1295     }
1296 
1297     if (end - begin > 1)
1298     {
1299         uint16_t pivot = (begin + end) >> 1;
1300         CalculateCurLvlInBGop(curFrameIdxInBGop, begin, pivot, curLvl + 1, curOrder, retLvl);
1301 
1302         if (pivot + 1 != end)
1303             CalculateCurLvlInBGop(curFrameIdxInBGop, pivot + 1, end, curLvl + 1, curOrder, retLvl);
1304     }
1305 }
1306 
MHW_SETPAR_DECL_SRC(VDENC_PIPE_MODE_SELECT,AvcEncodeBRC)1307 MHW_SETPAR_DECL_SRC(VDENC_PIPE_MODE_SELECT, AvcEncodeBRC)
1308 {
1309     params.frameStatisticsStreamOut = m_vdencBrcEnabled || m_basicFeature->m_picParam->StatusReportEnable.fields.FrameStats;
1310 
1311     return MOS_STATUS_SUCCESS;
1312 }
1313 
MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE,AvcEncodeBRC)1314 MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE, AvcEncodeBRC)
1315 {
1316     if (params.function == BRC_UPDATE)
1317     {
1318         ENCODE_CHK_NULL_RETURN(m_basicFeature);
1319 
1320         // Output regions
1321         params.regionParams[0].presRegion = m_basicFeature->m_recycleBuf->GetBuffer(VdencBRCHistoryBuffer, m_basicFeature->m_frameNum);
1322         params.regionParams[0].isWritable = true;
1323         params.regionParams[6].presRegion = const_cast<PMOS_RESOURCE>(&m_batchBufferForVdencImgStat.OsResource);
1324         params.regionParams[6].isWritable = true;
1325 
1326         // region 15 always in clear
1327         params.regionParams[15].presRegion = m_basicFeature->m_recycleBuf->GetBuffer(VdencBrcDebugBuffer, 0);
1328     }
1329 
1330     return MOS_STATUS_SUCCESS;
1331 }
1332 
1333 }  // namespace encode
1334