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