1 /*
2 * Copyright (c) 2018-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 //!
24 //! \file     decode_pipeline.cpp
25 //! \brief    Defines the common interface for decode pipeline
26 //! \details  The decode pipeline interface is further sub-divided by codec standard,
27 //!           this file is for the base interface which is shared by all codecs.
28 //!
29 #include "decode_pipeline.h"
30 #include "decode_utils.h"
31 #include "decode_status_report.h"
32 #include "media_packet.h"
33 #include "decode_predication_packet.h"
34 #include "decode_marker_packet.h"
35 #include "decode_downsampling_packet.h"
36 #include "codechal_setting.h"
37 #include "decode_basic_feature.h"
38 #include "mos_solo_generic.h"
39 #include "decode_sfc_histogram_postsubpipeline.h"
40 #include "decode_common_feature_defs.h"
41 #include "decode_resource_auto_lock.h"
42 
43 namespace decode {
44 
DecodePipeline(CodechalHwInterface * hwInterface,CodechalDebugInterface * debugInterface)45 DecodePipeline::DecodePipeline(
46     CodechalHwInterface *hwInterface,
47     CodechalDebugInterface *debugInterface):
48     MediaPipeline(hwInterface ? hwInterface->GetOsInterface() : nullptr)
49 {
50     DECODE_FUNC_CALL();
51 
52     DECODE_ASSERT(hwInterface != nullptr);
53     m_hwInterface = hwInterface;
54 
55     m_singleTaskPhaseSupported =
56         ReadUserFeature(__MEDIA_USER_FEATURE_VALUE_SINGLE_TASK_PHASE_ENABLE_ID, m_osInterface ? m_osInterface->pOsContext : nullptr).i32Data ? true : false;
57 
58     CODECHAL_DEBUG_TOOL(
59         DECODE_ASSERT(debugInterface != nullptr);
60         m_debugInterface = debugInterface;
61     );
62 }
63 
CreateStatusReport()64 MOS_STATUS DecodePipeline::CreateStatusReport()
65 {
66     m_statusReport = MOS_New(DecodeStatusReport, m_allocator, true);
67     DECODE_CHK_NULL(m_statusReport);
68     DECODE_CHK_STATUS(m_statusReport->Create());
69 
70     return MOS_STATUS_SUCCESS;
71 }
72 
CreatePreSubPipeLines(DecodeSubPipelineManager & subPipelineManager)73 MOS_STATUS DecodePipeline::CreatePreSubPipeLines(DecodeSubPipelineManager &subPipelineManager)
74 {
75     m_bitstream = MOS_New(DecodeInputBitstream, this, m_task, m_numVdbox);
76     DECODE_CHK_NULL(m_bitstream);
77     DECODE_CHK_STATUS(subPipelineManager.Register(*m_bitstream));
78 
79     m_streamout = MOS_New(DecodeStreamOut, this, m_task, m_numVdbox);
80     DECODE_CHK_NULL(m_streamout);
81     DECODE_CHK_STATUS(subPipelineManager.Register(*m_streamout));
82     return MOS_STATUS_SUCCESS;
83 }
84 
CreatePostSubPipeLines(DecodeSubPipelineManager & subPipelineManager)85 MOS_STATUS DecodePipeline::CreatePostSubPipeLines(DecodeSubPipelineManager &subPipelineManager)
86 {
87     DECODE_FUNC_CALL();
88 
89 #ifdef _DECODE_PROCESSING_SUPPORTED
90     auto sfcHistogramPostSubPipeline = MOS_New(DecodeSfcHistogramSubPipeline, this, m_task, m_numVdbox);
91     DECODE_CHK_NULL(sfcHistogramPostSubPipeline);
92     DECODE_CHK_STATUS(m_postSubPipeline->Register(*sfcHistogramPostSubPipeline));
93 #endif
94 
95     return MOS_STATUS_SUCCESS;
96 }
97 
CreateSubPipeLineManager(CodechalSetting * codecSettings)98 MOS_STATUS DecodePipeline::CreateSubPipeLineManager(CodechalSetting* codecSettings)
99 {
100     m_preSubPipeline = MOS_New(DecodeSubPipelineManager, *this);
101     DECODE_CHK_NULL(m_preSubPipeline);
102     DECODE_CHK_STATUS(CreatePreSubPipeLines(*m_preSubPipeline));
103     DECODE_CHK_STATUS(m_preSubPipeline->Init(*codecSettings));
104 
105     m_postSubPipeline = MOS_New(DecodeSubPipelineManager, *this);
106     DECODE_CHK_NULL(m_postSubPipeline);
107     DECODE_CHK_STATUS(CreatePostSubPipeLines(*m_postSubPipeline));
108     DECODE_CHK_STATUS(m_postSubPipeline->Init(*codecSettings));
109 
110     return MOS_STATUS_SUCCESS;
111 }
112 
CreateSubPackets(DecodeSubPacketManager & subPacketManager,CodechalSetting & codecSettings)113 MOS_STATUS DecodePipeline::CreateSubPackets(DecodeSubPacketManager& subPacketManager, CodechalSetting &codecSettings)
114 {
115     DecodePredicationPkt *predicationPkt = MOS_New(DecodePredicationPkt, this, m_hwInterface);
116     DECODE_CHK_NULL(predicationPkt);
117     DECODE_CHK_STATUS(subPacketManager.Register(
118                         DecodePacketId(this, predicationSubPacketId), *predicationPkt));
119 
120     DecodeMarkerPkt *markerPkt = MOS_New(DecodeMarkerPkt, this, m_hwInterface);
121     DECODE_CHK_NULL(markerPkt);
122     DECODE_CHK_STATUS(subPacketManager.Register(
123                         DecodePacketId(this, markerSubPacketId), *markerPkt));
124     return MOS_STATUS_SUCCESS;
125 }
126 
GetSubPacket(uint32_t subPacketId)127 DecodeSubPacket* DecodePipeline::GetSubPacket(uint32_t subPacketId)
128 {
129     return m_subPacketManager->GetSubPacket(subPacketId);
130 }
131 
CreateSubPacketManager(CodechalSetting * codecSettings)132 MOS_STATUS DecodePipeline::CreateSubPacketManager(CodechalSetting* codecSettings)
133 {
134     DECODE_CHK_NULL(codecSettings);
135     m_subPacketManager = MOS_New(DecodeSubPacketManager);
136     DECODE_CHK_NULL(m_subPacketManager);
137     DECODE_CHK_STATUS(CreateSubPackets(*m_subPacketManager, *codecSettings));
138     DECODE_CHK_STATUS(m_subPacketManager->Init());
139     return MOS_STATUS_SUCCESS;
140 }
141 
Initialize(void * settings)142 MOS_STATUS DecodePipeline::Initialize(void *settings)
143 {
144     DECODE_FUNC_CALL();
145 
146     DECODE_CHK_NULL(settings);
147 
148     DECODE_CHK_STATUS(MediaPipeline::InitPlatform());
149     DECODE_CHK_STATUS(MediaPipeline::CreateMediaCopy());
150 
151     DECODE_CHK_NULL(m_waTable);
152 
153     auto *codecSettings = (CodechalSetting*)settings;
154     DECODE_CHK_NULL(m_hwInterface);
155     DECODE_CHK_STATUS(m_hwInterface->Initialize(codecSettings));
156 
157     m_mediaContext = MOS_New(MediaContext, scalabilityDecoder, m_hwInterface, m_osInterface);
158     DECODE_CHK_NULL(m_mediaContext);
159 
160     m_task = CreateTask(MediaTask::TaskType::cmdTask);
161     DECODE_CHK_NULL(m_task);
162 
163     m_numVdbox = GetSystemVdboxNumber();
164 
165     bool limitedLMemBar = MEDIA_IS_SKU(m_skuTable, FtrLimitedLMemBar) ? true : false;
166     m_allocator = MOS_New(DecodeAllocator, m_osInterface, limitedLMemBar);
167     DECODE_CHK_NULL(m_allocator);
168 
169     DECODE_CHK_STATUS(CreateStatusReport());
170 
171     m_decodecp = Create_DecodeCpInterface(codecSettings, m_hwInterface);
172     if (m_decodecp)
173     {
174         m_decodecp->RegisterParams(codecSettings);
175     }
176     DECODE_CHK_STATUS(CreateFeatureManager());
177     DECODE_CHK_STATUS(m_featureManager->Init(codecSettings));
178 
179     DECODE_CHK_STATUS(CreateSubPipeLineManager(codecSettings));
180     DECODE_CHK_STATUS(CreateSubPacketManager(codecSettings));
181 
182     return MOS_STATUS_SUCCESS;
183 }
184 
Uninitialize()185 MOS_STATUS DecodePipeline::Uninitialize()
186 {
187     DECODE_FUNC_CALL();
188 
189     Delete_DecodeCpInterface(m_decodecp);
190     m_decodecp = nullptr;
191 
192     MOS_Delete(m_mediaContext);
193 
194     MOS_Delete(m_statusReport);
195 
196     MOS_Delete(m_featureManager);
197 
198     MOS_Delete(m_preSubPipeline);
199     MOS_Delete(m_postSubPipeline);
200     MOS_Delete(m_subPacketManager);
201 
202     MOS_Delete(m_allocator);
203 
204     return MOS_STATUS_SUCCESS;
205 }
206 
UserFeatureReport()207 MOS_STATUS DecodePipeline::UserFeatureReport()
208 {
209     DECODE_FUNC_CALL();
210     return MediaPipeline::UserFeatureReport();
211 }
212 
IsFirstProcessPipe(const DecodePipelineParams & pipelineParams)213 bool DecodePipeline::IsFirstProcessPipe(const DecodePipelineParams& pipelineParams)
214 {
215     if (pipelineParams.m_pipeMode != decodePipeModeProcess)
216     {
217         return false;
218     }
219 
220     CodechalDecodeParams *decodeParams = pipelineParams.m_params;
221     if (decodeParams == nullptr)
222     {
223         return false;
224     }
225 
226     return (decodeParams->m_executeCallIndex == 0);
227 }
228 
GetSystemVdboxNumber()229 uint8_t DecodePipeline::GetSystemVdboxNumber()
230 {
231     uint8_t numVdbox = 1;
232 
233     MEDIA_SYSTEM_INFO *gtSystemInfo = m_osInterface->pfnGetGtSystemInfo(m_osInterface);
234     if (gtSystemInfo != nullptr)
235     {
236         // Both VE mode and media solo mode should be able to get the VDBOX number via the same interface
237         numVdbox = (uint8_t)(gtSystemInfo->VDBoxInfo.NumberOfVDBoxEnabled);
238     }
239 
240     return numVdbox;
241 }
242 
Prepare(void * params)243 MOS_STATUS DecodePipeline::Prepare(void *params)
244 {
245     DECODE_FUNC_CALL();
246 
247     DECODE_CHK_NULL(params);
248     DecodePipelineParams *pipelineParams = (DecodePipelineParams *)params;
249     CodechalDecodeParams *decodeParams = pipelineParams->m_params;
250     DECODE_CHK_NULL(decodeParams);
251 
252     DECODE_CHK_STATUS(m_task->Clear());
253     m_activePacketList.clear();
254 
255     DECODE_CHK_NULL(m_featureManager);
256     DECODE_CHK_STATUS(m_featureManager->CheckFeatures(decodeParams));
257     DECODE_CHK_STATUS(m_featureManager->Update(decodeParams));
258     if (m_decodecp)
259     {
260         m_decodecp->UpdateParams(true);
261     }
262     DECODE_CHK_STATUS(m_subPacketManager->Prepare());
263 
264     DECODE_CHK_STATUS(Mos_Solo_SetGpuAppTaskEvent(m_osInterface, decodeParams->m_gpuAppTaskEvent));
265 
266     return MOS_STATUS_SUCCESS;
267 }
268 
ExecuteActivePackets()269 MOS_STATUS DecodePipeline::ExecuteActivePackets()
270 {
271     DECODE_FUNC_CALL();
272     MOS_TraceEventExt(EVENT_PIPE_EXE, EVENT_TYPE_START, nullptr, 0, nullptr, 0);
273 
274     // Last element in m_activePacketList must be immediately submitted
275     m_activePacketList.back().immediateSubmit = true;
276 
277     for (PacketProperty prop : m_activePacketList)
278     {
279         prop.stateProperty.singleTaskPhaseSupported = m_singleTaskPhaseSupported;
280         prop.stateProperty.statusReport = m_statusReport;
281         MOS_TraceEventExt(EVENT_PIPE_EXE, EVENT_TYPE_INFO, &prop.packetId, sizeof(uint32_t), nullptr, 0);
282 
283         MediaTask *task = prop.packet->GetActiveTask();
284         DECODE_CHK_STATUS(task->AddPacket(&prop));
285         if (prop.immediateSubmit)
286         {
287             DECODE_CHK_STATUS(task->Submit(true, m_scalability, m_debugInterface));
288         }
289     }
290 
291     m_activePacketList.clear();
292     MOS_TraceEventExt(EVENT_PIPE_EXE, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
293     return MOS_STATUS_SUCCESS;
294 }
295 
IsCompleteBitstream()296 bool DecodePipeline::IsCompleteBitstream()
297 {
298     return (m_bitstream == nullptr) ? false : m_bitstream->IsComplete();
299 }
300 
301 #ifdef _DECODE_PROCESSING_SUPPORTED
IsDownSamplingSupported()302 bool DecodePipeline::IsDownSamplingSupported()
303 {
304     DECODE_ASSERT(m_subPacketManager != nullptr);
305 
306     DecodeDownSamplingPkt *downSamplingPkt = dynamic_cast<DecodeDownSamplingPkt *>(
307         GetSubPacket(DecodePacketId(this, downSamplingSubPacketId)));
308     if (downSamplingPkt == nullptr)
309     {
310         return false;
311     }
312 
313     return downSamplingPkt->IsSupported();
314 }
315 #endif
316 
GetDummyReference()317 MOS_SURFACE* DecodePipeline::GetDummyReference()
318 {
319     auto* feature = dynamic_cast<DecodeBasicFeature*>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
320     return (feature != nullptr) ? &(feature->m_dummyReference) : nullptr;
321 }
322 
GetDummyReferenceStatus()323 CODECHAL_DUMMY_REFERENCE_STATUS DecodePipeline::GetDummyReferenceStatus()
324 {
325     auto* feature = dynamic_cast<DecodeBasicFeature*>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
326     return (feature != nullptr) ? feature->m_dummyReferenceStatus : CODECHAL_DUMMY_REFERENCE_INVALID;
327 }
328 
SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_STATUS status)329 void DecodePipeline::SetDummyReferenceStatus(CODECHAL_DUMMY_REFERENCE_STATUS status)
330 {
331     auto* feature = dynamic_cast<DecodeBasicFeature*>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
332     if (feature != nullptr)
333     {
334         feature->m_dummyReferenceStatus = status;
335     }
336 }
337 
338 #if USE_CODECHAL_DEBUG_TOOL
339 #ifdef _DECODE_PROCESSING_SUPPORTED
DumpDownSamplingParams(DecodeDownSamplingFeature & downSamplingParams)340 MOS_STATUS DecodePipeline::DumpDownSamplingParams(DecodeDownSamplingFeature &downSamplingParams)
341 {
342     CODECHAL_DEBUG_FUNCTION_ENTER;
343     if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDecodeProcParams))
344     {
345         return MOS_STATUS_SUCCESS;
346     }
347 
348     if(!downSamplingParams.IsEnabled())
349     {
350         return MOS_STATUS_SUCCESS;
351     }
352 
353     DECODE_CHK_NULL(downSamplingParams.m_inputSurface);
354 
355     std::ostringstream oss;
356     oss.setf(std::ios::showbase | std::ios::uppercase);
357 
358     oss << "Input Surface Resolution: "
359         << +downSamplingParams.m_inputSurface->dwWidth << " x " << +downSamplingParams.m_inputSurface->dwHeight << std::endl;
360     oss << "Input Region Resolution: "
361         << +downSamplingParams.m_inputSurfaceRegion.m_width << " x " << +downSamplingParams.m_inputSurfaceRegion.m_height << std::endl;
362     oss << "Input Region Offset: ("
363         << +downSamplingParams.m_inputSurfaceRegion.m_x << "," << +downSamplingParams.m_inputSurfaceRegion.m_y << ")" << std::endl;
364     oss << "Input Surface Format: "
365         << (downSamplingParams.m_inputSurface->Format == Format_NV12 ? "NV12" : "P010" )<< std::endl;
366     oss << "Output Surface Resolution: "
367         << +downSamplingParams.m_outputSurface.dwWidth << " x " << +downSamplingParams.m_outputSurface.dwHeight << std::endl;
368     oss << "Output Region Resolution: "
369         << +downSamplingParams.m_outputSurfaceRegion.m_width << " x " << +downSamplingParams.m_outputSurfaceRegion.m_height << std::endl;
370     oss << "Output Region Offset: ("
371         << +downSamplingParams.m_outputSurfaceRegion.m_x << ", " << +downSamplingParams.m_outputSurfaceRegion.m_y << ")" << std::endl;
372     oss << "Output Surface Format: "
373         << (downSamplingParams.m_outputSurface.Format == Format_NV12 ? "NV12" : "YUY2" )<< std::endl;
374 
375     const char* filePath = m_debugInterface->CreateFileName(
376         "_DEC",
377         CodechalDbgBufferType::bufDecProcParams,
378         CodechalDbgExtType::txt);
379 
380     std::ofstream ofs(filePath, std::ios::out);
381     ofs << oss.str();
382     ofs.close();
383 
384     return MOS_STATUS_SUCCESS;
385 }
386 #endif
387 
DumpOutput(const DecodeStatusReportData & reportData)388 MOS_STATUS DecodePipeline::DumpOutput(const DecodeStatusReportData& reportData)
389 {
390     DECODE_FUNC_CALL();
391 
392     if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDecodeOutputSurface))
393     {
394         MOS_SURFACE dstSurface;
395         MOS_ZeroMemory(&dstSurface, sizeof(dstSurface));
396         dstSurface.Format     = Format_NV12;
397         dstSurface.OsResource = reportData.currDecodedPicRes;
398         DECODE_CHK_STATUS(m_allocator->GetSurfaceInfo(&dstSurface));
399 
400         DECODE_CHK_STATUS(m_debugInterface->DumpYUVSurface(
401             &dstSurface, CodechalDbgAttr::attrDecodeOutputSurface, "DstSurf"));
402     }
403 
404 #ifdef _DECODE_PROCESSING_SUPPORTED
405     DecodeDownSamplingFeature* downSamplingFeature = dynamic_cast<DecodeDownSamplingFeature*>(
406         m_featureManager->GetFeature(DecodeFeatureIDs::decodeDownSampling));
407     if (downSamplingFeature != nullptr && downSamplingFeature->IsEnabled())
408     {
409         if (reportData.currSfcOutputPicRes != nullptr &&
410             m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSfcOutputSurface))
411         {
412             MOS_SURFACE sfcDstSurface;
413             MOS_ZeroMemory(&sfcDstSurface, sizeof(sfcDstSurface));
414             sfcDstSurface.Format     = Format_NV12;
415             sfcDstSurface.OsResource = *reportData.currSfcOutputPicRes;
416 
417             if (!Mos_ResourceIsNull(&sfcDstSurface.OsResource))
418             {
419                 DECODE_CHK_STATUS(m_allocator->GetSurfaceInfo(&sfcDstSurface));
420                 DECODE_CHK_STATUS(m_debugInterface->DumpYUVSurface(
421                     &sfcDstSurface, CodechalDbgAttr::attrSfcOutputSurface, "SfcDstSurf"));
422 
423 #if (_DEBUG || _RELEASE_INTERNAL)
424                 //rgb format read from reg key
425                 uint32_t sfcOutputRgbFormatFlag =
426                     ReadUserFeature(__MEDIA_USER_FEATURE_VALUE_DECODE_SFC_RGBFORMAT_OUTPUT_DEBUG_ID, m_osInterface->pOsContext).u32Data;
427 
428                 if (sfcOutputRgbFormatFlag)
429                 {
430                     DECODE_CHK_STATUS(m_debugInterface->DumpRgbDataOnYUVSurface(
431                         &sfcDstSurface, CodechalDbgAttr::attrSfcOutputSurface, "SfcDstRgbSurf"));
432                 }
433 #endif
434             }
435         }
436 
437         if (reportData.currHistogramOutBuf != nullptr &&
438             !Mos_ResourceIsNull(reportData.currHistogramOutBuf))
439         {
440             DECODE_CHK_STATUS(m_debugInterface->DumpBuffer(
441                 reportData.currHistogramOutBuf,
442                 CodechalDbgAttr::attrSfcHistogram,
443                 "_DEC",
444                 HISTOGRAM_BINCOUNT * downSamplingFeature->m_histogramBinWidth));
445         }
446     }
447 #endif
448 
449     return MOS_STATUS_SUCCESS;
450 }
451 #endif
452 
453 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
TraceDataDumpOutput(const DecodeStatusReportData & reportData)454 MOS_STATUS DecodePipeline::TraceDataDumpOutput(const DecodeStatusReportData &reportData)
455 {
456     bool bAllocate = false;
457     MOS_SURFACE dstSurface;
458     MOS_ZeroMemory(&dstSurface, sizeof(dstSurface));
459     dstSurface.OsResource = reportData.currDecodedPicRes;
460     DECODE_CHK_STATUS(m_allocator->GetSurfaceInfo(&dstSurface));
461 
462     DECODE_EVENTDATA_YUV_SURFACE_INFO eventData =
463     {
464         (uint32_t)reportData.currDecodedPic.PicFlags,
465         dstSurface.dwOffset,
466         dstSurface.YPlaneOffset.iYOffset,
467         dstSurface.dwPitch,
468         dstSurface.dwWidth,
469         dstSurface.dwHeight,
470         (uint32_t)dstSurface.Format,
471         dstSurface.UPlaneOffset.iLockSurfaceOffset,
472         dstSurface.VPlaneOffset.iLockSurfaceOffset,
473         dstSurface.UPlaneOffset.iSurfaceOffset,
474         dstSurface.VPlaneOffset.iSurfaceOffset,
475     };
476     MOS_TraceEvent(EVENT_DECODE_SURFACE_DUMPINFO, EVENT_TYPE_INFO, &eventData, sizeof(eventData), NULL, 0);
477 
478     if (!m_allocator->ResourceIsNull(&dstSurface.OsResource))
479     {
480         if (m_tempOutputSurf == nullptr || m_allocator->ResourceIsNull(&m_tempOutputSurf->OsResource))
481         {
482             bAllocate = true;
483         }
484         else if (m_tempOutputSurf->dwWidth  < dstSurface.dwWidth ||
485                  m_tempOutputSurf->dwHeight < dstSurface.dwHeight)
486         {
487             bAllocate = true;
488         }
489         else
490         {
491             bAllocate = false;
492         }
493 
494         if (bAllocate)
495         {
496             if (!m_allocator->ResourceIsNull(&m_tempOutputSurf->OsResource))
497             {
498                 m_allocator->Destroy(m_tempOutputSurf);
499             }
500 
501             m_tempOutputSurf = m_allocator->AllocateLinearSurface(
502                 dstSurface.dwWidth,
503                 dstSurface.dwHeight,
504                 "Decode Output Surf",
505                 dstSurface.Format,
506                 dstSurface.bIsCompressed,
507                 resourceOutputPicture,
508                 lockableSystemMem,
509                 MOS_TILE_LINEAR_GMM);
510         }
511 
512         DECODE_CHK_STATUS(m_osInterface->pfnDoubleBufferCopyResource(
513             m_osInterface,
514             &dstSurface.OsResource,
515             &m_tempOutputSurf->OsResource,
516             false));
517 
518         ResourceAutoLock resLock(m_allocator, &m_tempOutputSurf->OsResource);
519         auto             pData = (uint8_t *)resLock.LockResourceForRead();
520 
521         MOS_TraceDataDump(
522             "Decode_OutputSurf",
523             0,
524             pData,
525             (uint32_t)m_tempOutputSurf->OsResource.pGmmResInfo->GetSizeMainSurface());
526     }
527 
528     return MOS_STATUS_SUCCESS;
529 }
530 
TraceDataDump2ndLevelBB(PMHW_BATCH_BUFFER batchBuffer)531 MOS_STATUS DecodePipeline::TraceDataDump2ndLevelBB(PMHW_BATCH_BUFFER batchBuffer)
532 {
533     DECODE_FUNC_CALL();
534 
535     DECODE_CHK_NULL(batchBuffer);
536     batchBuffer->iLastCurrent = batchBuffer->iSize * batchBuffer->count;
537     batchBuffer->dwOffset     = 0;
538 
539     DECODE_CHK_STATUS(m_osInterface->pfnDumpTraceGpuData(
540         m_osInterface,
541         "Decode_2ndLevelCmdBB",
542         0,
543         &batchBuffer->OsResource,
544         batchBuffer->iLastCurrent));
545 
546     return MOS_STATUS_SUCCESS;
547 }
548 #endif
549 
550 #if (_DEBUG || _RELEASE_INTERNAL)
ReportVdboxIds(const DecodeStatusMfx & status)551 MOS_STATUS DecodePipeline::ReportVdboxIds(const DecodeStatusMfx& status)
552 {
553     DECODE_FUNC_CALL();
554 
555     // report the VDBOX IDs to user feature
556     uint32_t vdboxIds = ReadUserFeature(__MEDIA_USER_FEATURE_VALUE_VDBOX_ID_USED, m_osInterface->pOsContext).u32Data;
557 
558     for (auto i = 0; i < csInstanceIdMax; i++)
559     {
560         CsEngineId csEngineId;
561         csEngineId.value = status.m_mmioCsEngineIdReg[i];
562         if (csEngineId.value != 0)
563         {
564             DECODE_ASSERT(csEngineId.fields.classId == classIdVideoEngine);
565             DECODE_ASSERT(csEngineId.fields.instanceId < csInstanceIdMax);
566             vdboxIds |= 1 << ((csEngineId.fields.instanceId) << 2);
567         }
568     }
569 
570     if (vdboxIds != 0)
571     {
572         WriteUserFeature(__MEDIA_USER_FEATURE_VALUE_VDBOX_ID_USED, vdboxIds, m_osInterface->pOsContext);
573     }
574 
575     return MOS_STATUS_SUCCESS;
576 }
577 
578 #ifdef _DECODE_PROCESSING_SUPPORTED
ReportSfcLinearSurfaceUsage(const DecodeStatusReportData & reportData)579 MOS_STATUS DecodePipeline::ReportSfcLinearSurfaceUsage(const DecodeStatusReportData& reportData)
580 {
581     DECODE_FUNC_CALL();
582 
583     DecodeDownSamplingFeature *downSamplingFeature = dynamic_cast<DecodeDownSamplingFeature *>(
584         m_featureManager->GetFeature(DecodeFeatureIDs::decodeDownSampling));
585     if (downSamplingFeature != nullptr && downSamplingFeature->IsEnabled())
586     {
587         if (reportData.currSfcOutputPicRes != nullptr)
588         {
589             MOS_SURFACE sfcDstSurface;
590             MOS_ZeroMemory(&sfcDstSurface, sizeof(sfcDstSurface));
591             sfcDstSurface.Format     = Format_NV12;
592             sfcDstSurface.OsResource = *reportData.currSfcOutputPicRes;
593             if (!Mos_ResourceIsNull(&sfcDstSurface.OsResource))
594             {
595                 DECODE_CHK_STATUS(m_allocator->GetSurfaceInfo(&sfcDstSurface));
596                 if (sfcDstSurface.TileType == MOS_TILE_LINEAR)
597                 {
598                     WriteUserFeature(__MEDIA_USER_FEATURE_VALUE_SFC_LINEAR_OUTPUT_USED_ID, 1, m_osInterface->pOsContext);
599                 }
600                 else
601                 {
602                     WriteUserFeature(__MEDIA_USER_FEATURE_VALUE_SFC_LINEAR_OUTPUT_USED_ID, 0, m_osInterface->pOsContext);
603                 }
604             }
605         }
606     }
607     return MOS_STATUS_SUCCESS;
608 }
609 #endif
610 
StatusCheck()611 MOS_STATUS DecodePipeline::StatusCheck()
612 {
613     DECODE_FUNC_CALL();
614 
615     uint32_t completedCount = m_statusReport->GetCompletedCount();
616     if (completedCount <= m_statusCheckCount)
617     {
618         DECODE_CHK_COND(completedCount < m_statusCheckCount, "Invalid status check count");
619         return MOS_STATUS_SUCCESS;
620     }
621 
622     DecodeStatusReport* statusReport = dynamic_cast<DecodeStatusReport*>(m_statusReport);
623     DECODE_CHK_NULL(statusReport);
624 
625     while (m_statusCheckCount < completedCount)
626     {
627         const DecodeStatusMfx& status = statusReport->GetMfxStatus(m_statusCheckCount);
628         if (status.status != DecodeStatusReport::queryEnd)
629         {
630             DECODE_NORMALMESSAGE("Media reset may have occured at frame %d, status is %d, completedCount is %d.",
631                 m_statusCheckCount, status.status, completedCount);
632         }
633 
634         DECODE_NORMALMESSAGE("hucStatus2 is 0x%x at frame %d.", status.m_hucErrorStatus2, m_statusCheckCount);
635         DECODE_NORMALMESSAGE("hucStatus is 0x%x at frame %d.", status.m_hucErrorStatus, m_statusCheckCount);
636 
637         DECODE_CHK_STATUS(HwStatusCheck(status));
638 
639         DECODE_CHK_STATUS(ReportVdboxIds(status));
640 
641 #if USE_CODECHAL_DEBUG_TOOL
642         const DecodeStatusReportData& reportData = statusReport->GetReportData(m_statusCheckCount);
643 
644         auto bufferDumpNumTemp = m_debugInterface->m_bufferDumpFrameNum;
645         auto currPicTemp       = m_debugInterface->m_currPic;
646         auto frameTypeTemp     = m_debugInterface->m_frameType;
647 
648         m_debugInterface->m_bufferDumpFrameNum = m_statusCheckCount;
649         m_debugInterface->m_currPic            = reportData.currDecodedPic;
650         m_debugInterface->m_frameType          = reportData.frameType;
651 #ifdef _DECODE_PROCESSING_SUPPORTED
652         ReportSfcLinearSurfaceUsage(reportData);
653 #endif
654         DECODE_CHK_STATUS(DumpOutput(reportData));
655 
656         m_debugInterface->m_bufferDumpFrameNum = bufferDumpNumTemp;
657         m_debugInterface->m_currPic            = currPicTemp;
658         m_debugInterface->m_frameType          = frameTypeTemp;
659 #endif
660 
661 #if MOS_EVENT_TRACE_DUMP_SUPPORTED
662         if (MOS_GetTraceEventKeyword() & EVENT_DECODE_DSTYUV_KEYWORD)
663         {
664             DECODE_CHK_STATUS(TraceDataDumpOutput(reportData));
665         }
666 #endif
667 
668         m_statusCheckCount++;
669     }
670 
671     return MOS_STATUS_SUCCESS;
672 }
673 #endif
674 
675 }
676