1 /*
2 * Copyright (c) 2019-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_av1_vdenc_pipeline.cpp
24 //! \brief Defines the interface for av1 vdenc encode pipeline
25 //!
26 #include "encode_av1_vdenc_pipeline.h"
27 #include "codec_def_encode.h"
28 #include "encode_utils.h"
29 #include "encode_av1_tile.h"
30 #include "encode_av1_basic_feature.h"
31 #include "encode_av1_vdenc_preenc.h"
32 #include "codechal_debug.h"
33
34 namespace encode {
35
Av1VdencPipeline(CodechalHwInterfaceNext * hwInterface,CodechalDebugInterface * debugInterface)36 Av1VdencPipeline::Av1VdencPipeline(
37 CodechalHwInterfaceNext * hwInterface,
38 CodechalDebugInterface *debugInterface)
39 : Av1Pipeline(hwInterface, debugInterface)
40 {
41
42 }
43
Initialize(void * settings)44 MOS_STATUS Av1VdencPipeline::Initialize(void *settings)
45 {
46 ENCODE_FUNC_CALL();
47 ENCODE_CHK_STATUS_RETURN(Av1Pipeline::Initialize(settings));
48
49 // Init hwInterface
50 CodechalSetting *codecSettings = (CodechalSetting *)settings;
51 ENCODE_CHK_NULL_RETURN(m_hwInterface);
52 ENCODE_CHK_STATUS_RETURN(m_hwInterface->Initialize(codecSettings));
53
54 ENCODE_CHK_STATUS_RETURN(InitMmcState());
55
56 ENCODE_CHK_STATUS_RETURN(GetSystemVdboxNumber());
57
58 return MOS_STATUS_SUCCESS;
59 }
60
Destroy()61 MOS_STATUS Av1VdencPipeline::Destroy()
62 {
63 ENCODE_FUNC_CALL();
64
65 MOS_Delete(m_mmcState);
66
67 return Av1Pipeline::Uninitialize();
68 }
69
UserFeatureReport()70 MOS_STATUS Av1VdencPipeline::UserFeatureReport()
71 {
72 ENCODE_FUNC_CALL();
73 ENCODE_CHK_STATUS_RETURN(Av1Pipeline::UserFeatureReport());
74
75 ReportUserSetting(
76 m_userSettingPtr,
77 "AV1 Encode Mode",
78 m_codecFunction,
79 MediaUserSetting::Group::Sequence);
80
81 #if (_DEBUG || _RELEASE_INTERNAL)
82 ReportUserSettingForDebug(
83 m_userSettingPtr,
84 "VDENC In Use",
85 1,
86 MediaUserSetting::Group::Sequence);
87
88 ReportUserSettingForDebug(
89 m_userSettingPtr,
90 "Enable Encode VE CtxBasedScheduling",
91 MOS_VE_CTXBASEDSCHEDULING_SUPPORTED(m_osInterface),
92 MediaUserSetting::Group::Sequence);
93 #endif
94
95 return MOS_STATUS_SUCCESS;
96 }
97
Prepare(void * params)98 MOS_STATUS Av1VdencPipeline::Prepare(void *params)
99 {
100 EncoderParams *encodeParams = (EncoderParams *)params;
101
102 ENCODE_CHK_NULL_RETURN(encodeParams);
103
104 if (encodeParams->ExecCodecFunction != CODECHAL_FUNCTION_ENC_VDENC_PAK)
105 {
106 return MOS_STATUS_INVALID_PARAMETER;
107 }
108
109 auto feature = dynamic_cast<Av1BasicFeature *>(m_featureManager->GetFeature(Av1FeatureIDs::basicFeature));
110 ENCODE_CHK_NULL_RETURN(feature);
111 feature->m_dualEncEnable = m_dualEncEnable;
112
113 ENCODE_CHK_STATUS_RETURN(Av1Pipeline::Prepare(params));
114
115 uint16_t numTileRows = 0;
116 uint16_t numTileColumns = 0;
117 RUN_FEATURE_INTERFACE_RETURN(Av1EncodeTile, Av1FeatureIDs::encodeTile, GetTileRowColumns, numTileRows, numTileColumns);
118
119 ENCODE_CHK_STATUS_RETURN(SwitchContext(feature->m_outputChromaFormat, numTileRows, numTileColumns));
120
121 EncoderStatusParameters inputParameters = {};
122
123 ENCODE_CHK_STATUS_RETURN(FillStatusReportParameters(&inputParameters, encodeParams));
124
125 ENCODE_CHK_STATUS_RETURN(m_statusReport->Init(&inputParameters));
126
127 return MOS_STATUS_SUCCESS;
128 }
129
ResetParams()130 MOS_STATUS Av1VdencPipeline::ResetParams()
131 {
132 ENCODE_FUNC_CALL();
133
134 m_currRecycledBufIdx = (m_currRecycledBufIdx + 1) % CODECHAL_ENCODE_RECYCLED_BUFFER_NUM;
135
136 if (m_currRecycledBufIdx == 0)
137 {
138 MOS_ZeroMemory(m_recycledBufStatusNum, sizeof(m_recycledBufStatusNum));
139 }
140
141 auto feature = dynamic_cast<EncodeBasicFeature*>(m_featureManager->GetFeature(Av1FeatureIDs::basicFeature));
142 ENCODE_CHK_NULL_RETURN(feature);
143
144 // Only update user features for first frame.
145 if (feature->m_frameNum == 0)
146 {
147 ENCODE_CHK_STATUS_RETURN(UserFeatureReport());
148 }
149
150 feature->m_frameNum++;
151
152 ENCODE_CHK_STATUS_RETURN(m_statusReport->Reset());
153
154 return MOS_STATUS_SUCCESS;
155 }
156
GetStatusReport(void * status,uint16_t numStatus)157 MOS_STATUS Av1VdencPipeline::GetStatusReport(void *status, uint16_t numStatus)
158 {
159 ENCODE_FUNC_CALL();
160 ENCODE_CHK_STATUS_RETURN(m_statusReport->GetReport(numStatus, status));
161
162 return MOS_STATUS_SUCCESS;
163 }
164
Execute()165 MOS_STATUS Av1VdencPipeline::Execute()
166 {
167 ENCODE_FUNC_CALL();
168
169 ENCODE_CHK_STATUS_RETURN(ActivateVdencVideoPackets());
170 ENCODE_CHK_STATUS_RETURN(ExecuteActivePackets());
171
172 ENCODE_CHK_STATUS_RETURN(ResetParams());
173
174 return MOS_STATUS_SUCCESS;
175 }
176
HuCCheckAndInit()177 MOS_STATUS Av1VdencPipeline::HuCCheckAndInit()
178 {
179 ENCODE_FUNC_CALL();
180
181 bool immediateSubmit = !m_singleTaskPhaseSupported;
182 ENCODE_CHK_STATUS_RETURN(ActivatePacket(Av1HucBrcInit, immediateSubmit, 0, 0));
183
184 return MOS_STATUS_SUCCESS;
185 }
186
ActivateVdencVideoPackets()187 MOS_STATUS Av1VdencPipeline::ActivateVdencVideoPackets()
188 {
189 ENCODE_FUNC_CALL();
190
191 bool immediateSubmit = !m_singleTaskPhaseSupported;
192
193 ENCODE_CHK_NULL_RETURN(m_featureManager);
194
195 auto basicFeature = dynamic_cast<Av1BasicFeature*>(m_featureManager->GetFeature(Av1FeatureIDs::basicFeature));
196 ENCODE_CHK_NULL_RETURN(basicFeature);
197
198 auto brcFeature = dynamic_cast<Av1Brc*>(m_featureManager->GetFeature(Av1FeatureIDs::av1BrcFeature));
199 ENCODE_CHK_NULL_RETURN(brcFeature);
200
201 if (m_preEncEnabled)
202 {
203 ENCODE_CHK_STATUS_RETURN(ActivatePacket(encodePreEncPacket, immediateSubmit, 0, 0));
204 #if USE_CODECHAL_DEBUG_TOOL
205 uint32_t encodeMode = 0;
206 RUN_FEATURE_INTERFACE_RETURN(Av1VdencPreEnc, FeatureIDs::preEncFeature, GetEncodeMode, encodeMode);
207 if (encodeMode == MediaEncodeMode::MANUAL_RES_PRE_ENC || encodeMode == MediaEncodeMode::AUTO_RES_PRE_ENC)
208 {
209 m_activePacketList.back().immediateSubmit = true;
210 return MOS_STATUS_SUCCESS;
211 }
212 #endif
213 }
214
215 if (brcFeature->IsBRCInitRequired())
216 {
217 ENCODE_CHK_STATUS_RETURN(HuCCheckAndInit());
218 }
219
220 for (uint8_t curPass = 0; curPass < GetPassNum(); curPass++)
221 {
222 if (brcFeature->IsBRCEnabled())
223 {
224 ENCODE_CHK_STATUS_RETURN(ActivatePacket(Av1HucBrcUpdate, immediateSubmit, curPass, 0));
225 }
226
227 for (uint8_t curPipe = 0; curPipe < GetPipeNum(); curPipe++)
228 {
229 // force immediate submit to false irrespective of single/multi task phase at pipe 0 when dual enc enabled
230 ENCODE_CHK_STATUS_RETURN(ActivatePacket(Av1VdencPacket, m_dualEncEnable && curPipe == 0 ? false : immediateSubmit, curPass, curPipe, GetPipeNum()));
231 }
232
233 if ((basicFeature->m_enableTileStitchByHW || !basicFeature -> m_enableSWStitching || brcFeature->IsBRCEnabled()) && m_dualEncEnable)
234 {
235 ENCODE_CHK_STATUS_RETURN(ActivatePacket(Av1PakIntegrate, immediateSubmit, curPass, 0));
236 }
237
238 if (!basicFeature->m_enableSWBackAnnotation)
239 {
240 ENCODE_CHK_STATUS_RETURN(ActivatePacket(Av1BackAnnotation, immediateSubmit, curPass, 0));
241 }
242 }
243
244 SetFrameTrackingForMultiTaskPhase();
245
246 // Last element in m_activePacketList must be immediately submitted
247 m_activePacketList.back().immediateSubmit = true;
248
249 return MOS_STATUS_SUCCESS;
250 }
251
CreateFeatureManager()252 MOS_STATUS Av1VdencPipeline::CreateFeatureManager()
253 {
254 ENCODE_FUNC_CALL();
255 m_featureManager = MOS_New(EncodeAv1VdencFeatureManager, m_allocator, m_hwInterface, m_trackedBuf, m_recycleBuf);
256 ENCODE_CHK_NULL_RETURN(m_featureManager);
257 return MOS_STATUS_SUCCESS;
258 }
259
SwitchContext(uint8_t outputChromaFormat,uint16_t numTileRows,uint16_t numTileColumns)260 MOS_STATUS Av1VdencPipeline::SwitchContext(uint8_t outputChromaFormat, uint16_t numTileRows, uint16_t numTileColumns)
261 {
262 ENCODE_FUNC_CALL();
263
264 if (!m_scalPars)
265 {
266 m_scalPars = std::make_shared<EncodeScalabilityPars>();
267 }
268
269 *m_scalPars = {};
270 m_scalPars->enableVDEnc = true;
271 m_scalPars->enableVE = MOS_VE_SUPPORTED(m_osInterface);
272
273 //force to disable scalability for AV1 VDENC
274 if(m_dualEncEnable)
275 {
276 m_scalPars->numVdbox = m_numVdbox;
277 m_scalPars->forceMultiPipe = true;
278 m_scalPars->allowSwArbitarySplit = true;
279 }
280 else
281 {
282 m_scalPars->numVdbox = 1;
283 m_scalPars->forceMultiPipe = false;
284 m_scalPars->allowSwArbitarySplit = false;
285 }
286
287 m_scalPars->outputChromaFormat = outputChromaFormat;
288
289 m_scalPars->numTileRows = numTileRows;
290 m_scalPars->numTileColumns = numTileColumns;
291
292 m_scalPars->IsPak = true;
293
294 m_mediaContext->SwitchContext(VdboxEncodeFunc, &*m_scalPars, &m_scalability);
295 ENCODE_CHK_NULL_RETURN(m_scalability);
296
297 m_scalability->SetPassNumber(m_featureManager->GetNumPass());
298
299 return MOS_STATUS_SUCCESS;
300 }
301
FillStatusReportParameters(EncoderStatusParameters * pPar,EncoderParams * encodeParams)302 MOS_STATUS Av1VdencPipeline::FillStatusReportParameters(EncoderStatusParameters* pPar, EncoderParams* encodeParams)
303 {
304 ENCODE_CHK_NULL_RETURN(pPar);
305 ENCODE_CHK_NULL_RETURN(encodeParams);
306
307 PCODEC_AV1_ENCODE_PICTURE_PARAMS picParams = static_cast<PCODEC_AV1_ENCODE_PICTURE_PARAMS>(encodeParams->pPicParams);
308 ENCODE_CHK_NULL_RETURN(picParams);
309
310 auto feature = dynamic_cast<Av1BasicFeature *>(m_featureManager->GetFeature(Av1FeatureIDs::basicFeature));
311 ENCODE_CHK_NULL_RETURN(feature);
312
313 uint16_t numTileRows = 0;
314 uint16_t numTileColumns = 0;
315 RUN_FEATURE_INTERFACE_RETURN(Av1EncodeTile, Av1FeatureIDs::encodeTile, GetTileRowColumns,
316 numTileRows, numTileColumns);
317
318 pPar->statusReportFeedbackNumber = picParams->StatusReportFeedbackNumber;
319 pPar->codecFunction = encodeParams->ExecCodecFunction;
320 pPar->currRefList = feature->m_ref.GetCurrRefList();
321 pPar->picWidthInMb = feature->m_picWidthInMb;
322 pPar->frameFieldHeightInMb = feature->m_frameFieldHeightInMb;
323 pPar->currOriginalPic = feature->m_currOriginalPic;
324 pPar->pictureCodingType = feature->m_pictureCodingType;
325 pPar->numUsedVdbox = m_numVdbox;
326 pPar->hwWalker = false;
327 pPar->maxNumSlicesAllowed = 0;
328
329 pPar->numberTilesInFrame = numTileRows * numTileColumns;
330
331 pPar->av1EnableFrameObu = feature->m_av1PicParams->PicFlags.fields.EnableFrameOBU;
332 pPar->av1FrameHdrOBUSizeByteOffset = feature->m_frameHdrOBUSizeByteOffset;
333 pPar->frameWidth = feature->m_frameWidth;
334 pPar->frameHeight = feature->m_frameHeight;
335
336 return MOS_STATUS_SUCCESS;
337 }
338
339 }
340