1 /*
2 * Copyright (c) 2018-2021, 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 //!
24 //! \file     encode_huc_brc_update_packet.cpp
25 //! \brief    Defines the implementation of huc update packet
26 //!
27 
28 #include "encode_huc_brc_update_packet.h"
29 #include "codechal_debug.h"
30 #include "encode_hevc_vdenc_weighted_prediction.h"
31 #include "encode_hevc_brc.h"
32 #include "encode_hevc_vdenc_scc.h"
33 #include "encode_vdenc_lpla_analysis.h"
34 #include "encode_hevc_vdenc_lpla_enc.h"
35 #include "encode_hevc_header_packer.h"
36 
37 namespace encode
38 {
Init()39     MOS_STATUS HucBrcUpdatePkt::Init()
40     {
41         ENCODE_FUNC_CALL();
42         m_hwInterface->m_vdencBatchBuffer1stGroupSize = MOS_ALIGN_CEIL(m_hwInterface->m_vdencBatchBuffer1stGroupSize, CODECHAL_CACHELINE_SIZE);
43         m_hwInterface->m_vdencBatchBuffer2ndGroupSize = MOS_ALIGN_CEIL(m_hwInterface->m_vdencBatchBuffer2ndGroupSize, CODECHAL_CACHELINE_SIZE);
44         m_hwInterface->m_vdencReadBatchBufferSize =
45         m_hwInterface->m_vdenc2ndLevelBatchBufferSize = m_hwInterface->m_vdencBatchBuffer1stGroupSize
46                                          + m_hwInterface->m_vdencBatchBuffer2ndGroupSize
47                                          + ENCODE_HEVC_VDENC_NUM_MAX_SLICES * MOS_ALIGN_CEIL((2 * m_hcpItf->MHW_GETSIZE_F(HCP_WEIGHTOFFSET_STATE)()
48                                          + m_hcpItf->MHW_GETSIZE_F(HCP_SLICE_STATE)()
49                                          + 2 * m_hcpItf->MHW_GETSIZE_F(HCP_PAK_INSERT_OBJECT)()
50                                          + sizeof (HevcSlice)
51                                          + m_vdencItf->MHW_GETSIZE_F(VDENC_WEIGHTSOFFSETS_STATE)()
52                                          + 2 * m_miItf->MHW_GETSIZE_F(MI_BATCH_BUFFER_END)()), CODECHAL_CACHELINE_SIZE);
53         m_hwInterface->m_vdencBatchBufferPerSliceConstSize = m_hcpItf->MHW_GETSIZE_F(HCP_SLICE_STATE)()
54         + m_vdencItf->MHW_GETSIZE_F(VDENC_WEIGHTSOFFSETS_STATE)()
55         + m_hcpItf->MHW_GETSIZE_F(HCP_PAK_INSERT_OBJECT)()
56         + m_miItf->MHW_GETSIZE_F(MI_BATCH_BUFFER_END)() * 2;
57 
58         HUC_CHK_STATUS_RETURN(EncodeHucPkt::Init());
59 
60         ENCODE_CHK_NULL_RETURN(m_pipeline);
61         m_allocator = m_pipeline->GetEncodeAllocator();
62         ENCODE_CHK_NULL_RETURN(m_allocator);
63 
64         ENCODE_CHK_NULL_RETURN(m_featureManager);
65         m_basicFeature = dynamic_cast<HevcBasicFeature *>(m_featureManager->GetFeature(HevcFeatureIDs::basicFeature));
66         ENCODE_CHK_NULL_RETURN(m_basicFeature);
67 
68         return MOS_STATUS_SUCCESS;
69     }
70 
CalculateCommandSize(uint32_t & commandBufferSize,uint32_t & requestedPatchListSize)71     MOS_STATUS HucBrcUpdatePkt::CalculateCommandSize(uint32_t &commandBufferSize, uint32_t &requestedPatchListSize)
72     {
73         ENCODE_FUNC_CALL();
74 
75         auto osInterface = m_hwInterface->GetOsInterface();
76         ENCODE_CHK_NULL_RETURN(osInterface);
77 
78         uint32_t hucCommandsSize = 0;
79         uint32_t hucPatchListSize = 0;
80         MHW_VDBOX_STATE_CMDSIZE_PARAMS stateCmdSizeParams;
81 
82         stateCmdSizeParams.uNumStoreDataImm = 2;
83         stateCmdSizeParams.uNumStoreReg     = 4;
84         stateCmdSizeParams.uNumMfxWait      = 3;
85         stateCmdSizeParams.uNumAddConBBEnd  = 1;
86         ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetHucStateCommandSize(
87             m_basicFeature->m_mode, (uint32_t*)&hucCommandsSize, (uint32_t*)&hucPatchListSize, &stateCmdSizeParams));
88 
89         commandBufferSize = hucCommandsSize;
90         requestedPatchListSize = osInterface->bUsesPatchList ? hucPatchListSize : 0;
91 
92         if (m_pipeline->IsSingleTaskPhaseSupported())
93         {
94             commandBufferSize *= m_pipeline->GetPassNum();
95         }
96 
97         // 4K align since allocation is in chunks of 4K bytes.
98         commandBufferSize = MOS_ALIGN_CEIL(commandBufferSize, CODECHAL_PAGE_SIZE);
99 
100         return MOS_STATUS_SUCCESS;
101     }
102 
DumpOutput()103     MOS_STATUS HucBrcUpdatePkt::DumpOutput()
104     {
105         ENCODE_FUNC_CALL();
106 
107 #if USE_CODECHAL_DEBUG_TOOL
108         DumpHucBrcUpdate(false);
109 #endif
110         return MOS_STATUS_SUCCESS;
111     }
112 
AllocateResources()113     MOS_STATUS HucBrcUpdatePkt::AllocateResources()
114     {
115         ENCODE_FUNC_CALL();
116         ENCODE_CHK_STATUS_RETURN(EncodeHucPkt::AllocateResources());
117 
118         MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
119         MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
120         allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
121         allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
122         allocParamsForBufferLinear.Format = Format_Buffer;
123 
124         // HuC FW Region 6: Data Buffer of Current Picture
125         // Data (1024 bytes) for current
126         // Data (1024 bytes) for ref0
127         // Data (1024 bytes) for ref1
128         // Data (1024 bytes) for ref2
129         allocParamsForBufferLinear.dwBytes = CODECHAL_PAGE_SIZE * 4;
130         allocParamsForBufferLinear.pBufName = "Data from Pictures Buffer for Weighted Prediction";
131         allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
132         MOS_RESOURCE *allocatedbuffer       = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
133         ENCODE_CHK_NULL_RETURN(allocatedbuffer);
134         m_dataFromPicsBuffer = *allocatedbuffer;
135 
136         for (auto k = 0; k < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; k++)
137         {
138             // Const Data buffer
139             allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(m_vdencBrcConstDataBufferSize, CODECHAL_PAGE_SIZE);
140             allocParamsForBufferLinear.pBufName = "VDENC BRC Const Data Buffer";
141             allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_WRITE;
142             allocatedbuffer       = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
143             ENCODE_CHK_NULL_RETURN(allocatedbuffer);
144             m_vdencBrcConstDataBuffer[k] = *allocatedbuffer;
145 
146             for (auto i = 0; i < VDENC_BRC_NUM_OF_PASSES; i++)
147             {
148                 // VDEnc read batch buffer (input for HuC FW)
149                 allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(m_hwInterface->m_vdencReadBatchBufferSize, CODECHAL_PAGE_SIZE);
150                 allocParamsForBufferLinear.pBufName = "VDENC Read Batch Buffer";
151                 allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
152                 allocatedbuffer                     = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
153                 ENCODE_CHK_NULL_RETURN(allocatedbuffer);
154                 m_vdencReadBatchBuffer[k][i] = *allocatedbuffer;
155 
156                 // BRC update DMEM
157                 allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(m_vdencBrcUpdateDmemBufferSize, CODECHAL_CACHELINE_SIZE);
158                 allocParamsForBufferLinear.pBufName = "VDENC BrcUpdate DmemBuffer";
159                 allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
160                 allocatedbuffer                     = m_allocator->AllocateResource(allocParamsForBufferLinear, true, MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ);
161                 ENCODE_CHK_NULL_RETURN(allocatedbuffer);
162                 m_vdencBrcUpdateDmemBuffer[k][i] = *allocatedbuffer;
163             }
164         }
165 
166         return MOS_STATUS_SUCCESS;
167     }
168 
MHW_SETPAR_DECL_SRC(HUC_IMEM_STATE,HucBrcUpdatePkt)169     MHW_SETPAR_DECL_SRC(HUC_IMEM_STATE, HucBrcUpdatePkt)
170     {
171         if (m_basicFeature->m_hevcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_EXTREMELY_LOW)  // Low Delay BRC
172         {
173             params.kernelDescriptor = m_vdboxHucHevcBrcLowdelayKernelDescriptor;
174         }
175         else
176         {
177             params.kernelDescriptor = m_vdboxHucHevcBrcUpdateKernelDescriptor;
178         }
179 
180         return MOS_STATUS_SUCCESS;
181     }
182 
MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE,HucBrcUpdatePkt)183     MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE, HucBrcUpdatePkt)
184     {
185         ENCODE_CHK_STATUS_RETURN(SetDmemBuffer());
186 
187         params.function      = BRC_UPDATE;
188         params.passNum       = static_cast<uint8_t>(m_pipeline->GetPassNum());
189         params.currentPass   = static_cast<uint8_t> (m_pipeline->GetCurrentPass());
190         params.hucDataSource = const_cast<PMOS_RESOURCE> (&m_vdencBrcUpdateDmemBuffer[m_pipeline->m_currRecycledBufIdx][m_pipeline->GetCurrentPass()]);
191         params.dataLength    = MOS_ALIGN_CEIL(m_vdencBrcUpdateDmemBufferSize, CODECHAL_CACHELINE_SIZE);
192         params.dmemOffset    = HUC_DMEM_OFFSET_RTOS_GEMS;
193 
194         return MOS_STATUS_SUCCESS;
195     }
196 
MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE,HucBrcUpdatePkt)197     MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE, HucBrcUpdatePkt)
198     {
199         ENCODE_FUNC_CALL();
200 
201         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
202 
203         int32_t currentPass = m_pipeline->GetCurrentPass();
204         if (currentPass < 0)
205         {
206             eStatus = MOS_STATUS_INVALID_PARAMETER;
207             return eStatus;
208         }
209 
210         ENCODE_CHK_NULL_RETURN(m_basicFeature);
211         ENCODE_CHK_NULL_RETURN(m_basicFeature->m_recycleBuf);
212 
213         params.function = BRC_UPDATE;
214 
215         ENCODE_CHK_STATUS_RETURN(SetConstDataHuCBrcUpdate());
216 
217         // Add Virtual addr
218         RUN_FEATURE_INTERFACE_RETURN(HEVCEncodeBRC, HevcFeatureIDs::hevcBrcFeature,
219             SetCurrRecycledBufIdx, m_pipeline->m_currRecycledBufIdx);
220 
221         params.regionParams[2].presRegion = m_basicFeature->m_recycleBuf->GetBuffer(FrameStatStreamOutBuffer, 0);      // Region 2  PAK Statistics Buffer (Input) - MFX_PAK_FRAME_STATISTICS
222         params.regionParams[3].presRegion = const_cast<PMOS_RESOURCE>(&m_vdencReadBatchBuffer[m_pipeline->m_currRecycledBufIdx][currentPass]);    // Region 3 - Input SLB Buffer (Input)
223         params.regionParams[4].presRegion = const_cast<PMOS_RESOURCE>(&m_vdencBrcConstDataBuffer[m_pipeline->m_currRecycledBufIdx]);              // Region 4 - Constant Data (Input)
224         params.regionParams[6].presRegion = const_cast<PMOS_RESOURCE>(&m_dataFromPicsBuffer);                   // Region 6 - Data Buffer of Current and Reference Pictures for Weighted Prediction (Input/Output)
225         params.regionParams[6].isWritable = true;
226         params.regionParams[8].presRegion =
227             m_basicFeature->m_recycleBuf->GetBuffer(PakInfo, 0);                        // Region 8 - PAK Information (Input)
228 
229         params.regionParams[7].presRegion = m_basicFeature->m_recycleBuf->GetBuffer(LcuBaseAddressBuffer, 0);   // Region 7  Slice Stat Streamout (Input)
230 
231         bool tileEnabled = false;
232         RUN_FEATURE_INTERFACE_RETURN(HevcEncodeTile, HevcFeatureIDs::encodeTile, IsEnabled, tileEnabled);
233         if (tileEnabled)
234         {
235             MOS_RESOURCE *resHuCPakAggregatedFrameStatsBuffer = nullptr;
236             RUN_FEATURE_INTERFACE_RETURN(HevcEncodeTile, HevcFeatureIDs::encodeTile, GetHucPakAggregatedFrameStatsBuffer, resHuCPakAggregatedFrameStatsBuffer);
237             HevcTileStatusInfo tileStatsOffset = {};
238             HevcTileStatusInfo frameStatsOffset = {};
239             HevcTileStatusInfo statsSize = {};
240             RUN_FEATURE_INTERFACE_RETURN(HevcEncodeTile, HevcFeatureIDs::encodeTile, GetTileStatusInfo, tileStatsOffset, frameStatsOffset, statsSize);
241             params.regionParams[1].presRegion = resHuCPakAggregatedFrameStatsBuffer;
242             params.regionParams[1].dwOffset = frameStatsOffset.vdencStatistics;
243 
244             if (m_pipeline->GetPipeNum() > 1)
245             {
246                 params.regionParams[2].presRegion = resHuCPakAggregatedFrameStatsBuffer;  // Region 2  PAK Statistics Buffer (Input) - MFX_PAK_FRAME_STATISTICS
247                 params.regionParams[2].dwOffset = frameStatsOffset.hevcPakStatistics;
248                 params.regionParams[7].presRegion = resHuCPakAggregatedFrameStatsBuffer;  // Region 7  Slice Stat Streamout (Input)
249                 params.regionParams[7].dwOffset = frameStatsOffset.hevcSliceStreamout;
250                 // In scalable-mode, use PAK Integration kernel output to get bistream size
251                 MOS_RESOURCE *resBrcDataBuffer = nullptr;
252                 RUN_FEATURE_INTERFACE_RETURN(HEVCEncodeBRC, HevcFeatureIDs::hevcBrcFeature, GetBrcDataBuffer, resBrcDataBuffer);
253                 params.regionParams[8].presRegion = resBrcDataBuffer;
254             }
255         }
256         else
257         {
258             params.regionParams[1].presRegion = m_basicFeature->m_recycleBuf->GetBuffer(VdencStatsBuffer, 0);  // Region 1  VDEnc Statistics Buffer (Input) - VDENC_HEVC_VP9_FRAME_BASED_STATISTICS_STREAMOUT
259         }
260 
261         return MOS_STATUS_SUCCESS;
262     }
263 
SetCommonDmemBuffer(VdencHevcHucBrcUpdateDmem * hucVdencBrcUpdateDmem)264     MOS_STATUS HucBrcUpdatePkt::SetCommonDmemBuffer(VdencHevcHucBrcUpdateDmem *hucVdencBrcUpdateDmem)
265     {
266         RUN_FEATURE_INTERFACE_RETURN(HEVCEncodeBRC, HevcFeatureIDs::hevcBrcFeature, SetDmemForUpdate, hucVdencBrcUpdateDmem);
267 
268         hucVdencBrcUpdateDmem->TARGETSIZE_U32 =
269             (m_basicFeature->m_hevcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_EXTREMELY_LOW) ? m_basicFeature->m_hevcSeqParams->InitVBVBufferFullnessInBit : MOS_MIN(m_basicFeature->m_hevcSeqParams->InitVBVBufferFullnessInBit, m_basicFeature->m_hevcSeqParams->VBVBufferSizeInBit);
270         hucVdencBrcUpdateDmem->FrameID_U32                   = m_basicFeature->m_frameNum;  // frame number
271         hucVdencBrcUpdateDmem->TargetSliceSize_U16           = (uint16_t)m_basicFeature->m_hevcPicParams->MaxSliceSizeInBytes;
272         hucVdencBrcUpdateDmem->SLB_Data_SizeInBytes          = (uint16_t)m_slbDataSizeInBytes;
273         hucVdencBrcUpdateDmem->PIPE_MODE_SELECT_StartInBytes = 0xFFFF;  // HuC need not modify the pipe mode select command in Gen11+
274         hucVdencBrcUpdateDmem->CMD1_StartInBytes             = (uint16_t)m_hwInterface->m_vdencBatchBuffer1stGroupSize;
275         hucVdencBrcUpdateDmem->PIC_STATE_StartInBytes        = (uint16_t)m_basicFeature->m_picStateCmdStartInBytes;
276         hucVdencBrcUpdateDmem->CMD2_StartInBytes             = (uint16_t)m_cmd2StartInBytes;
277 
278         if (m_basicFeature->m_prevStoreData != m_basicFeature->m_frameNum)
279         {
280             m_basicFeature->m_prevStoreData = m_basicFeature->m_frameNum;
281 
282             int32_t  oldestIdx    = -1;
283             int32_t  selectedSlot = -1;
284             uint32_t oldestAge    = 0;
285             for (int i = 0; i < CODECHAL_ENCODE_HEVC_VDENC_WP_DATA_BLOCK_NUMBER; i++)
286             {
287                 if (slotInfo[i].isUsed == true && slotInfo[i].isRef)
288                 {
289                     slotInfo[i].age++;
290                     if (slotInfo[i].age >= oldestAge)
291                     {
292                         oldestAge = slotInfo[i].age;
293                         oldestIdx = i;
294                     }
295                 }
296                 if ((selectedSlot == -1) && (slotInfo[i].isUsed == false || !slotInfo[i].isRef))
297                 {
298                     selectedSlot = i;
299                 }
300             }
301 
302             if (selectedSlot == -1)
303             {
304                 selectedSlot = oldestIdx;
305             }
306 
307             if (selectedSlot == -1)
308             {
309                 ENCODE_ASSERTMESSAGE("No valid ref slot index");
310                 return MOS_STATUS_INVALID_PARAMETER;
311             }
312 
313             slotInfo[selectedSlot].age    = 0;
314             slotInfo[selectedSlot].poc    = m_basicFeature->m_hevcPicParams->CurrPicOrderCnt;
315             slotInfo[selectedSlot].isUsed = true;
316             slotInfo[selectedSlot].isRef  = m_basicFeature->m_hevcPicParams->bUsedAsRef;
317 
318             m_curPicSlot = selectedSlot;
319         }
320 
321         hucVdencBrcUpdateDmem->Current_Data_Offset = m_curPicSlot * m_weightHistSize;
322 
323         for (uint8_t refIdx = 0; refIdx <= m_basicFeature->m_hevcSliceParams->num_ref_idx_l0_active_minus1; refIdx++)
324         {
325             CODEC_PICTURE refPic = m_basicFeature->m_hevcSliceParams->RefPicList[LIST_0][refIdx];
326             auto          refPOC = m_basicFeature->m_hevcPicParams->RefFramePOCList[refPic.FrameIdx];
327             for (int i = 0; i < CODECHAL_ENCODE_HEVC_VDENC_WP_DATA_BLOCK_NUMBER; i++)
328             {
329                 if (slotInfo[i].poc == refPOC)
330                 {
331                     hucVdencBrcUpdateDmem->Ref_Data_Offset[refIdx] = i * m_weightHistSize;
332                     break;
333                 }
334             }
335         }
336 
337         for (uint8_t refIdx = 0; refIdx <= m_basicFeature->m_hevcSliceParams->num_ref_idx_l1_active_minus1; refIdx++)
338         {
339             CODEC_PICTURE refPic = m_basicFeature->m_hevcSliceParams->RefPicList[LIST_1][refIdx];
340             auto          refPOC = m_basicFeature->m_hevcPicParams->RefFramePOCList[refPic.FrameIdx];
341             for (int i = 0; i < CODECHAL_ENCODE_HEVC_VDENC_WP_DATA_BLOCK_NUMBER; i++)
342             {
343                 if (slotInfo[i].poc == refPOC)
344                 {
345                     hucVdencBrcUpdateDmem->Ref_Data_Offset[refIdx + m_basicFeature->m_hevcSliceParams->num_ref_idx_l0_active_minus1 + 1] = i * m_weightHistSize;
346                     break;
347                 }
348             }
349         }
350 
351         hucVdencBrcUpdateDmem->MaxNumSliceAllowed_U16 = (uint16_t)GetMaxAllowedSlices(m_basicFeature->m_hevcSeqParams->Level);
352 
353         hucVdencBrcUpdateDmem->OpMode_U8 = 0x4;
354 
355         bool enableTileReplay = false;
356         RUN_FEATURE_INTERFACE_RETURN(HevcEncodeTile, HevcFeatureIDs::encodeTile, IsTileReplayEnabled, enableTileReplay);
357         if (enableTileReplay)
358         {
359             hucVdencBrcUpdateDmem->OpMode_U8 = 0x8;
360         }
361         else
362         {
363             RUN_FEATURE_INTERFACE_RETURN(
364                 HevcVdencWeightedPred,
365                 HevcFeatureIDs::hevcVdencWpFeature,
366                 SetHucBrcUpdateDmemBuffer,
367                 m_pipeline->IsFirstPass(),
368                 *hucVdencBrcUpdateDmem);
369         }
370 
371         bool bAllowedPyramid = m_basicFeature->m_hevcSeqParams->GopRefDist != 3;
372 
373         if (m_basicFeature->m_pictureCodingType == I_TYPE)
374         {
375             hucVdencBrcUpdateDmem->CurrentFrameType_U8 = HEVC_BRC_FRAME_TYPE_I;
376         }
377         else if (m_basicFeature->m_hevcSeqParams->HierarchicalFlag && bAllowedPyramid)
378         {
379             if (m_basicFeature->m_hevcPicParams->HierarchLevelPlus1 > 0)
380             {
381                 std::map<int, HEVC_BRC_FRAME_TYPE> hierchLevelPlus1_to_brclevel{
382                     {1, HEVC_BRC_FRAME_TYPE_P_OR_LB},
383                     {2, HEVC_BRC_FRAME_TYPE_B},
384                     {3, HEVC_BRC_FRAME_TYPE_B1},
385                     {4, HEVC_BRC_FRAME_TYPE_B2}};
386                 hucVdencBrcUpdateDmem->CurrentFrameType_U8 = hierchLevelPlus1_to_brclevel.count(m_basicFeature->m_hevcPicParams->HierarchLevelPlus1) ? hierchLevelPlus1_to_brclevel[m_basicFeature->m_hevcPicParams->HierarchLevelPlus1] : HEVC_BRC_FRAME_TYPE_INVALID;
387                 //Invalid HierarchLevelPlus1 or LBD frames at level 3 eror check.
388                 if ((hucVdencBrcUpdateDmem->CurrentFrameType_U8 == HEVC_BRC_FRAME_TYPE_INVALID) ||
389                     (m_basicFeature->m_hevcSeqParams->LowDelayMode && hucVdencBrcUpdateDmem->CurrentFrameType_U8 == HEVC_BRC_FRAME_TYPE_B2))
390                 {
391                     ENCODE_ASSERTMESSAGE("HEVC_BRC_FRAME_TYPE_INVALID or LBD picture doesn't support Level 4\n");
392                     return MOS_STATUS_INVALID_PARAMETER;
393                 }
394             }
395             else if (!m_basicFeature->m_hevcSeqParams->LowDelayMode)  //RA
396             {
397                 //if L0/L1 both points to previous frame, then its LBD otherwise its is level 1 RA B.
398                 auto                               B_or_LDB_brclevel = m_basicFeature->m_ref.IsLowDelay() ? HEVC_BRC_FRAME_TYPE_P_OR_LB : HEVC_BRC_FRAME_TYPE_B;
399                 std::map<int, HEVC_BRC_FRAME_TYPE> codingtype_to_brclevel{
400                     {P_TYPE, HEVC_BRC_FRAME_TYPE_P_OR_LB},
401                     {B_TYPE, B_or_LDB_brclevel},
402                     {B1_TYPE, HEVC_BRC_FRAME_TYPE_B1},
403                     {B2_TYPE, HEVC_BRC_FRAME_TYPE_B2}};
404                 hucVdencBrcUpdateDmem->CurrentFrameType_U8 = codingtype_to_brclevel.count(m_basicFeature->m_pictureCodingType) ? codingtype_to_brclevel[m_basicFeature->m_pictureCodingType] : HEVC_BRC_FRAME_TYPE_INVALID;
405                 //Invalid CodingType.
406                 if (hucVdencBrcUpdateDmem->CurrentFrameType_U8 == HEVC_BRC_FRAME_TYPE_INVALID)
407                 {
408                     ENCODE_ASSERTMESSAGE("Invalid CodingType\n");
409                     return MOS_STATUS_INVALID_PARAMETER;
410                 }
411             }
412             else  //LDB
413             {
414                 hucVdencBrcUpdateDmem->CurrentFrameType_U8 = HEVC_BRC_FRAME_TYPE_P_OR_LB;  //No Hierarchical info for LDB, treated as flat case
415             }
416         }
417         else
418         {
419             hucVdencBrcUpdateDmem->CurrentFrameType_U8 = m_basicFeature->m_ref.IsLowDelay() ? HEVC_BRC_FRAME_TYPE_P_OR_LB : HEVC_BRC_FRAME_TYPE_B;
420         }
421 
422         // Num_Ref_L1 should be always same as Num_Ref_L0
423         hucVdencBrcUpdateDmem->Num_Ref_L0_U8 = m_basicFeature->m_hevcSliceParams->num_ref_idx_l0_active_minus1 + 1;
424         hucVdencBrcUpdateDmem->Num_Ref_L1_U8 = m_basicFeature->m_hevcSliceParams->num_ref_idx_l1_active_minus1 + 1;
425         hucVdencBrcUpdateDmem->Num_Slices    = (uint8_t)m_basicFeature->m_hevcPicParams->NumSlices;
426 
427         // CQP_QPValue_U8 setting is needed since ACQP is also part of ICQ
428         hucVdencBrcUpdateDmem->CQP_QPValue_U8 = m_basicFeature->m_hevcPicParams->QpY + m_basicFeature->m_hevcSliceParams->slice_qp_delta;
429         hucVdencBrcUpdateDmem->CQP_FracQP_U8  = 0;
430         if (m_basicFeature->m_hevcPicParams->BRCPrecision == 1)
431         {
432             hucVdencBrcUpdateDmem->MaxNumPass_U8 = 1;
433         }
434         else
435         {
436             hucVdencBrcUpdateDmem->MaxNumPass_U8 = VDENC_BRC_NUM_OF_PASSES;
437         }
438 
439         hucVdencBrcUpdateDmem->IPAverageCoeff_U8 = (m_basicFeature->m_hevcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_EXTREMELY_LOW) ? 0 : 64;
440         hucVdencBrcUpdateDmem->CurrentPass_U8    = (uint8_t)m_pipeline->GetCurrentPass();
441 
442         // chroma weights are not confirmed to be supported from HW team yet
443         hucVdencBrcUpdateDmem->DisabledFeature_U8 = 0;  // bit mask, 1 (bit0): disable chroma weight setting
444 
445         hucVdencBrcUpdateDmem->SlidingWindow_Enable_U8 = (m_basicFeature->m_hevcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_LOW);
446         hucVdencBrcUpdateDmem->LOG_LCU_Size_U8         = 6;
447 
448         RUN_FEATURE_INTERFACE_RETURN(
449             HevcVdencScc,
450             HevcFeatureIDs::hevcVdencSccFeature,
451             SetHucBrcUpdateDmem,
452             hucVdencBrcUpdateDmem);
453 
454         // reset skip frame statistics
455         //m_numSkipFrames = 0;
456         //m_sizeSkipFrames = 0;
457 
458         // For tile row based BRC
459         //if (m_basicFeature->m_TileRowLevelBRC)
460         //{
461         //    hucVdencBrcUpdateDmem->MaxNumTileHuCCallMinus1 = m_basicFeature->m_hevcPicParams->num_tile_rows_minus1 + 1;
462         //    hucVdencBrcUpdateDmem->TileHucCallIndex        = (uint8_t)m_CurrentTileRow;
463         //    hucVdencBrcUpdateDmem->TileHuCCallPassIndex    = m_CurrentPassForTileReplay + 1;
464         //    hucVdencBrcUpdateDmem->TileHuCCallPassMax      = m_NumPassesForTileReplay;
465 
466         //    hucVdencBrcUpdateDmem->TxSizeInBitsPerFrame    = 0; //threshold for the min frame size
467 
468         //    uint32_t numTileColumns = m_basicFeature->m_hevcPicParams->num_tile_columns_minus1 + 1;
469         //    uint32_t startIdx       = m_CurrentTileRow * numTileColumns;
470         //    uint32_t endIdx         = startIdx + numTileColumns - 1;
471         //    uint32_t LCUsInTile     = 0;
472 
473         //    for (uint32_t idx = 0; idx < numTileColumns; idx ++)
474         //    {
475         //        LCUsInTile += m_basicFeature->m_hevcPicParams->tile_row_height[m_CurrentTileRow] * m_hevcPicParams->tile_column_width[idx];
476         //    }
477 
478         //    hucVdencBrcUpdateDmem->StartTileIdx            = (uint8_t)startIdx;
479         //    hucVdencBrcUpdateDmem->EndTileIdx              = (uint8_t)endIdx;
480         //    hucVdencBrcUpdateDmem->TileSizeInLCU           = (uint16_t)LCUsInTile;
481         //}
482 
483         // Long term reference
484         hucVdencBrcUpdateDmem->IsLongTermRef = CodecHal_PictureIsLongTermRef(m_basicFeature->m_currReconstructedPic);
485 
486         return MOS_STATUS_SUCCESS;
487     }
488 
SetExtDmemBuffer(VdencHevcHucBrcUpdateDmem * hucVdencBrcUpdateDmem) const489     MOS_STATUS HucBrcUpdatePkt::SetExtDmemBuffer(VdencHevcHucBrcUpdateDmem *hucVdencBrcUpdateDmem) const
490     {
491         ENCODE_FUNC_CALL();
492 
493         // TCBRC
494         hucVdencBrcUpdateDmem->FrameSizeBoostForSceneChange = m_tcbrcQualityBoost;
495         hucVdencBrcUpdateDmem->TargetFrameSize              = m_basicFeature->m_hevcPicParams->TargetFrameSize << 3;
496 
497         auto CalculatedMaxFrame                   = m_basicFeature->GetProfileLevelMaxFrameSize();
498         hucVdencBrcUpdateDmem->UPD_UserMaxFrame   = m_basicFeature->m_hevcSeqParams->UserMaxIFrameSize > 0 ? MOS_MIN(m_basicFeature->m_hevcSeqParams->UserMaxIFrameSize, CalculatedMaxFrame) : CalculatedMaxFrame;
499         hucVdencBrcUpdateDmem->UPD_UserMaxFramePB = m_basicFeature->m_hevcSeqParams->UserMaxPBFrameSize > 0 ? MOS_MIN(m_basicFeature->m_hevcSeqParams->UserMaxPBFrameSize, CalculatedMaxFrame) : CalculatedMaxFrame;
500 
501         auto UserMaxFrame = m_basicFeature->m_hevcPicParams->CodingType == I_TYPE ? hucVdencBrcUpdateDmem->UPD_UserMaxFrame : hucVdencBrcUpdateDmem->UPD_UserMaxFramePB;
502         if (!(UserMaxFrame < hucVdencBrcUpdateDmem->TargetFrameSize / 4)
503             && !(hucVdencBrcUpdateDmem->FrameSizeBoostForSceneChange == 2)
504             && (m_basicFeature->m_hevcSeqParams->LookaheadDepth == 0))
505         {
506             hucVdencBrcUpdateDmem->TargetFrameSize = 0;
507         }
508         else if (m_basicFeature->m_hevcPicParams->CodingType == I_TYPE && (m_basicFeature->m_hevcSeqParams->LookaheadDepth == 0))
509         {
510             hucVdencBrcUpdateDmem->TargetFrameSize += m_basicFeature->m_hevcPicParams->TargetFrameSize;
511         }
512 
513         hucVdencBrcUpdateDmem->ROMCurrent                   = 8;
514         hucVdencBrcUpdateDmem->ROMZero                      = 0;
515 
516         // LPLA
517         RUN_FEATURE_INTERFACE_RETURN(
518             HEVCVdencLplaEnc,
519             HevcFeatureIDs::hevcVdencLplaEncFeature,
520             SetHucBrcUpdateExtBuffer,
521             hucVdencBrcUpdateDmem,
522             m_pipeline->IsLastPass());
523 
524         // CQM
525         hucVdencBrcUpdateDmem->CqmEnable = m_basicFeature->m_hevcSeqParams->scaling_list_enable_flag || m_basicFeature->m_hevcPicParams->scaling_list_data_present_flag;
526 
527         return MOS_STATUS_SUCCESS;
528     }
529 
SetDmemBuffer() const530     MOS_STATUS HucBrcUpdatePkt::SetDmemBuffer() const
531     {
532         ENCODE_FUNC_CALL();
533         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
534 
535         // Program update DMEM
536         auto hucVdencBrcUpdateDmem =
537             (VdencHevcHucBrcUpdateDmem *)m_allocator->LockResourceForWrite(const_cast<MOS_RESOURCE*>(&m_vdencBrcUpdateDmemBuffer[m_pipeline->m_currRecycledBufIdx][m_pipeline->GetCurrentPass()]));
538         ENCODE_CHK_NULL_RETURN(hucVdencBrcUpdateDmem);
539         MOS_ZeroMemory(hucVdencBrcUpdateDmem, sizeof(VdencHevcHucBrcUpdateDmem));
540 
541         const_cast<HucBrcUpdatePkt* const>(this)->SetCommonDmemBuffer(hucVdencBrcUpdateDmem);
542         SetExtDmemBuffer(hucVdencBrcUpdateDmem);
543 
544         m_allocator->UnLock(const_cast<MOS_RESOURCE*>(&m_vdencBrcUpdateDmemBuffer[m_pipeline->m_currRecycledBufIdx][m_pipeline->GetCurrentPass()]));
545 
546         return MOS_STATUS_SUCCESS;
547     }
548 
SetConstLambdaHucBrcUpdate(void * params) const549     MOS_STATUS HucBrcUpdatePkt::SetConstLambdaHucBrcUpdate(void *params) const
550     {
551         ENCODE_FUNC_CALL();
552         ENCODE_CHK_NULL_RETURN(params);
553         auto hucConstData = (VdencHevcHucBrcConstantData *)params;
554 
555         RUN_FEATURE_INTERFACE_RETURN(HEVCEncodeBRC, HevcFeatureIDs::hevcBrcFeature,
556             SetConstLambdaForUpdate, hucConstData, true);
557 
558         return MOS_STATUS_SUCCESS;
559     }
560 
SetConstDataHuCBrcUpdate() const561     MOS_STATUS HucBrcUpdatePkt::SetConstDataHuCBrcUpdate() const
562     {
563         ENCODE_FUNC_CALL();
564 
565         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
566 
567         auto hucConstData = (VdencHevcHucBrcConstantData *)m_allocator->LockResourceForWrite(const_cast<MOS_RESOURCE*>(&m_vdencBrcConstDataBuffer[m_pipeline->m_currRecycledBufIdx]));
568         ENCODE_CHK_NULL_RETURN(hucConstData);
569 
570         ENCODE_CHK_STATUS_RETURN(SetConstLambdaHucBrcUpdate(hucConstData));
571         RUN_FEATURE_INTERFACE_RETURN(HEVCEncodeBRC, HevcFeatureIDs::hevcBrcFeature,
572             SetConstForUpdate, hucConstData);
573 
574         // starting location in batch buffer for each slice
575         uint32_t baseLocation = m_hwInterface->m_vdencBatchBuffer1stGroupSize + m_hwInterface->m_vdencBatchBuffer2ndGroupSize;
576         uint32_t currentLocation = baseLocation;
577 
578         auto slcData = m_basicFeature->m_slcData;
579         // HCP_WEIGHTSOFFSETS_STATE + HCP_SLICE_STATE + HCP_PAK_INSERT_OBJECT + VDENC_WEIGHT_OFFSETS_STATE
580         for (uint32_t slcCount = 0; slcCount < m_basicFeature->m_numSlices; slcCount++)
581         {
582             m_basicFeature->m_curNumSlices = slcCount;
583             auto hevcSlcParams = &m_basicFeature->m_hevcSliceParams[slcCount];
584             // HuC FW require unit in Bytes
585             hucConstData->Slice[slcCount].SizeOfCMDs
586                 = (uint16_t)(m_hwInterface->m_vdencBatchBufferPerSliceConstSize + m_basicFeature->m_vdencBatchBufferPerSliceVarSize[slcCount]);
587 
588             // HCP_WEIGHTOFFSET_STATE cmd
589             RUN_FEATURE_INTERFACE_RETURN(
590                 HevcVdencWeightedPred,
591                 HevcFeatureIDs::hevcVdencWpFeature,
592                 SetHucBrcUpdateConstData,
593                 *hevcSlcParams,
594                 slcCount,
595                 m_hcpWeightOffsetStateCmdSize,
596                 currentLocation,
597                 *hucConstData);
598 
599             // HCP_SLICE_STATE cmd
600             hucConstData->Slice[slcCount].SliceState_StartInBytes = (uint16_t)currentLocation;  // HCP_WEIGHTOFFSET is not needed
601             currentLocation += m_hcpSliceStateCmdSize;
602 
603             // VDENC_WEIGHT_OFFSETS_STATE cmd
604             hucConstData->Slice[slcCount].VdencWeightOffset_StartInBytes                      // VdencWeightOffset cmd is the last one expect BatchBufferEnd cmd
605                 = (uint16_t)(baseLocation + hucConstData->Slice[slcCount].SizeOfCMDs - m_vdencWeightOffsetStateCmdSize - m_miBatchBufferEndCmdSize - m_alignSize[slcCount]);
606 
607             currentLocation += m_miBatchBufferEndCmdSize;
608 
609             // logic from PakInsertObject cmd
610             uint32_t bitSize         = (m_basicFeature->m_hevcSeqParams->SliceSizeControl) ? (hevcSlcParams->BitLengthSliceHeaderStartingPortion) : slcData[slcCount].BitSize;  // 40 for HEVC VDEnc Dynamic Slice
611             uint32_t byteSize = (bitSize + 7) >> 3;
612             uint32_t sliceHeaderSizeInBytes = (bitSize + 7) >> 3;
613             // 1st PakInsertObject cmd with AU, SPS, PPS headers only exists for the first slice
614             if (slcCount == 0)
615             {
616                 // assumes that there is no 3rd PakInsertObject cmd for SSC
617                 currentLocation += m_1stPakInsertObjectCmdSize;
618             }
619 
620             hucConstData->Slice[slcCount].SliceHeaderPIO_StartInBytes = (uint16_t)currentLocation;
621 
622             // HuC FW requires true slice header size in bits without byte alignment
623             hucConstData->Slice[slcCount].SliceHeader_SizeInBits = (uint16_t)(sliceHeaderSizeInBytes * 8);
624             if (!m_pipeline->IsFirstPass())
625             {
626                 PBSBuffer bsBuffer = &(m_basicFeature->m_bsBuffer);
627                 ENCODE_CHK_NULL_RETURN(bsBuffer);
628                 ENCODE_CHK_NULL_RETURN(bsBuffer->pBase);
629                 uint8_t *sliceHeaderLastByte = (uint8_t*)(bsBuffer->pBase + slcData[slcCount].SliceOffset + sliceHeaderSizeInBytes - 1);
630                 for (auto i = 0; i < 8; i++)
631                 {
632                     uint8_t mask = 1 << i;
633                     if (*sliceHeaderLastByte & mask)
634                     {
635                         hucConstData->Slice[slcCount].SliceHeader_SizeInBits -= (i + 1);
636                         break;
637                     }
638                 }
639             }
640 
641             baseLocation += hucConstData->Slice[slcCount].SizeOfCMDs;
642             currentLocation = baseLocation;
643         }
644 
645         m_allocator->UnLock(const_cast<MOS_RESOURCE*>(&m_vdencBrcConstDataBuffer[m_pipeline->m_currRecycledBufIdx]));
646 
647         return eStatus;
648     }
649 
Submit(MOS_COMMAND_BUFFER * commandBuffer,uint8_t packetPhase)650     MOS_STATUS HucBrcUpdatePkt::Submit(MOS_COMMAND_BUFFER *commandBuffer, uint8_t packetPhase)
651     {
652         ENCODE_FUNC_CALL();
653 
654         ENCODE_CHK_NULL_RETURN(m_basicFeature);
655         ENCODE_CHK_NULL_RETURN(m_basicFeature->m_recycleBuf);
656 
657         ENCODE_CHK_STATUS_RETURN(SetTcbrcMode());
658         ENCODE_CHK_STATUS_RETURN(ConstructBatchBufferHuCBRC(&m_vdencReadBatchBuffer[m_pipeline->m_currRecycledBufIdx][m_pipeline->GetCurrentPass()]));
659 
660         bool firstTaskInPhase = packetPhase & firstPacket;
661         bool requestProlog = false;
662 
663         auto brcFeature = dynamic_cast<HEVCEncodeBRC *>(m_featureManager->GetFeature(HevcFeatureIDs::hevcBrcFeature));
664         ENCODE_CHK_NULL_RETURN(brcFeature);
665 
666         uint16_t perfTag = m_pipeline->IsFirstPass() ? CODECHAL_ENCODE_PERFTAG_CALL_BRC_UPDATE : CODECHAL_ENCODE_PERFTAG_CALL_BRC_UPDATE_SECOND_PASS;
667         uint16_t pictureType = m_basicFeature->m_pictureCodingType;
668         if (m_basicFeature->m_pictureCodingType == B_TYPE && m_basicFeature->m_ref.IsLowDelay())
669         {
670             pictureType = 0;
671         }
672         SetPerfTag(perfTag, (uint16_t)m_basicFeature->m_mode, pictureType);
673 
674         if (!m_pipeline->IsSingleTaskPhaseSupported() || firstTaskInPhase)
675         {
676             // Send command buffer header at the beginning (OS dependent)
677             requestProlog = true;
678         }
679 
680         ENCODE_CHK_STATUS_RETURN(Execute(commandBuffer, true, requestProlog, BRC_UPDATE));
681 
682 #if _SW_BRC
683     if (!m_swBrc || !m_swBrc->SwBrcEnabled())
684     {
685 #endif
686         // Write HUC_STATUS mask: DW1 (mask value)
687         auto &storeDataParams            = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)();
688         storeDataParams                  = {};
689         storeDataParams.pOsResource      = m_basicFeature->m_recycleBuf->GetBuffer(VdencBrcPakMmioBuffer, 0);
690         storeDataParams.dwResourceOffset = sizeof(uint32_t);
691         storeDataParams.dwValue          = CODECHAL_VDENC_HEVC_BRC_HUC_STATUS_REENCODE_MASK;
692         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(commandBuffer));
693 
694         // store HUC_STATUS register: DW0 (actual value)
695         ENCODE_CHK_COND_RETURN((m_vdboxIndex > MHW_VDBOX_NODE_1), "ERROR - vdbox index exceed the maximum");
696         auto mmioRegisters              = m_hucItf->GetMmioRegisters(m_vdboxIndex);
697         auto &storeRegParams            = m_miItf->MHW_GETPAR_F(MI_STORE_REGISTER_MEM)();
698         storeDataParams                 = {};
699         storeRegParams.presStoreBuffer  = m_basicFeature->m_recycleBuf->GetBuffer(VdencBrcPakMmioBuffer, 0);
700         storeRegParams.dwOffset         = 0;
701         storeRegParams.dwRegister       = mmioRegisters->hucStatusRegOffset;
702         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_REGISTER_MEM)(commandBuffer));
703 #if _SW_BRC
704     }
705 #endif
706 
707         return MOS_STATUS_SUCCESS;
708     }
709 
ConstructBatchBufferHuCBRC(PMOS_RESOURCE batchBuffer)710     MOS_STATUS HucBrcUpdatePkt::ConstructBatchBufferHuCBRC(PMOS_RESOURCE batchBuffer)
711     {
712         ENCODE_FUNC_CALL();
713 
714         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
715 
716         ENCODE_CHK_NULL_RETURN(batchBuffer);
717 
718         m_batchbufferAddr = (uint8_t *)m_allocator->LockResourceForWrite(batchBuffer);
719         ENCODE_CHK_NULL_RETURN(m_batchbufferAddr);
720 
721         ENCODE_CHK_STATUS_RETURN(ConstructGroup1Cmds());
722         ENCODE_CHK_STATUS_RETURN(ConstructGroup2Cmds());
723         ENCODE_CHK_STATUS_RETURN(ConstructGroup3Cmds());
724 
725         m_allocator->UnLock(batchBuffer);
726 
727         return eStatus;
728     }
729 
ConstructGroup1Cmds()730     MOS_STATUS HucBrcUpdatePkt::ConstructGroup1Cmds()
731     {
732         ENCODE_FUNC_CALL();
733 
734         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
735 
736         MOS_COMMAND_BUFFER constructedCmdBuf;
737         MOS_ZeroMemory(&constructedCmdBuf, sizeof(constructedCmdBuf));
738         constructedCmdBuf.pCmdBase = constructedCmdBuf.pCmdPtr = (uint32_t *)m_batchbufferAddr;
739         constructedCmdBuf.iRemaining = MOS_ALIGN_CEIL(m_hwInterface->m_vdencReadBatchBufferSize, CODECHAL_PAGE_SIZE);
740 
741         // 1st Group : PIPE_MODE_SELECT
742         // set PIPE_MODE_SELECT command
743         // This is not needed for GEN11/GEN12 as single pass SAO is supported
744         // for Gen11+, we need to add MFX wait for both KIN and VRT before and after HCP Pipemode select...
745         auto &mfxWaitParams                 = m_miItf->MHW_GETPAR_F(MFX_WAIT)();
746         mfxWaitParams                       = {};
747         mfxWaitParams.iStallVdboxPipeline   = true;
748         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MFX_WAIT)(&constructedCmdBuf));
749 
750         SETPAR_AND_ADDCMD(HCP_PIPE_MODE_SELECT, m_hcpItf, &constructedCmdBuf);
751 
752         mfxWaitParams                       = {};
753         mfxWaitParams.iStallVdboxPipeline   = true;
754         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MFX_WAIT)(&constructedCmdBuf));
755 
756         MHW_BATCH_BUFFER TempBatchBuffer = {};
757         TempBatchBuffer.iSize       = MOS_ALIGN_CEIL(m_hwInterface->m_vdencReadBatchBufferSize, CODECHAL_PAGE_SIZE);
758         TempBatchBuffer.pData       = m_batchbufferAddr;
759 
760         // set MI_BATCH_BUFFER_END command
761         int32_t cmdBufOffset = constructedCmdBuf.iOffset;
762 
763         TempBatchBuffer.iCurrent    = constructedCmdBuf.iOffset;
764         TempBatchBuffer.iRemaining  = constructedCmdBuf.iRemaining;
765         ENCODE_CHK_STATUS_RETURN(m_miItf->AddMiBatchBufferEnd(nullptr, &TempBatchBuffer));
766         constructedCmdBuf.pCmdPtr     += (TempBatchBuffer.iCurrent - constructedCmdBuf.iOffset) / 4;
767         constructedCmdBuf.iOffset      = TempBatchBuffer.iCurrent;
768         constructedCmdBuf.iRemaining   = TempBatchBuffer.iRemaining;
769 
770         m_miBatchBufferEndCmdSize = constructedCmdBuf.iOffset - cmdBufOffset;
771 
772         uint32_t alignSize = m_hwInterface->m_vdencBatchBuffer1stGroupSize - constructedCmdBuf.iOffset;
773         if (alignSize)
774         {
775             for (uint32_t i = 0; i < (alignSize / 4); i++)
776             {
777                 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_NOOP)(&constructedCmdBuf));
778             }
779         }
780         ENCODE_CHK_COND_RETURN(
781             (m_hwInterface->m_vdencBatchBuffer1stGroupSize != constructedCmdBuf.iOffset),
782             "ERROR - constructed cmd size is mismatch with calculated");
783 
784         return eStatus;
785     }
786 
MHW_SETPAR_DECL_SRC(HCP_PIC_STATE,HucBrcUpdatePkt)787     MHW_SETPAR_DECL_SRC(HCP_PIC_STATE, HucBrcUpdatePkt)
788     {
789         params.bNotFirstPass = !m_pipeline->IsFirstPass();
790 
791         return MOS_STATUS_SUCCESS;
792     }
793 
ConstructGroup2Cmds()794     MOS_STATUS HucBrcUpdatePkt::ConstructGroup2Cmds()
795     {
796         ENCODE_FUNC_CALL();
797 
798         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
799 
800         MOS_COMMAND_BUFFER constructedCmdBuf;
801         MOS_ZeroMemory(&constructedCmdBuf, sizeof(constructedCmdBuf));
802         constructedCmdBuf.pCmdBase = (uint32_t *)m_batchbufferAddr;
803         constructedCmdBuf.iOffset = m_hwInterface->m_vdencBatchBuffer1stGroupSize;
804         constructedCmdBuf.pCmdPtr = constructedCmdBuf.pCmdBase + constructedCmdBuf.iOffset / 4;
805         constructedCmdBuf.iRemaining = MOS_ALIGN_CEIL(m_hwInterface->m_vdencReadBatchBufferSize, CODECHAL_PAGE_SIZE) - constructedCmdBuf.iOffset;
806 
807         SETPAR_AND_ADDCMD(VDENC_CMD1, m_vdencItf, &constructedCmdBuf);
808         m_basicFeature->m_picStateCmdStartInBytes = constructedCmdBuf.iOffset;
809 
810         // set HCP_PIC_STATE command
811         SETPAR_AND_ADDCMD(HCP_PIC_STATE, m_hcpItf, &constructedCmdBuf);
812         m_cmd2StartInBytes = constructedCmdBuf.iOffset;
813 
814         SETPAR_AND_ADDCMD(VDENC_CMD2, m_vdencItf, &constructedCmdBuf);
815 
816         // set MI_BATCH_BUFFER_END command
817         MHW_BATCH_BUFFER TempBatchBuffer = {};
818         TempBatchBuffer.iSize       = MOS_ALIGN_CEIL(m_hwInterface->m_vdencReadBatchBufferSize, CODECHAL_PAGE_SIZE);
819         TempBatchBuffer.pData       = m_batchbufferAddr;
820 
821         TempBatchBuffer.iCurrent    = constructedCmdBuf.iOffset;
822         TempBatchBuffer.iRemaining  = constructedCmdBuf.iRemaining;
823         ENCODE_CHK_STATUS_RETURN(m_miItf->AddMiBatchBufferEnd(nullptr, &TempBatchBuffer));
824         constructedCmdBuf.pCmdPtr     += (TempBatchBuffer.iCurrent - constructedCmdBuf.iOffset) / 4;
825         constructedCmdBuf.iOffset      = TempBatchBuffer.iCurrent;
826         constructedCmdBuf.iRemaining   = TempBatchBuffer.iRemaining;
827 
828         uint32_t alignSize = m_hwInterface->m_vdencBatchBuffer2ndGroupSize + m_hwInterface->m_vdencBatchBuffer1stGroupSize - constructedCmdBuf.iOffset;
829         if (alignSize)
830         {
831             for (uint32_t i = 0; i < (alignSize / 4); i++)
832             {
833                 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_NOOP)(&constructedCmdBuf));
834             }
835         }
836         ENCODE_CHK_COND_RETURN(
837             (m_hwInterface->m_vdencBatchBuffer2ndGroupSize + m_hwInterface->m_vdencBatchBuffer1stGroupSize != constructedCmdBuf.iOffset),
838             "ERROR - constructed cmd size is mismatch with calculated");
839 
840         return eStatus;
841     }
842 
ConstructGroup3Cmds()843     MOS_STATUS HucBrcUpdatePkt::ConstructGroup3Cmds()
844     {
845         ENCODE_FUNC_CALL();
846 
847         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
848         uint32_t cmdBufOffset = 0;
849 
850         ENCODE_CHK_NULL_RETURN(m_basicFeature->m_slcData);
851 
852         MOS_COMMAND_BUFFER constructedCmdBuf;
853         MOS_ZeroMemory(&constructedCmdBuf, sizeof(constructedCmdBuf));
854         constructedCmdBuf.pCmdBase = (uint32_t *)m_batchbufferAddr;
855         constructedCmdBuf.iOffset = m_hwInterface->m_vdencBatchBuffer1stGroupSize + m_hwInterface->m_vdencBatchBuffer2ndGroupSize;
856         constructedCmdBuf.pCmdPtr = constructedCmdBuf.pCmdBase + constructedCmdBuf.iOffset / 4;
857         constructedCmdBuf.iRemaining = MOS_ALIGN_CEIL(m_hwInterface->m_vdencReadBatchBufferSize, CODECHAL_PAGE_SIZE) - constructedCmdBuf.iOffset;
858 
859         // slice level cmds for each slice
860         PCODEC_ENCODER_SLCDATA slcData = m_basicFeature->m_slcData;
861         for (uint32_t startLCU = 0, slcCount = 0; slcCount < m_basicFeature->m_numSlices; slcCount++)
862         {
863             m_basicFeature->m_curNumSlices    = slcCount;
864             m_basicFeature->m_lastSliceInTile = true;
865 
866             if (m_pipeline->IsFirstPass())
867             {
868                 slcData[slcCount].CmdOffset = startLCU * (m_hcpItf->GetHcpPakObjSize()) * sizeof(uint32_t);
869             }
870 
871             RUN_FEATURE_INTERFACE_RETURN(HevcEncodeTile, HevcFeatureIDs::encodeTile, SetCurrentTileFromSliceIndex, slcCount, m_pipeline);
872 
873             m_basicFeature->m_vdencBatchBufferPerSliceVarSize[slcCount] = 0;
874             m_basicFeature->m_vdencBatchBufferPerSlicePart2Size[slcCount] = 0;
875 
876             // set HCP_WEIGHTOFFSET_STATE command
877             // This slice level command is issued, if the weighted_pred_flag or weighted_bipred_flag equals one.
878             //        If zero, then this command is not issued.
879             AddAllCmds_HCP_WEIGHTOFFSET_STATE(&constructedCmdBuf);
880 
881             // set HCP_SLICE_STATE command
882             cmdBufOffset = constructedCmdBuf.iOffset;
883             SETPAR_AND_ADDCMD(HCP_SLICE_STATE, m_hcpItf, &constructedCmdBuf);
884             m_hcpSliceStateCmdSize = constructedCmdBuf.iOffset - cmdBufOffset;
885 
886             // set MI_BATCH_BUFFER_END command
887             MHW_BATCH_BUFFER TempBatchBuffer = {};
888             TempBatchBuffer.iSize            = MOS_ALIGN_CEIL(m_hwInterface->m_vdencReadBatchBufferSize, CODECHAL_PAGE_SIZE);
889             TempBatchBuffer.pData            = m_batchbufferAddr;
890 
891             TempBatchBuffer.iCurrent   = constructedCmdBuf.iOffset;
892             TempBatchBuffer.iRemaining = constructedCmdBuf.iRemaining;
893             ENCODE_CHK_STATUS_RETURN(m_miItf->AddMiBatchBufferEnd(nullptr, &TempBatchBuffer));
894             constructedCmdBuf.pCmdPtr += (TempBatchBuffer.iCurrent - constructedCmdBuf.iOffset) / 4;
895             constructedCmdBuf.iOffset    = TempBatchBuffer.iCurrent;
896             constructedCmdBuf.iRemaining = TempBatchBuffer.iRemaining;
897 
898             m_basicFeature->m_vdencBatchBufferPerSlicePart2Start[slcCount] = constructedCmdBuf.iOffset;
899 
900             AddAllCmds_HCP_PAK_INSERT_OBJECT_SLICE(&constructedCmdBuf);
901 
902             cmdBufOffset = constructedCmdBuf.iOffset;
903             SETPAR_AND_ADDCMD(VDENC_WEIGHTSOFFSETS_STATE, m_vdencItf, &constructedCmdBuf);
904             m_vdencWeightOffsetStateCmdSize = constructedCmdBuf.iOffset - cmdBufOffset;
905 
906             // set MI_BATCH_BUFFER_END command
907             TempBatchBuffer = {};
908             TempBatchBuffer.iSize       = MOS_ALIGN_CEIL(m_hwInterface->m_vdencReadBatchBufferSize, CODECHAL_PAGE_SIZE);
909             TempBatchBuffer.pData       = m_batchbufferAddr;
910 
911             TempBatchBuffer.iCurrent    = constructedCmdBuf.iOffset;
912             TempBatchBuffer.iRemaining  = constructedCmdBuf.iRemaining;
913             ENCODE_CHK_STATUS_RETURN(m_miItf->AddMiBatchBufferEnd(nullptr, &TempBatchBuffer));
914             constructedCmdBuf.pCmdPtr     += (TempBatchBuffer.iCurrent - constructedCmdBuf.iOffset) / 4;
915             constructedCmdBuf.iOffset      = TempBatchBuffer.iCurrent;
916             constructedCmdBuf.iRemaining   = TempBatchBuffer.iRemaining;
917 
918             m_alignSize[slcCount] = MOS_ALIGN_CEIL(constructedCmdBuf.iOffset, 64) - constructedCmdBuf.iOffset;
919             if (m_alignSize[slcCount] > 0)
920             {
921                 for (uint32_t i = 0; i < (m_alignSize[slcCount] / 4); i++)
922                 {
923                     ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_NOOP)(&constructedCmdBuf));
924                 }
925             }
926             m_basicFeature->m_vdencBatchBufferPerSliceVarSize[slcCount] += m_alignSize[slcCount];
927             m_basicFeature->m_vdencBatchBufferPerSlicePart2Size[slcCount] = constructedCmdBuf.iOffset - m_basicFeature->m_vdencBatchBufferPerSlicePart2Start[slcCount];
928             startLCU += m_basicFeature->m_hevcSliceParams[slcCount].NumLCUsInSlice;
929         }
930 
931         m_slbDataSizeInBytes = constructedCmdBuf.iOffset;
932 
933         return eStatus;
934     }
935 
GetMaxAllowedSlices(uint8_t levelIdc) const936     uint32_t HucBrcUpdatePkt::GetMaxAllowedSlices(uint8_t levelIdc) const
937     {
938         uint32_t maxAllowedNumSlices = 0;
939 
940         switch (levelIdc)
941         {
942         case 10:
943         case 20:
944             maxAllowedNumSlices = 16;
945             break;
946         case 21:
947             maxAllowedNumSlices = 20;
948             break;
949         case 30:
950             maxAllowedNumSlices = 30;
951             break;
952         case 31:
953             maxAllowedNumSlices = 40;
954             break;
955         case 40:
956         case 41:
957             maxAllowedNumSlices = 75;
958             break;
959         case 50:
960         case 51:
961         case 52:
962             maxAllowedNumSlices = 200;
963             break;
964         case 60:
965         case 61:
966         case 62:
967             maxAllowedNumSlices = 600;
968             break;
969         default:
970             maxAllowedNumSlices = 0;
971             break;
972         }
973 
974         return maxAllowedNumSlices;
975     }
976 
977 #if USE_CODECHAL_DEBUG_TOOL
DumpHucBrcUpdate(bool isInput)978     MOS_STATUS HucBrcUpdatePkt::DumpHucBrcUpdate(bool isInput)
979     {
980         ENCODE_FUNC_CALL();
981 
982         CodechalDebugInterface *debugInterface = m_pipeline->GetDebugInterface();
983         ENCODE_CHK_NULL_RETURN(debugInterface);
984 
985         auto virtualAddrParams = m_hucItf->MHW_GETPAR_F(HUC_VIRTUAL_ADDR_STATE)();
986         int32_t currentPass = m_pipeline->GetCurrentPass();
987 
988         if (isInput)
989         {
990             //Dump HucBrcUpdate input buffers
991             ENCODE_CHK_STATUS_RETURN(debugInterface->DumpHucDmem(
992                 &m_vdencBrcUpdateDmemBuffer[m_pipeline->m_currRecycledBufIdx][currentPass],
993                 m_vdencBrcUpdateDmemBufferSize,
994                 currentPass,
995                 hucRegionDumpUpdate));
996 
997             // Region 1 - VDENC Statistics Buffer dump
998             HevcBasicFeature *hevcBasicFeature  = dynamic_cast<HevcBasicFeature *>(m_basicFeature);
999             ENCODE_CHK_NULL_RETURN(hevcBasicFeature);
1000             uint32_t vdencBRCStatsBufferSize = 1216;
1001             uint32_t size = MOS_ALIGN_CEIL(vdencBRCStatsBufferSize * hevcBasicFeature->m_maxTileNumber, CODECHAL_PAGE_SIZE);
1002             ENCODE_CHK_STATUS_RETURN(DumpRegion(1, "_VdencStats", true, hucRegionDumpUpdate, size));
1003 
1004             // Region 2 - PAK Statistics Buffer dump
1005             size = MOS_ALIGN_CEIL(HevcBasicFeature::m_sizeOfHcpPakFrameStats * hevcBasicFeature->m_maxTileNumber, CODECHAL_PAGE_SIZE);
1006             ENCODE_CHK_STATUS_RETURN(DumpRegion(2, "_PakStats", true, hucRegionDumpUpdate, size));
1007 
1008             // Region 3 - Input SLB Buffer
1009             ENCODE_CHK_STATUS_RETURN(DumpRegion(3, "_Slb", true, hucRegionDumpUpdate, m_hwInterface->m_vdencReadBatchBufferSize));
1010 
1011             // Region 4 - Constant Data Buffer dump
1012             ENCODE_CHK_STATUS_RETURN(DumpRegion(4, "_ConstData", true, hucRegionDumpUpdate, m_vdencBrcConstDataBufferSize));
1013 
1014             // Region 7 - Slice Stat Streamout (Input)
1015             ENCODE_CHK_STATUS_RETURN(DumpRegion(7, "_SliceStat", true, hucRegionDumpUpdate, CODECHAL_HEVC_MAX_NUM_SLICES_LVL_6 * CODECHAL_CACHELINE_SIZE));
1016 
1017             // Region 8 - PAK MMIO Buffer dump
1018             ENCODE_CHK_STATUS_RETURN(DumpRegion(8, "_PakMmio", true, hucRegionDumpUpdate, sizeof(CodechalVdencHevcPakInfo)));
1019 
1020             // Region 9 - Streamin Buffer for ROI (Input)
1021             auto streamInBufferSize = (MOS_ALIGN_CEIL(m_basicFeature->m_frameWidth, 64) / 32) * (MOS_ALIGN_CEIL(m_basicFeature->m_frameHeight, 64) / 32) * CODECHAL_CACHELINE_SIZE;
1022             ENCODE_CHK_STATUS_RETURN(DumpRegion(9, "_RoiStreamin", true, hucRegionDumpUpdate, streamInBufferSize));
1023 
1024             // Region 10 - Delta QP for ROI Buffer
1025             auto vdencDeltaQpBuffer = virtualAddrParams.regionParams[10].presRegion;
1026             if (vdencDeltaQpBuffer)
1027             {
1028                 ENCODE_CHK_STATUS_RETURN(DumpRegion(10, "_DeltaQp", true, hucRegionDumpUpdate, vdencDeltaQpBuffer->iSize));
1029             }
1030         }
1031         else
1032         {
1033             // Region 5 - Output SLB Buffer
1034             ENCODE_CHK_STATUS_RETURN(DumpRegion(5, "_Slb", false, hucRegionDumpUpdate, m_hwInterface->m_vdenc2ndLevelBatchBufferSize));
1035 
1036             // Region 11 - Output ROI Streamin Buffer
1037             auto vdencOutputROIStreaminBuffer = virtualAddrParams.regionParams[11].presRegion;
1038             if (vdencOutputROIStreaminBuffer)
1039             {
1040                 ENCODE_CHK_STATUS_RETURN(DumpRegion(11, "_RoiStreamin", false, hucRegionDumpUpdate, vdencOutputROIStreaminBuffer->iSize));
1041             }
1042         }
1043 
1044         // Region 0 - History Buffer dump (Input/Output)
1045         ENCODE_CHK_STATUS_RETURN(DumpRegion(0, "_History", isInput, hucRegionDumpUpdate));
1046 
1047         // Region 6 - Data from Pictures for Weighted Prediction (Input/Output)
1048         ENCODE_CHK_STATUS_RETURN(DumpRegion(6, "_PicsData", isInput, hucRegionDumpUpdate, CODECHAL_PAGE_SIZE * 4));
1049 
1050         // Region 15 - Debug Output
1051         auto debugBuffer = virtualAddrParams.regionParams[15].presRegion;
1052         if (debugBuffer)
1053         {
1054             ENCODE_CHK_STATUS_RETURN(DumpRegion(15, "_Debug", isInput, hucRegionDumpUpdate, debugBuffer->iSize));
1055         }
1056 
1057         return MOS_STATUS_SUCCESS;
1058     }
1059 
DumpInput()1060     MOS_STATUS HucBrcUpdatePkt::DumpInput()
1061     {
1062         ENCODE_FUNC_CALL();
1063         DumpHucBrcUpdate(true);
1064         return MOS_STATUS_SUCCESS;
1065     }
1066 #endif
1067 
MHW_SETPAR_DECL_SRC(HCP_PIPE_MODE_SELECT,HucBrcUpdatePkt)1068     MHW_SETPAR_DECL_SRC(HCP_PIPE_MODE_SELECT, HucBrcUpdatePkt)
1069     {
1070         params.codecStandardSelect = CodecHal_GetStandardFromMode(m_basicFeature->m_mode) - CODECHAL_HCP_BASE;
1071         params.bStreamOutEnabled   = true;
1072         params.bVdencEnabled       = true;
1073         params.multiEngineMode     = MHW_VDBOX_HCP_MULTI_ENGINE_MODE_FE_LEGACY;
1074         params.pipeWorkMode        = MHW_VDBOX_HCP_PIPE_WORK_MODE_LEGACY;
1075 
1076         MhwCpInterface *cpInterface     = m_hwInterface->GetCpInterface();
1077         bool            twoPassScalable = params.multiEngineMode != MHW_VDBOX_HCP_MULTI_ENGINE_MODE_FE_LEGACY && !params.bTileBasedReplayMode;
1078 
1079         ENCODE_CHK_NULL_RETURN(cpInterface);
1080         params.setProtectionSettings = [=](uint32_t *data) { return cpInterface->SetProtectionSettingsForHcpPipeModeSelect(data, twoPassScalable); };
1081 
1082         return MOS_STATUS_SUCCESS;
1083     }
1084 
MHW_SETPAR_DECL_SRC(HCP_SLICE_STATE,HucBrcUpdatePkt)1085     MHW_SETPAR_DECL_SRC(HCP_SLICE_STATE, HucBrcUpdatePkt)
1086     {
1087         ENCODE_FUNC_CALL();
1088 
1089         params.intrareffetchdisable = m_basicFeature->m_pakOnlyPass;
1090 
1091         return MOS_STATUS_SUCCESS;
1092     }
1093 
AddAllCmds_HCP_PAK_INSERT_OBJECT_SLICE(PMOS_COMMAND_BUFFER cmdBuffer) const1094     MOS_STATUS HucBrcUpdatePkt::AddAllCmds_HCP_PAK_INSERT_OBJECT_SLICE(PMOS_COMMAND_BUFFER cmdBuffer) const
1095     {
1096         ENCODE_FUNC_CALL();
1097 
1098         ENCODE_CHK_NULL_RETURN(cmdBuffer);
1099 
1100         auto &params = m_hcpItf->MHW_GETPAR_F(HCP_PAK_INSERT_OBJECT)();
1101 
1102         uint32_t                   cmdBufOffset    = 0;
1103         uint32_t                   bitSize         = 0;
1104         uint32_t                   offSet          = 0;
1105         PCODECHAL_NAL_UNIT_PARAMS *ppNalUnitParams = (CODECHAL_NAL_UNIT_PARAMS **)m_basicFeature->m_nalUnitParams;
1106         PBSBuffer                  pBsBuffer       = &(m_basicFeature->m_bsBuffer);
1107 
1108         params = {};
1109         // Insert slice header
1110         params.bLastHeader              = true;
1111         params.bEmulationByteBitsInsert = true;
1112 
1113         // App does the slice header packing, set the skip count passed by the app
1114         PCODEC_ENCODER_SLCDATA slcData    = m_basicFeature->m_slcData;
1115         uint32_t               currSlcIdx = m_basicFeature->m_curNumSlices;
1116 
1117         params.uiSkipEmulationCheckCount = slcData[currSlcIdx].SkipEmulationByteCount;
1118         bitSize                          = slcData[currSlcIdx].BitSize;
1119         offSet                           = slcData[currSlcIdx].SliceOffset;
1120 
1121         if (m_basicFeature->m_hevcSeqParams->SliceSizeControl)
1122         {
1123             params.bLastHeader                = false;
1124             params.bEmulationByteBitsInsert   = false;
1125             bitSize                           = m_basicFeature->m_hevcSliceParams->BitLengthSliceHeaderStartingPortion;
1126             params.bResetBitstreamStartingPos = true;
1127             params.dwPadding                  = (MOS_ALIGN_CEIL((bitSize + 7) >> 3, sizeof(uint32_t))) / sizeof(uint32_t);
1128             params.dataBitsInLastDw           = bitSize % 32;
1129             if (params.dataBitsInLastDw == 0)
1130             {
1131                 params.dataBitsInLastDw = 32;
1132             }
1133 
1134             m_hcpItf->MHW_ADDCMD_F(HCP_PAK_INSERT_OBJECT)(cmdBuffer);
1135             uint32_t byteSize = (bitSize + 7) >> 3;
1136             m_basicFeature->m_vdencBatchBufferPerSliceVarSize[m_basicFeature->m_curNumSlices] += (MOS_ALIGN_CEIL(byteSize, sizeof(uint32_t))) / sizeof(uint32_t) * 4;
1137             if (byteSize)
1138             {
1139                 MHW_MI_CHK_NULL(pBsBuffer);
1140                 MHW_MI_CHK_NULL(pBsBuffer->pBase);
1141                 uint8_t *data = (uint8_t *)(pBsBuffer->pBase + offSet);
1142                 MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, nullptr, data, byteSize));
1143             }
1144 
1145             // Send HCP_PAK_INSERT_OBJ command. For dynamic slice, we are skipping the beginning part of slice header.
1146             params.bLastHeader = true;
1147             bitSize            = slcData[currSlcIdx].BitSize - m_basicFeature->m_hevcSliceParams->BitLengthSliceHeaderStartingPortion;
1148             offSet += ((m_basicFeature->m_hevcSliceParams->BitLengthSliceHeaderStartingPortion + 7) / 8);  // Skips the first 5 bytes which is Start Code + Nal Unit Header
1149             params.dwPadding        = (MOS_ALIGN_CEIL((bitSize + 7) >> 3, sizeof(uint32_t))) / sizeof(uint32_t);
1150             params.dataBitsInLastDw = bitSize % 32;
1151             if (params.dataBitsInLastDw == 0)
1152             {
1153                 params.dataBitsInLastDw = 32;
1154             }
1155             params.bResetBitstreamStartingPos = true;
1156             cmdBufOffset                      = cmdBuffer->iOffset;
1157             m_hcpItf->MHW_ADDCMD_F(HCP_PAK_INSERT_OBJECT)(cmdBuffer);
1158             byteSize = (bitSize + 7) >> 3;
1159             if (byteSize)
1160             {
1161                 MHW_MI_CHK_NULL(pBsBuffer);
1162                 MHW_MI_CHK_NULL(pBsBuffer->pBase);
1163                 uint8_t *data = (uint8_t *)(pBsBuffer->pBase + offSet);
1164                 MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, nullptr, data, byteSize));
1165             }
1166             m_basicFeature->m_vdencBatchBufferPerSliceVarSize[m_basicFeature->m_curNumSlices] += (cmdBuffer->iOffset - cmdBufOffset);
1167         }
1168         else
1169         {
1170             params.dwPadding        = (MOS_ALIGN_CEIL((bitSize + 7) >> 3, sizeof(uint32_t))) / sizeof(uint32_t);
1171             params.dataBitsInLastDw = bitSize % 32;
1172             if (params.dataBitsInLastDw == 0)
1173             {
1174                 params.dataBitsInLastDw = 32;
1175             }
1176             m_hcpItf->MHW_ADDCMD_F(HCP_PAK_INSERT_OBJECT)(cmdBuffer);
1177             uint32_t byteSize = (bitSize + 7) >> 3;
1178             m_basicFeature->m_vdencBatchBufferPerSliceVarSize[m_basicFeature->m_curNumSlices] += (MOS_ALIGN_CEIL(byteSize, sizeof(uint32_t))) / sizeof(uint32_t) * 4;
1179             if (byteSize)
1180             {
1181                 MHW_MI_CHK_NULL(pBsBuffer);
1182                 MHW_MI_CHK_NULL(pBsBuffer->pBase);
1183                 uint8_t *data = (uint8_t *)(pBsBuffer->pBase + offSet);
1184                 MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(m_osInterface, cmdBuffer, nullptr, data, byteSize));
1185             }
1186         }
1187 
1188         return MOS_STATUS_SUCCESS;
1189     }
1190 
AddAllCmds_HCP_WEIGHTOFFSET_STATE(PMOS_COMMAND_BUFFER cmdBuffer) const1191     MOS_STATUS HucBrcUpdatePkt::AddAllCmds_HCP_WEIGHTOFFSET_STATE(PMOS_COMMAND_BUFFER cmdBuffer) const
1192     {
1193         ENCODE_FUNC_CALL();
1194 
1195         ENCODE_CHK_NULL_RETURN(cmdBuffer);
1196 
1197         auto &params                 = m_hcpItf->MHW_GETPAR_F(HCP_WEIGHTOFFSET_STATE)();
1198         params                       = {};
1199         auto wpFeature = dynamic_cast<HevcVdencWeightedPred *>(m_featureManager->GetFeature(HevcFeatureIDs::hevcVdencWpFeature));
1200         ENCODE_CHK_NULL_RETURN(wpFeature);
1201 
1202         if (wpFeature->IsEnabled() && m_basicFeature->m_hevcPicParams->bEnableGPUWeightedPrediction)
1203         {
1204             MHW_CHK_STATUS_RETURN(wpFeature->MHW_SETPAR_F(HCP_WEIGHTOFFSET_STATE)(params));
1205 
1206             uint32_t cmdBufOffset = 0;
1207             // 1st HCP_WEIGHTOFFSET_STATE cmd - P & B
1208             if (m_basicFeature->m_hevcSliceParams->slice_type == encodeHevcPSlice || m_basicFeature->m_hevcSliceParams->slice_type == encodeHevcBSlice)
1209             {
1210                 params.ucList = LIST_0;
1211                 cmdBufOffset = cmdBuffer->iOffset;
1212                 m_hcpItf->MHW_ADDCMD_F(HCP_WEIGHTOFFSET_STATE)(cmdBuffer);
1213                 m_hcpWeightOffsetStateCmdSize = cmdBuffer->iOffset - cmdBufOffset;
1214                 // 1st HcpWeightOffset cmd is not always inserted (except weighted prediction + P, B slices)
1215                 m_basicFeature->m_vdencBatchBufferPerSliceVarSize[m_basicFeature->m_curNumSlices] += m_hcpWeightOffsetStateCmdSize;
1216             }
1217 
1218             // 2nd HCP_WEIGHTOFFSET_STATE cmd - B only
1219             if (m_basicFeature->m_hevcSliceParams->slice_type == encodeHevcBSlice)
1220             {
1221                 params.ucList = LIST_1;
1222                 cmdBufOffset = cmdBuffer->iOffset;
1223                 m_hcpItf->MHW_ADDCMD_F(HCP_WEIGHTOFFSET_STATE)(cmdBuffer);
1224                 m_hcpWeightOffsetStateCmdSize = cmdBuffer->iOffset - cmdBufOffset;
1225                 // 1st HcpWeightOffset cmd is not always inserted (except weighted prediction + P, B slices)
1226                 m_basicFeature->m_vdencBatchBufferPerSliceVarSize[m_basicFeature->m_curNumSlices] += m_hcpWeightOffsetStateCmdSize;
1227             }
1228         }
1229 
1230         return MOS_STATUS_SUCCESS;
1231     }
1232 
SetTcbrcMode()1233     MOS_STATUS HucBrcUpdatePkt::SetTcbrcMode()
1234     {
1235         ENCODE_FUNC_CALL();
1236         ENCODE_CHK_NULL_RETURN(m_basicFeature);
1237         ENCODE_CHK_NULL_RETURN(m_basicFeature->m_hevcSeqParams);
1238         ENCODE_CHK_NULL_RETURN(m_hwInterface);
1239 
1240         if (m_basicFeature->m_newSeq)
1241         {
1242             //tcbrc mode set by scenarioInfo
1243             uint8_t tcbrcQualityBoostFromScenario = 0;
1244             switch (m_basicFeature->m_hevcSeqParams->ScenarioInfo)
1245             {
1246             case ESCENARIO_REMOTEGAMING:
1247                 tcbrcQualityBoostFromScenario = 0;
1248                 break;
1249             case ESCENARIO_VIDEOCONFERENCE:
1250                 tcbrcQualityBoostFromScenario = 1;
1251                 break;
1252             default:
1253                 tcbrcQualityBoostFromScenario = 0;
1254             }
1255 
1256 #if (_DEBUG || _RELEASE_INTERNAL)
1257             //tcbrc mode override by reg key
1258             uint8_t tcbrcQualityBoostFromRegkey = 3;
1259 
1260             MediaUserSetting::Value outValue;
1261             ReadUserSetting(m_userSettingPtr,
1262                 outValue,
1263                 "TCBRC Quality Boost Mode",
1264                 MediaUserSetting::Group::Sequence);
1265             tcbrcQualityBoostFromRegkey = static_cast<uint8_t>(outValue.Get<int32_t>());
1266             //if FrameSizeBoostForSceneChange is set by regkey, then override it
1267             if (tcbrcQualityBoostFromRegkey == 0 || tcbrcQualityBoostFromRegkey == 1 || tcbrcQualityBoostFromRegkey == 2)
1268             {
1269                 m_tcbrcQualityBoost = tcbrcQualityBoostFromRegkey;
1270                 ENCODE_VERBOSEMESSAGE("TCBRC FrameSizeBoostForSceneChange is override by regkey!");
1271             }
1272             else
1273 #endif
1274             {
1275                 m_tcbrcQualityBoost = tcbrcQualityBoostFromScenario;
1276             }
1277 #if (_DEBUG || _RELEASE_INTERNAL)
1278             ReportUserSettingForDebug(m_userSettingPtr,
1279                 "TCBRC Quality Boost Mode",
1280                 m_tcbrcQualityBoost,
1281                 MediaUserSetting::Group::Sequence);
1282 #endif
1283         }
1284         return MOS_STATUS_SUCCESS;
1285     }
1286 
1287     }
1288