1 /*############################################################################
2   # Copyright (C) 2005 Intel Corporation
3   #
4   # SPDX-License-Identifier: MIT
5   ############################################################################*/
6 
7 #include <algorithm>
8 #include "mfx_samples_config.h"
9 #include "sample_defs.h"
10 
11 #if defined(_WIN32) || defined(_WIN64)
12     #include <tchar.h>
13     #include <windows.h>
14 #endif
15 
16 #include <assert.h>
17 #include <algorithm>
18 #include <ctime>
19 #include <thread>
20 #include "pipeline_decode.h"
21 #include "sysmem_allocator.h"
22 
23 #if defined(_WIN32) || defined(_WIN64)
24     #include "d3d11_allocator.h"
25     #include "d3d11_device.h"
26     #include "d3d_allocator.h"
27     #include "d3d_device.h"
28 
29 #endif
30 
31 #if defined LIBVA_SUPPORT
32     #include "vaapi_allocator.h"
33     #include "vaapi_device.h"
34     #include "vaapi_utils.h"
35 #endif
36 
37 #if defined(LIBVA_WAYLAND_SUPPORT)
38     #include "class_wayland.h"
39 #endif
40 
41 #include "version.h"
42 
43 #define __SYNC_WA // avoid sync issue on Media SDK side
44 
45 #ifndef MFX_VERSION
46     #error MFX_VERSION not defined
47 #endif
48 
CDecodingPipeline()49 CDecodingPipeline::CDecodingPipeline()
50         : m_FileWriter(),
51           m_FileReader(),
52           m_mfxBS(8 * 1024 * 1024),
53           totalBytesProcessed(0),
54           m_pLoader(),
55           m_mfxSession(),
56           m_impl(0),
57           m_pmfxDEC(NULL),
58           m_pmfxVPP(NULL),
59           m_mfxVideoParams(),
60           m_mfxVppVideoParams(),
61           m_pGeneralAllocator(NULL),
62           m_pmfxAllocatorParams(NULL),
63           m_memType(SYSTEM_MEMORY),
64           m_bExternalAlloc(false),
65           m_bDecOutSysmem(false),
66           m_mfxResponse({}),
67           m_mfxVppResponse({}),
68           m_pCurrentFreeSurface(NULL),
69           m_pCurrentFreeVppSurface(NULL),
70           m_pCurrentFreeOutputSurface(NULL),
71           m_pCurrentOutputSurface(NULL),
72           m_pDeliverOutputSemaphore(NULL),
73           m_pDeliveredEvent(NULL),
74           m_error(MFX_ERR_NONE),
75           m_bStopDeliverLoop(false),
76           m_eWorkMode(MODE_PERFORMANCE),
77           m_bIsMVC(false),
78           m_bIsVideoWall(false),
79           m_bIsCompleteFrame(false),
80           m_fourcc(0),
81           m_bPrintLatency(false),
82           m_bOutI420(false),
83           m_vppOutWidth(0),
84           m_vppOutHeight(0),
85           m_nTimeout(0),
86           m_nMaxFps(0),
87           m_nFrames(0),
88           m_diMode(0),
89           m_bVppIsUsed(false),
90           m_bVppFullColorRange(false),
91           m_bSoftRobustFlag(false),
92           m_vLatency(),
93           m_fpsLimiter(),
94           m_VppVideoSignalInfo({}),
95           m_VppSurfaceExtParams(),
96 #if defined(LINUX32) || defined(LINUX64)
97           m_strDevicePath(),
98 #endif
99           m_hwdev(NULL),
100 #if D3D_SURFACES_SUPPORT
101           m_d3dRender(),
102 #endif
103           m_bRenderWin(false),
104           m_nRenderWinX(0),
105           m_nRenderWinY(0),
106           m_nRenderWinW(0),
107           m_nRenderWinH(0),
108 #ifdef LIBVA_SUPPORT
109           m_export_mode(vaapiAllocatorParams::DONOT_EXPORT),
110 #else
111           m_export_mode(0),
112 #endif
113           m_monitorType(0),
114 #ifdef LIBVA_SUPPORT
115           m_libvaBackend(0),
116           m_bPerfMode(false),
117 #endif
118           m_bResetFileWriter(false),
119           m_bResetFileReader(false) {
120     // reserve some space to reduce dynamic reallocation impact on pipeline execution
121     m_vLatency.reserve(1000);
122     m_VppVideoSignalInfo.Header.BufferId = MFX_EXTBUFF_VPP_VIDEO_SIGNAL_INFO;
123     m_VppVideoSignalInfo.Header.BufferSz = sizeof(m_VppVideoSignalInfo);
124 }
125 
~CDecodingPipeline()126 CDecodingPipeline::~CDecodingPipeline() {
127     Close();
128 }
129 
Init(sInputParams * pParams)130 mfxStatus CDecodingPipeline::Init(sInputParams* pParams) {
131     MSDK_CHECK_POINTER(pParams, MFX_ERR_NULL_PTR);
132 
133     mfxStatus sts = MFX_ERR_NONE;
134 
135     // prepare input stream file reader
136     // for VP8 complete and single frame reader is a requirement
137     // create reader that supports completeframe mode for latency oriented scenarios
138     if (pParams->bLowLat || pParams->bCalLat) {
139         switch (pParams->videoType) {
140             case MFX_CODEC_AVC:
141                 m_FileReader.reset(new CH264FrameReader());
142                 m_bIsCompleteFrame = true;
143                 m_bPrintLatency    = pParams->bCalLat;
144                 break;
145             case MFX_CODEC_JPEG:
146                 m_FileReader.reset(new CJPEGFrameReader());
147                 m_bIsCompleteFrame = true;
148                 m_bPrintLatency    = pParams->bCalLat;
149                 break;
150             case MFX_CODEC_VP8:
151             case MFX_CODEC_VP9:
152             case MFX_CODEC_AV1:
153                 m_FileReader.reset(new CIVFFrameReader());
154                 m_bIsCompleteFrame = true;
155                 m_bPrintLatency    = pParams->bCalLat;
156                 break;
157             default:
158                 return MFX_ERR_UNSUPPORTED; // latency mode is supported only for H.264 and JPEG codecs
159         }
160     }
161     else {
162         switch (pParams->videoType) {
163             case MFX_CODEC_VP8:
164             case MFX_CODEC_VP9:
165             case MFX_CODEC_AV1:
166                 m_FileReader.reset(new CIVFFrameReader());
167                 break;
168             default:
169                 m_FileReader.reset(new CSmplBitstreamReader());
170                 break;
171         }
172     }
173 
174     if (pParams->fourcc)
175         m_fourcc = pParams->fourcc;
176 
177 #ifdef LIBVA_SUPPORT
178     if (pParams->bPerfMode)
179         m_bPerfMode = true;
180 #endif
181 
182     if (pParams->Width)
183         m_vppOutWidth = pParams->Width;
184     if (pParams->Height)
185         m_vppOutHeight = pParams->Height;
186 
187 #if defined(LINUX32) || defined(LINUX64)
188     m_strDevicePath = pParams->strDevicePath;
189 #endif
190 
191     if (pParams->memType)
192         m_memType = pParams->memType;
193     else {
194         switch (pParams->mode) {
195             case MODE_PERFORMANCE:
196 #if defined(_WIN32) || defined(_WIN64)
197                 m_memType = pParams->bUseHWLib ? D3D11_MEMORY : SYSTEM_MEMORY;
198 #elif defined(LIBVA_SUPPORT)
199                 m_memType = pParams->bUseHWLib ? D3D9_MEMORY : SYSTEM_MEMORY;
200 #endif
201                 break;
202             case MODE_RENDERING:
203                 m_memType = D3D9_MEMORY;
204                 break;
205             case MODE_FILE_DUMP:
206                 m_memType = SYSTEM_MEMORY;
207                 break;
208             default:
209                 assert(0);
210                 MSDK_CHECK_STATUS(MFX_ERR_UNSUPPORTED, "Unexpected eWorkMode");
211         }
212     }
213 
214     m_nMaxFps = pParams->nMaxFPS;
215     m_nFrames = pParams->nFrames ? pParams->nFrames : MFX_INFINITE;
216 
217     m_bOutI420 = pParams->outI420;
218 
219     m_nTimeout        = pParams->nTimeout;
220     m_bSoftRobustFlag = pParams->bSoftRobustFlag;
221 
222     // Initializing file reader
223     totalBytesProcessed = 0;
224     sts                 = m_FileReader->Init(pParams->strSrcFile);
225     if (sts == MFX_ERR_UNSUPPORTED && pParams->videoType == MFX_CODEC_AV1) {
226         m_FileReader.reset(new CSmplBitstreamReader());
227         msdk_printf(MSDK_STRING("WARNING: Stream is not IVF, default reader\n"));
228     }
229     MSDK_CHECK_STATUS(sts, "m_FileReader->Init failed");
230 
231     mfxInitParamlWrap initPar;
232     auto threadsPar = initPar.AddExtBuffer<mfxExtThreadsParam>();
233     MSDK_CHECK_POINTER(threadsPar, MFX_ERR_MEMORY_ALLOC);
234 
235     initPar.GPUCopy = pParams->gpuCopy;
236 
237     if (pParams->nThreadsNum) {
238         threadsPar->NumThread = pParams->nThreadsNum;
239     }
240     if (pParams->SchedulingType) {
241         threadsPar->SchedulingType = pParams->SchedulingType;
242     }
243     if (pParams->Priority) {
244         threadsPar->Priority = pParams->Priority;
245     }
246 
247     if (pParams->eDeinterlace) {
248         m_diMode = pParams->eDeinterlace;
249     }
250     if (pParams->bUseFullColorRange) {
251         m_bVppFullColorRange = pParams->bUseFullColorRange;
252     }
253 
254     bool bResolutionSpecified =
255         pParams->Width || pParams->Height; // potentially VPP can be inserted
256 
257     if (bResolutionSpecified)
258         m_bDecOutSysmem = pParams->bUseHWLib ? false : true;
259     else
260         m_bDecOutSysmem = m_memType == SYSTEM_MEMORY;
261 
262     m_eWorkMode = pParams->mode;
263 
264     m_monitorType = pParams->monitorType;
265     // create device and allocator
266 #if defined(LIBVA_SUPPORT)
267     m_libvaBackend = pParams->libvaBackend;
268 #endif // defined(MFX_LIBVA_SUPPORT)
269 
270     initPar.Implementation = pParams->bUseHWLib ? MFX_IMPL_HARDWARE : MFX_IMPL_SOFTWARE;
271 
272     m_pLoader.reset(new VPLImplementationLoader);
273 
274     if (pParams->dGfxIdx >= 0)
275         m_pLoader->SetDiscreteAdapterIndex(pParams->dGfxIdx);
276     else
277         m_pLoader->SetAdapterType(pParams->adapterType);
278 
279     if (pParams->adapterNum >= 0)
280         m_pLoader->SetAdapterNum(pParams->adapterNum);
281 
282 #ifdef ONEVPL_EXPERIMENTAL
283     if (pParams->PCIDeviceSetup)
284         m_pLoader->SetPCIDevice(pParams->PCIDomain,
285                                 pParams->PCIBus,
286                                 pParams->PCIDevice,
287                                 pParams->PCIFunction);
288 
289     #if (defined(_WIN64) || defined(_WIN32))
290     if (pParams->luid.HighPart > 0 || pParams->luid.LowPart)
291         m_pLoader->SetupLUID(pParams->luid);
292     #else
293     m_pLoader->SetupDRMRenderNodeNum(pParams->DRMRenderNodeNum);
294     #endif
295 #endif
296 
297     if (!pParams->accelerationMode && pParams->bUseHWLib) {
298 #if D3D_SURFACES_SUPPORT
299         pParams->accelerationMode = MFX_ACCEL_MODE_VIA_D3D11;
300 #elif defined(LIBVA_SUPPORT)
301         pParams->accelerationMode = MFX_ACCEL_MODE_VIA_VAAPI;
302 #endif
303     }
304 
305     bool bLowLatencyMode = !pParams->dispFullSearch;
306 
307     sts = m_pLoader->ConfigureAndEnumImplementations(initPar.Implementation,
308                                                      pParams->accelerationMode,
309                                                      bLowLatencyMode);
310     MSDK_CHECK_STATUS(sts, "m_mfxSession.EnumImplementations failed");
311 
312     sts = m_mfxSession.CreateSession(m_pLoader.get());
313     MSDK_CHECK_STATUS(sts, "m_mfxSession.CreateSession failed");
314 
315     mfxVersion version;
316     sts = m_mfxSession.QueryVersion(&version); // get real API version of the loaded library
317     MSDK_CHECK_STATUS(sts, "m_mfxSession.QueryVersion failed");
318 
319     sts = m_mfxSession.QueryIMPL(&m_impl); // get actual library implementation
320     MSDK_CHECK_STATUS(sts, "m_mfxSession.QueryIMPL failed");
321 
322 #if defined(_WIN32) || defined(_WIN64)
323     if (pParams->videoType == MFX_CODEC_AV1 && MFX_IMPL_VIA_MASK(m_impl) == MFX_IMPL_VIA_D3D9) {
324         sts = MFX_ERR_UNSUPPORTED;
325         MSDK_CHECK_STATUS(sts, "AV1d have no DX9 support \n");
326     }
327 #endif
328 
329     bool isDeviceRequired = false;
330     mfxHandleType hdl_t;
331 #if D3D_SURFACES_SUPPORT
332     isDeviceRequired = m_memType != SYSTEM_MEMORY || !m_bDecOutSysmem;
333     hdl_t =
334     #if MFX_D3D11_SUPPORT
335         D3D11_MEMORY == m_memType ? MFX_HANDLE_D3D11_DEVICE :
336     #endif // #if MFX_D3D11_SUPPORT
337                                   MFX_HANDLE_D3D9_DEVICE_MANAGER;
338 #elif LIBVA_SUPPORT
339     if (MFX_IMPL_SOFTWARE != initPar.Implementation) {
340         isDeviceRequired = true; // on Linux MediaSDK doesn't create device internally
341         hdl_t            = MFX_HANDLE_VA_DISPLAY;
342     }
343 #endif
344     if (isDeviceRequired) {
345         sts = CreateHWDevice();
346         MSDK_CHECK_STATUS(sts, "CreateHWDevice failed");
347         if (pParams->bUseHWLib) {
348             mfxHDL hdl = NULL;
349             sts        = m_hwdev->GetHandle(hdl_t, &hdl);
350             MSDK_CHECK_STATUS(sts, "m_hwdev->GetHandle failed");
351             sts = m_mfxSession.SetHandle(hdl_t, hdl);
352             MSDK_CHECK_STATUS(sts, "m_mfxSession.SetHandle failed");
353         }
354     }
355 
356     if (pParams->bIsMVC && !CheckVersion(&version, MSDK_FEATURE_MVC)) {
357         msdk_printf(MSDK_STRING("error: MVC is not supported in the %d.%d API version\n"),
358                     (int)version.Major,
359                     (int)version.Minor);
360         return MFX_ERR_UNSUPPORTED;
361     }
362     if ((pParams->videoType == MFX_CODEC_JPEG) &&
363         !CheckVersion(&version, MSDK_FEATURE_JPEG_DECODE)) {
364         msdk_printf(MSDK_STRING("error: Jpeg is not supported in the %d.%d API version\n"),
365                     (int)version.Major,
366                     (int)version.Minor);
367         return MFX_ERR_UNSUPPORTED;
368     }
369     if (pParams->bLowLat && !CheckVersion(&version, MSDK_FEATURE_LOW_LATENCY)) {
370         msdk_printf(
371             MSDK_STRING("error: Low Latency mode is not supported in the %d.%d API version\n"),
372             (int)version.Major,
373             (int)version.Minor);
374         return MFX_ERR_UNSUPPORTED;
375     }
376 
377     if (pParams->eDeinterlace && (pParams->eDeinterlace != MFX_DEINTERLACING_ADVANCED) &&
378         (pParams->eDeinterlace != MFX_DEINTERLACING_BOB)) {
379         msdk_printf(MSDK_STRING("error: Unsupported deinterlace value: %d\n"),
380                     (int)pParams->eDeinterlace);
381         return MFX_ERR_UNSUPPORTED;
382     }
383 
384     if (pParams->bRenderWin) {
385         m_bRenderWin = pParams->bRenderWin;
386         // note: currently position is unsupported for Wayland
387 #if !defined(LIBVA_WAYLAND_SUPPORT)
388         m_nRenderWinX = pParams->nRenderWinX;
389         m_nRenderWinY = pParams->nRenderWinY;
390 #endif
391     }
392 
393     m_fpsLimiter.Reset(pParams->nMaxFPS);
394 
395     // create decoder
396     m_pmfxDEC = new MFXVideoDECODE(m_mfxSession);
397     MSDK_CHECK_POINTER(m_pmfxDEC, MFX_ERR_MEMORY_ALLOC);
398 
399     // set video type in parameters
400     m_mfxVideoParams.mfx.CodecId = pParams->videoType;
401 
402     m_mfxVideoParams.mfx.IgnoreLevelConstrain = pParams->bIgnoreLevelConstrain;
403 
404     // Populate parameters. Involves DecodeHeader call
405     sts = InitMfxParams(pParams);
406     MSDK_CHECK_STATUS(sts, "InitMfxParams failed");
407 
408     if (m_bVppIsUsed) {
409         m_pmfxVPP = new MFXVideoVPP(m_mfxSession);
410         if (!m_pmfxVPP)
411             return MFX_ERR_MEMORY_ALLOC;
412     }
413 
414     if (m_eWorkMode == MODE_FILE_DUMP) {
415         // prepare YUV file writer
416         sts = m_FileWriter.Init(pParams->strDstFile, pParams->numViews);
417         MSDK_CHECK_STATUS(sts, "m_FileWriter.Init failed");
418     }
419     else if ((m_eWorkMode != MODE_PERFORMANCE) && (m_eWorkMode != MODE_RENDERING)) {
420         msdk_printf(MSDK_STRING("error: unsupported work mode\n"));
421         return MFX_ERR_UNSUPPORTED;
422     }
423 
424     sts = CreateAllocator();
425     MSDK_CHECK_STATUS(sts, "CreateAllocator failed");
426 
427     // in case of HW accelerated decode frames must be allocated prior to decoder initialization
428     sts = AllocFrames();
429     MSDK_CHECK_STATUS(sts, "AllocFrames failed");
430 
431     sts = m_pmfxDEC->Init(&m_mfxVideoParams);
432     if (MFX_WRN_PARTIAL_ACCELERATION == sts) {
433         msdk_printf(MSDK_STRING("WARNING: partial acceleration\n"));
434         MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION);
435     }
436     MSDK_CHECK_STATUS(sts, "m_pmfxDEC->Init failed");
437 
438     if (m_bVppIsUsed) {
439         if (m_diMode)
440             m_mfxVppVideoParams.vpp.Out.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
441 
442         if (pParams->ScalingMode) {
443             auto par         = m_mfxVppVideoParams.AddExtBuffer<mfxExtVPPScaling>();
444             par->ScalingMode = pParams->ScalingMode;
445         }
446 
447         sts = m_pmfxVPP->Init(&m_mfxVppVideoParams);
448         if (MFX_WRN_PARTIAL_ACCELERATION == sts) {
449             msdk_printf(MSDK_STRING("WARNING: partial acceleration\n"));
450             MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION);
451         }
452         MSDK_CHECK_STATUS(sts, "m_pmfxVPP->Init failed");
453     }
454 
455     sts = m_pmfxDEC->GetVideoParam(&m_mfxVideoParams);
456     MSDK_CHECK_STATUS(sts, "m_pmfxDEC->GetVideoParam failed");
457 
458     if (m_eWorkMode == MODE_RENDERING) {
459         sts = CreateRenderingWindow(pParams);
460         MSDK_CHECK_STATUS(sts, "CreateRenderingWindow failed");
461     }
462 
463     return sts;
464 }
465 
IsVppRequired(sInputParams * pParams)466 bool CDecodingPipeline::IsVppRequired(sInputParams* pParams) {
467     bool bVppIsUsed = false;
468     /* Re-size */
469     if ((m_mfxVideoParams.mfx.FrameInfo.CropW != pParams->Width) ||
470         (m_mfxVideoParams.mfx.FrameInfo.CropH != pParams->Height)) {
471         bVppIsUsed = pParams->Width && pParams->Height;
472         if ((MODE_DECODER_POSTPROC_AUTO == pParams->nDecoderPostProcessing) ||
473             (MODE_DECODER_POSTPROC_FORCE == pParams->nDecoderPostProcessing)) {
474             /* Decoder will make decision about internal post-processing usage slightly later */
475             bVppIsUsed = false;
476         }
477     }
478 
479     // JPEG and Capture decoders can provide output in nv12 and rgb4 formats
480     if (pParams->videoType == MFX_CODEC_JPEG) {
481         bVppIsUsed |= m_fourcc && (m_fourcc != MFX_FOURCC_NV12) && (m_fourcc != MFX_FOURCC_RGB4);
482     }
483     else {
484         bVppIsUsed |= m_fourcc && (m_fourcc != m_mfxVideoParams.mfx.FrameInfo.FourCC);
485     }
486 
487     if (pParams->eDeinterlace) {
488         bVppIsUsed = true;
489     }
490 
491     if ((MODE_DECODER_POSTPROC_AUTO == pParams->nDecoderPostProcessing) ||
492         (MODE_DECODER_POSTPROC_FORCE == pParams->nDecoderPostProcessing)) {
493         /* Decoder will make decision about internal post-processing usage slightly later */
494         if ((pParams->videoType == MFX_CODEC_AVC) || (pParams->videoType == MFX_CODEC_HEVC))
495             bVppIsUsed = false;
496     }
497 
498     return bVppIsUsed;
499 }
500 
Close()501 void CDecodingPipeline::Close() {
502 #if D3D_SURFACES_SUPPORT
503     m_d3dRender.Close();
504 #endif
505     MSDK_SAFE_DELETE(m_pmfxDEC);
506     MSDK_SAFE_DELETE(m_pmfxVPP);
507 
508     DeleteFrames();
509 
510     DeallocateExtMVCBuffers();
511 
512     m_mfxSession.Close();
513     m_FileWriter.Close();
514     if (m_FileReader.get())
515         m_FileReader->Close();
516 
517     auto vppExtParams = m_mfxVppVideoParams.GetExtBuffer<mfxExtVPPDoNotUse>();
518     if (vppExtParams)
519         MSDK_SAFE_DELETE_ARRAY(vppExtParams->AlgList);
520 
521     // allocator if used as external for MediaSDK must be deleted after decoder
522     DeleteAllocator();
523 
524     return;
525 }
526 
CreateRenderingWindow(sInputParams * pParams)527 mfxStatus CDecodingPipeline::CreateRenderingWindow(sInputParams* pParams) {
528     mfxStatus sts = MFX_ERR_NONE;
529 
530 #if D3D_SURFACES_SUPPORT
531     sWindowParams windowParams;
532 
533     windowParams.lpWindowName = pParams->bWallNoTitle ? NULL : MSDK_STRING("sample_decode");
534     windowParams.nx           = pParams->nWallW;
535     windowParams.ny           = pParams->nWallH;
536     if (m_bVppIsUsed) {
537         windowParams.nWidth  = m_mfxVppVideoParams.vpp.Out.Width;
538         windowParams.nHeight = m_mfxVppVideoParams.vpp.Out.Height;
539     }
540     else {
541         windowParams.nWidth  = m_mfxVideoParams.mfx.FrameInfo.Width;
542         windowParams.nHeight = m_mfxVideoParams.mfx.FrameInfo.Height;
543     }
544 
545     windowParams.ncell    = pParams->nWallCell;
546     windowParams.nAdapter = pParams->nWallMonitor;
547 
548     windowParams.lpClassName = MSDK_STRING("Render Window Class");
549     windowParams.dwStyle     = WS_OVERLAPPEDWINDOW;
550     windowParams.hWndParent  = NULL;
551     windowParams.hMenu       = NULL;
552     windowParams.hInstance   = GetModuleHandle(NULL);
553     windowParams.lpParam     = NULL;
554     windowParams.bFullScreen = FALSE;
555 
556     sts = m_d3dRender.Init(windowParams);
557     MSDK_CHECK_STATUS(sts, "m_d3dRender.Init failed");
558 
559     //setting videowall flag
560     m_bIsVideoWall = 0 != windowParams.nx;
561 
562 #endif
563     return sts;
564 }
565 
InitMfxParams(sInputParams * pParams)566 mfxStatus CDecodingPipeline::InitMfxParams(sInputParams* pParams) {
567     MSDK_CHECK_POINTER(m_pmfxDEC, MFX_ERR_NULL_PTR);
568     mfxStatus sts    = MFX_ERR_NONE;
569     mfxU32& numViews = pParams->numViews;
570 
571     if (pParams->bErrorReport) {
572         auto decErrorReport = m_mfxBS.AddExtBuffer<mfxExtDecodeErrorReport>();
573         MSDK_CHECK_POINTER(decErrorReport, MFX_ERR_MEMORY_ALLOC);
574     }
575 
576     if (m_mfxVideoParams.mfx.CodecId == MFX_CODEC_VP9)
577         m_mfxVideoParams.mfx.EnableReallocRequest = MFX_CODINGOPTION_ON;
578 
579     // try to find a sequence header in the stream
580     // if header is not found this function exits with error (e.g. if device was lost and there's no header in the remaining stream)
581     for (;;) {
582         // trying to find PicStruct information in AVI headers
583         if (m_mfxVideoParams.mfx.CodecId == MFX_CODEC_JPEG)
584             MJPEG_AVI_ParsePicStruct(&m_mfxBS);
585         if (pParams->bErrorReport) {
586             auto errorReport = m_mfxBS.GetExtBuffer<mfxExtDecodeErrorReport>();
587             MSDK_CHECK_POINTER(errorReport, MFX_ERR_NOT_INITIALIZED);
588 
589             errorReport->ErrorTypes = 0;
590 
591             // parse bit stream and fill mfx params
592             sts = m_pmfxDEC->DecodeHeader(&m_mfxBS, &m_mfxVideoParams);
593 
594             PrintDecodeErrorReport(errorReport);
595         }
596         else {
597             // parse bit stream and fill mfx params
598             sts = m_pmfxDEC->DecodeHeader(&m_mfxBS, &m_mfxVideoParams);
599         }
600 
601         if (!sts) {
602             m_bVppIsUsed = IsVppRequired(pParams);
603         }
604 
605         if (MFX_ERR_MORE_DATA == sts) {
606             if (m_mfxBS.MaxLength == m_mfxBS.DataLength) {
607                 m_mfxBS.Extend(m_mfxBS.MaxLength * 2);
608             }
609             // read a portion of data
610             totalBytesProcessed += m_mfxBS.DataOffset;
611             sts = m_FileReader->ReadNextFrame(&m_mfxBS);
612             MSDK_CHECK_STATUS(sts, "m_FileReader->ReadNextFrame failed");
613 
614             continue;
615         }
616         else {
617             // Enter MVC mode
618             if (m_bIsMVC) {
619                 // Check for attached external parameters - if we have them already,
620                 // we don't need to attach them again
621                 if (NULL != m_mfxVideoParams.ExtParam)
622                     break;
623 
624                 auto mvcSeqDesc = m_mfxVideoParams.AddExtBuffer<mfxExtMVCSeqDesc>();
625                 MSDK_CHECK_POINTER(mvcSeqDesc, MFX_ERR_MEMORY_ALLOC);
626 
627                 sts = m_pmfxDEC->DecodeHeader(&m_mfxBS, &m_mfxVideoParams);
628 
629                 if (MFX_ERR_NOT_ENOUGH_BUFFER == sts) {
630                     sts = AllocateExtMVCBuffers();
631 
632                     MSDK_CHECK_STATUS(sts, "AllocateExtMVCBuffers failed");
633                     MSDK_CHECK_POINTER(m_mfxVideoParams.ExtParam, MFX_ERR_MEMORY_ALLOC);
634                     continue;
635                 }
636             }
637 
638             // if input is interlaced JPEG stream
639             if (m_mfxBS.PicStruct == MFX_PICSTRUCT_FIELD_TFF ||
640                 m_mfxBS.PicStruct == MFX_PICSTRUCT_FIELD_BFF) {
641                 m_mfxVideoParams.mfx.FrameInfo.CropH *= 2;
642                 m_mfxVideoParams.mfx.FrameInfo.Height =
643                     MSDK_ALIGN16(m_mfxVideoParams.mfx.FrameInfo.CropH);
644                 m_mfxVideoParams.mfx.FrameInfo.PicStruct = m_mfxBS.PicStruct;
645             }
646 
647             switch (pParams->nRotation) {
648                 case 0:
649                     m_mfxVideoParams.mfx.Rotation = MFX_ROTATION_0;
650                     break;
651                 case 90:
652                     m_mfxVideoParams.mfx.Rotation = MFX_ROTATION_90;
653                     break;
654                 case 180:
655                     m_mfxVideoParams.mfx.Rotation = MFX_ROTATION_180;
656                     break;
657                 case 270:
658                     m_mfxVideoParams.mfx.Rotation = MFX_ROTATION_270;
659                     break;
660                 default:
661                     return MFX_ERR_UNSUPPORTED;
662             }
663 
664             break;
665         }
666     }
667 
668     // check DecodeHeader status
669     if (MFX_WRN_PARTIAL_ACCELERATION == sts) {
670         msdk_printf(MSDK_STRING("WARNING: partial acceleration\n"));
671         MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION);
672     }
673     MSDK_CHECK_STATUS(sts, "m_pmfxDEC->DecodeHeader failed");
674 
675     if (!m_mfxVideoParams.mfx.FrameInfo.FrameRateExtN ||
676         !m_mfxVideoParams.mfx.FrameInfo.FrameRateExtD) {
677         msdk_printf(MSDK_STRING("pretending that stream is 30fps one\n"));
678         m_mfxVideoParams.mfx.FrameInfo.FrameRateExtN = 30;
679         m_mfxVideoParams.mfx.FrameInfo.FrameRateExtD = 1;
680     }
681     if (!m_mfxVideoParams.mfx.FrameInfo.AspectRatioW ||
682         !m_mfxVideoParams.mfx.FrameInfo.AspectRatioH) {
683         msdk_printf(MSDK_STRING("pretending that aspect ratio is 1:1\n"));
684         m_mfxVideoParams.mfx.FrameInfo.AspectRatioW = 1;
685         m_mfxVideoParams.mfx.FrameInfo.AspectRatioH = 1;
686     }
687 
688     // Videoparams for RGB4 JPEG decoder output
689     if ((pParams->fourcc == MFX_FOURCC_RGB4) && (pParams->videoType == MFX_CODEC_JPEG)) {
690         m_mfxVideoParams.mfx.FrameInfo.FourCC       = MFX_FOURCC_RGB4;
691         m_mfxVideoParams.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV444;
692         if (pParams->chromaType == MFX_JPEG_COLORFORMAT_RGB) {
693             m_mfxVideoParams.mfx.JPEGColorFormat = pParams->chromaType;
694         }
695     }
696 
697     /* Lets make final decision how to use VPP...*/
698     if (!m_bVppIsUsed) {
699         if ((m_mfxVideoParams.mfx.FrameInfo.CropW != pParams->Width && pParams->Width) ||
700             (m_mfxVideoParams.mfx.FrameInfo.CropH != pParams->Height && pParams->Height) ||
701             (pParams->nDecoderPostProcessing && pParams->videoType == MFX_CODEC_AVC) ||
702             (pParams->nDecoderPostProcessing && pParams->videoType == MFX_CODEC_HEVC) ||
703             (pParams->nDecoderPostProcessing && pParams->videoType == MFX_CODEC_JPEG &&
704              pParams->fourcc == MFX_FOURCC_RGB4 &&
705              // No need to use decoder's post processing for decoding of JPEG with RGB 4:4:4
706              // to MFX_FOURCC_RGB4, because this decoding is done in one step
707              // In every other case, color conversion is requred, so try decoder's post processing.
708              !(m_mfxVideoParams.mfx.JPEGColorFormat == MFX_JPEG_COLORFORMAT_RGB &&
709                m_mfxVideoParams.mfx.FrameInfo.ChromaFormat == MFX_CHROMAFORMAT_YUV444))) {
710             /* By default VPP used for resize */
711             m_bVppIsUsed = true;
712             /* But... lets try to use decoder's post processing */
713             if (((MODE_DECODER_POSTPROC_AUTO == pParams->nDecoderPostProcessing) ||
714                  (MODE_DECODER_POSTPROC_FORCE == pParams->nDecoderPostProcessing)) &&
715                 (MFX_CODEC_AVC == m_mfxVideoParams.mfx.CodecId ||
716                  MFX_CODEC_JPEG == m_mfxVideoParams.mfx.CodecId ||
717                  MFX_CODEC_HEVC == m_mfxVideoParams.mfx.CodecId ||
718                  MFX_CODEC_VP9 == m_mfxVideoParams.mfx.CodecId ||
719                  MFX_CODEC_AV1 == m_mfxVideoParams.mfx.CodecId) &&
720                 (MFX_PICSTRUCT_PROGRESSIVE ==
721                  m_mfxVideoParams.mfx.FrameInfo.PicStruct)) /* ...And only for progressive!*/
722             { /* it is possible to use decoder's post-processing */
723 
724                 // JPEG only suppoted w/o resize, so use W/H from DecodeHeader(), if they are not set
725                 if (MFX_CODEC_JPEG == m_mfxVideoParams.mfx.CodecId &&
726                     (!pParams->Width || !pParams->Height)) {
727                     pParams->Width  = m_mfxVideoParams.mfx.FrameInfo.CropW;
728                     pParams->Height = m_mfxVideoParams.mfx.FrameInfo.CropH;
729                 }
730 
731                 m_bVppIsUsed           = false;
732                 auto decPostProcessing = m_mfxVideoParams.AddExtBuffer<mfxExtDecVideoProcessing>();
733                 MSDK_CHECK_POINTER(decPostProcessing, MFX_ERR_MEMORY_ALLOC);
734 
735                 decPostProcessing->In.CropX = 0;
736                 decPostProcessing->In.CropY = 0;
737                 decPostProcessing->In.CropW = m_mfxVideoParams.mfx.FrameInfo.CropW;
738                 decPostProcessing->In.CropH = m_mfxVideoParams.mfx.FrameInfo.CropH;
739 
740                 decPostProcessing->Out.FourCC       = m_mfxVideoParams.mfx.FrameInfo.FourCC;
741                 decPostProcessing->Out.ChromaFormat = m_mfxVideoParams.mfx.FrameInfo.ChromaFormat;
742 
743                 if (pParams->videoType == MFX_CODEC_AVC || pParams->videoType == MFX_CODEC_HEVC) {
744                     switch (pParams->fourcc) {
745                         case MFX_FOURCC_RGB4:
746                             decPostProcessing->Out.FourCC       = MFX_FOURCC_RGB4;
747                             decPostProcessing->Out.ChromaFormat = MFX_CHROMAFORMAT_YUV444;
748                             break;
749 
750                         case MFX_FOURCC_NV12:
751                             decPostProcessing->Out.FourCC       = MFX_FOURCC_NV12;
752                             decPostProcessing->Out.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
753                             break;
754 
755                         case MFX_FOURCC_P010:
756                             decPostProcessing->Out.FourCC       = MFX_FOURCC_P010;
757                             decPostProcessing->Out.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
758                             break;
759 
760                         case MFX_FOURCC_P016:
761                             decPostProcessing->Out.FourCC       = MFX_FOURCC_P016;
762                             decPostProcessing->Out.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
763                             break;
764 
765                         case MFX_FOURCC_YUY2:
766                             decPostProcessing->Out.FourCC       = MFX_FOURCC_YUY2;
767                             decPostProcessing->Out.ChromaFormat = MFX_CHROMAFORMAT_YUV422;
768                             break;
769 
770                         case MFX_FOURCC_Y210:
771                             decPostProcessing->Out.FourCC       = MFX_FOURCC_Y210;
772                             decPostProcessing->Out.ChromaFormat = MFX_CHROMAFORMAT_YUV422;
773                             break;
774 
775                         case MFX_FOURCC_Y216:
776                             decPostProcessing->Out.FourCC       = MFX_FOURCC_Y216;
777                             decPostProcessing->Out.ChromaFormat = MFX_CHROMAFORMAT_YUV422;
778                             break;
779 
780                         case MFX_FOURCC_AYUV:
781                             decPostProcessing->Out.FourCC       = MFX_FOURCC_AYUV;
782                             decPostProcessing->Out.ChromaFormat = MFX_CHROMAFORMAT_YUV444;
783                             break;
784 
785                         case MFX_FOURCC_Y410:
786                             decPostProcessing->Out.FourCC       = MFX_FOURCC_Y410;
787                             decPostProcessing->Out.ChromaFormat = MFX_CHROMAFORMAT_YUV444;
788                             break;
789 
790                         case MFX_FOURCC_Y416:
791                             decPostProcessing->Out.FourCC       = MFX_FOURCC_Y416;
792                             decPostProcessing->Out.ChromaFormat = MFX_CHROMAFORMAT_YUV444;
793                             break;
794 
795                         default:
796                             break;
797                     }
798                 }
799                 decPostProcessing->Out.Width  = MSDK_ALIGN16(pParams->Width);
800                 decPostProcessing->Out.Height = MSDK_ALIGN16(pParams->Height);
801                 decPostProcessing->Out.CropX  = 0;
802                 decPostProcessing->Out.CropY  = 0;
803                 decPostProcessing->Out.CropW  = pParams->Width;
804                 decPostProcessing->Out.CropH  = pParams->Height;
805 
806                 msdk_printf(MSDK_STRING("Decoder's post-processing is used for resizing\n"));
807             }
808             /* POSTPROC_FORCE */
809             if (MODE_DECODER_POSTPROC_FORCE == pParams->nDecoderPostProcessing && m_bVppIsUsed) {
810                 /* it is impossible to use decoder's post-processing */
811                 msdk_printf(MSDK_STRING(
812                     "ERROR: decoder postprocessing (-dec_postproc forced) cannot resize this stream!\n"));
813                 return MFX_ERR_UNSUPPORTED;
814             }
815             if ((m_bVppIsUsed) && (MODE_DECODER_POSTPROC_AUTO == pParams->nDecoderPostProcessing))
816                 msdk_printf(MSDK_STRING(
817                     "Decoder post-processing is unsupported for this stream, VPP is used\n"));
818         }
819     }
820 
821     // If MVC mode we need to detect number of views in stream
822     if (m_bIsMVC) {
823         auto sequenceBuffer = m_mfxVideoParams.GetExtBuffer<mfxExtMVCSeqDesc>();
824         MSDK_CHECK_POINTER(sequenceBuffer, MFX_ERR_INVALID_VIDEO_PARAM);
825 
826         mfxU32 i = 0;
827         numViews = 0;
828         for (i = 0; i < sequenceBuffer->NumView; ++i) {
829             /* Some MVC streams can contain different information about
830                number of views and view IDs, e.x. numVews = 2
831                and ViewId[0, 1] = 0, 2 instead of ViewId[0, 1] = 0, 1.
832                numViews should be equal (max(ViewId[i]) + 1)
833                to prevent crashes during output files writing */
834             if (sequenceBuffer->View[i].ViewId >= numViews)
835                 numViews = sequenceBuffer->View[i].ViewId + 1;
836         }
837     }
838     else {
839         numViews = 1;
840     }
841 
842     // specify memory type
843     if (!m_bVppIsUsed)
844         m_mfxVideoParams.IOPattern =
845             (mfxU16)(m_memType != SYSTEM_MEMORY ? MFX_IOPATTERN_OUT_VIDEO_MEMORY
846                                                 : MFX_IOPATTERN_OUT_SYSTEM_MEMORY);
847     else
848         m_mfxVideoParams.IOPattern = (mfxU16)(pParams->bUseHWLib ? MFX_IOPATTERN_OUT_VIDEO_MEMORY
849                                                                  : MFX_IOPATTERN_OUT_SYSTEM_MEMORY);
850 
851     m_mfxVideoParams.AsyncDepth = pParams->nAsyncDepth;
852 
853     if (m_mfxVideoParams.mfx.CodecId == MFX_CODEC_AV1)
854         m_mfxVideoParams.mfx.FilmGrain =
855             pParams->bDisableFilmGrain ? 0 : m_mfxVideoParams.mfx.FilmGrain;
856 
857     return MFX_ERR_NONE;
858 }
859 
InitVppFilters()860 mfxStatus CDecodingPipeline::InitVppFilters() {
861     auto vppExtParams = m_mfxVppVideoParams.AddExtBuffer<mfxExtVPPDoNotUse>();
862     MSDK_CHECK_POINTER(vppExtParams, MFX_ERR_MEMORY_ALLOC);
863 
864     vppExtParams->NumAlg = 4;
865 
866     /* In case of Reset() this code called twice!
867      * But required to have only one allocation to prevent memleaks
868      * Deallocation done in Close() */
869     if (NULL == vppExtParams->AlgList)
870         vppExtParams->AlgList = new mfxU32[vppExtParams->NumAlg];
871 
872     if (!vppExtParams->AlgList)
873         return MFX_ERR_NULL_PTR;
874 
875     vppExtParams->AlgList[0] = MFX_EXTBUFF_VPP_DENOISE; // turn off denoising (on by default)
876     vppExtParams->AlgList[1] =
877         MFX_EXTBUFF_VPP_SCENE_ANALYSIS; // turn off scene analysis (on by default)
878     vppExtParams->AlgList[2] =
879         MFX_EXTBUFF_VPP_DETAIL; // turn off detail enhancement (on by default)
880     vppExtParams->AlgList[3] =
881         MFX_EXTBUFF_VPP_PROCAMP; // turn off processing amplified (on by default)
882 
883     if (m_diMode) {
884         auto vppDi = m_mfxVppVideoParams.AddExtBuffer<mfxExtVPPDeinterlacing>();
885         MSDK_CHECK_POINTER(vppDi, MFX_ERR_MEMORY_ALLOC);
886 
887         vppDi->Mode = m_diMode;
888     }
889 
890     return MFX_ERR_NONE;
891 }
892 
InitVppParams()893 mfxStatus CDecodingPipeline::InitVppParams() {
894     m_mfxVppVideoParams.IOPattern =
895         (mfxU16)(m_bDecOutSysmem ? MFX_IOPATTERN_IN_SYSTEM_MEMORY : MFX_IOPATTERN_IN_VIDEO_MEMORY);
896 
897     m_mfxVppVideoParams.IOPattern |= (m_memType != SYSTEM_MEMORY) ? MFX_IOPATTERN_OUT_VIDEO_MEMORY
898                                                                   : MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
899 
900     MSDK_MEMCPY_VAR(m_mfxVppVideoParams.vpp.In,
901                     &m_mfxVideoParams.mfx.FrameInfo,
902                     sizeof(mfxFrameInfo));
903     MSDK_MEMCPY_VAR(m_mfxVppVideoParams.vpp.Out, &m_mfxVppVideoParams.vpp.In, sizeof(mfxFrameInfo));
904 
905     if (m_fourcc) {
906         m_mfxVppVideoParams.vpp.Out.FourCC = m_fourcc;
907     }
908 
909     if (m_vppOutWidth && m_vppOutHeight) {
910         m_mfxVppVideoParams.vpp.Out.CropW = m_vppOutWidth;
911         m_mfxVppVideoParams.vpp.Out.Width = MSDK_ALIGN16(m_vppOutWidth);
912         m_mfxVppVideoParams.vpp.Out.CropH = m_vppOutHeight;
913         m_mfxVppVideoParams.vpp.Out.Height =
914             (MFX_PICSTRUCT_PROGRESSIVE == m_mfxVppVideoParams.vpp.Out.PicStruct)
915                 ? MSDK_ALIGN16(m_vppOutHeight)
916                 : MSDK_ALIGN32(m_vppOutHeight);
917     }
918 
919     m_mfxVppVideoParams.AsyncDepth = m_mfxVideoParams.AsyncDepth;
920 
921     m_VppSurfaceExtParams.clear();
922     if (m_bVppFullColorRange) {
923         //Let MSDK figure out the transfer matrix to use
924         m_VppVideoSignalInfo.TransferMatrix = MFX_TRANSFERMATRIX_UNKNOWN;
925         m_VppVideoSignalInfo.NominalRange   = MFX_NOMINALRANGE_0_255;
926 
927         m_VppSurfaceExtParams.push_back((mfxExtBuffer*)&m_VppVideoSignalInfo);
928     }
929 
930     // P010 video surfaces should be shifted
931     if (m_memType != SYSTEM_MEMORY && (m_mfxVppVideoParams.vpp.Out.FourCC == MFX_FOURCC_P010 ||
932                                        m_mfxVppVideoParams.vpp.Out.FourCC == MFX_FOURCC_Y210 ||
933                                        m_mfxVppVideoParams.vpp.Out.FourCC == MFX_FOURCC_P016 ||
934                                        m_mfxVppVideoParams.vpp.Out.FourCC == MFX_FOURCC_Y216 ||
935                                        m_mfxVppVideoParams.vpp.Out.FourCC == MFX_FOURCC_Y416)) {
936         m_mfxVppVideoParams.vpp.Out.Shift = 1;
937     }
938 
939     return MFX_ERR_NONE;
940 }
941 
CreateHWDevice()942 mfxStatus CDecodingPipeline::CreateHWDevice() {
943 #if D3D_SURFACES_SUPPORT
944     mfxStatus sts = MFX_ERR_NONE;
945 
946     HWND window = NULL;
947     bool render = (m_eWorkMode == MODE_RENDERING);
948 
949     if (render) {
950         window = (D3D11_MEMORY == m_memType) ? NULL : m_d3dRender.GetWindowHandle();
951     }
952 
953     #if MFX_D3D11_SUPPORT
954     if (D3D11_MEMORY == m_memType)
955         m_hwdev = new CD3D11Device();
956     else
957     #endif // #if MFX_D3D11_SUPPORT
958         m_hwdev = new CD3D9Device();
959 
960     if (NULL == m_hwdev)
961         return MFX_ERR_MEMORY_ALLOC;
962 
963     sts = m_hwdev->Init(window,
964                         render ? (m_bIsMVC ? 2 : 1) : 0,
965                         MSDKAdapter::GetNumber(m_pLoader.get()));
966     MSDK_CHECK_STATUS(sts, "m_hwdev->Init failed");
967 
968     if (render)
969         m_d3dRender.SetHWDevice(m_hwdev);
970 #elif LIBVA_SUPPORT
971     mfxStatus sts = MFX_ERR_NONE;
972 
973     m_hwdev = CreateVAAPIDevice(m_strDevicePath, m_libvaBackend);
974 
975     if (NULL == m_hwdev) {
976         return MFX_ERR_MEMORY_ALLOC;
977     }
978 
979     sts = m_hwdev->Init(&m_monitorType,
980                         (m_eWorkMode == MODE_RENDERING) ? 1 : 0,
981                         MSDKAdapter::GetNumber(m_pLoader.get()));
982     MSDK_CHECK_STATUS(sts, "m_hwdev->Init failed");
983 
984     #if defined(LIBVA_WAYLAND_SUPPORT)
985     if (m_eWorkMode == MODE_RENDERING && m_libvaBackend == MFX_LIBVA_WAYLAND) {
986         CVAAPIDeviceWayland* w_dev = dynamic_cast<CVAAPIDeviceWayland*>(m_hwdev);
987         if (!w_dev) {
988             MSDK_CHECK_STATUS(MFX_ERR_DEVICE_FAILED, "Failed to reach Wayland VAAPI device");
989         }
990         Wayland* wld = w_dev->GetWaylandHandle();
991         if (!wld) {
992             MSDK_CHECK_STATUS(MFX_ERR_DEVICE_FAILED, "Failed to reach Wayland VAAPI device");
993         }
994 
995         wld->SetRenderWinPos(m_nRenderWinX, m_nRenderWinY);
996         wld->SetPerfMode(m_bPerfMode);
997     }
998     #endif //LIBVA_WAYLAND_SUPPORT
999 
1000 #endif
1001     return MFX_ERR_NONE;
1002 }
1003 
ResetDevice()1004 mfxStatus CDecodingPipeline::ResetDevice() {
1005     if (m_hwdev)
1006         return m_hwdev->Reset();
1007 
1008     return CreateHWDevice();
1009 }
1010 
AllocFrames()1011 mfxStatus CDecodingPipeline::AllocFrames() {
1012     MSDK_CHECK_POINTER(m_pmfxDEC, MFX_ERR_NULL_PTR);
1013 
1014     mfxStatus sts = MFX_ERR_NONE;
1015 
1016     mfxFrameAllocRequest Request;
1017     mfxFrameAllocRequest VppRequest[2];
1018 
1019     mfxU16 nSurfNum    = 0; // number of surfaces for decoder
1020     mfxU16 nVppSurfNum = 0; // number of surfaces for vpp
1021 
1022     nSurfNum = std::max(0, 4);
1023 
1024     MSDK_ZERO_MEMORY(Request);
1025 
1026     MSDK_ZERO_MEMORY(VppRequest[0]);
1027     MSDK_ZERO_MEMORY(VppRequest[1]);
1028 
1029     sts = m_pmfxDEC->Query(&m_mfxVideoParams, &m_mfxVideoParams);
1030     MSDK_IGNORE_MFX_STS(sts, MFX_WRN_INCOMPATIBLE_VIDEO_PARAM);
1031     MSDK_CHECK_STATUS(sts, "m_pmfxDEC->Query failed");
1032 
1033     // calculate number of surfaces required for decoder
1034     sts = m_pmfxDEC->QueryIOSurf(&m_mfxVideoParams, &Request);
1035     if (MFX_WRN_PARTIAL_ACCELERATION == sts) {
1036         msdk_printf(MSDK_STRING("WARNING: partial acceleration\n"));
1037         MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION);
1038         m_bDecOutSysmem = true;
1039     }
1040     MSDK_CHECK_STATUS(sts, "m_pmfxDEC->QueryIOSurf failed");
1041 
1042     if (m_eWorkMode == MODE_RENDERING) {
1043         // Add surfaces for rendering smoothness
1044         Request.NumFrameSuggested += m_nMaxFps / 3;
1045     }
1046 
1047     if (m_bVppIsUsed) {
1048         // respecify memory type between Decoder and VPP
1049         m_mfxVideoParams.IOPattern = (mfxU16)(m_bDecOutSysmem ? MFX_IOPATTERN_OUT_SYSTEM_MEMORY
1050                                                               : MFX_IOPATTERN_OUT_VIDEO_MEMORY);
1051 
1052         // recalculate number of surfaces required for decoder
1053         sts = m_pmfxDEC->QueryIOSurf(&m_mfxVideoParams, &Request);
1054         MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION);
1055         MSDK_CHECK_STATUS(sts, "m_pmfxDEC->QueryIOSurf failed");
1056 
1057         sts = InitVppParams();
1058         MSDK_CHECK_STATUS(sts, "InitVppParams failed");
1059 
1060         sts = m_pmfxVPP->Query(&m_mfxVppVideoParams, &m_mfxVppVideoParams);
1061         MSDK_IGNORE_MFX_STS(sts, MFX_WRN_INCOMPATIBLE_VIDEO_PARAM);
1062         MSDK_CHECK_STATUS(sts, "m_pmfxVPP->Query failed");
1063 
1064         // VppRequest[0] for input frames request, VppRequest[1] for output frames request
1065         sts = m_pmfxVPP->QueryIOSurf(&m_mfxVppVideoParams, VppRequest);
1066         if (MFX_WRN_PARTIAL_ACCELERATION == sts) {
1067             msdk_printf(MSDK_STRING("WARNING: partial acceleration\n"));
1068             MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION);
1069         }
1070         MSDK_CHECK_STATUS(sts, "m_pmfxVPP->QueryIOSurf failed");
1071 
1072         if ((VppRequest[0].NumFrameSuggested < m_mfxVppVideoParams.AsyncDepth) ||
1073             (VppRequest[1].NumFrameSuggested < m_mfxVppVideoParams.AsyncDepth))
1074             return MFX_ERR_MEMORY_ALLOC;
1075 
1076         // If surfaces are shared by 2 components, c1 and c2. NumSurf = c1_out + c2_in - AsyncDepth + 1
1077         // The number of surfaces shared by vpp input and decode output
1078         nSurfNum = Request.NumFrameSuggested + VppRequest[0].NumFrameSuggested -
1079                    m_mfxVideoParams.AsyncDepth + 1;
1080 
1081         // The number of surfaces for vpp output
1082         // Need to add one more surface in render mode if AsyncDepth == 1
1083         nVppSurfNum = VppRequest[1].NumFrameSuggested +
1084                       (m_eWorkMode == MODE_RENDERING ? m_mfxVideoParams.AsyncDepth == 1 : 0);
1085 
1086         // prepare allocation request
1087         Request.NumFrameSuggested = Request.NumFrameMin = nSurfNum;
1088 
1089         // surfaces are shared between vpp input and decode output
1090         Request.Type |=
1091             MFX_MEMTYPE_EXTERNAL_FRAME | MFX_MEMTYPE_FROM_DECODE | MFX_MEMTYPE_FROM_VPPIN;
1092     }
1093 
1094     if ((Request.NumFrameSuggested < m_mfxVideoParams.AsyncDepth) &&
1095         (m_impl & MFX_IMPL_HARDWARE_ANY))
1096         return MFX_ERR_MEMORY_ALLOC;
1097 
1098     Request.Type |=
1099         (m_bDecOutSysmem) ? MFX_MEMTYPE_SYSTEM_MEMORY : MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
1100 
1101 #ifdef LIBVA_SUPPORT
1102     if (!m_bVppIsUsed && (m_export_mode != vaapiAllocatorParams::DONOT_EXPORT)) {
1103         Request.Type |= MFX_MEMTYPE_EXPORT_FRAME;
1104     }
1105 #endif
1106 
1107     // alloc frames for decoder
1108     sts = m_pGeneralAllocator->Alloc(m_pGeneralAllocator->pthis, &Request, &m_mfxResponse);
1109     MSDK_CHECK_STATUS(sts, "m_pGeneralAllocator->Alloc failed");
1110 
1111     if (m_bVppIsUsed) {
1112         // alloc frames for VPP
1113 #ifdef LIBVA_SUPPORT
1114         if (m_export_mode != vaapiAllocatorParams::DONOT_EXPORT) {
1115             VppRequest[1].Type |= MFX_MEMTYPE_EXPORT_FRAME;
1116         }
1117 #endif
1118         VppRequest[1].NumFrameSuggested = VppRequest[1].NumFrameMin = nVppSurfNum;
1119         MSDK_MEMCPY_VAR(VppRequest[1].Info, &(m_mfxVppVideoParams.vpp.Out), sizeof(mfxFrameInfo));
1120 
1121         sts = m_pGeneralAllocator->Alloc(m_pGeneralAllocator->pthis,
1122                                          &VppRequest[1],
1123                                          &m_mfxVppResponse);
1124         MSDK_CHECK_STATUS(sts, "m_pGeneralAllocator->Alloc failed");
1125 
1126         // prepare mfxFrameSurface1 array for decoder
1127         nVppSurfNum = m_mfxVppResponse.NumFrameActual;
1128 
1129         // AllocVppBuffers should call before AllocBuffers to set the value of m_OutputSurfacesNumber
1130         sts = AllocVppBuffers(nVppSurfNum);
1131         MSDK_CHECK_STATUS(sts, "AllocVppBuffers failed");
1132     }
1133 
1134     // prepare mfxFrameSurface1 array for decoder
1135     nSurfNum = m_mfxResponse.NumFrameActual;
1136 
1137     sts = AllocBuffers(nSurfNum);
1138     MSDK_CHECK_STATUS(sts, "AllocBuffers failed");
1139 
1140     for (int i = 0; i < nSurfNum; i++) {
1141         // initating each frame:
1142         MSDK_MEMCPY_VAR(m_pSurfaces[i].frame.Info, &(Request.Info), sizeof(mfxFrameInfo));
1143         m_pSurfaces[i].frame.Data.MemType = Request.Type;
1144         if (m_bExternalAlloc) {
1145             m_pSurfaces[i].frame.Data.MemId = m_mfxResponse.mids[i];
1146             if (m_bVppFullColorRange) {
1147                 m_pSurfaces[i].frame.Data.ExtParam    = &m_VppSurfaceExtParams[0];
1148                 m_pSurfaces[i].frame.Data.NumExtParam = (mfxU16)m_VppSurfaceExtParams.size();
1149             }
1150         }
1151     }
1152 
1153     // prepare mfxFrameSurface1 array for VPP
1154     for (int i = 0; i < nVppSurfNum; i++) {
1155         MSDK_MEMCPY_VAR(m_pVppSurfaces[i].frame.Info, &(VppRequest[1].Info), sizeof(mfxFrameInfo));
1156         if (m_bExternalAlloc) {
1157             m_pVppSurfaces[i].frame.Data.MemId = m_mfxVppResponse.mids[i];
1158             if (m_bVppFullColorRange) {
1159                 m_pVppSurfaces[i].frame.Data.ExtParam    = &m_VppSurfaceExtParams[0];
1160                 m_pVppSurfaces[i].frame.Data.NumExtParam = (mfxU16)m_VppSurfaceExtParams.size();
1161             }
1162         }
1163     }
1164     return MFX_ERR_NONE;
1165 }
1166 
ReallocCurrentSurface(const mfxFrameInfo & info)1167 mfxStatus CDecodingPipeline::ReallocCurrentSurface(const mfxFrameInfo& info) {
1168     mfxStatus sts   = MFX_ERR_NONE;
1169     mfxMemId inMid  = nullptr;
1170     mfxMemId outMid = nullptr;
1171 
1172     if (!m_pGeneralAllocator)
1173         return MFX_ERR_MEMORY_ALLOC;
1174 
1175     m_pCurrentFreeSurface->frame.Info.CropW = info.CropW;
1176     m_pCurrentFreeSurface->frame.Info.CropH = info.CropH;
1177     m_mfxVideoParams.mfx.FrameInfo.Width =
1178         MSDK_ALIGN16(std::max(info.Width, m_mfxVideoParams.mfx.FrameInfo.Width));
1179     m_mfxVideoParams.mfx.FrameInfo.Height =
1180         MSDK_ALIGN16(std::max(info.Height, m_mfxVideoParams.mfx.FrameInfo.Height));
1181     m_pCurrentFreeSurface->frame.Info.Width  = m_mfxVideoParams.mfx.FrameInfo.Width;
1182     m_pCurrentFreeSurface->frame.Info.Height = m_mfxVideoParams.mfx.FrameInfo.Height;
1183 
1184     inMid = m_pCurrentFreeSurface->frame.Data.MemId;
1185 
1186     sts = m_pGeneralAllocator->ReallocFrame(inMid,
1187                                             &m_pCurrentFreeSurface->frame.Info,
1188                                             m_pCurrentFreeSurface->frame.Data.MemType,
1189                                             &outMid);
1190     if (MFX_ERR_NONE == sts)
1191         m_pCurrentFreeSurface->frame.Data.MemId = outMid;
1192 
1193     return sts;
1194 }
1195 
CreateAllocator()1196 mfxStatus CDecodingPipeline::CreateAllocator() {
1197     mfxStatus sts = MFX_ERR_NONE;
1198 
1199     m_pGeneralAllocator = new GeneralAllocator();
1200     if (m_memType != SYSTEM_MEMORY || !m_bDecOutSysmem) {
1201 #if D3D_SURFACES_SUPPORT
1202         mfxHDL hdl = NULL;
1203         mfxHandleType hdl_t =
1204     #if MFX_D3D11_SUPPORT
1205             D3D11_MEMORY == m_memType ? MFX_HANDLE_D3D11_DEVICE :
1206     #endif // #if MFX_D3D11_SUPPORT
1207                                       MFX_HANDLE_D3D9_DEVICE_MANAGER;
1208 
1209         sts = m_hwdev->GetHandle(hdl_t, &hdl);
1210         MSDK_CHECK_STATUS(sts, "m_hwdev->GetHandle failed");
1211 
1212         // create D3D allocator
1213     #if MFX_D3D11_SUPPORT
1214         if (D3D11_MEMORY == m_memType) {
1215             D3D11AllocatorParams* pd3dAllocParams = new D3D11AllocatorParams;
1216             MSDK_CHECK_POINTER(pd3dAllocParams, MFX_ERR_MEMORY_ALLOC);
1217             pd3dAllocParams->pDevice = reinterpret_cast<ID3D11Device*>(hdl);
1218 
1219             m_pmfxAllocatorParams = pd3dAllocParams;
1220         }
1221         else
1222     #endif // #if MFX_D3D11_SUPPORT
1223         {
1224             D3DAllocatorParams* pd3dAllocParams = new D3DAllocatorParams;
1225             MSDK_CHECK_POINTER(pd3dAllocParams, MFX_ERR_MEMORY_ALLOC);
1226             pd3dAllocParams->pManager = reinterpret_cast<IDirect3DDeviceManager9*>(hdl);
1227 
1228             m_pmfxAllocatorParams = pd3dAllocParams;
1229         }
1230 
1231         /* In case of video memory we must provide MediaSDK with external allocator
1232         thus we demonstrate "external allocator" usage model.
1233         Call SetAllocator to pass allocator to mediasdk */
1234         sts = m_mfxSession.SetFrameAllocator(m_pGeneralAllocator);
1235         MSDK_CHECK_STATUS(sts, "m_mfxSession.SetFrameAllocator failed");
1236 
1237         m_bExternalAlloc = true;
1238 #elif LIBVA_SUPPORT
1239         VADisplay va_dpy = NULL;
1240         sts              = m_hwdev->GetHandle(MFX_HANDLE_VA_DISPLAY, (mfxHDL*)&va_dpy);
1241         MSDK_CHECK_STATUS(sts, "m_hwdev->GetHandle failed");
1242 
1243         vaapiAllocatorParams* p_vaapiAllocParams = new vaapiAllocatorParams;
1244         MSDK_CHECK_POINTER(p_vaapiAllocParams, MFX_ERR_MEMORY_ALLOC);
1245 
1246         p_vaapiAllocParams->m_dpy = va_dpy;
1247         if (m_eWorkMode == MODE_RENDERING) {
1248             if (m_libvaBackend == MFX_LIBVA_DRM_MODESET) {
1249     #if defined(LIBVA_DRM_SUPPORT)
1250                 CVAAPIDeviceDRM* drmdev           = dynamic_cast<CVAAPIDeviceDRM*>(m_hwdev);
1251                 p_vaapiAllocParams->m_export_mode = vaapiAllocatorParams::CUSTOM_FLINK;
1252                 p_vaapiAllocParams->m_exporter =
1253                     dynamic_cast<vaapiAllocatorParams::Exporter*>(drmdev->getRenderer());
1254     #endif
1255             }
1256             else if (m_libvaBackend == MFX_LIBVA_WAYLAND || m_libvaBackend == MFX_LIBVA_X11) {
1257                 p_vaapiAllocParams->m_export_mode = vaapiAllocatorParams::PRIME;
1258             }
1259         }
1260         m_export_mode         = p_vaapiAllocParams->m_export_mode;
1261         m_pmfxAllocatorParams = p_vaapiAllocParams;
1262 
1263         /* In case of video memory we must provide MediaSDK with external allocator
1264         thus we demonstrate "external allocator" usage model.
1265         Call SetAllocator to pass allocator to mediasdk */
1266         sts = m_mfxSession.SetFrameAllocator(m_pGeneralAllocator);
1267         MSDK_CHECK_STATUS(sts, "m_mfxSession.SetFrameAllocator failed");
1268 
1269         m_bExternalAlloc = true;
1270 #endif
1271     }
1272     else {
1273         sts = m_mfxSession.SetFrameAllocator(m_pGeneralAllocator);
1274         MSDK_CHECK_STATUS(sts, "m_mfxSession.SetFrameAllocator failed");
1275         m_bExternalAlloc = true;
1276     }
1277 
1278     // initialize memory allocator
1279     sts = m_pGeneralAllocator->Init(m_pmfxAllocatorParams);
1280     MSDK_CHECK_STATUS(sts, "m_pGeneralAllocator->Init failed");
1281 
1282     return MFX_ERR_NONE;
1283 }
1284 
DeleteFrames()1285 void CDecodingPipeline::DeleteFrames() {
1286     FreeBuffers();
1287 
1288     m_pCurrentFreeSurface = NULL;
1289     MSDK_SAFE_FREE(m_pCurrentFreeOutputSurface);
1290 
1291     m_pCurrentFreeVppSurface = NULL;
1292 
1293     // delete frames
1294     if (m_pGeneralAllocator) {
1295         m_pGeneralAllocator->Free(m_pGeneralAllocator->pthis, &m_mfxResponse);
1296     }
1297 
1298     return;
1299 }
1300 
DeleteAllocator()1301 void CDecodingPipeline::DeleteAllocator() {
1302     // delete allocator
1303     MSDK_SAFE_DELETE(m_pGeneralAllocator);
1304     MSDK_SAFE_DELETE(m_pmfxAllocatorParams);
1305     MSDK_SAFE_DELETE(m_hwdev);
1306 }
1307 
SetMultiView()1308 void CDecodingPipeline::SetMultiView() {
1309     m_FileWriter.SetMultiView();
1310     m_bIsMVC = true;
1311 }
1312 
AllocateExtMVCBuffers()1313 mfxStatus CDecodingPipeline::AllocateExtMVCBuffers() {
1314     mfxU32 i;
1315 
1316     auto mvcBuffer = m_mfxVideoParams.GetExtBuffer<mfxExtMVCSeqDesc>();
1317     MSDK_CHECK_POINTER(mvcBuffer, MFX_ERR_MEMORY_ALLOC);
1318 
1319     mvcBuffer->View = new mfxMVCViewDependency[mvcBuffer->NumView];
1320     MSDK_CHECK_POINTER(mvcBuffer->View, MFX_ERR_MEMORY_ALLOC);
1321     for (i = 0; i < mvcBuffer->NumView; ++i) {
1322         MSDK_ZERO_MEMORY(mvcBuffer->View[i]);
1323     }
1324     mvcBuffer->NumViewAlloc = mvcBuffer->NumView;
1325 
1326     mvcBuffer->ViewId = new mfxU16[mvcBuffer->NumViewId];
1327     MSDK_CHECK_POINTER(mvcBuffer->ViewId, MFX_ERR_MEMORY_ALLOC);
1328     for (i = 0; i < mvcBuffer->NumViewId; ++i) {
1329         MSDK_ZERO_MEMORY(mvcBuffer->ViewId[i]);
1330     }
1331     mvcBuffer->NumViewIdAlloc = mvcBuffer->NumViewId;
1332 
1333     mvcBuffer->OP = new mfxMVCOperationPoint[mvcBuffer->NumOP];
1334     MSDK_CHECK_POINTER(mvcBuffer->OP, MFX_ERR_MEMORY_ALLOC);
1335     for (i = 0; i < mvcBuffer->NumOP; ++i) {
1336         MSDK_ZERO_MEMORY(mvcBuffer->OP[i]);
1337     }
1338     mvcBuffer->NumOPAlloc = mvcBuffer->NumOP;
1339 
1340     return MFX_ERR_NONE;
1341 }
1342 
DeallocateExtMVCBuffers()1343 void CDecodingPipeline::DeallocateExtMVCBuffers() {
1344     auto mvcBuffer = m_mfxVideoParams.GetExtBuffer<mfxExtMVCSeqDesc>();
1345     if (mvcBuffer) {
1346         MSDK_SAFE_DELETE_ARRAY(mvcBuffer->View);
1347         MSDK_SAFE_DELETE_ARRAY(mvcBuffer->ViewId);
1348         MSDK_SAFE_DELETE_ARRAY(mvcBuffer->OP);
1349     }
1350 }
1351 
ResetDecoder(sInputParams * pParams)1352 mfxStatus CDecodingPipeline::ResetDecoder(sInputParams* pParams) {
1353     mfxStatus sts = MFX_ERR_NONE;
1354 
1355     // close decoder
1356     sts = m_pmfxDEC->Close();
1357     MSDK_IGNORE_MFX_STS(sts, MFX_ERR_NOT_INITIALIZED);
1358     MSDK_CHECK_STATUS(sts, "m_pmfxDEC->Close failed");
1359 
1360     // close VPP
1361     if (m_pmfxVPP) {
1362         sts = m_pmfxVPP->Close();
1363         MSDK_IGNORE_MFX_STS(sts, MFX_ERR_NOT_INITIALIZED);
1364         MSDK_CHECK_STATUS(sts, "m_pmfxVPP->Close failed");
1365     }
1366 
1367     // free allocated frames
1368     DeleteFrames();
1369 
1370     // initialize parameters with values from parsed header
1371     sts = InitMfxParams(pParams);
1372     MSDK_CHECK_STATUS(sts, "InitMfxParams failed");
1373 
1374     // in case of HW accelerated decode frames must be allocated prior to decoder initialization
1375     sts = AllocFrames();
1376     MSDK_CHECK_STATUS(sts, "AllocFrames failed");
1377 
1378     // init decoder
1379     sts = m_pmfxDEC->Init(&m_mfxVideoParams);
1380     if (MFX_WRN_PARTIAL_ACCELERATION == sts) {
1381         msdk_printf(MSDK_STRING("WARNING: partial acceleration\n"));
1382         MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION);
1383     }
1384     MSDK_CHECK_STATUS(sts, "m_pmfxDEC->Init failed");
1385 
1386     if (m_pmfxVPP) {
1387         if (m_diMode)
1388             m_mfxVppVideoParams.vpp.Out.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
1389 
1390         if (pParams->ScalingMode) {
1391             auto par         = m_mfxVppVideoParams.AddExtBuffer<mfxExtVPPScaling>();
1392             par->ScalingMode = pParams->ScalingMode;
1393         }
1394 
1395         sts = m_pmfxVPP->Init(&m_mfxVppVideoParams);
1396         if (MFX_WRN_PARTIAL_ACCELERATION == sts) {
1397             msdk_printf(MSDK_STRING("WARNING: partial acceleration\n"));
1398             MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION);
1399         }
1400         MSDK_CHECK_STATUS(sts, "m_pmfxVPP->Init failed");
1401     }
1402 
1403     return MFX_ERR_NONE;
1404 }
1405 
DeliverOutput(mfxFrameSurface1 * frame)1406 mfxStatus CDecodingPipeline::DeliverOutput(mfxFrameSurface1* frame) {
1407     CAutoTimer timer_fwrite(m_tick_fwrite);
1408 
1409     mfxStatus res = MFX_ERR_NONE, sts = MFX_ERR_NONE;
1410 
1411     if (!frame) {
1412         return MFX_ERR_NULL_PTR;
1413     }
1414 
1415     if (m_bResetFileWriter) {
1416         sts = m_FileWriter.Reset();
1417         MSDK_CHECK_STATUS(sts, "");
1418         m_bResetFileWriter = false;
1419     }
1420 
1421     if (m_bExternalAlloc) {
1422         if (m_eWorkMode == MODE_FILE_DUMP) {
1423             res = m_pGeneralAllocator->Lock(m_pGeneralAllocator->pthis,
1424                                             frame->Data.MemId,
1425                                             &(frame->Data));
1426             if (MFX_ERR_NONE == res) {
1427                 res = m_bOutI420 ? m_FileWriter.WriteNextFrameI420(frame)
1428                                  : m_FileWriter.WriteNextFrame(frame);
1429                 sts = m_pGeneralAllocator->Unlock(m_pGeneralAllocator->pthis,
1430                                                   frame->Data.MemId,
1431                                                   &(frame->Data));
1432             }
1433             if ((MFX_ERR_NONE == res) && (MFX_ERR_NONE != sts)) {
1434                 res = sts;
1435             }
1436         }
1437         else if (m_eWorkMode == MODE_RENDERING) {
1438 #if D3D_SURFACES_SUPPORT
1439             res = m_d3dRender.RenderFrame(frame, m_pGeneralAllocator);
1440 #elif LIBVA_SUPPORT
1441             res = m_hwdev->RenderFrame(frame, m_pGeneralAllocator);
1442 #endif
1443         }
1444     }
1445     else {
1446         res = m_bOutI420 ? m_FileWriter.WriteNextFrameI420(frame)
1447                          : m_FileWriter.WriteNextFrame(frame);
1448     }
1449 
1450     m_fpsLimiter.Work();
1451 
1452     return res;
1453 }
1454 
DeliverLoop(void)1455 void CDecodingPipeline::DeliverLoop(void) {
1456     while (!m_bStopDeliverLoop) {
1457         m_pDeliverOutputSemaphore->Wait();
1458         if (m_bStopDeliverLoop) {
1459             continue;
1460         }
1461         if (MFX_ERR_NONE != m_error) {
1462             continue;
1463         }
1464         msdkOutputSurface* pCurrentDeliveredSurface = m_DeliveredSurfacesPool.GetSurface();
1465         if (!pCurrentDeliveredSurface) {
1466             m_error = MFX_ERR_NULL_PTR;
1467             continue;
1468         }
1469         mfxFrameSurface1* frame = &(pCurrentDeliveredSurface->surface->frame);
1470 
1471         m_error = DeliverOutput(frame);
1472         ReturnSurfaceToBuffers(pCurrentDeliveredSurface);
1473 
1474         pCurrentDeliveredSurface = NULL;
1475         msdk_atomic_inc32(&m_output_count);
1476         m_pDeliveredEvent->Signal();
1477     }
1478     return;
1479 }
1480 
PrintPerFrameStat(bool force)1481 void CDecodingPipeline::PrintPerFrameStat(bool force) {
1482 #define MY_COUNT     1 // TODO: this will be cmd option
1483 #define MY_THRESHOLD 10000.0
1484     if ((!(m_output_count % MY_COUNT) && (m_eWorkMode != MODE_PERFORMANCE)) || force) {
1485         double fps, fps_fread, fps_fwrite;
1486 
1487         m_timer_overall.Sync();
1488 
1489         fps = (m_tick_overall) ? m_output_count / CTimer::ConvertToSeconds(m_tick_overall) : 0.0;
1490         fps_fread = (m_tick_fread) ? m_output_count / CTimer::ConvertToSeconds(m_tick_fread) : 0.0;
1491         fps_fwrite =
1492             (m_tick_fwrite) ? m_output_count / CTimer::ConvertToSeconds(m_tick_fwrite) : 0.0;
1493         // decoding progress
1494         msdk_printf(
1495             MSDK_STRING("Frame number: %4d, fps: %0.3f, fread_fps: %0.3f, fwrite_fps: %.3f\r"),
1496             (int)m_output_count,
1497             fps,
1498             (fps_fread < MY_THRESHOLD) ? fps_fread : 0.0,
1499             (fps_fwrite < MY_THRESHOLD) ? fps_fwrite : 0.0);
1500         fflush(NULL);
1501 #if D3D_SURFACES_SUPPORT
1502         m_d3dRender.UpdateTitle(fps);
1503 #elif LIBVA_SUPPORT
1504         if (m_hwdev)
1505             m_hwdev->UpdateTitle(fps);
1506 #endif
1507     }
1508 }
1509 
SyncOutputSurface(mfxU32 wait)1510 mfxStatus CDecodingPipeline::SyncOutputSurface(mfxU32 wait) {
1511     if (!m_pCurrentOutputSurface) {
1512         m_pCurrentOutputSurface = m_OutputSurfacesPool.GetSurface();
1513     }
1514     if (!m_pCurrentOutputSurface) {
1515         return MFX_ERR_MORE_DATA;
1516     }
1517 
1518     mfxStatus sts = m_mfxSession.SyncOperation(m_pCurrentOutputSurface->syncp, wait);
1519 
1520     if (MFX_ERR_GPU_HANG == sts && m_bSoftRobustFlag) {
1521         msdk_printf(MSDK_STRING("GPU hang happened\n"));
1522         // Output surface can be corrupted
1523         // But should be delivered to output anyway
1524         sts = MFX_ERR_NONE;
1525     }
1526 
1527     if (MFX_WRN_IN_EXECUTION == sts) {
1528         return sts;
1529     }
1530     if (MFX_ERR_NONE == sts) {
1531         // we got completely decoded frame - pushing it to the delivering thread...
1532         ++m_synced_count;
1533         if (m_bPrintLatency) {
1534             m_vLatency.push_back(m_timer_overall.Sync() - m_pCurrentOutputSurface->surface->submit);
1535         }
1536         else {
1537             PrintPerFrameStat();
1538         }
1539 
1540         if (m_eWorkMode == MODE_PERFORMANCE) {
1541             m_output_count = m_synced_count;
1542             m_fpsLimiter.Work();
1543             ReturnSurfaceToBuffers(m_pCurrentOutputSurface);
1544         }
1545         else if (m_eWorkMode == MODE_FILE_DUMP) {
1546             sts = DeliverOutput(&(m_pCurrentOutputSurface->surface->frame));
1547             if (MFX_ERR_NONE != sts) {
1548                 sts = MFX_ERR_UNKNOWN;
1549             }
1550             else {
1551                 m_output_count = m_synced_count;
1552             }
1553             ReturnSurfaceToBuffers(m_pCurrentOutputSurface);
1554         }
1555         else if (m_eWorkMode == MODE_RENDERING) {
1556             m_DeliveredSurfacesPool.AddSurface(m_pCurrentOutputSurface);
1557             m_pDeliveredEvent->Reset();
1558             m_pDeliverOutputSemaphore->Post();
1559         }
1560         m_pCurrentOutputSurface = NULL;
1561     }
1562 
1563     return sts;
1564 }
1565 
RunDecoding()1566 mfxStatus CDecodingPipeline::RunDecoding() {
1567     mfxFrameSurface1* pOutSurface    = NULL;
1568     mfxBitstream* pBitstream         = &m_mfxBS;
1569     mfxStatus sts                    = MFX_ERR_NONE;
1570     bool bErrIncompatibleVideoParams = false;
1571     CTimeInterval<> decodeTimer(m_bIsCompleteFrame);
1572     time_t start_time = time(0);
1573     std::thread deliverThread;
1574 
1575     if (m_eWorkMode == MODE_RENDERING) {
1576         m_pDeliverOutputSemaphore = new MSDKSemaphore(sts);
1577         m_pDeliveredEvent         = new MSDKEvent(sts, false, false);
1578 
1579         deliverThread = std::thread(&CDecodingPipeline::DeliverLoop, this);
1580     }
1581 
1582     while (((sts == MFX_ERR_NONE) || (MFX_ERR_MORE_DATA == sts) || (MFX_ERR_MORE_SURFACE == sts)) &&
1583            (m_nFrames > m_output_count)) {
1584         if (MFX_ERR_NONE != m_error) {
1585             msdk_printf(MSDK_STRING("DeliverOutput return error = %d\n"), (int)m_error);
1586             break;
1587         }
1588 
1589         if (pBitstream &&
1590             ((MFX_ERR_MORE_DATA == sts) || (m_bIsCompleteFrame && !pBitstream->DataLength))) {
1591             CAutoTimer timer_fread(m_tick_fread);
1592             sts = m_FileReader->ReadNextFrame(pBitstream); // read more data to input bit stream
1593 
1594             if (MFX_ERR_MORE_DATA == sts) {
1595                 sts = MFX_ERR_NONE;
1596                 // Timeout has expired or videowall mode
1597                 m_timer_overall.Sync();
1598                 if (((CTimer::ConvertToSeconds(m_tick_overall) < m_nTimeout) && m_nTimeout) ||
1599                     m_bIsVideoWall) {
1600                     m_FileReader->Reset();
1601                     m_bResetFileWriter = true;
1602 
1603                     // Reset bitstream state
1604                     pBitstream->DataFlag = 0;
1605 
1606                     continue;
1607                 }
1608 
1609                 // we almost reached end of stream, need to pull buffered data now
1610                 pBitstream = NULL;
1611             }
1612         }
1613 
1614         if ((MFX_ERR_NONE == sts) || (MFX_ERR_MORE_DATA == sts) || (MFX_ERR_MORE_SURFACE == sts)) {
1615             // here we check whether output is ready, though we do not wait...
1616 #ifndef __SYNC_WA
1617             mfxStatus _sts = SyncOutputSurface(0);
1618             if (MFX_ERR_UNKNOWN == _sts) {
1619                 sts = _sts;
1620                 break;
1621             }
1622             else if (MFX_ERR_NONE == _sts) {
1623                 continue;
1624             }
1625 #endif
1626         }
1627         else {
1628             MSDK_CHECK_STATUS_NO_RET(sts, "ReadNextFrame failed");
1629         }
1630 
1631         if ((MFX_ERR_NONE == sts) || (MFX_ERR_MORE_DATA == sts) || (MFX_ERR_MORE_SURFACE == sts)) {
1632             SyncFrameSurfaces();
1633             SyncVppFrameSurfaces();
1634             if (!m_pCurrentFreeSurface) {
1635                 m_pCurrentFreeSurface = m_FreeSurfacesPool.GetSurface();
1636             }
1637             if (!m_pCurrentFreeVppSurface) {
1638                 m_pCurrentFreeVppSurface = m_FreeVppSurfacesPool.GetSurface();
1639             }
1640 #ifndef __SYNC_WA
1641             if (!m_pCurrentFreeSurface || !m_pCurrentFreeVppSurface) {
1642 #else
1643             if (!m_pCurrentFreeSurface || (!m_pCurrentFreeVppSurface && m_bVppIsUsed) ||
1644                 (m_OutputSurfacesPool.GetSurfaceCount() == m_mfxVideoParams.AsyncDepth)) {
1645 #endif
1646                 // we stuck with no free surface available, now we will sync...
1647                 sts = SyncOutputSurface(MSDK_DEC_WAIT_INTERVAL);
1648                 if (MFX_ERR_MORE_DATA == sts) {
1649                     if ((m_eWorkMode == MODE_PERFORMANCE) || (m_eWorkMode == MODE_FILE_DUMP)) {
1650                         sts = MFX_ERR_NOT_FOUND;
1651                     }
1652                     else if (m_eWorkMode == MODE_RENDERING) {
1653                         if (m_synced_count != m_output_count) {
1654                             sts = m_pDeliveredEvent->TimedWait(MSDK_DEC_WAIT_INTERVAL);
1655                         }
1656                         else {
1657                             sts = MFX_ERR_NOT_FOUND;
1658                         }
1659                     }
1660                     if (MFX_ERR_NOT_FOUND == sts) {
1661                         msdk_printf(
1662                             MSDK_STRING("fatal: failed to find output surface, that's a bug!\n"));
1663                         break;
1664                     }
1665                 }
1666                 MSDK_CHECK_ERR_NONE_STATUS_NO_RET(sts, "SyncOperation fail or timeout");
1667                 // note: MFX_WRN_IN_EXECUTION will also be treated as an error at this point
1668                 continue;
1669             }
1670 
1671             if (!m_pCurrentFreeOutputSurface) {
1672                 m_pCurrentFreeOutputSurface = GetFreeOutputSurface();
1673             }
1674             if (!m_pCurrentFreeOutputSurface) {
1675                 sts = MFX_ERR_NOT_FOUND;
1676                 break;
1677             }
1678         }
1679 
1680         // exit by timeout
1681         if ((MFX_ERR_NONE == sts) && m_bIsVideoWall && (time(0) - start_time) >= m_nTimeout) {
1682             sts = MFX_ERR_NONE;
1683             break;
1684         }
1685 
1686         if ((MFX_ERR_NONE == sts) || (MFX_ERR_MORE_DATA == sts) || (MFX_ERR_MORE_SURFACE == sts)) {
1687             if (m_bIsCompleteFrame) {
1688                 m_pCurrentFreeSurface->submit = m_timer_overall.Sync();
1689             }
1690             pOutSurface = NULL;
1691             do {
1692                 mfxExtDecodeErrorReport* errorReport = nullptr;
1693                 if (pBitstream) {
1694                     errorReport =
1695                         (mfxExtDecodeErrorReport*)GetExtBuffer(pBitstream->ExtParam,
1696                                                                pBitstream->NumExtParam,
1697                                                                MFX_EXTBUFF_DECODE_ERROR_REPORT);
1698                 }
1699                 sts = m_pmfxDEC->DecodeFrameAsync(pBitstream,
1700                                                   &(m_pCurrentFreeSurface->frame),
1701                                                   &pOutSurface,
1702                                                   &(m_pCurrentFreeOutputSurface->syncp));
1703 
1704                 PrintDecodeErrorReport(errorReport);
1705 
1706                 if (pBitstream && MFX_ERR_MORE_DATA == sts &&
1707                     pBitstream->MaxLength == pBitstream->DataLength) {
1708                     m_mfxBS.Extend(pBitstream->MaxLength * 2);
1709                 }
1710 
1711                 if (MFX_WRN_DEVICE_BUSY == sts) {
1712                     if (m_bIsCompleteFrame) {
1713                         //in low latency mode device busy leads to increasing of latency
1714                         //msdk_printf(MSDK_STRING("Warning : latency increased due to MFX_WRN_DEVICE_BUSY\n"));
1715                     }
1716                     mfxStatus _sts = SyncOutputSurface(MSDK_DEC_WAIT_INTERVAL);
1717                     // note: everything except MFX_ERR_NONE are errors at this point
1718                     if (MFX_ERR_NONE == _sts) {
1719                         sts = MFX_WRN_DEVICE_BUSY;
1720                     }
1721                     else {
1722                         sts = _sts;
1723                         if (MFX_ERR_MORE_DATA == sts) {
1724                             // we can't receive MFX_ERR_MORE_DATA and have no output - that's a bug
1725                             sts = MFX_WRN_DEVICE_BUSY; //MFX_ERR_NOT_FOUND;
1726                         }
1727                     }
1728                 }
1729             } while (MFX_WRN_DEVICE_BUSY == sts);
1730 
1731             if (sts > MFX_ERR_NONE) {
1732                 // ignoring warnings...
1733                 if (m_pCurrentFreeOutputSurface->syncp) {
1734                     MSDK_SELF_CHECK(pOutSurface);
1735                     // output is available
1736                     sts = MFX_ERR_NONE;
1737                 }
1738                 else {
1739                     // output is not available
1740                     sts = MFX_ERR_MORE_SURFACE;
1741                 }
1742             }
1743             else if ((MFX_ERR_MORE_DATA == sts) && pBitstream) {
1744                 if (m_bIsCompleteFrame && pBitstream->DataLength) {
1745                     // In low_latency mode decoder have to process bitstream completely
1746                     msdk_printf(MSDK_STRING(
1747                         "error: Incorrect decoder behavior in low latency mode (bitstream length is not equal to 0 after decoding)\n"));
1748                     sts = MFX_ERR_UNDEFINED_BEHAVIOR;
1749                     continue;
1750                 }
1751             }
1752             else if ((MFX_ERR_MORE_DATA == sts) && !pBitstream) {
1753                 // that's it - we reached end of stream; now we need to render bufferred data...
1754                 do {
1755                     sts = SyncOutputSurface(MSDK_DEC_WAIT_INTERVAL);
1756                 } while (MFX_ERR_NONE == sts);
1757 
1758                 MSDK_IGNORE_MFX_STS(sts, MFX_ERR_MORE_DATA);
1759                 if (sts)
1760                     MSDK_PRINT_WRN_MSG(sts, "SyncOutputSurface failed")
1761 
1762                 while (m_synced_count != m_output_count) {
1763                     m_pDeliveredEvent->Wait();
1764                 }
1765                 break;
1766             }
1767             else if (MFX_ERR_INCOMPATIBLE_VIDEO_PARAM == sts) {
1768                 bErrIncompatibleVideoParams = true;
1769                 // need to go to the buffering loop prior to reset procedure
1770                 pBitstream = NULL;
1771                 sts        = MFX_ERR_NONE;
1772                 continue;
1773             }
1774             else if (MFX_ERR_REALLOC_SURFACE == sts) {
1775                 mfxVideoParam param{};
1776                 sts = m_pmfxDEC->GetVideoParam(&param);
1777                 if (MFX_ERR_NONE != sts) {
1778                     // need to go to the buffering loop prior to reset procedure
1779                     pBitstream = NULL;
1780                     sts        = MFX_ERR_NONE;
1781                     continue;
1782                 }
1783 
1784                 sts = ReallocCurrentSurface(param.mfx.FrameInfo);
1785                 if (MFX_ERR_NONE != sts) {
1786                     // need to go to the buffering loop prior to reset procedure
1787                     pBitstream = NULL;
1788                     sts        = MFX_ERR_NONE;
1789                 }
1790                 continue;
1791             }
1792         }
1793 
1794         if ((MFX_ERR_NONE == sts) || (MFX_ERR_MORE_DATA == sts) || (MFX_ERR_MORE_SURFACE == sts)) {
1795             // if current free surface is locked we are moving it to the used surfaces array
1796             /*if (m_pCurrentFreeSurface->frame.Data.Locked)*/ {
1797                 m_UsedSurfacesPool.AddSurface(m_pCurrentFreeSurface);
1798                 m_pCurrentFreeSurface = NULL;
1799             }
1800         }
1801         else {
1802             MSDK_CHECK_STATUS_NO_RET(sts, "DecodeFrameAsync returned error status");
1803         }
1804 
1805         if (MFX_ERR_NONE == sts) {
1806             if (m_bVppIsUsed) {
1807                 if (m_pCurrentFreeVppSurface) {
1808                     do {
1809                         if ((m_pCurrentFreeVppSurface->frame.Info.CropW == 0) ||
1810                             (m_pCurrentFreeVppSurface->frame.Info.CropH == 0)) {
1811                             m_pCurrentFreeVppSurface->frame.Info.CropW = pOutSurface->Info.CropW;
1812                             m_pCurrentFreeVppSurface->frame.Info.CropH = pOutSurface->Info.CropH;
1813                             m_pCurrentFreeVppSurface->frame.Info.CropX = pOutSurface->Info.CropX;
1814                             m_pCurrentFreeVppSurface->frame.Info.CropY = pOutSurface->Info.CropY;
1815                         }
1816                         if (pOutSurface->Info.PicStruct !=
1817                             m_pCurrentFreeVppSurface->frame.Info.PicStruct) {
1818                             m_pCurrentFreeVppSurface->frame.Info.PicStruct =
1819                                 pOutSurface->Info.PicStruct;
1820                         }
1821                         if ((pOutSurface->Info.PicStruct == 0) &&
1822                             (m_pCurrentFreeVppSurface->frame.Info.PicStruct == 0)) {
1823                             m_pCurrentFreeVppSurface->frame.Info.PicStruct =
1824                                 pOutSurface->Info.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
1825                         }
1826 
1827                         if (m_diMode)
1828                             m_pCurrentFreeVppSurface->frame.Info.PicStruct =
1829                                 MFX_PICSTRUCT_PROGRESSIVE;
1830 
1831                         // WA: RunFrameVPPAsync doesn't copy ViewId from input to output
1832                         m_pCurrentFreeVppSurface->frame.Info.FrameId.ViewId =
1833                             pOutSurface->Info.FrameId.ViewId;
1834                         sts = m_pmfxVPP->RunFrameVPPAsync(pOutSurface,
1835                                                           &(m_pCurrentFreeVppSurface->frame),
1836                                                           NULL,
1837                                                           &(m_pCurrentFreeOutputSurface->syncp));
1838 
1839                         if (MFX_WRN_DEVICE_BUSY == sts) {
1840                             MSDK_SLEEP(
1841                                 1); // just wait and then repeat the same call to RunFrameVPPAsync
1842                         }
1843                     } while (MFX_WRN_DEVICE_BUSY == sts);
1844 
1845                     // process errors
1846                     if (MFX_ERR_MORE_DATA == sts) { // will never happen actually
1847                         continue;
1848                     }
1849                     else if (MFX_ERR_NONE != sts) {
1850                         MSDK_PRINT_RET_MSG(sts, "RunFrameVPPAsync failed");
1851                         break;
1852                     }
1853 
1854                     m_UsedVppSurfacesPool.AddSurface(m_pCurrentFreeVppSurface);
1855                     msdk_atomic_inc16(&(m_pCurrentFreeVppSurface->render_lock));
1856 
1857                     m_pCurrentFreeOutputSurface->surface = m_pCurrentFreeVppSurface;
1858                     m_OutputSurfacesPool.AddSurface(m_pCurrentFreeOutputSurface);
1859 
1860                     m_pCurrentFreeOutputSurface = NULL;
1861                     m_pCurrentFreeVppSurface    = NULL;
1862                 }
1863             }
1864             else {
1865                 msdkFrameSurface* surface = FindUsedSurface(pOutSurface);
1866 
1867                 msdk_atomic_inc16(&(surface->render_lock));
1868 
1869                 m_pCurrentFreeOutputSurface->surface = surface;
1870                 m_OutputSurfacesPool.AddSurface(m_pCurrentFreeOutputSurface);
1871                 m_pCurrentFreeOutputSurface = NULL;
1872             }
1873         }
1874     } //while processing
1875 
1876     if (m_nFrames == m_output_count) {
1877         if (sts != MFX_ERR_NONE)
1878             msdk_printf(
1879                 MSDK_STRING(
1880                     "[WARNING] Decoder returned error %s that could be compensated during next iterations of decoding process.\
1881                                     But requested amount of frames is already successfully decoded, so whole process is finished successfully."),
1882                 StatusToString(sts).c_str());
1883         sts = MFX_ERR_NONE;
1884     }
1885 
1886     PrintPerFrameStat(true);
1887 
1888     if (m_bPrintLatency && m_vLatency.size() > 0) {
1889         unsigned int frame_idx = 0;
1890         msdk_tick sum          = 0;
1891         for (std::vector<msdk_tick>::iterator it = m_vLatency.begin(); it != m_vLatency.end();
1892              ++it) {
1893             sum += *it;
1894             msdk_printf(MSDK_STRING("Frame %4d, latency=%5.5f ms\n"),
1895                         ++frame_idx,
1896                         (double)(CTimer::ConvertToSeconds(*it) * 1000));
1897         }
1898         msdk_printf(MSDK_STRING("\nLatency summary:\n"));
1899         msdk_printf(
1900             MSDK_STRING("\nAVG=%5.5f ms, MAX=%5.5f ms, MIN=%5.5f ms"),
1901             (double)CTimer::ConvertToSeconds((msdk_tick)((mfxF64)sum / m_vLatency.size())) * 1000,
1902             (double)CTimer::ConvertToSeconds(
1903                 *std::max_element(m_vLatency.begin(), m_vLatency.end())) *
1904                 1000,
1905             (double)CTimer::ConvertToSeconds(
1906                 *std::min_element(m_vLatency.begin(), m_vLatency.end())) *
1907                 1000);
1908     }
1909 
1910     if (m_eWorkMode == MODE_RENDERING) {
1911         m_bStopDeliverLoop = true;
1912         m_pDeliverOutputSemaphore->Post();
1913 
1914         if (deliverThread.joinable())
1915             deliverThread.join();
1916     }
1917 
1918     MSDK_SAFE_DELETE(m_pDeliverOutputSemaphore);
1919     MSDK_SAFE_DELETE(m_pDeliveredEvent);
1920 
1921     // exit in case of other errors
1922     MSDK_CHECK_STATUS(sts, "Unexpected error!!");
1923 
1924     // if we exited main decoding loop with ERR_INCOMPATIBLE_PARAM we need to send this status to caller
1925     if (bErrIncompatibleVideoParams) {
1926         sts = MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
1927     }
1928 
1929     return sts; // ERR_NONE or ERR_INCOMPATIBLE_VIDEO_PARAM
1930 }
1931 
1932 void CDecodingPipeline::PrintInfo() {
1933     msdk_printf(MSDK_STRING("Decoding Sample Version %s\n\n"), GetMSDKSampleVersion().c_str());
1934     msdk_printf(MSDK_STRING("\nInput video\t%s\n"),
1935                 CodecIdToStr(m_mfxVideoParams.mfx.CodecId).c_str());
1936     if (m_bVppIsUsed) {
1937         msdk_printf(MSDK_STRING("Output format\t%s (using vpp)\n"),
1938                     m_bOutI420 ? MSDK_STRING("I420(YUV)")
1939                                : CodecIdToStr(m_mfxVppVideoParams.vpp.Out.FourCC).c_str());
1940     }
1941     else {
1942         msdk_printf(MSDK_STRING("Output format\t%s\n"),
1943                     m_bOutI420 ? MSDK_STRING("I420(YUV)")
1944                                : CodecIdToStr(m_mfxVideoParams.mfx.FrameInfo.FourCC).c_str());
1945     }
1946 
1947     mfxFrameInfo Info = m_mfxVideoParams.mfx.FrameInfo;
1948     msdk_printf(MSDK_STRING("Input:\n"));
1949     msdk_printf(MSDK_STRING("  Resolution\t%dx%d\n"), (int)Info.Width, (int)Info.Height);
1950     msdk_printf(MSDK_STRING("  Crop X,Y,W,H\t%d,%d,%d,%d\n"),
1951                 (int)Info.CropX,
1952                 (int)Info.CropY,
1953                 (int)Info.CropW,
1954                 (int)Info.CropH);
1955     msdk_printf(MSDK_STRING("Output:\n"));
1956     if (m_vppOutHeight && m_vppOutWidth) {
1957         msdk_printf(MSDK_STRING("  Resolution\t%hux%hu\n"),
1958                     (short int)m_vppOutWidth,
1959                     (short int)m_vppOutHeight);
1960     }
1961     else {
1962         msdk_printf(MSDK_STRING("  Resolution\t%dx%d\n"),
1963                     Info.CropW ? (int)Info.CropW : (int)Info.Width,
1964                     Info.CropH ? (int)Info.CropH : (int)Info.Height);
1965     }
1966 
1967     mfxF64 dFrameRate = CalculateFrameRate(Info.FrameRateExtN, Info.FrameRateExtD);
1968     msdk_printf(MSDK_STRING("Frame rate\t%.2f\n"), (double)dFrameRate);
1969 
1970     const msdk_char* sMemType =
1971 #if defined(_WIN32) || defined(_WIN64)
1972         m_memType == D3D9_MEMORY
1973             ? MSDK_STRING("d3d")
1974 #else
1975         m_memType == D3D9_MEMORY
1976             ? MSDK_STRING("vaapi")
1977 #endif
1978             : (m_memType == D3D11_MEMORY ? MSDK_STRING("d3d11") : MSDK_STRING("system"));
1979     msdk_printf(MSDK_STRING("Memory type\t\t%s\n"), sMemType);
1980 
1981     const msdk_char* sImpl = (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(m_impl))
1982                                  ? MSDK_STRING("hw_d3d11")
1983                                  : (MFX_IMPL_SOFTWARE == MFX_IMPL_BASETYPE(m_impl))
1984                                        ? MSDK_STRING("sw")
1985                                        : MSDK_STRING("hw");
1986     msdk_printf(MSDK_STRING("MediaSDK impl\t\t%s\n"), sImpl);
1987 
1988     mfxVersion ver;
1989     m_mfxSession.QueryVersion(&ver);
1990     msdk_printf(MSDK_STRING("MediaSDK version\t%d.%d\n"), (int)ver.Major, (int)ver.Minor);
1991 
1992     msdk_printf(MSDK_STRING("\n"));
1993 
1994     return;
1995 }
1996