1 /*
2 * Copyright (c) 2019-2021, 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     decode_av1_pipeline_g12.cpp
24 //! \brief    Defines the interface for av1 decode pipeline
25 //!
26 #include "decode_av1_pipeline_g12.h"
27 #include "decode_av1_packet_g12.h"
28 #include "decode_av1_picture_packet_g12.h"
29 #include "decode_av1_tile_packet_g12.h"
30 #include "decode_utils.h"
31 #include "codechal_debug.h"
32 #include "decode_av1_tile_coding_g12.h"
33 #include "decode_av1_feature_manager_g12.h"
34 #include "decode_mem_compression_g12.h"
35 #include "decode_av1_feature_defs_g12.h"
36 #include "decode_marker_packet_g12.h"
37 #include "decode_predication_packet_g12.h"
38 
39 namespace decode
40 {
Av1PipelineG12(CodechalHwInterface * hwInterface,CodechalDebugInterface * debugInterface)41     Av1PipelineG12::Av1PipelineG12(
42         CodechalHwInterface *   hwInterface,
43         CodechalDebugInterface *debugInterface)
44         : Av1PipelineG12_Base(hwInterface, debugInterface)
45     {
46 
47     }
48 
Init(void * settings)49     MOS_STATUS Av1PipelineG12::Init(void *settings)
50     {
51         DECODE_FUNC_CALL();
52 
53         DECODE_CHK_NULL(settings);
54         DECODE_CHK_STATUS(Initialize(settings));
55 
56         if (MEDIA_IS_SKU(m_skuTable, FtrWithSlimVdbox))
57         {
58             m_numVdbox = 1;
59         }
60 
61         m_av1DecodePkt = MOS_New(Av1DecodePktG12, this, m_task, m_hwInterface);
62         DECODE_CHK_STATUS(RegisterPacket(DecodePacketId(this, av1DecodePacketId), m_av1DecodePkt));
63         DECODE_CHK_STATUS(m_av1DecodePkt->Init());
64 
65         if (m_numVdbox == 2)
66         {
67             m_allowVirtualNodeReassign = true;
68         }
69 
70         return MOS_STATUS_SUCCESS;
71     }
72 
InitContext()73     MOS_STATUS Av1PipelineG12::InitContext()
74     {
75         DECODE_FUNC_CALL();
76 
77         auto basicFeature = dynamic_cast<Av1BasicFeatureG12*>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
78         DECODE_CHK_NULL(basicFeature);
79 
80         DecodeScalabilityPars scalPars;
81         MOS_ZeroMemory(&scalPars, sizeof(scalPars));
82         scalPars.disableScalability = true;
83         scalPars.enableVE = MOS_VE_SUPPORTED(m_osInterface);
84         if (MEDIA_IS_SKU(m_skuTable, FtrWithSlimVdbox))
85         {
86             scalPars.usingSlimVdbox = true;
87         }
88         else
89         {
90             scalPars.usingSlimVdbox = false;
91         }
92         scalPars.numVdbox = m_numVdbox;
93 
94         if (m_allowVirtualNodeReassign)
95         {
96             // reassign decoder virtual node at the first frame for each stream
97             DECODE_CHK_STATUS(m_mediaContext->ReassignContextForDecoder(basicFeature->m_frameNum, &scalPars, &m_scalability));
98             m_mediaContext->SetLatestDecoderVirtualNode();
99         }
100         else
101         {
102             DECODE_CHK_STATUS(m_mediaContext->SwitchContext(VdboxDecodeFunc, &scalPars, &m_scalability));
103         }
104         DECODE_CHK_NULL(m_scalability);
105 
106         m_decodeContext = m_osInterface->pfnGetGpuContext(m_osInterface);
107         m_decodeContextHandle = m_osInterface->CurrentGpuContextHandle;
108         DECODE_CHK_STATUS(basicFeature->m_tileCoding.CalcNumPass(*basicFeature->m_av1PicParams, basicFeature->m_av1TileParams));
109         m_passNum = basicFeature->m_tileCoding.GetNumPass();
110         m_scalability->SetPassNumber(m_passNum);
111 
112         if (scalPars.disableScalability)
113             m_osInterface->pfnSetMultiEngineEnabled(m_osInterface, COMPONENT_Decode, false);
114 
115         return MOS_STATUS_SUCCESS;
116     }
117 
Prepare(void * params)118     MOS_STATUS Av1PipelineG12::Prepare(void *params)
119     {
120         DECODE_FUNC_CALL();
121 
122         DECODE_CHK_NULL(params);
123         DecodePipelineParams *pipelineParams = (DecodePipelineParams *)params;
124         m_pipeMode = pipelineParams->m_pipeMode;
125 
126         PERF_UTILITY_AUTO((__FUNCTION__ + std::to_string((int)m_pipeMode)).c_str(), PERF_DECODE, PERF_LEVEL_HAL);
127 
128         auto basicFeature = dynamic_cast<Av1BasicFeatureG12*>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
129         DECODE_CHK_NULL(basicFeature);
130 
131         if (IsFirstProcessPipe(*pipelineParams))
132         {
133             DECODE_CHK_STATUS(Av1PipelineG12_Base::Prepare(params));
134         }
135 
136         DECODE_CHK_STATUS(m_preSubPipeline->Prepare(*pipelineParams));
137         DECODE_CHK_STATUS(m_postSubPipeline->Prepare(*pipelineParams));
138 
139         if (m_pipeMode == decodePipeModeProcess)
140         {
141             if (IsCompleteBitstream())
142             {
143                 CODECHAL_DEBUG_TOOL(DECODE_CHK_STATUS(DumpParams(*basicFeature)));
144 
145                 DecodeStatusParameters inputParameters = {};
146                 MOS_ZeroMemory(&inputParameters, sizeof(DecodeStatusParameters));
147                 inputParameters.statusReportFeedbackNumber = basicFeature->m_av1PicParams->m_statusReportFeedbackNumber;
148                 inputParameters.codecFunction              = basicFeature->m_codecFunction;
149                 inputParameters.picWidthInMb               = basicFeature->m_picWidthInMb;
150                 inputParameters.pictureCodingType          = basicFeature->m_pictureCodingType;
151                 inputParameters.currOriginalPic            = basicFeature->m_curRenderPic;
152                 inputParameters.currDecodedPicRes          = basicFeature->m_destSurface.OsResource;
153                 inputParameters.numUsedVdbox               = m_numVdbox;
154 
155                 CODECHAL_DEBUG_TOOL(
156                     if (m_streamout != nullptr)
157                     {
158                         DECODE_CHK_STATUS(m_streamout->InitStatusReportParam(inputParameters));
159                     }
160                 );
161 
162 #if (_DEBUG || _RELEASE_INTERNAL)
163                 auto filmGrainFeature = dynamic_cast<Av1DecodeFilmGrainG12*>(m_featureManager->GetFeature(
164                         Av1FeatureIDs::av1SwFilmGrain));
165                 if (filmGrainFeature != nullptr && filmGrainFeature->m_filmGrainEnabled)
166                 {
167                     auto frameIdx = basicFeature->m_curRenderPic.FrameIdx;
168                     inputParameters.fgOutputPicRes = &filmGrainFeature->m_fgOutputSurfList[frameIdx].OsResource;
169                 }
170 #endif
171                 m_allocator->UpdateResoreceUsageType(&inputParameters.currDecodedPicRes, resourceOutputPicture);
172                 m_statusReport->Init(&inputParameters);
173             }
174         }
175 
176         return MOS_STATUS_SUCCESS;
177     }
178 
Execute()179     MOS_STATUS Av1PipelineG12::Execute()
180     {
181         DECODE_FUNC_CALL();
182 
183         PERF_UTILITY_AUTO((__FUNCTION__ + std::to_string((int)m_pipeMode)).c_str(), PERF_DECODE, PERF_LEVEL_HAL);
184 
185         if (m_pipeMode == decodePipeModeBegin)
186         {
187             return MOS_STATUS_SUCCESS;
188         }
189 
190         auto basicFeature = dynamic_cast<Av1BasicFeatureG12*>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
191         DECODE_CHK_NULL(basicFeature);
192         DECODE_CHK_NULL(basicFeature->m_av1PicParams);
193         if (basicFeature->m_av1PicParams->m_anchorFrameInsertion)
194         {
195             return MOS_STATUS_SUCCESS;
196         }
197 
198         if (m_pipeMode == decodePipeModeProcess)
199         {
200             DECODE_CHK_STATUS(m_preSubPipeline->Execute());
201 
202             if (IsCompleteBitstream())
203             {
204                 DECODE_CHK_STATUS(InitContext());
205                 DECODE_CHK_STATUS(ActivateDecodePackets());
206                 DECODE_CHK_STATUS(ExecuteActivePackets());
207 
208                 DECODE_CHK_STATUS(m_postSubPipeline->Execute());
209 
210                 CODECHAL_DEBUG_TOOL(
211                     PMHW_BATCH_BUFFER batchBuffer = m_av1DecodePkt->GetSecondLvlBB();
212                     if (batchBuffer != nullptr)
213                     {
214                         batchBuffer->iLastCurrent = batchBuffer->iSize;
215                         batchBuffer->dwOffset = 0;
216                         DECODE_CHK_STATUS(m_debugInterface->Dump2ndLvlBatch(
217                             batchBuffer,
218                             CODECHAL_NUM_MEDIA_STATES,
219                             "AV1_DEC_Secondary"));
220                     })
221 
222 #if (_DEBUG || _RELEASE_INTERNAL)
223                 DECODE_CHK_STATUS(StatusCheck());
224 #endif
225                 // Only update user features for the first frame.
226                 if (basicFeature->m_frameNum == 0)
227                 {
228                     DECODE_CHK_STATUS(UserFeatureReport());
229                 }
230 
231                 DecodeFrameIndex++;
232                 basicFeature->m_frameNum = DecodeFrameIndex;
233 
234                 DECODE_CHK_STATUS(m_statusReport->Reset());
235             }
236         }
237 
238         return MOS_STATUS_SUCCESS;
239     }
240 
GetStatusReport(void * status,uint16_t numStatus)241     MOS_STATUS Av1PipelineG12::GetStatusReport(void *status, uint16_t numStatus)
242     {
243         DECODE_FUNC_CALL();
244 
245         m_statusReport->GetReport(numStatus, status);
246 
247         return MOS_STATUS_SUCCESS;
248     }
249 
GetCompletedReport()250     uint32_t Av1PipelineG12::GetCompletedReport()
251     {
252         DECODE_FUNC_CALL();
253 
254         uint32_t completedCount = m_statusReport->GetCompletedCount();
255         uint32_t reportedCount = m_statusReport->GetReportedCount();
256 
257         if (reportedCount > completedCount)
258         {
259             DECODE_ASSERTMESSAGE("No report available at all");
260             return 0;
261         }
262         else
263         {
264             uint32_t availableCount = completedCount - reportedCount;
265             return availableCount;
266         }
267     }
268 
Destroy()269     MOS_STATUS Av1PipelineG12::Destroy()
270     {
271         DECODE_FUNC_CALL();
272 
273         Uninitialize();
274 
275         return MOS_STATUS_SUCCESS;
276     }
277 
Initialize(void * settings)278     MOS_STATUS Av1PipelineG12::Initialize(void *settings)
279     {
280         DECODE_FUNC_CALL();
281 
282         DECODE_CHK_STATUS(Av1PipelineG12_Base::Initialize(settings));
283         DECODE_CHK_STATUS(InitMmcState());
284 
285         auto *codecSettings     = (CodechalSetting *)settings;
286         m_fgCoordValSurfInitPipeline = MOS_New(FilmGrainSurfaceInit, this, m_task, m_numVdbox, m_hwInterface);
287         DECODE_CHK_NULL(m_fgCoordValSurfInitPipeline);
288         DECODE_CHK_STATUS(m_preSubPipeline->Register(*m_fgCoordValSurfInitPipeline));
289         DECODE_CHK_STATUS(m_fgCoordValSurfInitPipeline->Init(*codecSettings));
290 
291         //pre subpipeline for generate noise
292         m_fgGenNoiseSubPipeline = MOS_New(FilmGrainPreSubPipeline, this, m_task, m_numVdbox, m_hwInterface);
293         DECODE_CHK_NULL(m_fgGenNoiseSubPipeline);
294         DECODE_CHK_STATUS(m_preSubPipeline->Register(*m_fgGenNoiseSubPipeline));
295         DECODE_CHK_STATUS(m_fgGenNoiseSubPipeline->Init(*codecSettings));
296 
297         //post subpipeline for apply noise
298         m_fgAppNoiseSubPipeline = MOS_New(FilmGrainPostSubPipeline, this, m_task, m_numVdbox, m_hwInterface);
299         DECODE_CHK_NULL(m_fgAppNoiseSubPipeline);
300         DECODE_CHK_STATUS(m_postSubPipeline->Register(*m_fgAppNoiseSubPipeline));
301         DECODE_CHK_STATUS(m_fgAppNoiseSubPipeline->Init(*codecSettings));
302 
303         return MOS_STATUS_SUCCESS;
304     }
305 
Uninitialize()306     MOS_STATUS Av1PipelineG12::Uninitialize()
307     {
308         DECODE_FUNC_CALL();
309 
310         for (auto pair : m_packetList)
311         {
312             pair.second->Destroy();
313         }
314 
315 #ifdef _MMC_SUPPORTED
316         if (m_mmcState != nullptr)
317         {
318             MOS_Delete(m_mmcState);
319         }
320 #endif
321 
322         return Av1PipelineG12_Base::Uninitialize();
323     }
324 
UserFeatureReport()325     MOS_STATUS Av1PipelineG12::UserFeatureReport()
326     {
327         DECODE_FUNC_CALL();
328 
329         return Av1PipelineG12_Base::UserFeatureReport();
330     }
331 
CreateSubPackets(DecodeSubPacketManager & subPacketManager,CodechalSetting & codecSettings)332     MOS_STATUS Av1PipelineG12::CreateSubPackets(DecodeSubPacketManager &subPacketManager, CodechalSetting &codecSettings)
333     {
334         DecodePredicationPktG12 *predicationPkt = MOS_New(DecodePredicationPktG12, this, m_hwInterface);
335         DECODE_CHK_NULL(predicationPkt);
336         DECODE_CHK_STATUS(subPacketManager.Register(
337             DecodePacketId(this, predicationSubPacketId), *predicationPkt));
338 
339         DecodeMarkerPktG12 *markerPkt = MOS_New(DecodeMarkerPktG12, this, m_hwInterface);
340         DECODE_CHK_NULL(markerPkt);
341         DECODE_CHK_STATUS(subPacketManager.Register(
342             DecodePacketId(this, markerSubPacketId), *markerPkt));
343 
344         Av1DecodePicPktG12 *pictureDecodePkt = MOS_New(Av1DecodePicPktG12, this, m_hwInterface);
345         DECODE_CHK_NULL(pictureDecodePkt);
346         DECODE_CHK_STATUS(subPacketManager.Register(
347                             DecodePacketId(this, av1PictureSubPacketId), *pictureDecodePkt));
348 
349         Av1DecodeTilePktG12 *tileDecodePkt = MOS_New(Av1DecodeTilePktG12, this, m_hwInterface);
350         DECODE_CHK_NULL(tileDecodePkt);
351         DECODE_CHK_STATUS(subPacketManager.Register(
352                             DecodePacketId(this, av1TileSubPacketId), *tileDecodePkt));
353 
354         return MOS_STATUS_SUCCESS;
355     }
356 
InitMmcState()357     MOS_STATUS Av1PipelineG12::InitMmcState()
358     {
359     #ifdef _MMC_SUPPORTED
360         DECODE_CHK_NULL(m_hwInterface);
361         m_mmcState = MOS_New(DecodeMemCompG12, m_hwInterface);
362         DECODE_CHK_NULL(m_mmcState);
363 
364         Av1BasicFeatureG12 *basicFeature = dynamic_cast<Av1BasicFeatureG12*>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
365         DECODE_CHK_NULL(basicFeature);
366         DECODE_CHK_STATUS(basicFeature->SetMmcState(m_mmcState->IsMmcEnabled()));
367     #endif
368         return MOS_STATUS_SUCCESS;
369     }
370 
371 #if USE_CODECHAL_DEBUG_TOOL
DumpOutput(const DecodeStatusReportData & reportData)372     MOS_STATUS Av1PipelineG12::DumpOutput(const DecodeStatusReportData& reportData)
373     {
374         DECODE_FUNC_CALL();
375 
376         DECODE_CHK_STATUS(DecodePipeline::DumpOutput(reportData));
377 
378         auto feature = dynamic_cast<Av1BasicFeatureG12*>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
379         DECODE_CHK_NULL(feature);
380         auto filmGrainFeature = dynamic_cast<Av1DecodeFilmGrainG12*>(m_featureManager->GetFeature(
381             Av1FeatureIDs::av1SwFilmGrain));
382         if (filmGrainFeature != nullptr && filmGrainFeature->m_filmGrainEnabled)
383         {
384             if (reportData.currFgOutputPicRes != nullptr)
385             {
386                 MOS_SURFACE fgOutputSurface;
387                 MOS_ZeroMemory(&fgOutputSurface, sizeof(fgOutputSurface));
388                 fgOutputSurface.Format     = Format_NV12;
389                 fgOutputSurface.OsResource = *reportData.currFgOutputPicRes;
390                 if (!Mos_ResourceIsNull(&fgOutputSurface.OsResource))
391                 {
392                     DECODE_CHK_STATUS(m_allocator->GetSurfaceInfo(&fgOutputSurface));
393                     DECODE_CHK_STATUS(m_debugInterface->DumpYUVSurface(
394                         &fgOutputSurface, CodechalDbgAttr::attrFilmGrain, "FilmGrain"));
395                 }
396             }
397         }
398 
399         return MOS_STATUS_SUCCESS;
400     }
401 #endif
402 
CreateFeatureManager()403     MOS_STATUS Av1PipelineG12::CreateFeatureManager()
404     {
405         DECODE_FUNC_CALL();
406         m_featureManager = MOS_New(DecodeAv1FeatureManagerG12, m_allocator, m_hwInterface, m_osInterface);
407         DECODE_CHK_NULL(m_featureManager);
408         return MOS_STATUS_SUCCESS;
409     }
410 }
411