1 /*
2 * Copyright (c) 2018-2020, 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_hevc_vdenc_roi.cpp
24 //! \brief    implementation of ROI feature of HEVC VDENC
25 
26 #include "mos_defs.h"
27 #include "encode_hevc_vdenc_roi.h"
28 #include "encode_hevc_vdenc_feature_manager.h"
29 
30 namespace encode
31 {
32 
HevcVdencRoi(MediaFeatureManager * featureManager,EncodeAllocator * allocator,CodechalHwInterfaceNext * hwInterface,void * constSettings)33 HevcVdencRoi::HevcVdencRoi(
34     MediaFeatureManager *featureManager,
35     EncodeAllocator *allocator,
36     CodechalHwInterfaceNext *hwInterface,
37     void *constSettings) :
38     MediaFeature(constSettings, hwInterface ? hwInterface->GetOsInterface() : nullptr),
39     m_allocator(allocator),
40     m_hwInterface(hwInterface)
41 {
42     ENCODE_CHK_NULL_NO_STATUS_RETURN(m_hwInterface);
43     m_osInterface = m_hwInterface->GetOsInterface();
44     ENCODE_CHK_NULL_NO_STATUS_RETURN(m_osInterface);
45 
46     m_featureManager = featureManager;
47     ENCODE_CHK_NULL_NO_STATUS_RETURN(m_featureManager);
48 
49     m_basicFeature = dynamic_cast<EncodeBasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
50     ENCODE_CHK_NULL_NO_STATUS_RETURN(m_basicFeature);
51 }
ClearStreaminBuffer(uint32_t lucNumber)52 MOS_STATUS HevcVdencRoi::ClearStreaminBuffer(uint32_t lucNumber)
53 {
54     // Clear streamin
55     ENCODE_CHK_NULL_RETURN(m_streamInTemp);
56 
57     uint8_t *data = (uint8_t *)m_allocator->LockResourceForWrite(m_streamIn);
58     ENCODE_CHK_NULL_RETURN(data);
59 
60     MOS_ZeroMemory(m_streamInTemp, lucNumber * 64);
61     MOS_SecureMemcpy(data, m_streamInSize, m_streamInTemp, m_streamInSize);
62 
63     ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(m_streamIn));
64 
65     return MOS_STATUS_SUCCESS;
66 }
67 
Init(void * setting)68 MOS_STATUS HevcVdencRoi::Init(void *setting)
69 {
70     ENCODE_FUNC_CALL();
71     ENCODE_CHK_NULL_RETURN(setting);
72     ENCODE_CHK_NULL_RETURN(m_basicFeature);
73     ENCODE_CHK_NULL_RETURN(m_basicFeature->m_recycleBuf);
74 
75 #if (_DEBUG || _RELEASE_INTERNAL)
76     MediaUserSetting::Value outValue;
77     ReadUserSetting(
78         m_userSettingPtr,
79         outValue,
80         "Disable TCBRC ARB for HEVC VDEnc",
81         MediaUserSetting::Group::Sequence);
82     m_isArbRoiSupported = !outValue.Get<bool>();
83 #endif
84 
85     MOS_ALLOC_GFXRES_PARAMS allocParams;
86     MOS_ZeroMemory(&allocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS));
87     allocParams.Type     = MOS_GFXRES_BUFFER;
88     allocParams.TileType = MOS_TILE_LINEAR;
89     allocParams.Format   = Format_Buffer;
90 
91     //reuse 1 streamIn buffer to save latency so enlarge 8-rows buffer w/ different offset for each frame in arb cycle
92     allocParams.dwBytes = (MOS_ALIGN_CEIL(m_basicFeature->m_frameWidth, 64) / 32) *
93                           ((MOS_ALIGN_CEIL(m_basicFeature->m_frameHeight, 64) / 32) + 8) * CODECHAL_CACHELINE_SIZE;
94     m_streamInSize      = allocParams.dwBytes;
95 
96     allocParams.pBufName = "VDEnc StreamIn Data Buffer";
97     allocParams.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
98     m_basicFeature->m_recycleBuf->RegisterResource(RecycleResId::StreamInBuffer, allocParams);
99 
100     return MOS_STATUS_SUCCESS;
101 }
102 
Update(void * params)103 MOS_STATUS HevcVdencRoi::Update(void *params)
104 {
105     ENCODE_FUNC_CALL();
106     ENCODE_CHK_NULL_RETURN(params);
107     ENCODE_CHK_NULL_RETURN(m_basicFeature->m_recycleBuf);
108 
109     PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams = nullptr;
110     PCODEC_HEVC_ENCODE_PICTURE_PARAMS  hevcPicParams = nullptr;
111     PCODEC_HEVC_ENCODE_SLICE_PARAMS    hevcSlcParams = nullptr;
112 
113     EncoderParams *encodeParams = (EncoderParams *)params;
114 
115     hevcSeqParams = static_cast<PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS>(encodeParams->pSeqParams);
116     hevcPicParams = static_cast<PCODEC_HEVC_ENCODE_PICTURE_PARAMS>(encodeParams->pPicParams);
117     hevcSlcParams = static_cast<PCODEC_HEVC_ENCODE_SLICE_PARAMS>(encodeParams->pSliceParams);
118     ENCODE_CHK_NULL_RETURN(hevcSeqParams);
119     ENCODE_CHK_NULL_RETURN(hevcPicParams);
120     ENCODE_CHK_NULL_RETURN(hevcSlcParams);
121 
122     bool pririotyDirtyROI = true;
123 
124     m_dirtyRoiEnabled = hevcPicParams->NumDirtyRects && (B_TYPE == hevcPicParams->CodingType);
125     m_mbQpDataEnabled = m_basicFeature->m_mbQpDataEnabled;
126     // Adaptive region boost is enabled for TCBRC only
127     m_isArbRoi        = hevcPicParams->TargetFrameSize != 0 && (hevcSeqParams->LookaheadDepth == 0) && m_isArbRoiSupported;
128     m_roiEnabled      = hevcPicParams->NumROI > 0 || m_mbQpDataEnabled || m_isArbRoi;
129 
130     m_enabled = (m_roiEnabled || m_dirtyRoiEnabled) ? true : false;
131 
132     if (!m_enabled)
133     {
134         return MOS_STATUS_SUCCESS;
135     }
136 
137     if (!m_isArbRoi)
138     {
139         m_streamIn = m_basicFeature->m_recycleBuf->GetBuffer(RecycleResId::StreamInBuffer, m_basicFeature->m_frameNum);
140     }
141     else
142     {
143         uint32_t streamInBufferIdx = hevcPicParams->CodingType == I_TYPE ? 0 : 1;
144         m_streamIn                 = m_basicFeature->m_recycleBuf->GetBuffer(RecycleResId::StreamInBuffer, streamInBufferIdx);
145 
146         uint16_t ArbBoostRow[8] = {0, 3, 5, 2, 7, 4, 1, 6};
147         uint16_t factor = 8 - ArbBoostRow[m_basicFeature->m_frameNum % 8];
148 
149         if (factor % 2 == 0)
150         {
151             m_streamIn->dwResourceOffset = factor * (MOS_ALIGN_CEIL(m_basicFeature->m_frameWidth, 64) / 32) * CODECHAL_CACHELINE_SIZE;
152         }
153         else
154         {
155             m_streamIn->dwResourceOffset = ((factor + 1) * (MOS_ALIGN_CEIL(m_basicFeature->m_frameWidth, 64) / 32) - 2) * CODECHAL_CACHELINE_SIZE;
156         }
157     }
158     ENCODE_CHK_NULL_RETURN(m_streamIn);
159 
160     if (!m_isArbRoi || (hevcPicParams->CodingType == I_TYPE && !IFrameIsSet) || ((hevcPicParams->CodingType == P_TYPE || hevcPicParams->CodingType == B_TYPE) && !PBFrameIsSet))
161     {
162         m_streamInTemp = (uint8_t *)MOS_AllocMemory(m_streamInSize);
163         ENCODE_CHK_NULL_RETURN(m_streamInTemp);
164 
165         uint32_t lcuNumber = GetLCUNumber();
166 
167         ENCODE_CHK_STATUS_RETURN(ClearStreaminBuffer(lcuNumber));
168 
169         m_roiOverlap.Update(lcuNumber);
170 
171         ENCODE_CHK_STATUS_RETURN(ExecuteDirtyRoi(hevcSeqParams, hevcPicParams, hevcSlcParams));
172 
173         MEDIA_WA_TABLE *waTable = m_basicFeature->GetWaTable();
174         ENCODE_CHK_NULL_RETURN(waTable);
175 
176         if (MEDIA_IS_WA(waTable, WaHEVCVDEncForceDeltaQpRoiNotSupported) || m_isArbRoi || m_mbQpDataEnabled)
177         {
178             m_roiMode = false;
179             ENCODE_CHK_STATUS_RETURN(ExecuteRoi(hevcSeqParams, hevcPicParams, hevcSlcParams));
180         }
181         else
182         {
183             m_roiMode = true;
184             ENCODE_CHK_STATUS_RETURN(ExecuteRoiExt(hevcSeqParams, hevcPicParams, hevcSlcParams));
185         }
186 
187         ENCODE_CHK_STATUS_RETURN(WriteStreaminData());
188 
189         MOS_SafeFreeMemory(m_streamInTemp);
190 
191 #if (_DEBUG || _RELEASE_INTERNAL)
192         ENCODE_CHK_NULL_RETURN(m_hwInterface);
193         ENCODE_CHK_NULL_RETURN(m_hwInterface->GetOsInterface());
194         ReportUserSettingForDebug(
195             m_userSettingPtr ,
196             "HEVC VDEnc Force Delta QP Enable",
197             m_roiMode,
198             MediaUserSetting::Group::Sequence);
199 #endif
200 
201         if (hevcPicParams->CodingType == I_TYPE)
202         {
203             IFrameIsSet = true;
204         }
205         else
206         {
207             PBFrameIsSet = true;
208         }
209     }
210 
211     return MOS_STATUS_SUCCESS;
212 }
213 
WriteStreaminData()214 MOS_STATUS HevcVdencRoi::WriteStreaminData()
215 {
216     ENCODE_CHK_NULL_RETURN(m_streamIn);
217     ENCODE_CHK_NULL_RETURN(m_streamInTemp);
218 
219     uint8_t *streaminBuffer = (uint8_t *)m_allocator->LockResourceForWrite(m_streamIn);
220     ENCODE_CHK_NULL_RETURN(streaminBuffer);
221 
222     m_roiOverlap.WriteStreaminData(
223         m_strategyFactory.GetRoi(),
224         m_strategyFactory.GetDirtyRoi(),
225         m_streamInTemp);
226 
227     MOS_SecureMemcpy(streaminBuffer, m_streamInSize, m_streamInTemp, m_streamInSize);
228 
229     m_allocator->UnLock(m_streamIn);
230     return MOS_STATUS_SUCCESS;
231 }
232 
ExecuteRoi(SeqParams * hevcSeqParams,PicParams * hevcPicParams,SlcParams * hevcSlcParams)233 MOS_STATUS HevcVdencRoi::ExecuteRoi(
234     SeqParams *hevcSeqParams,
235     PicParams *hevcPicParams,
236     SlcParams *hevcSlcParams)
237 {
238     if (!m_roiEnabled)
239     {
240         return MOS_STATUS_SUCCESS;
241     }
242 
243     ENCODE_CHK_NULL_RETURN(m_featureManager);
244 
245     if (!m_mbQpDataEnabled)
246     {
247         uint8_t numDistinctDeltaQp = sizeof(hevcPicParams->ROIDistinctDeltaQp) / sizeof(int8_t);
248         m_isNativeRoi = ProcessRoiDeltaQp(
249             hevcPicParams->NumROI,
250             hevcPicParams->ROI,
251             numDistinctDeltaQp,
252             hevcPicParams->ROIDistinctDeltaQp);
253 
254         if (m_isArbRoi)
255         {
256             m_isNativeRoi = false;
257         }
258     }
259 
260     RoiStrategy *strategy = m_strategyFactory.CreateStrategy(
261         m_allocator, m_featureManager, m_osInterface, m_isArbRoi, false, m_isNativeRoi, m_mbQpDataEnabled);
262     ENCODE_CHK_NULL_RETURN(strategy);
263     strategy->SetFeatureSetting(static_cast<HevcVdencFeatureSettings *>(m_constSettings));
264     ENCODE_CHK_STATUS_RETURN(
265         strategy->PrepareParams(hevcSeqParams, hevcPicParams, hevcSlcParams));
266 
267     ENCODE_CHK_STATUS_RETURN(strategy->SetupRoi(m_roiOverlap));
268     return MOS_STATUS_SUCCESS;
269 }
270 
ExecuteRoiExt(SeqParams * hevcSeqParams,PicParams * hevcPicParams,SlcParams * hevcSlcParams)271 MOS_STATUS HevcVdencRoi::ExecuteRoiExt(
272     SeqParams *hevcSeqParams,
273     PicParams *hevcPicParams,
274     SlcParams *hevcSlcParams)
275 {
276     if (!m_roiEnabled)
277     {
278         return MOS_STATUS_SUCCESS;
279     }
280 
281     ENCODE_CHK_NULL_RETURN(m_featureManager);
282 
283 
284     RoiStrategy* strategy = m_strategyFactory.CreateStrategyForceDeltaQP(
285                                      m_allocator, m_featureManager, m_osInterface);
286 
287     ENCODE_CHK_NULL_RETURN(strategy);
288     strategy->SetFeatureSetting(static_cast<HevcVdencFeatureSettings *>(m_constSettings));
289     ENCODE_CHK_STATUS_RETURN(
290         strategy->PrepareParams(hevcSeqParams, hevcPicParams, hevcSlcParams));
291 
292     ENCODE_CHK_STATUS_RETURN(strategy->SetupRoi(m_roiOverlap));
293     return MOS_STATUS_SUCCESS;
294 }
295 
ExecuteDirtyRoi(SeqParams * hevcSeqParams,PicParams * hevcPicParams,SlcParams * hevcSlcParams)296 MOS_STATUS HevcVdencRoi::ExecuteDirtyRoi(
297     SeqParams *hevcSeqParams,
298     PicParams *hevcPicParams,
299     SlcParams *hevcSlcParams)
300 {
301     if (!m_dirtyRoiEnabled)
302     {
303         return MOS_STATUS_SUCCESS;
304     }
305 
306     ENCODE_CHK_NULL_RETURN(m_featureManager);
307 
308     RoiStrategy *strategy = m_strategyFactory.CreateStrategy(
309                                     m_allocator, m_featureManager, m_osInterface, false, true, false);
310     ENCODE_CHK_NULL_RETURN(strategy);
311     strategy->SetFeatureSetting(static_cast<HevcVdencFeatureSettings *>(m_constSettings));
312     ENCODE_CHK_STATUS_RETURN(
313         strategy->PrepareParams(hevcSeqParams, hevcPicParams, hevcSlcParams));
314 
315     ENCODE_CHK_STATUS_RETURN(strategy->SetupRoi(m_roiOverlap));
316 
317     return MOS_STATUS_SUCCESS;
318 }
319 
ProcessRoiDeltaQp(uint8_t numROI,CODEC_ROI * roiRegions,uint8_t numDistinctDeltaQp,int8_t * roiDistinctDeltaQp)320 bool HevcVdencRoi::ProcessRoiDeltaQp(
321     uint8_t    numROI,
322     CODEC_ROI  *roiRegions,
323     uint8_t    numDistinctDeltaQp,
324     int8_t     *roiDistinctDeltaQp)
325 {
326     ENCODE_FUNC_CALL();
327 
328     // Intialize ROIDistinctDeltaQp to be min expected delta qp, setting to -128
329     // Check if forceQp is needed or not
330     // forceQp is enabled if there are greater than 3 distinct delta qps or if the deltaqp is beyond range (-8, 7)
331     for (auto k = 0; k < numDistinctDeltaQp; k++)
332     {
333         roiDistinctDeltaQp[k] = -128;
334     }
335 
336     int32_t numQp = 0;
337     for (int32_t i = 0; i < numROI; i++)
338     {
339         bool dqpNew = true;
340 
341         //Get distinct delta Qps among all ROI regions, index 0 having the lowest delta qp
342         int32_t k = numQp - 1;
343         for (; k >= 0; k--)
344         {
345             if (roiRegions[i].PriorityLevelOrDQp == roiDistinctDeltaQp[k] ||
346                 roiRegions[i].PriorityLevelOrDQp == 0)
347             {
348                 dqpNew = false;
349                 break;
350             }
351             else if (roiRegions[i].PriorityLevelOrDQp < roiDistinctDeltaQp[k])
352             {
353                 continue;
354             }
355             else
356             {
357                 break;
358             }
359         }
360 
361         if (dqpNew)
362         {
363             for (int32_t j = numQp - 1; j >= k + 1; j--)
364             {
365                 roiDistinctDeltaQp[j + 1] = roiDistinctDeltaQp[j];
366             }
367             roiDistinctDeltaQp[k + 1] = roiRegions[i].PriorityLevelOrDQp;
368             numQp++;
369         }
370     }
371 
372     //Set the ROI DeltaQp to zero for remaining array elements
373     for (auto k = numQp; k < m_maxNumRoi; k++)
374     {
375         roiDistinctDeltaQp[k] = 0;
376     }
377 
378     // return whether is native ROI or not
379     return (!(numQp > m_maxNumNativeRoi || roiDistinctDeltaQp[0] < -8 || roiDistinctDeltaQp[numQp - 1] > 7));
380 }
381 
SetVdencPipeBufAddrParams(MHW_VDBOX_PIPE_BUF_ADDR_PARAMS & pipeBufAddrParams)382 MOS_STATUS HevcVdencRoi::SetVdencPipeBufAddrParams(
383     MHW_VDBOX_PIPE_BUF_ADDR_PARAMS &pipeBufAddrParams)
384 {
385     if (!m_enabled)
386     {
387         return MOS_STATUS_SUCCESS;
388     }
389 
390     RoiStrategy *strategy = GetStrategyForParamsSetting();
391     ENCODE_CHK_NULL_RETURN(strategy);
392 
393     strategy->SetVdencPipeBufAddrParams(m_streamIn, pipeBufAddrParams);
394     return MOS_STATUS_SUCCESS;
395 }
396 
SetDmemHuCBrcInitReset(VdencHevcHucBrcInitDmem * hucVdencBrcInitDmem)397 MOS_STATUS HevcVdencRoi::SetDmemHuCBrcInitReset(
398     VdencHevcHucBrcInitDmem *hucVdencBrcInitDmem)
399 {
400     if (!m_enabled)
401     {
402         return MOS_STATUS_SUCCESS;
403     }
404 
405     RoiStrategy *strategy = GetStrategyForParamsSetting();
406     ENCODE_CHK_NULL_RETURN(strategy);
407 
408     return strategy->SetDmemHuCBrcInitReset(hucVdencBrcInitDmem);
409 }
410 
MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE,HevcVdencRoi)411 MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE, HevcVdencRoi)
412 {
413     if (!m_enabled)
414     {
415         return MOS_STATUS_SUCCESS;
416     }
417 
418     RoiStrategy *strategy = GetStrategyForParamsSetting();
419     ENCODE_CHK_NULL_RETURN(strategy);
420 
421     auto buf = strategy->GetStreamInBuf();
422     params.streamInBuffer = (buf == nullptr) ? m_streamIn : buf;
423 
424     return MOS_STATUS_SUCCESS;
425 }
426 
MHW_SETPAR_DECL_SRC(VDENC_CMD2,HevcVdencRoi)427 MHW_SETPAR_DECL_SRC(VDENC_CMD2, HevcVdencRoi)
428 {
429     if (!m_enabled)
430     {
431         return MOS_STATUS_SUCCESS;
432     }
433 
434     auto hevcFeature = dynamic_cast<HevcBasicFeature *>(m_basicFeature);
435     ENCODE_CHK_NULL_RETURN(hevcFeature);
436 
437     params.vdencStreamIn = m_enabled;
438     params.roiStreamIn   = m_isNativeRoi || m_isArbRoi;
439 
440     if (m_isNativeRoi)
441     {
442         int8_t roiTable[ENCODE_VDENC_HEVC_MAX_STREAMINROI_G10] = {0};
443 
444         for (uint8_t i = 0; i < ENCODE_VDENC_HEVC_MAX_STREAMINROI_G10; i++)
445         {
446             roiTable[i] = (int8_t)CodecHal_Clip3(
447                 ENCODE_VDENC_HEVC_MIN_ROI_DELTA_QP_G10, ENCODE_VDENC_HEVC_MAX_ROI_DELTA_QP_G10, hevcFeature->m_hevcPicParams->ROIDistinctDeltaQp[i]);
448         }
449 
450 #if !(_MEDIA_RESERVED)
451         params.extSettings.emplace_back(
452             [&roiTable](uint32_t *data) {
453                 data[13] |= (roiTable[0] << 4);
454                 data[13] |= (roiTable[1] << 8);
455                 data[13] |= (roiTable[2] << 12);
456                 return MOS_STATUS_SUCCESS;
457             });
458 #else
459         params.vdencCmd2Par43[1] = roiTable[0];
460         params.vdencCmd2Par43[2] = roiTable[1];
461         params.vdencCmd2Par43[3] = roiTable[2];
462 #endif  // !(_MEDIA_RESERVED)
463     }
464 
465     bool flag0 = false;
466     bool flag1 = false;
467     if (m_roiMode)
468     {
469         flag0 = 1;
470         flag1 = 1;
471     }
472     else if (!m_roiMode && !m_isNativeRoi && !m_dirtyRoiEnabled && !m_isArbRoi)
473     {
474         flag0 = 0;
475         flag1 = 1;
476     }
477 
478 #if !(_MEDIA_RESERVED)
479     params.extSettings.emplace_back(
480         [flag0, flag1](uint32_t *data) {
481             data[20] |= (flag0 << 17);
482             data[20] |= (flag1 << 19);
483             return MOS_STATUS_SUCCESS;
484         });
485 #else
486     params.vdencCmd2Par60 = flag0;
487     params.vdencCmd2Par61 = flag1;
488 #endif  // !(_MEDIA_RESERVED)
489 
490     return MOS_STATUS_SUCCESS;
491 }
492 }
493