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