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