1 /*
2 * Copyright (c) 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 //! \file     encode_vdenc_lpla_analysis.cpp
24 //! \brief    Implementation for encode lowpower lookahead(Lookahead Analysis Pass) feature
25 //!
26 
27 #include "encode_vdenc_lpla_analysis.h"
28 #include "encode_hevc_vdenc_feature_manager.h"
29 
30 namespace encode
31 {
VdencLplaAnalysis(MediaFeatureManager * featureManager,EncodeAllocator * allocator,CodechalHwInterfaceNext * hwInterface,void * constSettings)32     VdencLplaAnalysis::VdencLplaAnalysis(
33         MediaFeatureManager *featureManager,
34         EncodeAllocator     *allocator,
35         CodechalHwInterfaceNext *hwInterface,
36         void                *constSettings) :
37         MediaFeature(constSettings, hwInterface ? hwInterface->GetOsInterface() : nullptr),
38         m_hwInterface(hwInterface),
39         m_allocator(allocator)
40     {
41         auto encFeatureManager = dynamic_cast<EncodeHevcVdencFeatureManager *>(featureManager);
42         ENCODE_CHK_NULL_NO_STATUS_RETURN(encFeatureManager);
43 
44         m_basicFeature = dynamic_cast<EncodeBasicFeature *>(encFeatureManager->GetFeature(FeatureIDs::basicFeature));
45         ENCODE_CHK_NULL_NO_STATUS_RETURN(m_basicFeature);
46         ENCODE_CHK_NULL_NO_STATUS_RETURN(hwInterface);
47         m_osInterface = hwInterface->GetOsInterface();
48 
49 #if (_DEBUG || _RELEASE_INTERNAL)
50         MediaUserSetting::Value outValue;
51         auto statusKey = ReadUserSettingForDebug(m_userSettingPtr,
52             outValue,
53             "lpla ds data address",
54             MediaUserSetting::Group::Sequence);
55         const char *path_buffer = outValue.ConstString().c_str();
56 
57         if (statusKey == MOS_STATUS_SUCCESS && strcmp(path_buffer, "") != 0)
58             m_useDSData = true;
59 
60         if (m_useDSData)
61         {
62             std::ifstream fp(path_buffer);
63             if (!fp.is_open())
64             {
65                 m_useDSData = false;
66                 ENCODE_ASSERTMESSAGE("lpla ds data load failed!");
67                 return;
68             }
69 
70             std::string   line = "";
71             getline(fp, line);
72             for (int i = 0; i < 600; i++)
73             {
74                 getline(fp, line);
75                 std::string        number = "";
76                 std::istringstream readstr(line);
77                 getline(readstr, number, ',');
78                 getline(readstr, number, ',');
79                 getline(readstr, number, ',');
80                 m_statsBuffer[i][2] = atoi(number.c_str());
81                 m_statsBuffer[i][2] *= 4;
82                 getline(readstr, number, ',');
83                 m_statsBuffer[i][0] = atoi(number.c_str());
84                 getline(readstr, number, ',');
85                 m_statsBuffer[i][1] = atoi(number.c_str());
86                 m_statsBuffer[i][1] *= 8;
87             }
88         }
89 #endif
90     }
91 
~VdencLplaAnalysis()92     VdencLplaAnalysis::~VdencLplaAnalysis()
93     {
94         if (m_lplaHelper)
95         {
96             MOS_Delete(m_lplaHelper);
97             m_lplaHelper = nullptr;
98         }
99     }
100 
Init(void * setting)101     MOS_STATUS VdencLplaAnalysis::Init(void *setting)
102     {
103         ENCODE_FUNC_CALL();
104         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
105 
106         m_hcpItf = m_hwInterface->GetHcpInterfaceNext();
107         ENCODE_CHK_NULL_RETURN(m_hcpItf);
108 
109         m_miItf = m_hwInterface->GetMiInterfaceNext();
110         ENCODE_CHK_NULL_RETURN(m_miItf);
111 
112         m_lplaHelper = MOS_New(EncodeLPLA);
113         ENCODE_CHK_NULL_RETURN(m_lplaHelper);
114 
115         ENCODE_CHK_STATUS_RETURN(AllocateResources());
116 
117         return eStatus;
118     }
119 
SetSequenceStructs()120     MOS_STATUS VdencLplaAnalysis::SetSequenceStructs()
121     {
122         ENCODE_FUNC_CALL();
123         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
124 
125         if (m_hevcSeqParams->MaxAdaptiveGopPicSize < m_hevcSeqParams->MinAdaptiveGopPicSize)
126         {
127             m_hevcSeqParams->MaxAdaptiveGopPicSize = m_hevcSeqParams->MinAdaptiveGopPicSize;
128         }
129         else if ((m_hevcSeqParams->MaxAdaptiveGopPicSize > 0) && (m_hevcSeqParams->MinAdaptiveGopPicSize == 0))
130         {
131             m_hevcSeqParams->MinAdaptiveGopPicSize = (m_hevcSeqParams->MaxAdaptiveGopPicSize + 1) >> 1;
132         }
133 
134         m_lookaheadAdaptiveI = (m_hevcSeqParams->MaxAdaptiveGopPicSize != m_hevcSeqParams->MinAdaptiveGopPicSize);
135         if (!m_lookaheadAdaptiveI && (m_hevcSeqParams->MaxAdaptiveGopPicSize == 0))
136         {
137             if (m_hevcSeqParams->GopPicSize > 0)
138             {
139                 m_hevcSeqParams->MaxAdaptiveGopPicSize = m_hevcSeqParams->GopPicSize;
140                 m_hevcSeqParams->MinAdaptiveGopPicSize = m_hevcSeqParams->GopPicSize;
141             }
142             else
143             {
144                 ENCODE_ASSERTMESSAGE("Invalid GopPicSize in LPLA!");
145                 return MOS_STATUS_INVALID_PARAMETER;
146             }
147         }
148 
149         ENCODE_CHK_STATUS_RETURN(m_lplaHelper->CheckFrameRate(m_hevcSeqParams->FrameRate.Numerator,
150             m_hevcSeqParams->FrameRate.Denominator,
151             m_hevcSeqParams->TargetBitRate,
152             m_averageFrameSize));
153 
154         ENCODE_CHK_STATUS_RETURN(m_lplaHelper->CheckVBVBuffer(m_hevcSeqParams->VBVBufferSizeInBit,
155             m_hevcSeqParams->InitVBVBufferFullnessInBit));
156 
157         if (m_targetBufferFulness == 0 && m_prevTargetFrameSize == 0)
158         {
159             m_targetBufferFulness            = m_hevcSeqParams->VBVBufferSizeInBit - m_hevcSeqParams->InitVBVBufferFullnessInBit;
160             uint32_t initVbvFullnessInFrames = MOS_MIN(m_hevcSeqParams->InitVBVBufferFullnessInBit, m_hevcSeqParams->VBVBufferSizeInBit) / m_averageFrameSize;
161             uint32_t vbvBufferSizeInFrames   = m_hevcSeqParams->VBVBufferSizeInBit / m_averageFrameSize;
162             uint32_t encBufferFullness       = (vbvBufferSizeInFrames - initVbvFullnessInFrames) * m_averageFrameSize;
163             m_bufferFulnessError             = (int32_t)((int64_t)m_targetBufferFulness - (int64_t)encBufferFullness);
164         }
165 
166         return eStatus;
167     }
168 
EnableStreamIn(bool is1stPass,bool isLastPass,bool & streaminEnabled)169     MOS_STATUS VdencLplaAnalysis::EnableStreamIn(bool is1stPass, bool isLastPass, bool &streaminEnabled)
170     {
171         ENCODE_FUNC_CALL();
172         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
173 
174         if (!m_enabled)
175         {
176             return eStatus;
177         }
178 
179         if (m_hevcSeqParams->MaxAdaptiveGopPicSize > 0)
180         {
181             bool forceIntra = m_intraInterval >= m_hevcSeqParams->MaxAdaptiveGopPicSize;
182             if (((!is1stPass && isLastPass) || forceIntra) && (m_hevcPicParams->CodingType != I_TYPE))
183             {
184                 streaminEnabled = true;
185             }
186 
187             if (!m_lookaheadAdaptiveI && isLastPass)
188             {
189                 m_intraInterval = forceIntra ? 1 : m_intraInterval + 1;
190             }
191         }
192         m_streamInEnabled = m_enabled && streaminEnabled;
193 
194         return eStatus;
195     }
196 
SetConditionalPass(bool blastPass,bool & condPass)197     MOS_STATUS VdencLplaAnalysis::SetConditionalPass(bool blastPass, bool &condPass)
198     {
199         ENCODE_FUNC_CALL();
200         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
201 
202         if (!m_enabled)
203         {
204             return eStatus;
205         }
206 
207         if (m_hevcPicParams->CodingType != I_TYPE && m_lookaheadAdaptiveI)
208         {
209             if (!blastPass)
210             {
211                 condPass = false;
212             }
213         }
214 
215         return eStatus;
216     }
217 
SetupForceIntraStreamIn()218     MOS_STATUS VdencLplaAnalysis::SetupForceIntraStreamIn()
219     {
220         ENCODE_FUNC_CALL();
221         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
222 
223         if (!m_enabled || m_forceIntraSteamInSetupDone)
224         {
225             return eStatus;
226         }
227 
228         MOS_LOCK_PARAMS lockFlags;
229         MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS));
230         lockFlags.WriteOnly = true;
231 
232         uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(m_osInterface, m_forceIntraStreamInBuf, &lockFlags);
233         ENCODE_CHK_NULL_RETURN(data);
234 
235         mhw::vdbox::vdenc::VDENC_STREAMIN_STATE_PAR streaminDataParams;
236         uint32_t streamInWidth  = (MOS_ALIGN_CEIL(m_basicFeature->m_frameWidth, 64) / 32);
237         uint32_t streamInHeight = (MOS_ALIGN_CEIL(m_basicFeature->m_frameHeight, 64) / 32);
238 
239         // lookahead pass should lower QP by 2 to encode force intra frame.
240         MOS_ZeroMemory(&streaminDataParams, sizeof(streaminDataParams));
241         streaminDataParams.setQpRoiCtrl = true;
242         streaminDataParams.forceQp[0] = m_hevcPicParams->QpY - 2;
243         streaminDataParams.forceQp[1] = m_hevcPicParams->QpY - 2;
244         streaminDataParams.forceQp[2] = m_hevcPicParams->QpY - 2;
245         streaminDataParams.forceQp[3] = m_hevcPicParams->QpY - 2;
246         SetStreaminDataPerRegion(streamInWidth, 0, streamInHeight, 0, streamInWidth, &streaminDataParams, data);
247 
248         MOS_ZeroMemory(&streaminDataParams, sizeof(streaminDataParams));
249         streaminDataParams.puTypeCtrl = 1;  //force intra
250         streaminDataParams.maxTuSize = 3;
251         streaminDataParams.maxCuSize = 1;
252         streaminDataParams.numMergeCandidateCu64x64 = 2;
253         streaminDataParams.numMergeCandidateCu32x32 = 2;
254         streaminDataParams.numMergeCandidateCu16x16 = 2;
255         streaminDataParams.numMergeCandidateCu8x8 = 0;
256         streaminDataParams.numImePredictors = 4;
257 
258         uint32_t streamInNumCUs = streamInWidth * streamInHeight;
259         for (uint32_t i = 0; i < streamInNumCUs; i++)
260         {
261             SetStreaminDataPerLcu(&streaminDataParams, data + (i * 64));
262         }
263 
264         m_osInterface->pfnUnlockResource(m_osInterface, m_forceIntraStreamInBuf);
265 
266         m_forceIntraSteamInSetupDone = true;
267 
268         return eStatus;
269     }
270 
SetStreaminDataPerRegion(uint32_t streamInWidth,uint32_t top,uint32_t bottom,uint32_t left,uint32_t right,mhw::vdbox::vdenc::VDENC_STREAMIN_STATE_PAR * streaminParams,void * streaminData)271     MOS_STATUS VdencLplaAnalysis::SetStreaminDataPerRegion(
272         uint32_t streamInWidth, uint32_t top, uint32_t bottom, uint32_t left, uint32_t right,
273         mhw::vdbox::vdenc::VDENC_STREAMIN_STATE_PAR *streaminParams, void *streaminData)
274     {
275         ENCODE_FUNC_CALL();
276 
277         uint8_t *data = (uint8_t *)streaminData;
278 
279         for (auto y = top; y < bottom; y++)
280         {
281             for (auto x = left; x < right; x++)
282             {
283                 //Calculate X Y for the zig zag scan
284                 uint32_t offset = 0, xyOffset = 0;
285                 StreaminZigZagToLinearMap(streamInWidth, x, y, &offset, &xyOffset);
286 
287                 SetStreaminDataPerLcu(streaminParams, data + (offset + xyOffset) * 64);
288             }
289         }
290 
291         return MOS_STATUS_SUCCESS;
292     }
293 
StreaminZigZagToLinearMap(uint32_t streamInWidth,uint32_t x,uint32_t y,uint32_t * offset,uint32_t * xyOffset)294     MOS_STATUS VdencLplaAnalysis::StreaminZigZagToLinearMap(
295         uint32_t  streamInWidth, uint32_t  x, uint32_t  y,
296         uint32_t *offset, uint32_t *xyOffset)
297     {
298         ENCODE_FUNC_CALL();
299 
300         *offset = streamInWidth * y;
301         uint32_t yOffset = 0;
302         uint32_t xOffset = 2 * x;
303 
304         //Calculate X Y Offset for the zig zag scan with in each 64x64 LCU
305         //dwOffset gives the 64 LCU row
306         if (y % 2)
307         {
308             *offset = streamInWidth * (y - 1);
309             yOffset = 2;
310         }
311 
312         if (x % 2)
313         {
314             xOffset = (2 * x) - 1;
315         }
316 
317         *xyOffset = xOffset + yOffset;
318 
319         return MOS_STATUS_SUCCESS;
320     }
321 
SetStreaminDataPerLcu(mhw::vdbox::vdenc::VDENC_STREAMIN_STATE_PAR * streaminParams,void * streaminData)322     MOS_STATUS VdencLplaAnalysis::SetStreaminDataPerLcu(
323         mhw::vdbox::vdenc::VDENC_STREAMIN_STATE_PAR *streaminParams,
324         void * streaminData)
325     {
326         ENCODE_FUNC_CALL();
327 
328         VdencStreamInState *data = (VdencStreamInState *)streaminData;
329         if (streaminParams->setQpRoiCtrl)
330         {
331             if (0)  //(m_vdencNativeROIEnabled || m_brcAdaptiveRegionBoostEnable)
332             {
333                 data->DW0.RoiCtrl = streaminParams->roiCtrl;
334             }
335             else
336             {
337                 data->DW7.QpEnable = 0xf;
338                 data->DW14.ForceQp_0 = streaminParams->forceQp[0];
339                 data->DW14.ForceQp_1 = streaminParams->forceQp[1];
340                 data->DW14.ForceQp_2 = streaminParams->forceQp[2];
341                 data->DW14.ForceQp_3 = streaminParams->forceQp[3];
342             }
343         }
344         else
345         {
346             data->DW0.MaxTuSize = streaminParams->maxTuSize;
347             data->DW0.MaxCuSize = streaminParams->maxCuSize;
348             data->DW0.NumImePredictors = streaminParams->numImePredictors;
349             data->DW0.PuTypeCtrl = streaminParams->puTypeCtrl;
350             data->DW6.NumMergeCandidateCu64x64 = streaminParams->numMergeCandidateCu64x64;
351             data->DW6.NumMergeCandidateCu32x32 = streaminParams->numMergeCandidateCu32x32;
352             data->DW6.NumMergeCandidateCu16x16 = streaminParams->numMergeCandidateCu16x16;
353             data->DW6.NumMergeCandidateCu8x8 = streaminParams->numMergeCandidateCu8x8;
354         }
355 
356         return MOS_STATUS_SUCCESS;
357     }
358 
AllocateResources()359     MOS_STATUS VdencLplaAnalysis::AllocateResources()
360     {
361         ENCODE_FUNC_CALL();
362         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
363 
364         MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
365         MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
366         allocParamsForBufferLinear.Type     = MOS_GFXRES_BUFFER;
367         allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
368         allocParamsForBufferLinear.Format   = Format_Buffer;
369         allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
370 
371         // Buffer to store VDEnc frame statistics for lookahead BRC
372         m_brcLooaheadStatsBufferSize        = m_numLaDataEntry * sizeof(VdencHevcLaStats);
373         allocParamsForBufferLinear.dwBytes  = MOS_ALIGN_CEIL(m_brcLooaheadStatsBufferSize, CODECHAL_PAGE_SIZE);
374         allocParamsForBufferLinear.pBufName = "VDENC Lookahead Statistics Buffer";
375         m_vdencLaStatsBuffer                = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
376 
377         VdencHevcLaStats *lookaheadInfo = (VdencHevcLaStats *)m_allocator->LockResourceForWrite(m_vdencLaStatsBuffer);
378         ENCODE_CHK_NULL_RETURN(lookaheadInfo);
379         MOS_ZeroMemory(lookaheadInfo, allocParamsForBufferLinear.dwBytes);
380         m_allocator->UnLock(m_vdencLaStatsBuffer);
381 
382         // Buffer to store lookahead output
383         m_brcLooaheadDataBufferSize            = m_numLaDataEntry * sizeof(VdencHevcLaData);
384         allocParamsForBufferLinear.dwBytes     = MOS_ALIGN_CEIL(m_brcLooaheadDataBufferSize, CODECHAL_PAGE_SIZE);
385         allocParamsForBufferLinear.pBufName    = "VDENC Lookahead Data Buffer";
386         m_vdencLaDataBuffer                    = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
387         VdencHevcLaData *lookaheadData         = (VdencHevcLaData *)m_allocator->LockResourceForWrite(m_vdencLaDataBuffer);
388         ENCODE_CHK_NULL_RETURN(lookaheadData);
389         MOS_ZeroMemory(lookaheadData, allocParamsForBufferLinear.dwBytes);
390         m_allocator->UnLock(m_vdencLaDataBuffer);
391 
392         // Lookahead Init DMEM
393         m_vdencLaInitDmemBufferSize         = sizeof(VdencHevcHucLaDmem);
394         allocParamsForBufferLinear.dwBytes  = MOS_ALIGN_CEIL(m_vdencLaInitDmemBufferSize, CODECHAL_CACHELINE_SIZE);
395         allocParamsForBufferLinear.pBufName = "VDENC Lookahead Init DmemBuffer";
396         m_vdencLaInitDmemBuffer             = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
397         ENCODE_CHK_NULL_RETURN(m_vdencLaInitDmemBuffer);
398 
399         // Lookahead history buffer
400         allocParamsForBufferLinear.dwBytes  = MOS_ALIGN_CEIL(m_LaHistoryBufSize, CODECHAL_PAGE_SIZE);
401         allocParamsForBufferLinear.pBufName = "VDENC Lookahead History Buffer";
402         m_vdencLaHistoryBuffer              = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
403         ENCODE_CHK_NULL_RETURN(m_vdencLaHistoryBuffer);
404 
405         // Lookahead Update DMEM
406         m_vdencLaUpdateDmemBufferSize = sizeof(VdencHevcHucLaDmem);
407         MOS_RESOURCE *allocatedbuffer;
408         for (auto k = 0; k < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; k++)
409         {
410             for (auto i = 0; i < CODECHAL_LPLA_NUM_OF_PASSES; i++)
411             {
412                 allocParamsForBufferLinear.dwBytes  = MOS_ALIGN_CEIL(m_vdencLaUpdateDmemBufferSize, CODECHAL_CACHELINE_SIZE);
413                 allocParamsForBufferLinear.pBufName = "VDENC Lookahead update Dmem Buffer";
414                 m_vdencLaUpdateDmemBuffer[k][i] = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
415                 ENCODE_CHK_NULL_RETURN(m_vdencLaUpdateDmemBuffer[k][i]);
416             }
417         }
418 
419         // streamin Buffer for forced intra encode pass
420         allocParamsForBufferLinear.dwBytes  = (MOS_ALIGN_CEIL(m_basicFeature->m_frameWidth, 64) / 32) * (MOS_ALIGN_CEIL(m_basicFeature->m_frameHeight, 64) / 32) * CODECHAL_CACHELINE_SIZE;
421         allocParamsForBufferLinear.pBufName = "ForceIntra Streamin Buffer";
422         m_forceIntraStreamInBuf = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
423         ENCODE_CHK_NULL_RETURN(m_forceIntraStreamInBuf);
424 
425         return eStatus;
426     }
427 
Update(void * params)428     MOS_STATUS VdencLplaAnalysis::Update(void *params)
429     {
430         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
431         ENCODE_FUNC_CALL();
432 
433         ENCODE_CHK_NULL_RETURN(params);
434         EncoderParams *encodeParams = (EncoderParams *)params;
435         m_hevcSeqParams = static_cast<PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS>(encodeParams->pSeqParams);
436         ENCODE_CHK_NULL_RETURN(m_hevcSeqParams);
437         m_lookaheadDepth = m_hevcSeqParams->LookaheadDepth;
438         m_enabled = (m_lookaheadDepth > 0) && m_hevcSeqParams->bLookAheadPhase;
439         if (!m_enabled)
440         {
441             return eStatus;
442         }
443 
444         m_hevcPicParams = static_cast<PCODEC_HEVC_ENCODE_PICTURE_PARAMS>(encodeParams->pPicParams);
445         ENCODE_CHK_NULL_RETURN(m_hevcPicParams);
446         m_nalUnitParams = encodeParams->ppNALUnitParams;
447         ENCODE_CHK_NULL_RETURN(m_nalUnitParams);
448         m_slcData = (PCODEC_ENCODER_SLCDATA)(encodeParams->pSlcHeaderData);
449         ENCODE_CHK_NULL_RETURN(m_slcData);
450         m_numSlices = encodeParams->dwNumSlices;
451         ENCODE_CHK_STATUS_RETURN(SetSequenceStructs());
452         m_lastPicInStream = m_hevcPicParams->bLastPicInStream;
453 
454         m_hevcSliceParams = static_cast<PCODEC_HEVC_ENCODE_SLICE_PARAMS>(encodeParams->pSliceParams);
455         ENCODE_CHK_STATUS_RETURN(SetupForceIntraStreamIn());
456 
457         if (!m_lastPicInStream)
458         {
459             m_numValidLaRecords++;
460         }
461 
462         if (m_lastPicInStream && m_bLastPicFlagFirstIn)
463         {
464             m_currLaDataIdx -= 1;
465             m_bLastPicFlagFirstIn = false;
466         }
467 
468         return eStatus;
469     }
470 
GetLplaStatusReport(EncodeStatusMfx * encodeStatusMfx,EncodeStatusReportData * statusReportData)471     MOS_STATUS VdencLplaAnalysis::GetLplaStatusReport(
472         EncodeStatusMfx *encodeStatusMfx,
473         EncodeStatusReportData *statusReportData)
474     {
475         ENCODE_FUNC_CALL();
476         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
477 
478         if (!m_enabled)
479         {
480             return eStatus;
481         }
482 
483         if (m_lookaheadReport && (encodeStatusMfx->lookaheadStatus.targetFrameSize > 0))
484         {
485             statusReportData->pLookaheadStatus = &encodeStatusMfx->lookaheadStatus;
486             encodeStatusMfx->lookaheadStatus.isValid = 1;
487             uint64_t targetFrameSize = (uint64_t)encodeStatusMfx->lookaheadStatus.targetFrameSize * m_averageFrameSize;
488             encodeStatusMfx->lookaheadStatus.targetFrameSize = (uint32_t)((targetFrameSize + (32 * 8)) / (64 * 8));  // Convert bits to bytes. 64 is normalized average frame size used in lookahead analysis kernel
489             uint64_t targetBufferFulness = (uint64_t)encodeStatusMfx->lookaheadStatus.targetBufferFulness * m_averageFrameSize;
490             encodeStatusMfx->lookaheadStatus.targetBufferFulness = (uint32_t)((targetBufferFulness + 32) / 64);  // 64 is normalized average frame size used in lookahead analysis kernel
491 
492             if (encodeStatusMfx->lookaheadStatus.miniGopSize == 2)
493             {
494                 encodeStatusMfx->lookaheadStatus.miniGopSize = 2;
495             }
496             else if (encodeStatusMfx->lookaheadStatus.pyramidDeltaQP == 0)
497             {
498                 encodeStatusMfx->lookaheadStatus.miniGopSize = 1;
499             }
500             else
501             {
502                 if (m_hevcSeqParams->GopRefDist == 1) // LPLA only supports P pyramid for this condition
503                 {
504                     encodeStatusMfx->lookaheadStatus.miniGopSize = 4;
505                 }
506                 else
507                 {
508                     encodeStatusMfx->lookaheadStatus.miniGopSize = m_hevcSeqParams->GopRefDist;
509                 }
510             }
511         }
512 
513         return eStatus;
514     }
515 
516 #if USE_CODECHAL_DEBUG_TOOL
DumpLaResource(EncodePipeline * pipeline,bool isInput)517     MOS_STATUS VdencLplaAnalysis::DumpLaResource(EncodePipeline *pipeline, bool isInput)
518     {
519         ENCODE_FUNC_CALL();
520         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
521 
522         if (!m_enabled)
523         {
524             return eStatus;
525         }
526 
527         CodechalDebugInterface *debugInterface = pipeline->GetDebugInterface();
528         ENCODE_CHK_NULL_RETURN(debugInterface);
529         int32_t currentPass = pipeline->GetCurrentPass();
530 
531         ENCODE_CHK_STATUS_RETURN(debugInterface->DumpHucDmem(
532             m_vdencLaUpdateDmemBuffer[pipeline->m_currRecycledBufIdx][currentPass],
533             sizeof(VdencHevcHucLaDmem),
534             currentPass,
535             hucRegionDumpLAUpdate));
536 
537         ENCODE_CHK_STATUS_RETURN(debugInterface->DumpHucRegion(
538             m_vdencLaHistoryBuffer,
539             0,
540             m_LaHistoryBufSize,
541             0,
542             "_History",
543             isInput,
544             currentPass,
545             hucRegionDumpLAUpdate));
546 
547         ENCODE_CHK_STATUS_RETURN(debugInterface->DumpHucRegion(
548             m_vdencLaStatsBuffer,
549             0,
550             m_brcLooaheadStatsBufferSize,
551             1,
552             "_Stats",
553             isInput,
554             currentPass,
555             hucRegionDumpLAUpdate));
556 
557         ENCODE_CHK_STATUS_RETURN(debugInterface->DumpHucRegion(
558             m_vdencLaDataBuffer,
559             0,
560             m_brcLooaheadDataBufferSize,
561             2,
562             "_Data",
563             isInput,
564             currentPass,
565             hucRegionDumpLAUpdate));
566 
567         return eStatus;
568     }
569 #endif
570 
GetLaStatsStoreIdx(uint8_t & index)571     MOS_STATUS VdencLplaAnalysis::GetLaStatsStoreIdx(uint8_t &index)
572     {
573         ENCODE_FUNC_CALL();
574         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
575 
576         index = m_currLaDataIdx;
577 
578         return eStatus;
579     }
580 
StoreLookaheadStatistics(MOS_COMMAND_BUFFER & cmdBuffer,MHW_VDBOX_NODE_IND vdboxIndex)581     MOS_STATUS VdencLplaAnalysis::StoreLookaheadStatistics(MOS_COMMAND_BUFFER &cmdBuffer, MHW_VDBOX_NODE_IND vdboxIndex)
582     {
583         ENCODE_FUNC_CALL();
584         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
585 
586         if (!m_enabled)
587         {
588             return eStatus;
589         }
590 
591         uint8_t index = 0;
592         ENCODE_CHK_STATUS_RETURN(GetLaStatsStoreIdx(index));
593         uint32_t offset = sizeof(VdencHevcLaStats) * index;
594         if (m_useDSData)
595         {
596             auto &storeFrameByteCount            = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)();
597             storeFrameByteCount                  = {};
598             storeFrameByteCount.pOsResource      = m_vdencLaStatsBuffer;
599             storeFrameByteCount.dwResourceOffset = offset + CODECHAL_OFFSETOF(VdencHevcLaStats, frameByteCount);
600             storeFrameByteCount.dwValue          = m_statsBuffer[index][0];
601             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(&cmdBuffer));
602 
603             auto &storeHeaderBitCount            = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)();
604             storeHeaderBitCount                  = {};
605             storeHeaderBitCount.pOsResource      = m_vdencLaStatsBuffer;
606             storeHeaderBitCount.dwResourceOffset = offset + CODECHAL_OFFSETOF(VdencHevcLaStats, headerBitCount);
607             storeHeaderBitCount.dwValue          = m_statsBuffer[index][1];
608             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(&cmdBuffer));
609 
610             auto &storeIntraCuCount            = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)();
611             storeIntraCuCount                  = {};
612             storeIntraCuCount.pOsResource      = m_vdencLaStatsBuffer;
613             storeIntraCuCount.dwResourceOffset = offset + CODECHAL_OFFSETOF(VdencHevcLaStats, intraCuCount);
614             storeIntraCuCount.dwValue          = m_statsBuffer[index][2];
615             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(&cmdBuffer));
616 
617             auto &flushDwParams = m_miItf->MHW_GETPAR_F(MI_FLUSH_DW)();
618             flushDwParams       = {};
619             // Make Flush DW call to make sure all previous work is done
620             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FLUSH_DW)(&cmdBuffer));
621         }
622         else
623         {
624             auto &miStoreRegMemParams = m_miItf->MHW_GETPAR_F(MI_STORE_REGISTER_MEM)();
625             auto &miLoadRegMemParams  = m_miItf->MHW_GETPAR_F(MI_LOAD_REGISTER_MEM)();
626             auto &flushDwParams       = m_miItf->MHW_GETPAR_F(MI_FLUSH_DW)();
627 
628             miStoreRegMemParams = {};
629             miLoadRegMemParams  = {};
630             flushDwParams       = {};
631 
632             auto mmioRegistersHcp          = m_hcpItf->GetMmioRegisters(vdboxIndex);
633             miStoreRegMemParams.dwRegister = mmioRegistersHcp->hcpEncBitstreamBytecountFrameRegOffset;
634             // Store BitstreamBytecount to m_vdencLaStatsBuffer
635             miStoreRegMemParams.presStoreBuffer = m_vdencLaStatsBuffer;
636             miStoreRegMemParams.dwOffset        = offset + CODECHAL_OFFSETOF(VdencHevcLaStats, frameByteCount);
637             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_REGISTER_MEM)(&cmdBuffer));
638 
639             // Calculate header size including LCU header
640             uint32_t headerBitSize = 0;
641             for (uint32_t i = 0; i < HEVC_MAX_NAL_UNIT_TYPE; i++)
642             {
643                 headerBitSize += m_nalUnitParams[i]->uiSize * 8;
644             }
645             for (uint32_t i = 0; i < m_numSlices; i++)
646             {
647                 headerBitSize += m_slcData[i].BitSize;
648             }
649 
650             // Store headerBitCount to m_vdencLaStatsBuffer
651             auto &storeDataParams            = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)();
652             storeDataParams                  = {};
653             storeDataParams.pOsResource      = m_vdencLaStatsBuffer;
654             storeDataParams.dwResourceOffset = offset + CODECHAL_OFFSETOF(VdencHevcLaStats, headerBitCount);
655             storeDataParams.dwValue          = headerBitSize;
656             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(&cmdBuffer));
657 
658             auto mmioRegs = m_miItf->GetMmioRegisters();
659             ENCODE_CHK_NULL_RETURN(mmioRegs);
660             // VCS_GPR0_Lo = LCUHdrBits
661             miLoadRegMemParams.presStoreBuffer = m_basicFeature->m_recycleBuf->GetBuffer(FrameStatStreamOutBuffer, 0);  // LCUHdrBits is in m_resFrameStatStreamOutBuffer DW4
662             miLoadRegMemParams.dwOffset        = 4 * sizeof(uint32_t);
663             miLoadRegMemParams.dwRegister      = mmioRegs->generalPurposeRegister0LoOffset;  // VCS_GPR0_Lo
664             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_LOAD_REGISTER_MEM)(&cmdBuffer));
665             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FLUSH_DW)(&cmdBuffer));
666 
667             // load headerBitCount(in m_vdencLaStatsBuffer) to VCS_GPR4_Lo
668             miLoadRegMemParams.presStoreBuffer = m_vdencLaStatsBuffer;
669             miLoadRegMemParams.dwOffset        = offset + CODECHAL_OFFSETOF(VdencHevcLaStats, headerBitCount);
670             miLoadRegMemParams.dwRegister      = mmioRegs->generalPurposeRegister4LoOffset;
671             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_LOAD_REGISTER_MEM)(&cmdBuffer));
672 
673             mhw::mi::MHW_MI_ALU_PARAMS aluParams[4] = {};
674             int32_t                    aluCount     = 0;
675 
676             //load1 srca, reg1
677             aluParams[aluCount].AluOpcode = MHW_MI_ALU_LOAD;
678             aluParams[aluCount].Operand1  = MHW_MI_ALU_SRCA;
679             aluParams[aluCount].Operand2  = MHW_MI_ALU_GPREG0;
680             ++aluCount;
681 
682             //load2 srcb, reg2
683             aluParams[aluCount].AluOpcode = MHW_MI_ALU_LOAD;
684             aluParams[aluCount].Operand1  = MHW_MI_ALU_SRCB;
685             aluParams[aluCount].Operand2  = MHW_MI_ALU_GPREG4;
686             ++aluCount;
687 
688             //add srca + srcb
689             aluParams[aluCount].AluOpcode = MHW_MI_ALU_ADD;
690             ++aluCount;
691 
692             //store reg1, accu
693             aluParams[aluCount].AluOpcode = MHW_MI_ALU_STORE;
694             aluParams[aluCount].Operand1  = MHW_MI_ALU_GPREG0;
695             aluParams[aluCount].Operand2  = MHW_MI_ALU_ACCU;
696             ++aluCount;
697 
698             auto &miMathParams          = m_miItf->MHW_GETPAR_F(MI_MATH)();
699             miMathParams                = {};
700             miMathParams.dwNumAluParams = aluCount;
701             miMathParams.pAluPayload    = aluParams;
702             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_MATH)(&cmdBuffer));
703 
704             //store VCS_GPR0_Lo to m_vdencLaStatsBuffer
705             miStoreRegMemParams.presStoreBuffer = m_vdencLaStatsBuffer;
706             miStoreRegMemParams.dwOffset        = offset + CODECHAL_OFFSETOF(VdencHevcLaStats, headerBitCount);
707             miStoreRegMemParams.dwRegister      = mmioRegs->generalPurposeRegister0LoOffset;
708             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_REGISTER_MEM)(&cmdBuffer));
709 
710             // Make Flush DW call to make sure all previous work is done
711             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FLUSH_DW)(&cmdBuffer));
712 
713             ENCODE_CHK_STATUS_RETURN(StoreVdencStatistics(cmdBuffer, index));
714         }
715         return eStatus;
716     }
717 
StoreVdencStatistics(MOS_COMMAND_BUFFER & cmdBuffer,uint8_t index)718     MOS_STATUS VdencLplaAnalysis::StoreVdencStatistics(MOS_COMMAND_BUFFER &cmdBuffer, uint8_t index)
719     {
720         ENCODE_FUNC_CALL();
721         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
722 
723         uint32_t offset = sizeof(VdencHevcLaStats) * index;
724         auto &miCpyMemMemParams       = m_miItf->MHW_GETPAR_F(MI_COPY_MEM_MEM)();
725         miCpyMemMemParams             = {};
726         miCpyMemMemParams.presSrc     = m_basicFeature->m_recycleBuf->GetBuffer(VdencStatsBuffer, 0);  // 8X8 Normalized intra CU count is in m_resVdencStatsBuffer DW1
727         miCpyMemMemParams.dwSrcOffset = 4;
728         miCpyMemMemParams.presDst     = m_vdencLaStatsBuffer;
729         miCpyMemMemParams.dwDstOffset = offset + CODECHAL_OFFSETOF(VdencHevcLaStats, intraCuCount);
730         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(&cmdBuffer));
731 
732         return eStatus;
733     }
734 
ReadLPLAData(PMOS_COMMAND_BUFFER cmdBuffer,PMOS_RESOURCE resource,uint32_t baseOffset)735     MOS_STATUS VdencLplaAnalysis::ReadLPLAData(PMOS_COMMAND_BUFFER cmdBuffer, PMOS_RESOURCE resource, uint32_t baseOffset)
736     {
737         ENCODE_FUNC_CALL();
738 
739         // Write lookahead status to encode status buffer
740         auto &miCpyMemMemParams = m_miItf->MHW_GETPAR_F(MI_COPY_MEM_MEM)();
741         auto &flushDwParams     = m_miItf->MHW_GETPAR_F(MI_FLUSH_DW)();
742 
743         miCpyMemMemParams             = {};
744         miCpyMemMemParams.presSrc     = m_vdencLaDataBuffer;
745         miCpyMemMemParams.dwSrcOffset = m_offset * sizeof(CodechalVdencHevcLaData) + CODECHAL_OFFSETOF(CodechalVdencHevcLaData, encodeHints);
746         miCpyMemMemParams.presDst     = resource;
747         miCpyMemMemParams.dwDstOffset = baseOffset + CODECHAL_OFFSETOF(LookaheadReport, encodeHints);
748         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(cmdBuffer));
749         miCpyMemMemParams.dwSrcOffset = m_offset * sizeof(CodechalVdencHevcLaData) + CODECHAL_OFFSETOF(CodechalVdencHevcLaData, targetFrameSize);
750         miCpyMemMemParams.dwDstOffset = baseOffset + CODECHAL_OFFSETOF(LookaheadReport, targetFrameSize);
751         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(cmdBuffer));
752         miCpyMemMemParams.dwSrcOffset = m_offset * sizeof(CodechalVdencHevcLaData) + CODECHAL_OFFSETOF(CodechalVdencHevcLaData, targetBufferFulness);
753         miCpyMemMemParams.dwDstOffset = baseOffset + CODECHAL_OFFSETOF(LookaheadReport, targetBufferFulness);
754         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(cmdBuffer));
755         miCpyMemMemParams.dwSrcOffset = m_offset * sizeof(CodechalVdencHevcLaData) + CODECHAL_OFFSETOF(CodechalVdencHevcLaData, pyramidDeltaQP);
756         miCpyMemMemParams.dwDstOffset = baseOffset + CODECHAL_OFFSETOF(LookaheadReport, pyramidDeltaQP);
757         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(cmdBuffer));
758         //MI_COPY_MEM_MEM reads a DWord from memory and stores it to memory. This copy will include adaptive_rounding and minigop
759         miCpyMemMemParams.dwSrcOffset = m_offset * sizeof(CodechalVdencHevcLaData) + CODECHAL_OFFSETOF(CodechalVdencHevcLaData, adaptive_rounding);
760         miCpyMemMemParams.dwDstOffset = baseOffset + CODECHAL_OFFSETOF(LookaheadReport, adaptive_rounding);
761         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(cmdBuffer));
762 
763         flushDwParams = {};
764         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FLUSH_DW)(cmdBuffer));
765 
766         return MOS_STATUS_SUCCESS;
767     }
768 
SetLaUpdateDmemParameters(HUC_DMEM_STATE_PAR_ALIAS & params,uint8_t currRecycledBufIdx,uint16_t curPass,uint16_t numPasses)769     MOS_STATUS VdencLplaAnalysis::SetLaUpdateDmemParameters(HUC_DMEM_STATE_PAR_ALIAS &params, uint8_t currRecycledBufIdx, uint16_t curPass, uint16_t numPasses)
770     {
771         ENCODE_FUNC_CALL();
772         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
773 
774         if (!m_enabled)
775         {
776             return eStatus;
777         }
778 
779         ENCODE_CHK_STATUS_RETURN(SetLaUpdateDmemBuffer(currRecycledBufIdx, m_currLaDataIdx, m_numValidLaRecords, curPass, numPasses));
780 
781         params.hucDataSource = m_vdencLaUpdateDmemBuffer[currRecycledBufIdx][curPass];
782         params.dataLength = MOS_ALIGN_CEIL(m_vdencLaUpdateDmemBufferSize, CODECHAL_CACHELINE_SIZE);
783         params.dmemOffset = HUC_DMEM_OFFSET_RTOS_GEMS;
784 
785         return eStatus;
786     }
787 
UpdateLaDataIdx()788     MOS_STATUS VdencLplaAnalysis::UpdateLaDataIdx()
789     {
790         ENCODE_FUNC_CALL();
791         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
792 
793         if (!m_lastPicInStream)
794         {
795             m_currLaDataIdx = (m_currLaDataIdx + 1) % m_numLaDataEntry;
796         }
797 
798         return eStatus;
799     }
800 
SetLaInitDmemBuffer() const801     MOS_STATUS VdencLplaAnalysis::SetLaInitDmemBuffer() const
802     {
803         ENCODE_FUNC_CALL();
804         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
805 
806         // Setup LAInit DMEM
807         auto hucVdencLaInitDmem = (VdencHevcHucLaDmem *)m_allocator->LockResourceForWrite(m_vdencLaInitDmemBuffer);
808         ENCODE_CHK_NULL_RETURN(hucVdencLaInitDmem);
809         MOS_ZeroMemory(hucVdencLaInitDmem, sizeof(VdencHevcHucLaDmem));
810 
811         uint32_t initVbvFullness = MOS_MIN(m_hevcSeqParams->InitVBVBufferFullnessInBit, m_hevcSeqParams->VBVBufferSizeInBit);
812         uint8_t downscaleRatioIndicator = 2;  // 4x downscaling
813         if (m_hevcPicParams->DownScaleRatio.fields.X16Minus1_X == 15 && m_hevcPicParams->DownScaleRatio.fields.X16Minus1_Y == 15)
814         {
815             downscaleRatioIndicator = 0;  // no downscaling
816         }
817 
818         hucVdencLaInitDmem->lookAheadFunc = 0;
819         hucVdencLaInitDmem->lengthAhead = m_hevcSeqParams->LookaheadDepth;
820         hucVdencLaInitDmem->vbvBufferSize = m_hevcSeqParams->VBVBufferSizeInBit / m_averageFrameSize;
821         hucVdencLaInitDmem->vbvInitialFullness = initVbvFullness / m_averageFrameSize;
822         hucVdencLaInitDmem->statsRecords = m_numLaDataEntry;
823         hucVdencLaInitDmem->averageFrameSize = m_averageFrameSize >> 3;
824         hucVdencLaInitDmem->downscaleRatio = downscaleRatioIndicator;
825         ENCODE_CHK_NULL_RETURN(m_basicFeature);
826         hucVdencLaInitDmem->enc_frame_width = m_basicFeature->m_frameWidth;
827         hucVdencLaInitDmem->enc_frame_height = m_basicFeature->m_frameHeight;
828         hucVdencLaInitDmem->codec_type = m_hevcSeqParams->FullPassCodecType;
829         hucVdencLaInitDmem->mbr_ratio = (m_hevcSeqParams->TargetBitRate > 0 && m_hevcSeqParams->MaxBitRate >= m_hevcSeqParams->TargetBitRate) ?
830                                         m_hevcSeqParams->MaxBitRate * 100 / m_hevcSeqParams->TargetBitRate : 100;
831 
832         if (m_hevcSeqParams->GopRefDist == 1)
833         {
834             hucVdencLaInitDmem->PGop = 4;
835         }
836         else
837         {
838             hucVdencLaInitDmem->BGop   = m_hevcSeqParams->GopRefDist;
839             hucVdencLaInitDmem->maxGop = m_hevcSeqParams->GopPicSize;
840         }
841 
842         hucVdencLaInitDmem->GopOpt = m_hevcSeqParams->GopFlags.fields.StrictGop ? 2 : m_hevcSeqParams->GopFlags.fields.ClosedGop;
843         hucVdencLaInitDmem->AGop   = m_hevcSeqParams->GopFlags.fields.AdaptiveGop;
844         if (m_hevcSeqParams->GopFlags.fields.AdaptiveGop)
845         {
846             hucVdencLaInitDmem->AGop_Threshold = 16;
847         }
848         hucVdencLaInitDmem->maxGop = m_hevcSeqParams->MaxAdaptiveGopPicSize;
849         hucVdencLaInitDmem->minGop = m_hevcSeqParams->MinAdaptiveGopPicSize;
850         hucVdencLaInitDmem->adaptiveIDR = (uint8_t)m_lookaheadAdaptiveI;
851         hucVdencLaInitDmem->la_dump_type = 4;
852 
853         m_allocator->UnLock(m_vdencLaInitDmemBuffer);
854 
855         return eStatus;
856     }
857 
SetLaUpdateDmemBuffer(uint8_t currRecycledBufIdx,uint8_t currLaDataIdx,uint32_t numValidLaRecords,uint16_t curPass,uint16_t numPasses)858     MOS_STATUS VdencLplaAnalysis::SetLaUpdateDmemBuffer(uint8_t currRecycledBufIdx, uint8_t currLaDataIdx, uint32_t numValidLaRecords, uint16_t curPass, uint16_t numPasses)
859     {
860         ENCODE_FUNC_CALL();
861         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
862 
863         // Setup LAUpdate DMEM
864         auto hucVdencLaUpdateDmem = (VdencHevcHucLaDmem *)m_allocator->LockResourceForWrite(m_vdencLaUpdateDmemBuffer[currRecycledBufIdx][curPass]);
865         ENCODE_CHK_NULL_RETURN(hucVdencLaUpdateDmem);
866         MOS_ZeroMemory(hucVdencLaUpdateDmem, sizeof(VdencHevcHucLaDmem));
867 
868         hucVdencLaUpdateDmem->lookAheadFunc = 1;
869         hucVdencLaUpdateDmem->validStatsRecords = numValidLaRecords;
870         hucVdencLaUpdateDmem->offset = m_offset = (m_numLaDataEntry + currLaDataIdx + 1 - numValidLaRecords) % m_numLaDataEntry;
871         hucVdencLaUpdateDmem->cqmQpThreshold = m_cqmQpThreshold;
872         hucVdencLaUpdateDmem->currentPass = (uint8_t)curPass;
873 
874         m_allocator->UnLock(m_vdencLaUpdateDmemBuffer[currRecycledBufIdx][curPass]);
875 
876         return eStatus;
877     }
878 
SetVdencPipeBufAddrParams(bool enableStreamIn,MHW_VDBOX_PIPE_BUF_ADDR_PARAMS & pipeBufAddrParams)879     MOS_STATUS VdencLplaAnalysis::SetVdencPipeBufAddrParams(bool enableStreamIn, MHW_VDBOX_PIPE_BUF_ADDR_PARAMS &pipeBufAddrParams)
880     {
881         ENCODE_FUNC_CALL();
882         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
883 
884         if (!m_enabled)
885         {
886             return eStatus;
887         }
888 
889         if (enableStreamIn)
890         {
891             pipeBufAddrParams.presVdencStreamInBuffer = m_forceIntraStreamInBuf;
892         }
893 
894         return eStatus;
895     }
896 
IsLaAnalysisRequired()897     bool VdencLplaAnalysis::IsLaAnalysisRequired()
898     {
899         return m_enabled;
900     }
901 
IsLaRecordsEmpty()902     bool VdencLplaAnalysis::IsLaRecordsEmpty()
903     {
904         if (!m_numValidLaRecords)
905         {
906             return true;
907         }
908         m_numValidLaRecords--;
909         return false;
910     }
911 
CalculateLaRecords(bool blastPass)912     MOS_STATUS VdencLplaAnalysis::CalculateLaRecords(bool blastPass)
913     {
914         ENCODE_FUNC_CALL();
915 
916         if ((blastPass && m_numValidLaRecords >= m_lookaheadDepth) ||
917             (m_lastPicInStream && m_numValidLaRecords))
918         {
919             m_numValidLaRecords--;
920             m_lookaheadReport = true;
921         }
922         return MOS_STATUS_SUCCESS;
923     }
924 
MHW_SETPAR_DECL_SRC(VDENC_PIPE_MODE_SELECT,VdencLplaAnalysis)925     MHW_SETPAR_DECL_SRC(VDENC_PIPE_MODE_SELECT, VdencLplaAnalysis)
926     {
927         ENCODE_FUNC_CALL();
928 
929         params.frameStatisticsStreamOut = m_enabled ? true : params.frameStatisticsStreamOut;
930 
931         return MOS_STATUS_SUCCESS;
932     }
933 
MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE,VdencLplaAnalysis)934     MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE, VdencLplaAnalysis)
935     {
936         ENCODE_FUNC_CALL();
937 
938         if (m_streamInEnabled)
939         {
940             params.streamInBuffer = m_forceIntraStreamInBuf;
941         }
942 
943         return MOS_STATUS_SUCCESS;
944     }
945 
MHW_SETPAR_DECL_SRC(VDENC_CMD2,VdencLplaAnalysis)946     MHW_SETPAR_DECL_SRC(VDENC_CMD2, VdencLplaAnalysis)
947     {
948         ENCODE_FUNC_CALL();
949 
950         if (m_streamInEnabled)
951         {
952             params.vdencStreamIn = true;
953         }
954 
955         return MOS_STATUS_SUCCESS;
956     }
957 
MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE,VdencLplaAnalysis)958     MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE, VdencLplaAnalysis)
959     {
960         ENCODE_FUNC_CALL();
961 
962         if (params.function == LA_INIT)
963         {
964             ENCODE_CHK_STATUS_RETURN(SetLaInitDmemBuffer());
965 
966             params.hucDataSource = m_vdencLaInitDmemBuffer;
967             params.dataLength    = MOS_ALIGN_CEIL(m_vdencLaInitDmemBufferSize, CODECHAL_CACHELINE_SIZE);
968             params.dmemOffset    = HUC_DMEM_OFFSET_RTOS_GEMS;
969         }
970 
971         return MOS_STATUS_SUCCESS;
972     }
973 
MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE,VdencLplaAnalysis)974     MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE, VdencLplaAnalysis)
975     {
976         ENCODE_FUNC_CALL();
977 
978         switch (params.function)
979         {
980             case LA_INIT:
981             {
982                 params.regionParams[0].presRegion = m_vdencLaHistoryBuffer;
983                 params.regionParams[0].isWritable = true;
984                 m_lookaheadInit                   = false;
985 
986                 break;
987             }
988             case LA_UPDATE:
989             {
990                 params.regionParams[0].presRegion = m_vdencLaHistoryBuffer;
991                 params.regionParams[0].isWritable = true;
992                 params.regionParams[1].presRegion = m_vdencLaStatsBuffer;
993                 params.regionParams[2].presRegion = m_vdencLaDataBuffer;
994                 params.regionParams[2].isWritable = true;
995 
996                 break;
997             }
998             default:
999                 break;
1000         }
1001 
1002         return MOS_STATUS_SUCCESS;
1003     }
1004 
1005 } //encode
1006