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 "media_user_settings_mgr_g12_plus.h"
29 #include "codechal_setting.h"
30 #include "decode_vp9_phase_single.h"
31 #include "decode_vp9_phase_front_end.h"
32 #include "decode_vp9_phase_back_end.h"
33 #include "decode_vp9_feature_manager.h"
34 #include "decode_vp9_buffer_update.h"
35 
36 namespace decode
37 {
Vp9Pipeline(CodechalHwInterface * hwInterface,CodechalDebugInterface * debugInterface)38 Vp9Pipeline::Vp9Pipeline(
39     CodechalHwInterface *   hwInterface,
40     CodechalDebugInterface *debugInterface)
41     : DecodePipeline(hwInterface, debugInterface)
42 {
43 }
44 
Initialize(void * settings)45 MOS_STATUS Vp9Pipeline::Initialize(void *settings)
46 {
47     DECODE_FUNC_CALL();
48     DECODE_CHK_STATUS(DecodePipeline::Initialize(settings));
49 
50     // Create basic GPU context
51     DecodeScalabilityPars scalPars;
52     MOS_ZeroMemory(&scalPars, sizeof(scalPars));
53     DECODE_CHK_STATUS(m_mediaContext->SwitchContext(VdboxDecodeFunc, &scalPars, &m_scalability));
54     m_decodeContext = m_osInterface->pfnGetGpuContext(m_osInterface);
55 
56     m_basicFeature = dynamic_cast<Vp9BasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
57     DECODE_CHK_NULL(m_basicFeature);
58 
59     auto *codecSettings = (CodechalSetting *)settings;
60     DECODE_CHK_NULL(codecSettings);
61 
62     auto *bufferUpdatePipeline = MOS_New(DecodeVp9BufferUpdate, this, m_task, m_numVdbox);
63     DECODE_CHK_NULL(bufferUpdatePipeline);
64     DECODE_CHK_STATUS(m_preSubPipeline->Register(*bufferUpdatePipeline));
65     DECODE_CHK_STATUS(bufferUpdatePipeline->Init(*codecSettings));
66 
67     return MOS_STATUS_SUCCESS;
68 }
69 
Prepare(void * params)70 MOS_STATUS Vp9Pipeline::Prepare(void *params)
71 {
72     DECODE_FUNC_CALL();
73     DECODE_CHK_NULL(params);
74 
75     auto basicFeature = dynamic_cast<Vp9BasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
76     DECODE_CHK_NULL(basicFeature);
77     DECODE_CHK_STATUS(DecodePipeline::Prepare(params));
78 
79     return MOS_STATUS_SUCCESS;
80 }
81 
Uninitialize()82 MOS_STATUS Vp9Pipeline::Uninitialize()
83 {
84     DECODE_FUNC_CALL();
85 
86 #if (_DEBUG || _RELEASE_INTERNAL)
87     // Report real tile frame count and virtual tile frame count
88     MOS_USER_FEATURE_VALUE_WRITE_DATA userFeatureWriteData = __NULL_USER_FEATURE_VALUE_WRITE_DATA__;
89     userFeatureWriteData.Value.i32Data                     = m_vtFrameCount;
90     userFeatureWriteData.ValueID                           = __MEDIA_USER_FEATURE_VALUE_ENABLE_HEVC_DECODE_VT_FRAME_COUNT_ID;
91     MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);
92 #endif
93 
94     DECODE_CHK_STATUS(DestoryPhaseList());
95     return DecodePipeline::Uninitialize();
96 }
97 
UserFeatureReport()98 MOS_STATUS Vp9Pipeline::UserFeatureReport()
99 {
100     DECODE_FUNC_CALL();
101     DECODE_CHK_STATUS(DecodePipeline::UserFeatureReport());
102 #if (_DEBUG || _RELEASE_INTERNAL)
103     WriteUserFeature(__MEDIA_USER_FEATURE_VALUE_APOGEIOS_VP9D_ENABLE_ID, 1, m_osInterface->pOsContext);
104 #endif
105 
106 #ifdef _MMC_SUPPORTED
107     CODECHAL_DEBUG_TOOL(
108         if (m_mmcState != nullptr) {
109             m_mmcState->UpdateUserFeatureKey(&(m_basicFeature->m_destSurface));
110         })
111 #endif
112     return MOS_STATUS_SUCCESS;
113 }
114 
Execute()115 MOS_STATUS Vp9Pipeline::Execute()
116 {
117     DECODE_FUNC_CALL();
118 
119 #if (_DEBUG || _RELEASE_INTERNAL)
120     if (GetDecodeMode() == virtualTileDecodeMode)
121     {
122         m_vtFrameCount++;
123     }
124 #endif
125 
126     for (auto &phase : m_phaseList)
127     {
128         DECODE_ASSERT(phase != nullptr);
129         if (phase->RequiresContextSwitch())
130         {
131             // switch context
132             DecodeScalabilityOption *scalabOption = phase->GetDecodeScalabilityOption();
133             DECODE_CHK_NULL(scalabOption);
134             DECODE_CHK_STATUS(m_mediaContext->SwitchContext(VdboxDecodeFunc, *scalabOption, &m_scalability));
135             if (scalabOption->IsScalabilityOptionMatched(m_scalabOption))
136             {
137                 m_decodeContext = m_osInterface->pfnGetGpuContext(m_osInterface);
138             }
139         }
140 
141         StateParams stateProperty;
142         stateProperty.currentPipe        = phase->GetPipe();
143         stateProperty.currentPass        = phase->GetPass();
144         stateProperty.pipeIndexForSubmit = phase->GetPipe() + 1;
145         stateProperty.componentState     = phase;
146         DECODE_CHK_STATUS(ActivatePacket(phase->GetPktId(), phase->ImmediateSubmit(), stateProperty));
147 
148         if (phase->ImmediateSubmit())
149         {
150             m_scalability->SetPassNumber(phase->GetPass() + 1);
151             DECODE_CHK_STATUS(ExecuteActivePackets());
152         }
153     }
154 
155     return MOS_STATUS_SUCCESS;
156 }
157 
CreateFeatureManager()158 MOS_STATUS Vp9Pipeline::CreateFeatureManager()
159 {
160     DECODE_FUNC_CALL();
161     m_featureManager = MOS_New(DecodeVp9FeatureManager, m_allocator, m_hwInterface);
162     DECODE_CHK_NULL(m_featureManager);
163     return MOS_STATUS_SUCCESS;
164 }
165 
CreateSubPackets(DecodeSubPacketManager & subPacketManager,CodechalSetting & codecSettings)166 MOS_STATUS Vp9Pipeline::CreateSubPackets(DecodeSubPacketManager &subPacketManager, CodechalSetting &codecSettings)
167 {
168     DECODE_FUNC_CALL();
169 
170     DECODE_CHK_STATUS(DecodePipeline::CreateSubPackets(subPacketManager, codecSettings));
171 
172     return MOS_STATUS_SUCCESS;
173 }
174 
GetDecodeMode()175 Vp9Pipeline::Vp9DecodeMode Vp9Pipeline::GetDecodeMode()
176 {
177     return m_decodeMode;
178 }
179 
InitContexOption(Vp9BasicFeature & basicFeature)180 MOS_STATUS Vp9Pipeline::InitContexOption(Vp9BasicFeature &basicFeature)
181 {
182     DecodeScalabilityPars scalPars;
183     MOS_ZeroMemory(&scalPars, sizeof(scalPars));
184 
185     scalPars.usingHcp           = true;
186     scalPars.enableVE           = MOS_VE_SUPPORTED(m_osInterface);
187     scalPars.disableScalability = m_hwInterface->IsDisableScalability();
188     scalPars.surfaceFormat      = basicFeature.m_destSurface.Format;
189     scalPars.frameWidth         = basicFeature.m_frameWidthAlignedMinBlk;
190     scalPars.frameHeight        = basicFeature.m_frameHeightAlignedMinBlk;
191     scalPars.numVdbox           = m_numVdbox;
192 
193 #if (_DEBUG || _RELEASE_INTERNAL)
194     if (m_osInterface->bHcpDecScalabilityMode == MOS_SCALABILITY_ENABLE_MODE_FALSE)
195     {
196         scalPars.disableScalability = true;
197     }
198     else if (m_osInterface->bHcpDecScalabilityMode == MOS_SCALABILITY_ENABLE_MODE_USER_FORCE)
199     {
200         scalPars.disableScalability = false;
201     }
202     scalPars.modeSwithThreshold1 =
203         ReadUserFeature(__MEDIA_USER_FEATURE_VALUE_HCP_DECODE_MODE_SWITCH_THRESHOLD1_ID, m_osInterface->pOsContext).u32Data;
204     scalPars.modeSwithThreshold2 =
205         ReadUserFeature(__MEDIA_USER_FEATURE_VALUE_HCP_DECODE_MODE_SWITCH_THRESHOLD2_ID, m_osInterface->pOsContext).u32Data;
206     scalPars.forceMultiPipe =
207         ReadUserFeature(__MEDIA_USER_FEATURE_VALUE_HCP_DECODE_ALWAYS_FRAME_SPLIT_ID, m_osInterface->pOsContext).u32Data ? true : false;
208     scalPars.userPipeNum =
209         uint8_t(ReadUserFeature(__MEDIA_USER_FEATURE_VALUE_HCP_DECODE_USER_PIPE_NUM_ID, m_osInterface->pOsContext).u32Data);
210 #endif
211 
212 #ifdef _DECODE_PROCESSING_SUPPORTED
213     DecodeDownSamplingFeature *downSamplingFeature = dynamic_cast<DecodeDownSamplingFeature *>(
214         m_featureManager->GetFeature(DecodeFeatureIDs::decodeDownSampling));
215     if (downSamplingFeature != nullptr && downSamplingFeature->IsEnabled())
216     {
217         scalPars.usingSfc = true;
218         if (!MEDIA_IS_SKU(m_skuTable, FtrSfcScalability))
219         {
220             scalPars.disableScalability = true;
221         }
222     }
223     //Disable Scalability when histogram is enabled
224     if (downSamplingFeature != nullptr && (downSamplingFeature->m_histogramDestSurf || downSamplingFeature->m_histogramDebug))
225     {
226         scalPars.disableScalability = true;
227     }
228 #endif
229 
230     DECODE_CHK_STATUS(m_scalabOption.SetScalabilityOption(&scalPars));
231     return MOS_STATUS_SUCCESS;
232 }
233 
InitDecodeMode(ScalabilityMode scalabMode)234 MOS_STATUS Vp9Pipeline::InitDecodeMode(ScalabilityMode scalabMode)
235 {
236     if (scalabMode == scalabilityVirtualTileMode)
237     {
238         m_decodeMode = virtualTileDecodeMode;
239     }
240     else if (scalabMode == scalabilitySingleMode)
241     {
242         m_decodeMode = baseDecodeMode;
243     }
244     else
245     {
246         return MOS_STATUS_INVALID_PARAMETER;
247     }
248 
249     return MOS_STATUS_SUCCESS;
250 }
251 
252 template <typename T>
CreatePhase(uint8_t pass,uint8_t pipe,uint8_t activePipeNum)253 MOS_STATUS Vp9Pipeline::CreatePhase(uint8_t pass, uint8_t pipe, uint8_t activePipeNum)
254 {
255     DECODE_FUNC_CALL();
256     T *phase = MOS_New(T, *this, m_scalabOption);
257     DECODE_CHK_NULL(phase);
258     DECODE_CHK_STATUS(phase->Initialize(pass, pipe, activePipeNum));
259     m_phaseList.push_back(phase);
260     return MOS_STATUS_SUCCESS;
261 }
262 
CreatePhaseList(const ScalabilityMode scalabMode,const uint8_t numPipe)263 MOS_STATUS Vp9Pipeline::CreatePhaseList(const ScalabilityMode scalabMode, const uint8_t numPipe)
264 {
265     DECODE_FUNC_CALL();
266     DECODE_ASSERT(m_phaseList.empty());
267 
268     if (scalabMode == scalabilityVirtualTileMode)
269     {
270         DECODE_CHK_STATUS(CreatePhase<Vp9PhaseFrontEnd>());
271         for (uint8_t i = 0; i < numPipe; i++)
272         {
273             DECODE_CHK_STATUS(CreatePhase<Vp9PhaseBackEnd>(0, i, numPipe));
274         }
275     }
276     else
277     {
278         DECODE_CHK_STATUS(CreatePhase<Vp9PhaseSingle>());
279     }
280 
281     return MOS_STATUS_SUCCESS;
282 }
283 
DestoryPhaseList()284 MOS_STATUS Vp9Pipeline::DestoryPhaseList()
285 {
286     for (auto &phase : m_phaseList)
287     {
288         MOS_Delete(phase);
289     }
290     m_phaseList.clear();
291     return MOS_STATUS_SUCCESS;
292 }
293 
294 #if USE_CODECHAL_DEBUG_TOOL
DumpPicParams(CODEC_VP9_PIC_PARAMS * picParams)295 MOS_STATUS Vp9Pipeline::DumpPicParams(CODEC_VP9_PIC_PARAMS *picParams)
296 {
297     CODECHAL_DEBUG_FUNCTION_ENTER;
298 
299     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrPicParams))
300     {
301         return MOS_STATUS_SUCCESS;
302     }
303     CODECHAL_DEBUG_CHK_NULL(picParams);
304 
305     std::ostringstream oss;
306     oss.setf(std::ios::showbase | std::ios::uppercase);
307 
308     oss << "CurrPic FrameIdx: " << std::hex << +picParams->CurrPic.FrameIdx << std::endl;
309     oss << "CurrPic PicFlags: " << std::hex << +picParams->CurrPic.PicFlags << std::endl;
310 
311     for (uint8_t i = 0; i < 8; ++i)
312     {
313         oss << "RefFrameList[" << +i << "] FrameIdx:" << std::hex << +picParams->RefFrameList[i].FrameIdx << std::endl;
314         oss << "RefFrameList[" << +i << "] PicFlags:" << std::hex << +picParams->RefFrameList[i].PicFlags << std::endl;
315     }
316     oss << "FrameWidthMinus1: " << std::hex << +picParams->FrameWidthMinus1 << std::endl;
317     oss << "FrameHeightMinus1: " << std::hex << +picParams->FrameHeightMinus1 << std::endl;
318     oss << "PicFlags value: " << std::hex << +picParams->PicFlags.value << std::endl;
319     oss << "frame_type: " << std::hex << +picParams->PicFlags.fields.frame_type << std::endl;
320     oss << "show_frame: " << std::hex << +picParams->PicFlags.fields.show_frame << std::endl;
321     oss << "error_resilient_mode: " << std::hex << +picParams->PicFlags.fields.error_resilient_mode << std::endl;
322     oss << "intra_only: " << std::hex << +picParams->PicFlags.fields.intra_only << std::endl;
323     oss << "LastRefIdx: " << std::hex << +picParams->PicFlags.fields.LastRefIdx << std::endl;
324     oss << "LastRefSignBias: " << std::hex << +picParams->PicFlags.fields.LastRefSignBias << std::endl;
325     oss << "GoldenRefIdx: " << std::hex << +picParams->PicFlags.fields.GoldenRefIdx << std::endl;
326     oss << "GoldenRefSignBias: " << std::hex << +picParams->PicFlags.fields.GoldenRefSignBias << std::endl;
327     oss << "AltRefIdx: " << std::hex << +picParams->PicFlags.fields.AltRefIdx << std::endl;
328     oss << "AltRefSignBias: " << std::hex << +picParams->PicFlags.fields.AltRefSignBias << std::endl;
329     oss << "allow_high_precision_mv: " << std::hex << +picParams->PicFlags.fields.allow_high_precision_mv << std::endl;
330     oss << "mcomp_filter_type: " << std::hex << +picParams->PicFlags.fields.mcomp_filter_type << std::endl;
331     oss << "frame_parallel_decoding_mode: " << std::hex << +picParams->PicFlags.fields.frame_parallel_decoding_mode << std::endl;
332     oss << "segmentation_enabled: " << std::hex << +picParams->PicFlags.fields.segmentation_enabled << std::endl;
333     oss << "segmentation_temporal_update: " << std::hex << +picParams->PicFlags.fields.segmentation_temporal_update << std::endl;
334     oss << "segmentation_update_map: " << std::hex << +picParams->PicFlags.fields.segmentation_update_map << std::endl;
335     oss << "reset_frame_context: " << std::hex << +picParams->PicFlags.fields.reset_frame_context << std::endl;
336     oss << "refresh_frame_context: " << std::hex << +picParams->PicFlags.fields.refresh_frame_context << std::endl;
337     oss << "frame_context_idx: " << std::hex << +picParams->PicFlags.fields.frame_context_idx << std::endl;
338     oss << "LosslessFlag: " << std::hex << +picParams->PicFlags.fields.LosslessFlag << std::endl;
339     oss << "ReservedField: " << std::hex << +picParams->PicFlags.fields.ReservedField << std::endl;
340     oss << "filter_level: " << std::hex << +picParams->filter_level << std::endl;
341     oss << "sharpness_level: " << std::hex << +picParams->sharpness_level << std::endl;
342     oss << "log2_tile_rows: " << std::hex << +picParams->log2_tile_rows << std::endl;
343     oss << "log2_tile_columns: " << std::hex << +picParams->log2_tile_columns << std::endl;
344     oss << "UncompressedHeaderLengthInBytes: " << std::hex << +picParams->UncompressedHeaderLengthInBytes << std::endl;
345     oss << "FirstPartitionSize: " << std::hex << +picParams->FirstPartitionSize << std::endl;
346     oss << "profile: " << std::hex << +picParams->profile << std::endl;
347     oss << "BitDepthMinus8: " << std::hex << +picParams->BitDepthMinus8 << std::endl;
348     oss << "subsampling_x: " << std::hex << +picParams->subsampling_x << std::endl;
349     oss << "subsampling_y: " << std::hex << +picParams->subsampling_y << std::endl;
350 
351     for (uint8_t i = 0; i < 7; ++i)
352     {
353         oss << "SegTreeProbs[" << +i << "]: " << std::hex << +picParams->SegTreeProbs[i] << std::endl;
354     }
355     for (uint8_t i = 0; i < 3; ++i)
356     {
357         oss << "SegPredProbs[" << +i << "]: " << std::hex << +picParams->SegPredProbs[i] << std::endl;
358     }
359     oss << "BSBytesInBuffer: " << std::hex << +picParams->BSBytesInBuffer << std::endl;
360     oss << "StatusReportFeedbackNumber: " << std::hex << +picParams->StatusReportFeedbackNumber << std::endl;
361 
362     const char *fileName = m_debugInterface->CreateFileName(
363         "_DEC",
364         CodechalDbgBufferType::bufPicParams,
365         CodechalDbgExtType::txt);
366 
367     std::ofstream ofs(fileName, std::ios::out);
368     ofs << oss.str();
369     ofs.close();
370 
371     return MOS_STATUS_SUCCESS;
372 }
373 
DumpSegmentParams(CODEC_VP9_SEGMENT_PARAMS * segmentParams)374 MOS_STATUS Vp9Pipeline::DumpSegmentParams(CODEC_VP9_SEGMENT_PARAMS *segmentParams)
375 {
376     CODECHAL_DEBUG_FUNCTION_ENTER;
377 
378     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSegmentParams))
379     {
380         return MOS_STATUS_SUCCESS;
381     }
382 
383     CODECHAL_DEBUG_CHK_NULL(segmentParams);
384 
385     std::ostringstream oss;
386     oss.setf(std::ios::showbase | std::ios::uppercase);
387 
388     for (uint8_t i = 0; i < 8; ++i)
389     {
390         oss << "SegData[" << +i << "] SegmentFlags value: " << std::hex << +segmentParams->SegData[i].SegmentFlags.value << std::endl;
391         oss << "SegData[" << +i << "] SegmentReferenceEnabled: " << std::hex << +segmentParams->SegData[i].SegmentFlags.fields.SegmentReferenceEnabled << std::endl;
392         oss << "SegData[" << +i << "] SegmentReference: " << std::hex << +segmentParams->SegData[i].SegmentFlags.fields.SegmentReference << std::endl;
393         oss << "SegData[" << +i << "] SegmentReferenceSkipped: " << std::hex << +segmentParams->SegData[i].SegmentFlags.fields.SegmentReferenceSkipped << std::endl;
394         oss << "SegData[" << +i << "] ReservedField3: " << std::hex << +segmentParams->SegData[i].SegmentFlags.fields.ReservedField3 << std::endl;
395 
396         for (uint8_t j = 0; j < 4; ++j)
397         {
398             oss << "SegData[" << +i << "] FilterLevel[" << +j << "]:";
399             oss << std::hex << +segmentParams->SegData[i].FilterLevel[j][0] << " ";
400             oss << std::hex << +segmentParams->SegData[i].FilterLevel[j][1] << std::endl;
401         }
402         oss << "SegData[" << +i << "] LumaACQuantScale: " << std::hex << +segmentParams->SegData[i].LumaACQuantScale << std::endl;
403         oss << "SegData[" << +i << "] LumaDCQuantScale: " << std::hex << +segmentParams->SegData[i].LumaDCQuantScale << std::endl;
404         oss << "SegData[" << +i << "] ChromaACQuantScale: " << std::hex << +segmentParams->SegData[i].ChromaACQuantScale << std::endl;
405         oss << "SegData[" << +i << "] ChromaDCQuantScale: " << std::hex << +segmentParams->SegData[i].ChromaDCQuantScale << std::endl;
406     }
407 
408     const char *fileName = m_debugInterface->CreateFileName(
409         "_DEC",
410         CodechalDbgBufferType::bufSegmentParams,
411         CodechalDbgExtType::txt);
412 
413     std::ofstream ofs(fileName, std::ios::out);
414     ofs << oss.str();
415     ofs.close();
416     return MOS_STATUS_SUCCESS;
417 }
418 #endif
419 
420 }  // namespace decode
421