1 /*
2 * Copyright (c) 2023, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     encode_hevc_vdenc_fastpass.cpp
24 //! \brief    Defines the Xe2_HPM+ Base interface for hevc encode fastpass features
25 //!
26 
27 #include "encode_vdenc_hevc_fastpass.h"
28 #include "encode_hevc_vdenc_feature_manager.h"
29 
30 namespace encode
31 {
32 
HevcVdencFastPass(MediaFeatureManager * featureManager,EncodeAllocator * allocator,CodechalHwInterfaceNext * hwInterface,void * constSettings)33 HevcVdencFastPass::HevcVdencFastPass(
34     MediaFeatureManager     *featureManager,
35     EncodeAllocator         *allocator,
36     CodechalHwInterfaceNext *hwInterface,
37     void* constSettings):
38     MediaFeature(constSettings,hwInterface ? hwInterface->GetOsInterface() : nullptr)
39 {
40     ENCODE_FUNC_CALL();
41     auto encFeatureManager = dynamic_cast<EncodeHevcVdencFeatureManager *>(featureManager);
42     ENCODE_CHK_NULL_NO_STATUS_RETURN(encFeatureManager);
43 
44     m_hevcFeature = dynamic_cast<HevcBasicFeature *>(encFeatureManager->GetFeature(FeatureIDs::basicFeature));
45     ENCODE_CHK_NULL_NO_STATUS_RETURN(m_hevcFeature);
46 
47     //regkey to control fast pass encode settings
48     MediaUserSetting::Value outValue;
49     ReadUserSetting(m_userSettingPtr,
50         outValue,
51         "Enable Fast Pass Encode",
52         MediaUserSetting::Group::Sequence);
53 
54     m_enableFastPass = outValue.Get<bool>();
55     if (m_enableFastPass)
56     {
57         MediaUserSetting::Value outValue_ratio;
58         MediaUserSetting::Value outValue_type;
59 #if (_DEBUG || _RELEASE_INTERNAL)
60 
61         ReadUserSetting(m_userSettingPtr,
62             outValue_ratio,
63             "Fast Pass Encode Downscale Ratio",
64             MediaUserSetting::Group::Sequence);
65         ReadUserSetting(m_userSettingPtr,
66             outValue_type,
67             "Fast Pass Encode Downscale Type",
68             MediaUserSetting::Group::Sequence);
69 #endif
70 
71         if (outValue_ratio.Get<int32_t>() == 0)
72         {
73             m_fastPassShiftIndex = 2;
74         }
75         else if (outValue_ratio.Get<int32_t>() == 1)
76         {
77             m_fastPassShiftIndex = 1;
78         }
79         else
80             m_fastPassShiftIndex = 2;
81         m_fastPassDownScaleType = (uint8_t)outValue_type.Get<int32_t>();
82     }
83 }
84 
Update(void * params)85 MOS_STATUS HevcVdencFastPass::Update(void *params)
86 {
87     if (!m_enableFastPass)
88     {
89         return MOS_STATUS_SUCCESS;
90     }
91 
92     ENCODE_CHK_NULL_RETURN(m_hevcFeature);
93     m_hevcSeqParams = m_hevcFeature->m_hevcSeqParams;
94     ENCODE_CHK_NULL_RETURN(m_hevcSeqParams);
95 
96     // hevc needs 8-pixels aligned
97     m_dsWidth  = MOS_ALIGN_FLOOR((m_hevcSeqParams->wFrameWidthInMinCbMinus1 + 1) << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3) >> m_fastPassShiftIndex, 8);
98     m_dsHeight = MOS_ALIGN_FLOOR((m_hevcSeqParams->wFrameHeightInMinCbMinus1 + 1) << (m_hevcSeqParams->log2_min_coding_block_size_minus3 + 3) >> m_fastPassShiftIndex, 8);
99 
100     return MOS_STATUS_SUCCESS;
101 }
102 
MHW_SETPAR_DECL_SRC(VDENC_PIPE_MODE_SELECT,HevcVdencFastPass)103 MHW_SETPAR_DECL_SRC(VDENC_PIPE_MODE_SELECT, HevcVdencFastPass)
104 {
105     ENCODE_FUNC_CALL();
106 
107     if (!m_enableFastPass)
108     {
109         return MOS_STATUS_SUCCESS;
110     }
111 
112     params.fastPassEn    = m_enableFastPass;
113     params.fastPassScale = m_fastPassShiftIndex == 2 ? 0 : 1;  // fastPassScale:0 indicates 4x4 ds, fastPassScale:1 indicates 2x2 ds
114     params.DownScaleType = m_fastPassDownScaleType;            // DownScaleType:0 indicates bilinear, DownScaleType:1 indicates NN
115     params.chromaType     = 1;                                 // Fast pass uses 420 type
116     params.bitDepthMinus8 = 0;                                 // Fast pass uses bitdepth 8
117     return MOS_STATUS_SUCCESS;
118 }
119 
MHW_SETPAR_DECL_SRC(VDENC_CMD2,HevcVdencFastPass)120 MHW_SETPAR_DECL_SRC(VDENC_CMD2, HevcVdencFastPass)
121 {
122     ENCODE_FUNC_CALL();
123 
124     if (!m_enableFastPass)
125     {
126         return MOS_STATUS_SUCCESS;
127     }
128 
129     params.width  = m_dsWidth;
130     params.height = m_dsHeight;
131 
132     return MOS_STATUS_SUCCESS;
133 }
134 
MHW_SETPAR_DECL_SRC(VDENC_HEVC_VP9_TILE_SLICE_STATE,HevcVdencFastPass)135 MHW_SETPAR_DECL_SRC(VDENC_HEVC_VP9_TILE_SLICE_STATE, HevcVdencFastPass)
136 {
137     ENCODE_FUNC_CALL();
138 
139     if (!m_enableFastPass)
140     {
141         return MOS_STATUS_SUCCESS;
142     }
143 
144     uint32_t widthInPix  = m_dsWidth;
145     uint32_t heightInPix = m_dsHeight;
146     //no tiling
147     params.tileWidth = widthInPix;
148     params.tileHeight = heightInPix;
149 
150     if (m_hevcSeqParams->palette_mode_enabled_flag && m_hevcSeqParams->bit_depth_luma_minus8 == 2)
151     {
152         uint32_t SliceQP = m_hevcFeature->m_hevcPicParams->QpY + m_hevcFeature->m_hevcSliceParams->slice_qp_delta;
153         uint32_t tableIdx;
154         if (SliceQP <= 12)
155         {
156             tableIdx = 0;
157         }
158         else if (SliceQP > 12 && SliceQP <= 17)
159         {
160             tableIdx = 1;
161         }
162         else if (SliceQP > 17 && SliceQP <= 22)
163         {
164             tableIdx = 2;
165         }
166         else if (SliceQP > 22 && SliceQP <= 27)
167         {
168             tableIdx = 3;
169         }
170         else if (SliceQP > 27 && SliceQP <= 32)
171         {
172             tableIdx = 4;
173         }
174         else if (SliceQP > 32 && SliceQP <= 37)
175         {
176             tableIdx = 5;
177         }
178         else if (SliceQP > 37 && SliceQP <= 42)
179         {
180             tableIdx = 6;
181         }
182         else if (SliceQP > 42 && SliceQP <= 47)
183         {
184             tableIdx = 7;
185         }
186         else if (SliceQP > 47 && SliceQP <= 49)
187         {
188             tableIdx = 8;
189         }
190         else
191         {
192             tableIdx = 9;
193         }
194 
195         static const uint32_t table[3][10][11] =
196             {
197                 {
198                     {16},
199                     {16},
200                     {16},
201                     {16},
202                     {32},
203                     {48},
204                     {64},
205                     {96},
206                     {128},
207                     {256},
208                 },
209                 {
210                     {16},
211                     {16},
212                     {16},
213                     {16},
214                     {32},
215                     {48},
216                     {64},
217                     {96},
218                     {128},
219                     {256},
220                 },
221                 {
222                     {256},
223                     {256},
224                     {256},
225                     {256},
226                     {256},
227                     {768},
228                     {768},
229                     {768},
230                     {768},
231                     {768},
232                 },
233             };
234 
235         params.VdencHEVCVP9TileSlicePar5  = 4;
236         params.VdencHEVCVP9TileSlicePar14 = table[params.VdencHEVCVP9TileSlicePar1][tableIdx][0];
237         params.VdencHEVCVP9TileSlicePar6  >>= 2;
238         params.VdencHEVCVP9TileSlicePar7  >>= 2;
239     }
240 
241     return MOS_STATUS_SUCCESS;
242 }
243 
MHW_SETPAR_DECL_SRC(VDENC_WALKER_STATE,HevcVdencFastPass)244 MHW_SETPAR_DECL_SRC(VDENC_WALKER_STATE, HevcVdencFastPass)
245 {
246     ENCODE_FUNC_CALL();
247 
248     if (!m_enableFastPass)
249     {
250         return MOS_STATUS_SUCCESS;
251     }
252 
253     auto                            t_sliceParams = m_hevcFeature->m_hevcSliceParams;
254     CODEC_HEVC_ENCODE_SLICE_PARAMS *sliceParams   = (CODEC_HEVC_ENCODE_SLICE_PARAMS *)&t_sliceParams[m_hevcFeature->m_curNumSlices];
255 
256     uint32_t ctbSize     = 1 << (m_hevcSeqParams->log2_max_coding_block_size_minus3 + 3);
257     uint32_t widthInCtb  = (m_dsWidth / ctbSize) + ((m_dsWidth % ctbSize) ? 1 : 0);  // round up
258     uint32_t heightInCtb = (m_dsHeight / ctbSize) + ((m_dsHeight % ctbSize) ? 1 : 0);  // round up
259     //no tiling
260     params.tileSliceStartLcuMbY     = sliceParams->slice_segment_address / widthInCtb;
261     params.nextTileSliceStartLcuMbX = (sliceParams->slice_segment_address + widthInCtb * heightInCtb) / heightInCtb;
262     params.nextTileSliceStartLcuMbY = (sliceParams->slice_segment_address + widthInCtb * heightInCtb) / widthInCtb;
263 
264     return MOS_STATUS_SUCCESS;
265 }
266 
MHW_SETPAR_DECL_SRC(VDENC_REF_SURFACE_STATE,HevcVdencFastPass)267 MHW_SETPAR_DECL_SRC(VDENC_REF_SURFACE_STATE, HevcVdencFastPass)
268 {
269     ENCODE_FUNC_CALL();
270 
271     if (!m_enableFastPass)
272     {
273         return MOS_STATUS_SUCCESS;
274     }
275 
276     params.width  = m_dsWidth;
277     params.height = m_dsHeight;
278 
279     //Fast pass uses 420 type
280     if (m_hevcSeqParams->chroma_format_idc != 1)
281     {
282         params.format = Format_NV12;
283         params.vOffset = params.uOffset;
284     }
285 
286     return MOS_STATUS_SUCCESS;
287 }
288 
MHW_SETPAR_DECL_SRC(VDENC_DS_REF_SURFACE_STATE,HevcVdencFastPass)289 MHW_SETPAR_DECL_SRC(VDENC_DS_REF_SURFACE_STATE, HevcVdencFastPass)
290 {
291     ENCODE_FUNC_CALL();
292 
293     if (!m_enableFastPass)
294     {
295         return MOS_STATUS_SUCCESS;
296     }
297 
298     uint32_t dsWidth4x  = m_dsWidth / SCALE_FACTOR_4x;
299     uint32_t dsHeight4x = m_dsHeight / SCALE_FACTOR_4x;
300 
301     params.heightStage1 = dsHeight4x >> 1;
302     params.widthStage1  = dsWidth4x >> 1;
303     params.heightStage2 = dsHeight4x;
304     params.widthStage2  = dsWidth4x;
305 
306     return MOS_STATUS_SUCCESS;
307 }
MHW_SETPAR_DECL_SRC(HCP_PIC_STATE,HevcVdencFastPass)308 MHW_SETPAR_DECL_SRC(HCP_PIC_STATE, HevcVdencFastPass)
309 {
310     ENCODE_FUNC_CALL();
311 
312     if (!m_enableFastPass)
313     {
314         return MOS_STATUS_SUCCESS;
315     }
316 
317     params.framewidthinmincbminus1  = (m_dsWidth >> 3) - 1;
318     params.frameheightinmincbminus1 = (m_dsHeight >> 3) - 1;
319 
320     //Fast pass  uses 420 type, bitdepth 8
321     if (m_hevcSeqParams->chroma_format_idc != 1)
322     {
323         params.chromaSubsampling = 1;
324         params.lcuMaxBitSizeAllowedMsb2its >>= 1;
325         params.lcuMaxBitsizeAllowed >>= 1;
326     }
327     if (m_hevcSeqParams->bit_depth_luma_minus8 == 2)
328     {
329         params.bitDepthChromaMinus8 = 0;
330         params.bitDepthLumaMinus8   = 0;
331     }
332 
333     //RDOQ TU7 is related to framesize, it needs to be downscaled.
334     if (m_hevcFeature->m_targetUsage == 7)
335     {
336         uint32_t frameSize_ds       = m_dsWidth * m_dsHeight;
337         params.rdoqintratuthreshold = MOS_MIN(((frameSize_ds * 30) / 100) >> 8, 0xffff);
338     }
339     return MOS_STATUS_SUCCESS;
340 }
341 
MHW_SETPAR_DECL_SRC(HCP_SURFACE_STATE,HevcVdencFastPass)342 MHW_SETPAR_DECL_SRC(HCP_SURFACE_STATE, HevcVdencFastPass)
343 {
344     ENCODE_FUNC_CALL();
345 
346     if (!m_enableFastPass)
347     {
348         return MOS_STATUS_SUCCESS;
349     }
350 
351     using namespace mhw::vdbox;
352 
353     //Fast pass  uses 420 type, bitdepth 8
354     if (m_hevcSeqParams->chroma_format_idc != 1)
355     {
356         params.yOffsetForVCr = (uint16_t)params.yOffsetForUCbInPixel;
357     }
358     params.surfaceFormat = hcp::SURFACE_FORMAT::SURFACE_FORMAT_PLANAR4208;
359 
360     return MOS_STATUS_SUCCESS;
361 }
362 
MHW_SETPAR_DECL_SRC(HEVC_VP9_RDOQ_STATE,HevcVdencFastPass)363 MHW_SETPAR_DECL_SRC(HEVC_VP9_RDOQ_STATE, HevcVdencFastPass)
364 {
365     ENCODE_FUNC_CALL();
366 
367     if (!m_enableFastPass)
368     {
369         return MOS_STATUS_SUCCESS;
370     }
371 
372     PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams = m_hevcFeature->m_hevcPicParams;
373     ENCODE_CHK_NULL_RETURN(hevcPicParams);
374 
375     //Fast pass  uses bitdepth 8
376     uint8_t bitDepthLumaMinus8   = 0;
377     uint8_t bitDepthChromaMinus8 = 0;
378     uint8_t codingType           = hevcPicParams->CodingType;
379     auto    settings             = static_cast<HevcVdencFeatureSettings *>(m_constSettings);
380     ENCODE_CHK_NULL_RETURN(settings);
381 
382     uint32_t sliceTypeIdx = (codingType == I_TYPE) ? 0 : 1;
383 
384     //Intra lambda
385     MOS_ZeroMemory(params.lambdaTab, sizeof(params.lambdaTab));
386     if (bitDepthLumaMinus8 == 0)
387     {
388         std::copy(settings->rdoqLamdas8bits[sliceTypeIdx][0][0].begin(),
389             settings->rdoqLamdas8bits[sliceTypeIdx][0][0].end(),
390             std::begin(params.lambdaTab[0][0]));
391 
392         std::copy(settings->rdoqLamdas8bits[sliceTypeIdx][0][1].begin(),
393             settings->rdoqLamdas8bits[sliceTypeIdx][0][1].end(),
394             std::begin(params.lambdaTab[0][1]));
395 
396         std::copy(settings->rdoqLamdas8bits[sliceTypeIdx][1][0].begin(),
397             settings->rdoqLamdas8bits[sliceTypeIdx][1][0].end(),
398             std::begin(params.lambdaTab[1][0]));
399 
400         std::copy(settings->rdoqLamdas8bits[sliceTypeIdx][1][1].begin(),
401             settings->rdoqLamdas8bits[sliceTypeIdx][1][1].end(),
402             std::begin(params.lambdaTab[1][1]));
403     }
404 
405     if (m_hevcFeature->m_hevcRDOQPerfDisabled)
406     {
407         params.disableHtqPerformanceFix0 = true;
408         params.disableHtqPerformanceFix1 = true;
409     }
410     return MOS_STATUS_SUCCESS;
411 }
412 
413 }  // namespace encode
414