1 /*
2 * Copyright (c) 2018-2022, 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_hevc_vdenc_feature_manager.cpp
25 //! \brief Defines the common interface for hevc vdenc feature manager
26 //! \details The encode feature manager is further sub-divided by codec type
27 //! this file is for the base interface which is shared by all components.
28 //!
29
30 #include "encode_hevc_vdenc_feature_manager.h"
31 #include "encode_hevc_reference_frames.h"
32 #include "encode_hevc_vdenc_const_settings.h"
33 #include "encode_hevc_vdenc_weighted_prediction.h"
34 #include "encode_hevc_brc.h"
35 #include "encode_vdenc_lpla_analysis.h"
36 #include "encode_hevc_vdenc_lpla_enc.h"
37
38 namespace encode
39 {
CreateConstSettings()40 MOS_STATUS EncodeHevcVdencFeatureManager::CreateConstSettings()
41 {
42 ENCODE_FUNC_CALL();
43 m_featureConstSettings = MOS_New(EncodeHevcVdencConstSettings);
44
45 return MOS_STATUS_SUCCESS;
46 }
47
CheckFeatures(void * params)48 MOS_STATUS EncodeHevcVdencFeatureManager::CheckFeatures(void *params)
49 {
50 ENCODE_FUNC_CALL();
51 EncoderParams *encodeParams = (EncoderParams *)params;
52
53 PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams =
54 static_cast<PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS>(encodeParams->pSeqParams);
55 ENCODE_CHK_NULL_RETURN(hevcSeqParams);
56 PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams =
57 static_cast<PCODEC_HEVC_ENCODE_PICTURE_PARAMS>(encodeParams->pPicParams);
58 ENCODE_CHK_NULL_RETURN(hevcPicParams);
59 PCODEC_HEVC_ENCODE_SLICE_PARAMS hevcSliceParams =
60 static_cast<PCODEC_HEVC_ENCODE_SLICE_PARAMS>(encodeParams->pSliceParams);
61 ENCODE_CHK_NULL_RETURN(hevcSliceParams);
62
63 auto settings = static_cast<EncodeHevcVdencConstSettings *>(m_featureConstSettings);
64 ENCODE_CHK_NULL_RETURN(settings);
65 settings->Update(params);
66
67 if (encodeParams->bNewSeq)
68 {
69 m_ddiTargetUsage = hevcSeqParams->TargetUsage;
70 ENCODE_CHK_STATUS_RETURN(MapTargetUsage(hevcSeqParams->TargetUsage));
71 m_targetUsage = hevcSeqParams->TargetUsage;
72 }
73
74 auto sliceParams = hevcSliceParams;
75 ENCODE_CHK_NULL_RETURN(sliceParams);
76 for (uint32_t s = 0; s < encodeParams->dwNumSlices; s++, sliceParams++)
77 {
78 ENCODE_CHK_STATUS_RETURN(ValidateRandomAccess(hevcSeqParams, hevcPicParams, sliceParams));
79 }
80
81 // Screen content flag will come in with PPS on Android, but in SPS on Android,
82 // we will use screen content flag in PPS for kernel programming, and update
83 // the PPS screen content flag based on the SPS screen content flag if enabled.
84 hevcPicParams->bScreenContent |= hevcSeqParams->bScreenContent;
85
86 ENCODE_CHK_STATUS_RETURN(ValidateSCC(hevcPicParams));
87
88 ENCODE_CHK_STATUS_RETURN(ValidateACQP(hevcSeqParams, hevcPicParams));
89
90 ENCODE_CHK_STATUS_RETURN(ValidatePassNum(hevcSeqParams, hevcPicParams));
91
92 ENCODE_CHK_STATUS_RETURN(CheckPlatformCapability(hevcSeqParams, hevcPicParams, hevcSliceParams));
93
94 return MOS_STATUS_SUCCESS;
95 }
96
CreateFeatures(void * constSettings)97 MOS_STATUS EncodeHevcVdencFeatureManager::CreateFeatures(void *constSettings)
98 {
99 ENCODE_FUNC_CALL();
100
101 auto setting = static_cast<EncodeHevcVdencConstSettings *>(m_featureConstSettings);
102 ENCODE_CHK_NULL_RETURN(setting);
103 setting->SetOsInterface(m_hwInterface->GetOsInterface());
104
105 EncodeBasicFeature *encBasic = MOS_New(HevcBasicFeature, m_allocator, m_hwInterface, m_trackedBuf, m_recycleResource, constSettings);
106 ENCODE_CHK_STATUS_RETURN(RegisterFeatures(HevcFeatureIDs::basicFeature, encBasic));
107
108 HevcEncodeCqp *encCqp = MOS_New(HevcEncodeCqp, this, m_allocator, m_hwInterface, constSettings);
109 ENCODE_CHK_STATUS_RETURN(RegisterFeatures(HevcFeatureIDs::hevcCqpFeature, encCqp));
110
111 HevcEncodeTile *encTile = MOS_New(HevcEncodeTile, this, m_allocator, m_hwInterface, constSettings);
112 ENCODE_CHK_STATUS_RETURN(RegisterFeatures(HevcFeatureIDs::encodeTile, encTile));
113
114 HEVCEncodeBRC *brc = MOS_New(HEVCEncodeBRC, this, m_allocator, m_hwInterface, constSettings);
115 ENCODE_CHK_STATUS_RETURN(RegisterFeatures(HevcFeatureIDs::hevcBrcFeature, brc));
116
117 HevcVdencRoi *hevcRoi = MOS_New(HevcVdencRoi, this, m_allocator, m_hwInterface, constSettings);
118 ENCODE_CHK_STATUS_RETURN(RegisterFeatures(HevcFeatureIDs::hevcVdencRoiFeature, hevcRoi));
119
120 HevcVdencWeightedPred *hevcWeightedPred = MOS_New(HevcVdencWeightedPred, this, m_allocator, m_hwInterface, constSettings);
121 ENCODE_CHK_STATUS_RETURN(RegisterFeatures(HevcFeatureIDs::hevcVdencWpFeature, hevcWeightedPred));
122
123 HevcEncodeDss *hevcDss = MOS_New(HevcEncodeDss, this, m_allocator, m_hwInterface, constSettings);
124 ENCODE_CHK_STATUS_RETURN(RegisterFeatures(HevcFeatureIDs::hevcVdencDssFeature, hevcDss));
125
126 HevcVdencScc *hevcScc = MOS_New(HevcVdencScc, this, m_allocator, m_hwInterface, constSettings);
127 ENCODE_CHK_STATUS_RETURN(RegisterFeatures(HevcFeatureIDs::hevcVdencSccFeature, hevcScc));
128
129 VdencLplaAnalysis *lplaAnalysis = MOS_New(VdencLplaAnalysis, this, m_allocator, m_hwInterface, constSettings);
130 ENCODE_CHK_STATUS_RETURN(RegisterFeatures(HevcFeatureIDs::vdencLplaAnalysisFeature, lplaAnalysis));
131
132 HEVCVdencLplaEnc *lplaEnc = MOS_New(HEVCVdencLplaEnc, this, m_allocator, m_hwInterface, constSettings);
133 ENCODE_CHK_STATUS_RETURN(RegisterFeatures(HevcFeatureIDs::hevcVdencLplaEncFeature, lplaEnc));
134
135 return MOS_STATUS_SUCCESS;
136 }
137
MapTargetUsage(uint8_t & targetUsage)138 MOS_STATUS EncodeHevcVdencFeatureManager::MapTargetUsage(uint8_t &targetUsage)
139 {
140 ENCODE_FUNC_CALL();
141
142 switch (targetUsage)
143 {
144 case 1: case 2:
145 targetUsage = 2;
146 break;
147 case 3: case 4: case 5:
148 targetUsage = 4;
149 break;
150 case 6: case 7:
151 targetUsage = 7;
152 break;
153 default:
154 targetUsage = 4;
155 break;
156 }
157 return MOS_STATUS_SUCCESS;
158 }
159
ValidateRandomAccess(PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams,PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams,PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams)160 MOS_STATUS EncodeHevcVdencFeatureManager::ValidateRandomAccess(
161 PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams,
162 PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams,
163 PCODEC_HEVC_ENCODE_SLICE_PARAMS slcParams)
164 {
165 ENCODE_FUNC_CALL();
166
167 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
168 bool isRandomAccess = false;
169
170 ENCODE_CHK_NULL_RETURN(slcParams);
171
172 if (slcParams->slice_type == CODECHAL_HEVC_B_SLICE)
173 {
174 if (slcParams->num_ref_idx_l0_active_minus1 != slcParams->num_ref_idx_l1_active_minus1)
175 {
176 isRandomAccess = true;
177 }
178
179 for (auto j = 0; j < CODEC_MAX_NUM_REF_FRAME_HEVC; j++)
180 {
181 if (slcParams->RefPicList[0][j].PicEntry != slcParams->RefPicList[1][j].PicEntry)
182 {
183 isRandomAccess = true;
184 }
185 }
186 }
187
188 if (isRandomAccess)
189 {
190 ENCODE_CHK_NULL_RETURN(hevcPicParams);
191 ENCODE_CHK_NULL_RETURN(hevcSeqParams);
192
193 // SCC + RA B is not supported.
194 auto sccFeature = dynamic_cast<HevcVdencScc *>(GetFeature(HevcFeatureIDs::hevcVdencSccFeature));
195 if (sccFeature && sccFeature->IsSCCEnabled())
196 {
197 ENCODE_ASSERTMESSAGE("SCC is in conflict with RandomAccess.");
198 eStatus = MOS_STATUS_INVALID_PARAMETER;
199 }
200
201 if (hevcPicParams->bEnableRollingIntraRefresh)
202 {
203 ENCODE_ASSERT(false);
204 eStatus = MOS_STATUS_INVALID_PARAMETER;
205 }
206 }
207
208 uint8_t maxNumRef0 = isRandomAccess ? 2 : HevcReferenceFrames::m_numMaxVdencL0Ref;
209 uint8_t maxNumRef1 = isRandomAccess ? 1 : HevcReferenceFrames::m_numMaxVdencL1Ref;
210
211 if (slcParams->num_ref_idx_l0_active_minus1 > maxNumRef0 - 1)
212 {
213 ENCODE_ASSERT(false);
214 slcParams->num_ref_idx_l0_active_minus1 = maxNumRef0 - 1;
215 }
216
217 if (slcParams->num_ref_idx_l1_active_minus1 > maxNumRef1 - 1)
218 {
219 ENCODE_ASSERT(false);
220 slcParams->num_ref_idx_l1_active_minus1 = maxNumRef1 - 1;
221 }
222
223 return eStatus;
224 }
225
ValidateSCC(PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams)226 MOS_STATUS EncodeHevcVdencFeatureManager::ValidateSCC(PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams)
227 {
228 ENCODE_FUNC_CALL();
229 ENCODE_CHK_NULL_RETURN(hevcPicParams);
230
231 if (hevcPicParams->tiles_enabled_flag)
232 {
233 auto sccFeature = dynamic_cast<HevcVdencScc *>(GetFeature(HevcFeatureIDs::hevcVdencSccFeature));
234 ENCODE_CHK_NULL_RETURN(sccFeature);
235 if (sccFeature->IsSCCEnabled() && hevcPicParams->pps_curr_pic_ref_enabled_flag)
236 {
237 for (int i = 0; i < hevcPicParams->num_tile_columns_minus1 + 1; i++)
238 {
239 if (hevcPicParams->tile_column_width[i] < 5)
240 {
241 ENCODE_ASSERTMESSAGE("IBC can not be enabled if tile width is less than 320.");
242 return MOS_STATUS_INVALID_PARAMETER;
243 }
244 }
245 }
246 }
247
248 return MOS_STATUS_SUCCESS;
249 }
250
ValidateACQP(PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams,PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams)251 MOS_STATUS EncodeHevcVdencFeatureManager::ValidateACQP(
252 PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams,
253 PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams)
254 {
255 ENCODE_FUNC_CALL();
256 ENCODE_CHK_NULL_RETURN(hevcSeqParams);
257 ENCODE_CHK_NULL_RETURN(hevcPicParams);
258
259 // ACQP is by default disabled, only enable it when WP/SSC/QpAdjust required.
260 if (hevcSeqParams->SliceSizeControl == true ||
261 hevcSeqParams->QpAdjustment == true ||
262 ((hevcPicParams->weighted_pred_flag ||
263 hevcPicParams->weighted_bipred_flag) &&
264 hevcPicParams->bEnableGPUWeightedPrediction == true))
265 {
266 auto brcFeature = dynamic_cast<HEVCEncodeBRC *>(GetFeature(HevcFeatureIDs::hevcBrcFeature));
267
268 ENCODE_CHK_NULL_RETURN(brcFeature);
269 brcFeature->SetACQPStatus(true);
270 }
271
272 return MOS_STATUS_SUCCESS;
273 }
ValidatePassNum(PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams,PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams)274 MOS_STATUS EncodeHevcVdencFeatureManager::ValidatePassNum(
275 PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams,
276 PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams)
277 {
278 ENCODE_FUNC_CALL();
279 ENCODE_CHK_NULL_RETURN(hevcSeqParams);
280 ENCODE_CHK_NULL_RETURN(hevcPicParams);
281
282 auto brcFeature = dynamic_cast<HEVCEncodeBRC *>(GetFeature(HevcFeatureIDs::hevcBrcFeature));
283
284 auto basicFeature = dynamic_cast<HevcBasicFeature *>(GetFeature(FeatureIDs::basicFeature));
285 ENCODE_CHK_NULL_RETURN(basicFeature);
286 if (basicFeature->m_422State && basicFeature->m_422State->GetFeature422Flag())
287 {
288 hevcPicParams->BRCPrecision = 1;
289 }
290
291 // dynamic slice size control and brc to be added later here
292 if (((hevcPicParams->weighted_pred_flag ||
293 hevcPicParams->weighted_bipred_flag) &&
294 hevcPicParams->bEnableGPUWeightedPrediction == true) ||
295 hevcSeqParams->SliceSizeControl || (brcFeature->IsRateControlBrc(hevcSeqParams->RateControlMethod) && hevcPicParams->BRCPrecision != 1))
296 {
297 m_passNum = 2;
298 }
299 else
300 {
301 // Currently no advance feature to combine with tile replay CQP
302 // Also no extra frame level pass for tile replay BRC
303 m_passNum = 1;
304 }
305
306 auto lplaFeature = dynamic_cast<VdencLplaAnalysis *>(GetFeature(HevcFeatureIDs::vdencLplaAnalysisFeature));
307 if (lplaFeature && hevcSeqParams->LookaheadDepth > 0 && hevcSeqParams->bLookAheadPhase)
308 {
309 m_passNum = 1;
310
311 if (hevcPicParams->CodingType != I_TYPE && lplaFeature->IsLplaAIdrEnabled())
312 {
313 m_passNum += 1;
314 }
315 }
316
317 return MOS_STATUS_SUCCESS;
318 }
319
CheckPlatformCapability(PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams,PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams,PCODEC_HEVC_ENCODE_SLICE_PARAMS hevcSliceParams)320 MOS_STATUS EncodeHevcVdencFeatureManager::CheckPlatformCapability(
321 PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams,
322 PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams,
323 PCODEC_HEVC_ENCODE_SLICE_PARAMS hevcSliceParams)
324 {
325 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
326
327 ENCODE_FUNC_CALL();
328 ENCODE_CHK_NULL_RETURN(hevcSeqParams);
329 ENCODE_CHK_NULL_RETURN(hevcPicParams);
330 ENCODE_CHK_NULL_RETURN(hevcSliceParams);
331
332 return eStatus;
333 }
334
335 } // namespace encode
336