1 /*
2 * Copyright (c) 2020-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_vp9_pipeline.cpp
24 //! \brief    Defines the interface for vp9 decode pipeline
25 //!
26 #include "decode_vp9_pipeline.h"
27 #include "decode_utils.h"
28 #include "codechal_setting.h"
29 #include "decode_vp9_phase_single.h"
30 #include "decode_vp9_phase_front_end.h"
31 #include "decode_vp9_phase_back_end.h"
32 #include "decode_vp9_feature_manager.h"
33 #include "decode_vp9_buffer_update.h"
34 #include "media_debug_fast_dump.h"
35 
36 namespace decode
37 {
Vp9Pipeline(CodechalHwInterfaceNext * hwInterface,CodechalDebugInterface * debugInterface)38 Vp9Pipeline::Vp9Pipeline(
39     CodechalHwInterfaceNext *hwInterface,
40     CodechalDebugInterface *debugInterface)
41     : DecodePipeline(hwInterface, debugInterface)
42 {
43     MOS_STATUS m_status = InitUserSetting(m_userSettingPtr);
44 }
45 
Initialize(void * settings)46 MOS_STATUS Vp9Pipeline::Initialize(void *settings)
47 {
48     DECODE_FUNC_CALL();
49     DECODE_CHK_STATUS(DecodePipeline::Initialize(settings));
50 
51     // Create basic GPU context
52     DecodeScalabilityPars scalPars;
53     MOS_ZeroMemory(&scalPars, sizeof(scalPars));
54     DECODE_CHK_STATUS(m_mediaContext->SwitchContext(VdboxDecodeFunc, &scalPars, &m_scalability));
55     m_decodeContext = m_osInterface->pfnGetGpuContext(m_osInterface);
56     m_decodeContextHandle = m_osInterface->CurrentGpuContextHandle;
57 
58     m_basicFeature = dynamic_cast<Vp9BasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
59     DECODE_CHK_NULL(m_basicFeature);
60 
61     auto *codecSettings = (CodechalSetting *)settings;
62     DECODE_CHK_NULL(codecSettings);
63 
64     auto *bufferUpdatePipeline = MOS_New(DecodeVp9BufferUpdate, this, m_task, m_numVdbox);
65     DECODE_CHK_NULL(bufferUpdatePipeline);
66     DECODE_CHK_STATUS(m_preSubPipeline->Register(*bufferUpdatePipeline));
67     DECODE_CHK_STATUS(bufferUpdatePipeline->Init(*codecSettings));
68 
69     return MOS_STATUS_SUCCESS;
70 }
71 
Prepare(void * params)72 MOS_STATUS Vp9Pipeline::Prepare(void *params)
73 {
74     DECODE_FUNC_CALL();
75     DECODE_CHK_NULL(params);
76 
77     auto basicFeature = dynamic_cast<Vp9BasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
78     DECODE_CHK_NULL(basicFeature);
79     DECODE_CHK_STATUS(DecodePipeline::Prepare(params));
80 
81     return MOS_STATUS_SUCCESS;
82 }
83 
Uninitialize()84 MOS_STATUS Vp9Pipeline::Uninitialize()
85 {
86     DECODE_FUNC_CALL();
87 
88 #if (_DEBUG || _RELEASE_INTERNAL)
89     // Report real tile frame count and virtual tile frame count
90     ReportUserSettingForDebug(
91         m_userSettingPtr,
92         "VT Decoded Count",
93         m_vtFrameCount,
94         MediaUserSetting::Group::Sequence);
95 #endif
96 
97     DECODE_CHK_STATUS(DestoryPhaseList());
98     return DecodePipeline::Uninitialize();
99 }
100 
UserFeatureReport()101 MOS_STATUS Vp9Pipeline::UserFeatureReport()
102 {
103     DECODE_FUNC_CALL();
104     DECODE_CHK_STATUS(DecodePipeline::UserFeatureReport());
105 #if (_DEBUG || _RELEASE_INTERNAL)
106     WriteUserFeature(__MEDIA_USER_FEATURE_VALUE_APOGEIOS_VP9D_ENABLE_ID, 1, m_osInterface->pOsContext);
107 #endif
108 
109 #ifdef _MMC_SUPPORTED
110     CODECHAL_DEBUG_TOOL(
111         if (m_mmcState != nullptr) {
112             m_mmcState->UpdateUserFeatureKey(&(m_basicFeature->m_destSurface));
113         })
114 #endif
115     return MOS_STATUS_SUCCESS;
116 }
117 
Execute()118 MOS_STATUS Vp9Pipeline::Execute()
119 {
120     DECODE_FUNC_CALL();
121 
122 #if (_DEBUG || _RELEASE_INTERNAL)
123     if (GetDecodeMode() == virtualTileDecodeMode)
124     {
125         m_vtFrameCount++;
126     }
127 #endif
128 
129     for (auto &phase : m_phaseList)
130     {
131         DECODE_ASSERT(phase != nullptr);
132         if (phase->RequiresContextSwitch())
133         {
134             // switch context
135             DecodeScalabilityOption *scalabOption = phase->GetDecodeScalabilityOption();
136             DECODE_CHK_NULL(scalabOption);
137             DECODE_CHK_STATUS(m_mediaContext->SwitchContext(VdboxDecodeFunc, *scalabOption, &m_scalability));
138             if (scalabOption->IsScalabilityOptionMatched(m_scalabOption))
139             {
140                 m_decodeContext = m_osInterface->pfnGetGpuContext(m_osInterface);
141                 m_decodeContextHandle = m_osInterface->CurrentGpuContextHandle;
142             }
143         }
144 
145         StateParams stateProperty;
146         stateProperty.currentPipe        = phase->GetPipe();
147         stateProperty.currentPass        = phase->GetPass();
148         stateProperty.pipeIndexForSubmit = phase->GetPipe() + 1;
149         stateProperty.componentState     = phase;
150         DECODE_CHK_STATUS(ActivatePacket(phase->GetPktId(), phase->ImmediateSubmit(), stateProperty));
151 
152         if (phase->ImmediateSubmit())
153         {
154             m_scalability->SetPassNumber(phase->GetPass() + 1);
155             DECODE_CHK_STATUS(ExecuteActivePackets());
156         }
157     }
158 
159     return MOS_STATUS_SUCCESS;
160 }
161 
CreateFeatureManager()162 MOS_STATUS Vp9Pipeline::CreateFeatureManager()
163 {
164     DECODE_FUNC_CALL();
165     m_featureManager = MOS_New(DecodeVp9FeatureManager, m_allocator, m_hwInterface, m_osInterface);
166     DECODE_CHK_NULL(m_featureManager);
167     return MOS_STATUS_SUCCESS;
168 }
169 
CreateSubPackets(DecodeSubPacketManager & subPacketManager,CodechalSetting & codecSettings)170 MOS_STATUS Vp9Pipeline::CreateSubPackets(DecodeSubPacketManager &subPacketManager, CodechalSetting &codecSettings)
171 {
172     DECODE_FUNC_CALL();
173 
174     DECODE_CHK_STATUS(DecodePipeline::CreateSubPackets(subPacketManager, codecSettings));
175 
176     return MOS_STATUS_SUCCESS;
177 }
178 
GetDecodeMode()179 Vp9Pipeline::Vp9DecodeMode Vp9Pipeline::GetDecodeMode()
180 {
181     return m_decodeMode;
182 }
183 
InitContexOption(Vp9BasicFeature & basicFeature)184 MOS_STATUS Vp9Pipeline::InitContexOption(Vp9BasicFeature &basicFeature)
185 {
186     DecodeScalabilityPars scalPars;
187     MOS_ZeroMemory(&scalPars, sizeof(scalPars));
188 
189     scalPars.usingHcp           = true;
190     scalPars.enableVE           = MOS_VE_SUPPORTED(m_osInterface);
191     scalPars.disableScalability = m_hwInterface->IsDisableScalability();
192     scalPars.surfaceFormat      = basicFeature.m_destSurface.Format;
193     scalPars.frameWidth         = basicFeature.m_frameWidthAlignedMinBlk;
194     scalPars.frameHeight        = basicFeature.m_frameHeightAlignedMinBlk;
195     scalPars.numVdbox           = m_numVdbox;
196     if (m_osInterface->pfnIsMultipleCodecDevicesInUse(m_osInterface))
197     {
198         scalPars.disableScalability = true;
199     }
200 #if (_DEBUG || _RELEASE_INTERNAL)
201     if (m_osInterface->bHcpDecScalabilityMode == MOS_SCALABILITY_ENABLE_MODE_FALSE)
202     {
203         scalPars.disableScalability = true;
204     }
205     else if (m_osInterface->bHcpDecScalabilityMode == MOS_SCALABILITY_ENABLE_MODE_USER_FORCE)
206     {
207         scalPars.disableScalability = false;
208     }
209     scalPars.modeSwithThreshold1 =
210         ReadUserFeature(m_userSettingPtr, "HCP Decode Mode Switch TH1", MediaUserSetting::Group::Sequence).Get<uint32_t>();
211     scalPars.modeSwithThreshold2 =
212         ReadUserFeature(m_userSettingPtr, "HCP Decode Mode Switch TH2", MediaUserSetting::Group::Sequence).Get<uint32_t>();
213     scalPars.forceMultiPipe =
214         ReadUserFeature(m_userSettingPtr, "HCP Decode Always Frame Split", MediaUserSetting::Group::Sequence).Get<bool>();
215     scalPars.userPipeNum =
216         ReadUserFeature(m_userSettingPtr, "HCP Decode User Pipe Num", MediaUserSetting::Group::Sequence).Get<uint8_t>();
217 #endif
218 
219 #ifdef _DECODE_PROCESSING_SUPPORTED
220     DecodeDownSamplingFeature *downSamplingFeature = dynamic_cast<DecodeDownSamplingFeature *>(
221         m_featureManager->GetFeature(DecodeFeatureIDs::decodeDownSampling));
222     if (downSamplingFeature != nullptr && downSamplingFeature->IsEnabled())
223     {
224         scalPars.usingSfc = true;
225         if (!MEDIA_IS_SKU(m_skuTable, FtrSfcScalability))
226         {
227             scalPars.disableScalability = true;
228         }
229     }
230     //Disable Scalability when histogram is enabled
231     if (downSamplingFeature != nullptr && (downSamplingFeature->m_histogramDestSurf || downSamplingFeature->m_histogramDebug))
232     {
233         scalPars.disableScalability = true;
234     }
235 #endif
236 
237     if (MEDIA_IS_SKU(m_skuTable, FtrVirtualTileScalabilityDisable))
238     {
239         scalPars.disableScalability = true;
240         scalPars.disableVirtualTile = true;
241     }
242 
243     DECODE_CHK_STATUS(m_scalabOption.SetScalabilityOption(&scalPars));
244     return MOS_STATUS_SUCCESS;
245 }
246 
InitDecodeMode(ScalabilityMode scalabMode)247 MOS_STATUS Vp9Pipeline::InitDecodeMode(ScalabilityMode scalabMode)
248 {
249     if (scalabMode == scalabilityVirtualTileMode)
250     {
251         m_decodeMode = virtualTileDecodeMode;
252     }
253     else if (scalabMode == scalabilitySingleMode)
254     {
255         m_decodeMode = baseDecodeMode;
256     }
257     else
258     {
259         return MOS_STATUS_INVALID_PARAMETER;
260     }
261 
262     return MOS_STATUS_SUCCESS;
263 }
264 
265 template <typename T>
CreatePhase(uint8_t pass,uint8_t pipe,uint8_t activePipeNum)266 MOS_STATUS Vp9Pipeline::CreatePhase(uint8_t pass, uint8_t pipe, uint8_t activePipeNum)
267 {
268     DECODE_FUNC_CALL();
269     T *phase = MOS_New(T, *this, m_scalabOption);
270     DECODE_CHK_NULL(phase);
271     MOS_STATUS status = phase->Initialize(pass, pipe, activePipeNum);
272     if (status != MOS_STATUS_SUCCESS)
273     {
274         MOS_Delete(phase);
275         return status;
276     }
277     m_phaseList.push_back(phase);
278     return MOS_STATUS_SUCCESS;
279 }
280 
CreatePhaseList(const ScalabilityMode scalabMode,const uint8_t numPipe)281 MOS_STATUS Vp9Pipeline::CreatePhaseList(const ScalabilityMode scalabMode, const uint8_t numPipe)
282 {
283     DECODE_FUNC_CALL();
284     DECODE_ASSERT(m_phaseList.empty());
285 
286     if (scalabMode == scalabilityVirtualTileMode)
287     {
288         DECODE_CHK_STATUS(CreatePhase<Vp9PhaseFrontEnd>());
289         for (uint8_t i = 0; i < numPipe; i++)
290         {
291             DECODE_CHK_STATUS(CreatePhase<Vp9PhaseBackEnd>(0, i, numPipe));
292         }
293     }
294     else
295     {
296         DECODE_CHK_STATUS(CreatePhase<Vp9PhaseSingle>());
297     }
298 
299     return MOS_STATUS_SUCCESS;
300 }
301 
DestoryPhaseList()302 MOS_STATUS Vp9Pipeline::DestoryPhaseList()
303 {
304     for (auto &phase : m_phaseList)
305     {
306         MOS_Delete(phase);
307     }
308     m_phaseList.clear();
309     return MOS_STATUS_SUCCESS;
310 }
311 
312 #if USE_CODECHAL_DEBUG_TOOL
DumpPicParams(CODEC_VP9_PIC_PARAMS * picParams)313 MOS_STATUS Vp9Pipeline::DumpPicParams(CODEC_VP9_PIC_PARAMS *picParams)
314 {
315     CODECHAL_DEBUG_FUNCTION_ENTER;
316 
317     if (picParams == nullptr)
318     {
319         return MOS_STATUS_SUCCESS;
320     }
321 
322     if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrPicParams))
323     {
324         const char *fileName = m_debugInterface->CreateFileName(
325             "_DEC",
326             CodechalDbgBufferType::bufPicParams,
327             CodechalDbgExtType::txt);
328 
329         if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrEnableFastDump))
330         {
331             MediaDebugFastDump::Dump(
332                 (uint8_t *)picParams,
333                 fileName,
334                 sizeof(CODEC_VP9_PIC_PARAMS),
335                 0,
336                 MediaDebugSerializer<CODEC_VP9_PIC_PARAMS>());
337         }
338         else
339         {
340             DumpDecodeVp9PicParams(picParams, fileName);
341         }
342     }
343 
344     return MOS_STATUS_SUCCESS;
345 }
346 
DumpSliceParams(CODEC_VP9_SLICE_PARAMS * slcParams)347 MOS_STATUS Vp9Pipeline::DumpSliceParams(CODEC_VP9_SLICE_PARAMS *slcParams)
348 {
349     CODECHAL_DEBUG_FUNCTION_ENTER;
350 
351     if (slcParams == nullptr)
352     {
353         return MOS_STATUS_SUCCESS;
354     }
355 
356     if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSlcParams))
357     {
358         const char *fileName = m_debugInterface->CreateFileName(
359             "_DEC",
360             CodechalDbgBufferType::bufSlcParams,
361             CodechalDbgExtType::txt);
362 
363         if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrEnableFastDump))
364         {
365             MediaDebugFastDump::Dump(
366                 (uint8_t *)slcParams,
367                 fileName,
368                 sizeof(CODEC_VP9_SLICE_PARAMS),
369                 0,
370                 MediaDebugSerializer<CODEC_VP9_SLICE_PARAMS>());
371         }
372         else
373         {
374             DumpDecodeVp9SliceParams(slcParams, fileName);
375         }
376     }
377 
378     return MOS_STATUS_SUCCESS;
379 }
380 
DumpSegmentParams(CODEC_VP9_SEGMENT_PARAMS * segmentParams)381 MOS_STATUS Vp9Pipeline::DumpSegmentParams(CODEC_VP9_SEGMENT_PARAMS *segmentParams)
382 {
383     CODECHAL_DEBUG_FUNCTION_ENTER;
384 
385     if (segmentParams == nullptr)
386     {
387         return MOS_STATUS_SUCCESS;
388     }
389 
390     if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSegmentParams))
391     {
392         const char *fileName = m_debugInterface->CreateFileName(
393             "_DEC",
394             CodechalDbgBufferType::bufSegmentParams,
395             CodechalDbgExtType::txt);
396 
397         if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrEnableFastDump))
398         {
399             MediaDebugFastDump::Dump(
400                 (uint8_t *)segmentParams,
401                 fileName,
402                 sizeof(CODEC_VP9_SEGMENT_PARAMS),
403                 0,
404                 MediaDebugSerializer<CODEC_VP9_SEGMENT_PARAMS>());
405         }
406         else
407         {
408             DumpDecodeVp9SegmentParams(segmentParams, fileName);
409         }
410     }
411 
412     return MOS_STATUS_SUCCESS;
413 }
414 #endif
415 
416 }  // namespace decode
417