1 /*############################################################################
2   # Copyright (C) 2012-2020 Intel Corporation
3   #
4   # SPDX-License-Identifier: MIT
5   ############################################################################*/
6 
7 #include <windows.h>
8 
9 #include <stringapiset.h>
10 
11 #include <memory>
12 #include <new>
13 
14 #include "windows/mfx_critical_section.h"
15 #include "windows/mfx_dispatcher.h"
16 #include "windows/mfx_dispatcher_log.h"
17 #include "windows/mfx_library_iterator.h"
18 #include "windows/mfx_load_dll.h"
19 
20 #include "windows/mfx_vector.h"
21 
22 #if defined(MEDIASDK_UWP_DISPATCHER)
23     #include "windows/mfx_driver_store_loader.h"
24 #endif
25 
26 #include <string.h> /* for memset on Linux */
27 
28 #include <stdlib.h> /* for qsort on Linux */
29 
30 // module-local definitions
31 namespace {
32 
33 const struct {
34     // instance implementation type
35     eMfxImplType implType;
36     // real implementation
37     mfxIMPL impl;
38     // adapter numbers
39     mfxU32 adapterID;
40 
41 } implTypes[] = {
42     // MFX_IMPL_AUTO case
43     { MFX_LIB_HARDWARE, MFX_IMPL_HARDWARE, 0 },
44     { MFX_LIB_SOFTWARE, MFX_IMPL_SOFTWARE, 0 },
45 
46     // MFX_IMPL_ANY case
47     { MFX_LIB_HARDWARE, MFX_IMPL_HARDWARE, 0 },
48     { MFX_LIB_HARDWARE, MFX_IMPL_HARDWARE2, 1 },
49     { MFX_LIB_HARDWARE, MFX_IMPL_HARDWARE3, 2 },
50     { MFX_LIB_HARDWARE, MFX_IMPL_HARDWARE4, 3 },
51     { MFX_LIB_SOFTWARE, MFX_IMPL_SOFTWARE, 0 },
52     { MFX_LIB_SOFTWARE, MFX_IMPL_SOFTWARE, 0 }, // unused - was MFX_IMPL_AUDIO
53 };
54 
55 const struct {
56     // start index in implTypes table for specified implementation
57     mfxU32 minIndex;
58     // last index in implTypes table for specified implementation
59     mfxU32 maxIndex;
60 
61 } implTypesRange[] = {
62     { 0, 1 }, // MFX_IMPL_AUTO
63     { 1, 1 }, // MFX_IMPL_SOFTWARE
64     { 0, 0 }, // MFX_IMPL_HARDWARE
65     { 2, 6 }, // MFX_IMPL_AUTO_ANY
66     { 2, 5 }, // MFX_IMPL_HARDWARE_ANY
67     { 3, 3 }, // MFX_IMPL_HARDWARE2
68     { 4, 4 }, // MFX_IMPL_HARDWARE3
69     { 5, 5 }, // MFX_IMPL_HARDWARE4
70     { 2, 6 }, // MFX_IMPL_RUNTIME, same as MFX_IMPL_HARDWARE_ANY
71 };
72 
73 MFX::mfxCriticalSection dispGuard = 0;
74 
75 } // namespace
76 
77 using namespace MFX;
78 
79 #if !defined(MEDIASDK_UWP_DISPATCHER)
80 
81 //
82 // Implement DLL exposed functions. MFXInit and MFXClose have to do
83 // slightly more than other. They require to be implemented explicitly.
84 // All other functions are implemented implicitly.
85 //
86 
87 typedef MFXVector<MFX_DISP_HANDLE_EX *> HandleVector;
88 typedef MFXVector<mfxStatus> StatusVector;
89 
90 struct VectorHandleGuard {
VectorHandleGuardVectorHandleGuard91     explicit VectorHandleGuard(HandleVector &aVector) : m_vector(aVector) {}
~VectorHandleGuardVectorHandleGuard92     ~VectorHandleGuard() {
93         HandleVector::iterator it = m_vector.begin(), et = m_vector.end();
94         for (; it != et; ++it) {
95             delete *it;
96         }
97     }
98 
99     HandleVector &m_vector;
100 
101 private:
102     void operator=(const VectorHandleGuard &);
103 };
104 
HandleSort(const void * plhs,const void * prhs)105 static int HandleSort(const void *plhs, const void *prhs) {
106     const MFX_DISP_HANDLE_EX *lhs   = *(const MFX_DISP_HANDLE_EX **)plhs;
107     const MFX_DISP_HANDLE_EX *rhs   = *(const MFX_DISP_HANDLE_EX **)prhs;
108     const mfxVersion vplInitVersion = { 255, 1 };
109 
110     // prefer oneVPL runtime (API = 1.255)
111     if ((lhs->actualApiVersion.Version == vplInitVersion.Version) &&
112         (rhs->actualApiVersion < lhs->actualApiVersion)) {
113         return -1;
114     }
115     if ((rhs->actualApiVersion.Version == vplInitVersion.Version) &&
116         (lhs->actualApiVersion < rhs->actualApiVersion)) {
117         return 1;
118     }
119 
120     // prefer HW implementation
121     if (lhs->implType != MFX_LIB_HARDWARE && rhs->implType == MFX_LIB_HARDWARE) {
122         return 1;
123     }
124     if (lhs->implType == MFX_LIB_HARDWARE && rhs->implType != MFX_LIB_HARDWARE) {
125         return -1;
126     }
127 
128     // prefer integrated GPU
129     if (lhs->mediaAdapterType != MFX_MEDIA_INTEGRATED &&
130         rhs->mediaAdapterType == MFX_MEDIA_INTEGRATED) {
131         return 1;
132     }
133     if (lhs->mediaAdapterType == MFX_MEDIA_INTEGRATED &&
134         rhs->mediaAdapterType != MFX_MEDIA_INTEGRATED) {
135         return -1;
136     }
137 
138     // prefer dll with lower API version
139     if (lhs->actualApiVersion < rhs->actualApiVersion) {
140         return -1;
141     }
142     if (rhs->actualApiVersion < lhs->actualApiVersion) {
143         return 1;
144     }
145 
146     // if versions are equal prefer library with HW
147     if (lhs->loadStatus == MFX_WRN_PARTIAL_ACCELERATION && rhs->loadStatus == MFX_ERR_NONE) {
148         return 1;
149     }
150     if (lhs->loadStatus == MFX_ERR_NONE && rhs->loadStatus == MFX_WRN_PARTIAL_ACCELERATION) {
151         return -1;
152     }
153 
154     return 0;
155 }
156 
MFXInitEx(mfxInitParam par,mfxSession * session)157 mfxStatus MFXInitEx(mfxInitParam par, mfxSession *session) {
158     MFX::MFXAutomaticCriticalSection guard(&dispGuard);
159 
160     DISPATCHER_LOG_BLOCK(("MFXInitEx (impl=%s, pVer=%d.%d, ExternalThreads=%d session=0x%p\n",
161                           DispatcherLog_GetMFXImplString(par.Implementation).c_str(),
162                           par.Version.Major,
163                           par.Version.Minor,
164                           par.ExternalThreads,
165                           session));
166 
167     mfxStatus mfxRes = MFX_ERR_UNSUPPORTED;
168     HandleVector allocatedHandle;
169     VectorHandleGuard handleGuard(allocatedHandle);
170 
171     MFX_DISP_HANDLE_EX *pHandle;
172     wchar_t dllName[MFX_MAX_DLL_PATH] = { 0 };
173     MFX::MFXLibraryIterator libIterator;
174 
175     // there iterators are used only if the caller specified implicit type like AUTO
176     mfxU32 curImplIdx, maxImplIdx;
177     // implementation method masked from the input parameter
178     // special case for audio library
179     const mfxIMPL implMethod = par.Implementation & (MFX_IMPL_VIA_ANY - 1);
180 
181     // implementation interface masked from the input parameter
182     mfxIMPL implInterface      = par.Implementation & -MFX_IMPL_VIA_ANY;
183     mfxIMPL implInterfaceOrig  = implInterface;
184     mfxVersion requiredVersion = { { MFX_VERSION_MINOR, MFX_VERSION_MAJOR } };
185 
186     mfxInitializationParam vplParam = {};
187     if (implMethod == MFX_IMPL_SOFTWARE) {
188         vplParam.AccelerationMode = MFX_ACCEL_MODE_NA;
189     }
190     else {
191         // hardware - D3D11 by default
192         if (implInterface == MFX_IMPL_VIA_D3D9)
193             vplParam.AccelerationMode = MFX_ACCEL_MODE_VIA_D3D9;
194         else
195             vplParam.AccelerationMode = MFX_ACCEL_MODE_VIA_D3D11;
196     }
197 
198     // check error(s)
199     if (NULL == session) {
200         return MFX_ERR_NULL_PTR;
201     }
202 
203     if (((MFX_IMPL_AUTO > implMethod) || (MFX_IMPL_RUNTIME < implMethod))) {
204         return MFX_ERR_UNSUPPORTED;
205     }
206 
207     // set the minimal required version
208     requiredVersion = par.Version;
209 
210     try {
211         // reset the session value
212         *session = 0;
213 
214         // allocate the dispatching handle and call-table
215         pHandle = new MFX_DISP_HANDLE_EX(requiredVersion);
216     }
217     catch (...) {
218         return MFX_ERR_MEMORY_ALLOC;
219     }
220 
221     DISPATCHER_LOG_INFO(
222         (("Required API version is %u.%u\n"), requiredVersion.Major, requiredVersion.Minor));
223     // particular implementation value
224     mfxIMPL curImpl;
225 
226     // Load HW library or RT from system location
227     curImplIdx = implTypesRange[implMethod].minIndex;
228     maxImplIdx = implTypesRange[implMethod].maxIndex;
229     do {
230         int currentStorage = MFX::MFX_STORAGE_ID_FIRST;
231         implInterface      = implInterfaceOrig;
232         do {
233             // this storage will be checked below
234             if (currentStorage == MFX::MFX_APP_FOLDER) {
235                 currentStorage += 1;
236                 continue;
237             }
238 
239             // initialize the library iterator
240             mfxRes = libIterator.Init(implTypes[curImplIdx].implType,
241                                       implInterface,
242                                       implTypes[curImplIdx].adapterID,
243                                       currentStorage);
244 
245             // look through the list of installed SDK version,
246             // looking for a suitable library with higher merit value.
247             if (MFX_ERR_NONE == mfxRes) {
248                 if (MFX_LIB_HARDWARE == implTypes[curImplIdx].implType &&
249                     (!implInterface || MFX_IMPL_VIA_ANY == implInterface)) {
250                     implInterface = libIterator.GetImplementationType();
251                 }
252 
253                 do {
254                     eMfxImplType implType = implTypes[curImplIdx].implType;
255 
256                     // select a desired DLL
257                     mfxRes = libIterator.SelectDLLVersion(dllName,
258                                                           sizeof(dllName) / sizeof(dllName[0]),
259                                                           &implType,
260                                                           pHandle->apiVersion);
261                     if (MFX_ERR_NONE != mfxRes) {
262                         break;
263                     }
264                     DISPATCHER_LOG_INFO((("loading library %S\n"), dllName));
265                     // try to load the selected DLL
266                     curImpl = implTypes[curImplIdx].impl;
267                     mfxRes  = pHandle->LoadSelectedDLL(dllName,
268                                                       implType,
269                                                       curImpl,
270                                                       implInterface,
271                                                       par,
272                                                       vplParam);
273                     // unload the failed DLL
274                     if (MFX_ERR_NONE != mfxRes) {
275                         pHandle->Close();
276                         continue;
277                     }
278 
279                     mfxPlatform platform = { MFX_PLATFORM_UNKNOWN, 0, MFX_MEDIA_UNKNOWN };
280                     if (pHandle->callTable[eMFXVideoCORE_QueryPlatform]) {
281                         mfxRes = MFXVideoCORE_QueryPlatform((mfxSession)pHandle, &platform);
282                         if (MFX_ERR_NONE != mfxRes) {
283                             DISPATCHER_LOG_WRN(
284                                 ("MFXVideoCORE_QueryPlatform failed, rejecting loaded library\n"));
285                             pHandle->Close();
286                             continue;
287                         }
288                     }
289                     pHandle->mediaAdapterType = platform.MediaAdapterType;
290                     DISPATCHER_LOG_INFO(
291                         (("media adapter type is %d\n"), pHandle->mediaAdapterType));
292 
293                     libIterator.GetSubKeyName(
294                         pHandle->subkeyName,
295                         sizeof(pHandle->subkeyName) / sizeof(pHandle->subkeyName[0]));
296                     pHandle->storageID = libIterator.GetStorageID();
297                     allocatedHandle.push_back(pHandle);
298                     pHandle = new MFX_DISP_HANDLE_EX(requiredVersion);
299                 } while (MFX_ERR_NONE != mfxRes);
300             }
301 
302             // select another place for loading engine
303             currentStorage += 1;
304 
305         } while ((MFX_ERR_NONE != mfxRes) && (MFX::MFX_STORAGE_ID_LAST >= currentStorage));
306 
307     } while ((MFX_ERR_NONE != mfxRes) && (++curImplIdx <= maxImplIdx));
308 
309     curImplIdx = implTypesRange[implMethod].minIndex;
310     maxImplIdx = implTypesRange[implMethod].maxIndex;
311 
312     // Load RT from app folder (libmfxsw64 with API >= 1.10)
313     do {
314         implInterface = implInterfaceOrig;
315         // initialize the library iterator
316         mfxRes = libIterator.Init(implTypes[curImplIdx].implType,
317                                   implInterface,
318                                   implTypes[curImplIdx].adapterID,
319                                   MFX::MFX_APP_FOLDER);
320 
321         if (MFX_ERR_NONE == mfxRes) {
322             if (MFX_LIB_HARDWARE == implTypes[curImplIdx].implType &&
323                 (!implInterface || MFX_IMPL_VIA_ANY == implInterface)) {
324                 implInterface = libIterator.GetImplementationType();
325             }
326 
327             do {
328                 eMfxImplType implType;
329 
330                 // select a desired DLL
331                 mfxRes = libIterator.SelectDLLVersion(dllName,
332                                                       sizeof(dllName) / sizeof(dllName[0]),
333                                                       &implType,
334                                                       pHandle->apiVersion);
335                 if (MFX_ERR_NONE != mfxRes) {
336                     break;
337                 }
338                 DISPATCHER_LOG_INFO((("loading library %S\n"), dllName));
339 
340                 // try to load the selected DLL
341                 curImpl = implTypes[curImplIdx].impl;
342                 mfxRes  = pHandle->LoadSelectedDLL(dllName,
343                                                   implType,
344                                                   curImpl,
345                                                   implInterface,
346                                                   par,
347                                                   vplParam);
348                 // unload the failed DLL
349                 if (MFX_ERR_NONE != mfxRes) {
350                     pHandle->Close();
351                 }
352                 else {
353                     if (pHandle->actualApiVersion.Major == 1 &&
354                         pHandle->actualApiVersion.Minor <= 9) {
355                         // this is not RT, skip it
356                         mfxRes = MFX_ERR_ABORTED;
357                         break;
358                     }
359                     pHandle->storageID = MFX::MFX_UNKNOWN_KEY;
360                     allocatedHandle.push_back(pHandle);
361                     pHandle = new MFX_DISP_HANDLE_EX(requiredVersion);
362                 }
363 
364             } while (MFX_ERR_NONE != mfxRes);
365         }
366     } while ((MFX_ERR_NONE != mfxRes) && (++curImplIdx <= maxImplIdx));
367 
368     // Load HW and SW libraries using legacy default DLL search mechanism
369     // set current library index again
370     curImplIdx = implTypesRange[implMethod].minIndex;
371     do {
372         implInterface = implInterfaceOrig;
373 
374         mfxRes = MFX::mfx_get_default_dll_name(dllName,
375                                                sizeof(dllName) / sizeof(dllName[0]),
376                                                implTypes[curImplIdx].implType);
377 
378         if (MFX_ERR_NONE == mfxRes) {
379             DISPATCHER_LOG_INFO((("loading default library %S\n"), dllName))
380 
381             // try to load the selected DLL using default DLL search mechanism
382             if (MFX_LIB_HARDWARE == implTypes[curImplIdx].implType) {
383                 if (!implInterface) {
384                     implInterface = MFX_IMPL_VIA_ANY;
385                 }
386                 mfxU32 curVendorID = 0, curDeviceID = 0;
387                 mfxRes = MFX::SelectImplementationType(implTypes[curImplIdx].adapterID,
388                                                        &implInterface,
389                                                        &curVendorID,
390                                                        &curDeviceID);
391                 if (curVendorID != INTEL_VENDOR_ID)
392                     mfxRes = MFX_ERR_UNKNOWN;
393             }
394             if (MFX_ERR_NONE == mfxRes) {
395                 // try to load the selected DLL using default DLL search mechanism
396                 mfxRes = pHandle->LoadSelectedDLL(dllName,
397                                                   implTypes[curImplIdx].implType,
398                                                   implTypes[curImplIdx].impl,
399                                                   implInterface,
400                                                   par,
401                                                   vplParam);
402             }
403             // unload the failed DLL
404             if ((MFX_ERR_NONE != mfxRes) && (MFX_WRN_PARTIAL_ACCELERATION != mfxRes)) {
405                 pHandle->Close();
406             }
407             else {
408                 pHandle->storageID = MFX::MFX_UNKNOWN_KEY;
409                 allocatedHandle.push_back(pHandle);
410                 pHandle = new MFX_DISP_HANDLE_EX(requiredVersion);
411             }
412         }
413     } while ((MFX_ERR_NONE > mfxRes) && (++curImplIdx <= maxImplIdx));
414     delete pHandle;
415 
416     if (allocatedHandle.size() == 0)
417         return MFX_ERR_UNSUPPORTED;
418 
419     { // sort candidate list
420         bool NeedSort                = false;
421         HandleVector::iterator first = allocatedHandle.begin(), it = allocatedHandle.begin(),
422                                et = allocatedHandle.end();
423         for (it++; it != et; ++it)
424             if (HandleSort(&(*first), &(*it)) != 0)
425                 NeedSort = true;
426 
427         // sort allocatedHandle so that the most preferred dll is at the beginning
428         if (NeedSort)
429             qsort(&(*allocatedHandle.begin()),
430                   allocatedHandle.size(),
431                   sizeof(MFX_DISP_HANDLE_EX *),
432                   &HandleSort);
433     }
434     HandleVector::iterator candidate = allocatedHandle.begin();
435     // check the final result of loading
436     try {
437         pHandle = *candidate;
438         //pulling up current mediasdk version, that required to match plugin version
439         //block for now to avoid KW scanning failure (UNUSED)
440         //mfxVersion apiVerActual = { { 0, 0 } };
441         //mfxStatus stsQueryVersion =
442         //    MFXQueryVersion((mfxSession)pHandle, &apiVerActual);
443     }
444     catch (...) {
445         DISPATCHER_LOG_ERROR((("unknown exception while loading plugins\n")))
446     }
447 
448     // everything is OK. Save pointers to the output variable
449     *candidate = 0; // keep this one safe from guard destructor
450 
451     //===================================
452 
453     // MFXVideoCORE_QueryPlatform call creates d3d device handle, so we have handle right after MFXInit and can't accept external handle
454     // This is a workaround which calls close-init to remove that handle
455 
456     mfxFunctionPointer *actualTable = pHandle->callTable;
457     mfxFunctionPointer pFunc;
458 
459     pFunc  = actualTable[eMFXClose];
460     mfxRes = (*(mfxStatus(MFX_CDECL *)(mfxSession))pFunc)(pHandle->session);
461     if (mfxRes != MFX_ERR_NONE)
462         return mfxRes;
463 
464     pHandle->session = 0;
465     bool callOldInit = !actualTable[eMFXInitEx];
466     pFunc            = actualTable[(callOldInit) ? eMFXInit : eMFXInitEx];
467 
468     mfxVersion version(pHandle->apiVersion);
469     if (callOldInit) {
470         pHandle->loadStatus = (*(mfxStatus(MFX_CDECL *)(mfxIMPL, mfxVersion *, mfxSession *))pFunc)(
471             pHandle->impl | pHandle->implInterface,
472             &version,
473             &pHandle->session);
474     }
475     else {
476         mfxInitParam initPar   = par;
477         initPar.Implementation = pHandle->impl | pHandle->implInterface;
478         initPar.Version        = version;
479         pHandle->loadStatus =
480             (*(mfxStatus(MFX_CDECL *)(mfxInitParam, mfxSession *))pFunc)(initPar,
481                                                                          &pHandle->session);
482     }
483 
484     //===================================
485 
486     *((MFX_DISP_HANDLE_EX **)session) = pHandle;
487 
488     return pHandle->loadStatus;
489 
490 } // mfxStatus MFXInitEx(mfxIMPL impl, mfxVersion *ver, mfxSession *session)
491 
492 // internal function - load a specific DLL, return unsupported if it fails
493 // vplParam is required for API >= 2.0 (load via MFXInitialize)
MFXInitEx2(mfxVersion version,mfxInitializationParam vplParam,mfxIMPL hwImpl,mfxSession * session,mfxU16 * deviceID,wchar_t * dllName)494 mfxStatus MFXInitEx2(mfxVersion version,
495                      mfxInitializationParam vplParam,
496                      mfxIMPL hwImpl,
497                      mfxSession *session,
498                      mfxU16 *deviceID,
499                      wchar_t *dllName) {
500     MFX::MFXAutomaticCriticalSection guard(&dispGuard);
501 
502     mfxStatus mfxRes = MFX_ERR_NONE;
503     HandleVector allocatedHandle;
504     VectorHandleGuard handleGuard(allocatedHandle);
505 
506     MFX_DISP_HANDLE *pHandle;
507 
508     *deviceID = 0;
509 
510     // fill minimal 1.x parameters for LoadSelectedDLL to choose correct initialization path
511     mfxInitParam par = {};
512     par.Version      = version;
513 
514     // select first adapter if not specified
515     // only relevant for MSDK-via-MFXLoad path
516     if (!hwImpl)
517         hwImpl = MFX_IMPL_HARDWARE;
518 
519     switch (vplParam.AccelerationMode) {
520         case MFX_ACCEL_MODE_NA:
521             par.Implementation = MFX_IMPL_SOFTWARE;
522             break;
523         case MFX_ACCEL_MODE_VIA_D3D9:
524             par.Implementation = hwImpl | MFX_IMPL_VIA_D3D9;
525             break;
526         case MFX_ACCEL_MODE_VIA_D3D11:
527             par.Implementation = hwImpl | MFX_IMPL_VIA_D3D11;
528             break;
529         case MFX_ACCEL_MODE_VIA_VAAPI:
530             par.Implementation = hwImpl | MFX_IMPL_VIA_VAAPI;
531             break;
532         default:
533             par.Implementation = hwImpl;
534             break;
535     }
536 
537     // also pass extBuf array (if any) to MFXInitEx for 1.x API
538     par.NumExtParam = vplParam.NumExtParam;
539     par.ExtParam    = (vplParam.NumExtParam ? vplParam.ExtParam : nullptr);
540 
541     eMfxImplType implType =
542         (par.Implementation == MFX_IMPL_SOFTWARE ? MFX_LIB_SOFTWARE : MFX_LIB_HARDWARE);
543     mfxIMPL implInterface    = par.Implementation & -MFX_IMPL_VIA_ANY;
544     const mfxIMPL implMethod = par.Implementation & (MFX_IMPL_VIA_ANY - 1);
545 
546     // check error(s)
547     if (NULL == session || NULL == dllName) {
548         return MFX_ERR_NULL_PTR;
549     }
550 
551     try {
552         // reset the session value
553         *session = 0;
554 
555         // allocate the dispatching handle and call-table
556         pHandle = new MFX_DISP_HANDLE(par.Version);
557     }
558     catch (...) {
559         return MFX_ERR_MEMORY_ALLOC;
560     }
561 
562     if (MFX_ERR_NONE == mfxRes) {
563         DISPATCHER_LOG_INFO((("loading default library %S\n"), dllName))
564 
565         if (MFX_ERR_NONE == mfxRes) {
566             // try to load the selected DLL using given DLL name
567             mfxRes = pHandle->LoadSelectedDLL(dllName,
568                                               implType,
569                                               implMethod,
570                                               implInterface,
571                                               par,
572                                               vplParam);
573         }
574         // unload the failed DLL
575         if (MFX_ERR_NONE != mfxRes) {
576             pHandle->Close();
577             delete pHandle;
578             return MFX_ERR_UNSUPPORTED;
579         }
580         else {
581             pHandle->storageID = MFX::MFX_UNKNOWN_KEY;
582         }
583     }
584 
585     // everything is OK. Save pointers to the output variable
586     *((MFX_DISP_HANDLE **)session) = pHandle;
587 
588     return pHandle->loadStatus;
589 }
590 
MFXClose(mfxSession session)591 mfxStatus MFXClose(mfxSession session) {
592     MFX::MFXAutomaticCriticalSection guard(&dispGuard);
593 
594     mfxStatus mfxRes         = MFX_ERR_INVALID_HANDLE;
595     MFX_DISP_HANDLE *pHandle = (MFX_DISP_HANDLE *)session;
596 
597     // check error(s)
598     if (pHandle) {
599         try {
600             // unload the DLL library
601             mfxRes = pHandle->Close();
602 
603             // it is possible, that there is an active child session.
604             // can't unload library in that case.
605             if (MFX_ERR_UNDEFINED_BEHAVIOR != mfxRes) {
606                 // release the handle
607                 delete pHandle;
608             }
609         }
610         catch (...) {
611             mfxRes = MFX_ERR_INVALID_HANDLE;
612         }
613     }
614 
615     return mfxRes;
616 
617 } // mfxStatus MFXClose(mfxSession session)
618 
619 #else // relates to !defined (MEDIASDK_UWP_DISPATCHER), i.e. #else part as if MEDIASDK_UWP_DISPATCHER defined
620 
621 static mfxModuleHandle hModule;
622 
623 // for the UWP_DISPATCHER purposes implementation of MFXinitEx is calling
624 // InitialiseMediaSession() implemented in intel_gfx_api.dll
MFXInitEx(mfxInitParam par,mfxSession * session)625 mfxStatus MFXInitEx(mfxInitParam par, mfxSession *session) {
626     #if defined(MEDIASDK_ARM_LOADER)
627 
628     return MFX_ERR_UNSUPPORTED;
629 
630     #else
631 
632     wchar_t IntelGFXAPIdllName[MFX_MAX_DLL_PATH] = { 0 };
633     mfxI32 adapterNum                            = -1;
634 
635     switch (par.Implementation & 0xf) {
636         case MFX_IMPL_SOFTWARE:
637         #if (MFX_VERSION >= MFX_VERSION_NEXT)
638         case MFX_IMPL_SINGLE_THREAD:
639         #endif
640             return MFX_ERR_UNSUPPORTED;
641         case MFX_IMPL_AUTO:
642         case MFX_IMPL_HARDWARE:
643             adapterNum = 0;
644             break;
645         case MFX_IMPL_HARDWARE2:
646             adapterNum = 1;
647             break;
648         case MFX_IMPL_HARDWARE3:
649             adapterNum = 2;
650             break;
651         case MFX_IMPL_HARDWARE4:
652             adapterNum = 3;
653             break;
654         default:
655             return GfxApiInitPriorityIntegrated(par, session, hModule);
656     }
657 
658     return GfxApiInitByAdapterNum(par, adapterNum, session, hModule);
659 
660     #endif
661 }
662 
663 // for the UWP_DISPATCHER purposes implementation of MFXClose is calling
664 // DisposeMediaSession() implemented in intel_gfx_api.dll
MFXClose(mfxSession session)665 mfxStatus MFXClose(mfxSession session) {
666     if (NULL == session) {
667         return MFX_ERR_INVALID_HANDLE;
668     }
669 
670     mfxStatus sts = MFX_ERR_NONE;
671 
672     #if defined(MEDIASDK_ARM_LOADER)
673 
674     sts = MFX_ERR_UNSUPPORTED;
675 
676     #else
677 
678     sts = GfxApiClose(session, hModule);
679 
680     #endif
681 
682     session = (mfxSession)NULL;
683     return sts;
684 }
685 
686     #undef FUNCTION
687     #define FUNCTION(return_value, func_name, formal_param_list, actual_param_list)               \
688         return_value func_name formal_param_list {                                                \
689             mfxStatus mfxRes = MFX_ERR_INVALID_HANDLE;                                            \
690                                                                                                   \
691             _mfxSession *pHandle = (_mfxSession *)session;                                        \
692                                                                                                   \
693             /* get the function's address and make a call */                                      \
694             if (pHandle) {                                                                        \
695                 mfxFunctionPointer pFunc = pHandle->callPlugInsTable[e##func_name];               \
696                 if (pFunc) {                                                                      \
697                     /* pass down the call */                                                      \
698                     mfxRes = (*(mfxStatus(MFX_CDECL *) formal_param_list)pFunc)actual_param_list; \
699                 }                                                                                 \
700             }                                                                                     \
701             return mfxRes;                                                                        \
702         }
703 
704 FUNCTION(mfxStatus,
705          MFXVideoUSER_Load,
706          (mfxSession session, const mfxPluginUID *uid, mfxU32 version),
707          (session, uid, version))
708 FUNCTION(
709     mfxStatus,
710     MFXVideoUSER_LoadByPath,
711     (mfxSession session, const mfxPluginUID *uid, mfxU32 version, const mfxChar *path, mfxU32 len),
712     (session, uid, version, path, len))
713 FUNCTION(mfxStatus,
714          MFXVideoUSER_UnLoad,
715          (mfxSession session, const mfxPluginUID *uid),
716          (session, uid))
717 FUNCTION(mfxStatus,
718          MFXAudioUSER_Load,
719          (mfxSession session, const mfxPluginUID *uid, mfxU32 version),
720          (session, uid, version))
721 FUNCTION(mfxStatus,
722          MFXAudioUSER_UnLoad,
723          (mfxSession session, const mfxPluginUID *uid),
724          (session, uid))
725 
726 #endif //!defined(MEDIASDK_UWP_DISPATCHER)
727 
MFXJoinSession(mfxSession session,mfxSession child_session)728 mfxStatus MFXJoinSession(mfxSession session, mfxSession child_session) {
729     mfxStatus mfxRes              = MFX_ERR_INVALID_HANDLE;
730     MFX_DISP_HANDLE *pHandle      = (MFX_DISP_HANDLE *)session;
731     MFX_DISP_HANDLE *pChildHandle = (MFX_DISP_HANDLE *)child_session;
732 
733     // get the function's address and make a call
734     if ((pHandle) && (pChildHandle) &&
735         (pHandle->actualApiVersion == pChildHandle->actualApiVersion)) {
736         /* check whether it is audio session or video */
737         int tableIndex = eMFXJoinSession;
738         mfxFunctionPointer pFunc;
739         pFunc = pHandle->callTable[tableIndex];
740 
741         if (pFunc) {
742             // pass down the call
743             mfxRes =
744                 (*(mfxStatus(MFX_CDECL *)(mfxSession, mfxSession))pFunc)(pHandle->session,
745                                                                          pChildHandle->session);
746         }
747     }
748 
749     return mfxRes;
750 
751 } // mfxStatus MFXJoinSession(mfxSession session, mfxSession child_session)
752 
AllocateCloneHandle(MFX_DISP_HANDLE * parentHandle,MFX_DISP_HANDLE ** cloneHandle)753 static mfxStatus AllocateCloneHandle(MFX_DISP_HANDLE *parentHandle, MFX_DISP_HANDLE **cloneHandle) {
754     MFX_DISP_HANDLE *ph = parentHandle;
755     MFX_DISP_HANDLE *ch = nullptr;
756 
757     if (!ph || !ph->hModule)
758         return MFX_ERR_NULL_PTR;
759 
760     // get full path to the DLL of the parent session
761     wchar_t dllName[MFX::msdk_disp_path_len];
762     DWORD nSize = GetModuleFileNameW((HMODULE)(ph->hModule), dllName, msdk_disp_path_len);
763     if (nSize == 0 || nSize == msdk_disp_path_len)
764         return MFX_ERR_UNSUPPORTED;
765 
766     try {
767         // requested version matches original session
768         ch = new MFX_DISP_HANDLE(ph->apiVersion);
769     }
770     catch (...) {
771         return MFX_ERR_MEMORY_ALLOC;
772     }
773 
774     // initialization param structs are not used when bCloneSession == true
775     mfxInitParam par                = {};
776     mfxInitializationParam vplParam = {};
777 
778     // initialization extBufs are not saved at this level
779     // the RT should save these when the parent session is created and may use
780     //   them when creating the cloned session
781     par.NumExtParam = 0;
782 
783     // load the selected DLL, fill out function pointer tables and other state
784     mfxStatus sts = ch->LoadSelectedDLL(dllName,
785                                         ph->implType,
786                                         ph->impl,
787                                         ph->implInterface,
788                                         par,
789                                         vplParam,
790                                         true);
791 
792     // unload the failed DLL
793     if (sts) {
794         ch->Close();
795         delete ch;
796         return MFX_ERR_UNSUPPORTED;
797     }
798     else {
799         ch->storageID = MFX::MFX_UNKNOWN_KEY;
800     }
801 
802     *cloneHandle = ch;
803 
804     return MFX_ERR_NONE;
805 }
806 
MFXCloneSession(mfxSession session,mfxSession * clone)807 mfxStatus MFXCloneSession(mfxSession session, mfxSession *clone) {
808     mfxStatus mfxRes         = MFX_ERR_INVALID_HANDLE;
809     MFX_DISP_HANDLE *pHandle = (MFX_DISP_HANDLE *)session;
810     mfxVersion apiVersion;
811     mfxIMPL impl;
812 
813     if (!clone)
814         return MFX_ERR_NULL_PTR;
815     *clone = NULL;
816 
817     // check error(s)
818     if (pHandle) {
819         // initialize the clone session
820         // for runtimes with 1.x API, call MFXInit followed by MFXJoinSession
821         // for runtimes with 2.x API, use RT implementation of MFXCloneSession (passthrough)
822         apiVersion = pHandle->actualApiVersion;
823 
824         if (apiVersion.Major == 1) {
825             impl   = pHandle->impl | pHandle->implInterface;
826             mfxRes = MFXInit(impl, &apiVersion, clone);
827             if (MFX_ERR_NONE != mfxRes) {
828                 return mfxRes;
829             }
830 
831             // join the sessions
832             mfxRes = MFXJoinSession(session, *clone);
833             if (MFX_ERR_NONE != mfxRes) {
834                 MFXClose(*clone);
835                 *clone = NULL;
836                 return mfxRes;
837             }
838         }
839         else if (apiVersion.Major == 2) {
840             int tableIndex = eMFXCloneSession;
841             mfxFunctionPointer pFunc;
842             pFunc = pHandle->callTable[tableIndex];
843             if (!pFunc)
844                 return MFX_ERR_UNSUPPORTED;
845 
846             // allocate new dispatcher-level session object and initialize state
847             //   (function pointer tables, impl type, etc.)
848             MFX_DISP_HANDLE *cloneHandle;
849             mfxRes = AllocateCloneHandle(pHandle, &cloneHandle);
850             if (mfxRes != MFX_ERR_NONE)
851                 return mfxRes;
852 
853             // call RT implementation of MFXCloneSession
854             mfxSession cloneRT;
855             mfxRes = (*(mfxStatus(MFX_CDECL *)(mfxSession, mfxSession *))pFunc)(pHandle->session,
856                                                                                 &cloneRT);
857 
858             if (mfxRes != MFX_ERR_NONE || cloneRT == NULL) {
859                 // RT call failed, delete cloned session
860                 delete cloneHandle;
861                 return MFX_ERR_UNSUPPORTED;
862             }
863             cloneHandle->session = cloneRT;
864 
865             // get version of cloned session
866             mfxVersion cloneVersion = {};
867             mfxRes                  = MFXQueryVersion((mfxSession)cloneHandle, &cloneVersion);
868             if (mfxRes != MFX_ERR_NONE) {
869                 MFXClose(cloneHandle);
870                 return MFX_ERR_UNSUPPORTED;
871             }
872 
873             cloneHandle->actualApiVersion = cloneVersion;
874             *clone                        = (mfxSession)cloneHandle;
875         }
876         else {
877             return MFX_ERR_UNSUPPORTED;
878         }
879     }
880 
881     return mfxRes;
882 
883 } // mfxStatus MFXCloneSession(mfxSession session, mfxSession *clone)
884 
MFXInit(mfxIMPL impl,mfxVersion * pVer,mfxSession * session)885 mfxStatus MFXInit(mfxIMPL impl, mfxVersion *pVer, mfxSession *session) {
886     mfxInitParam par = {};
887 
888     par.Implementation = impl;
889     if (pVer) {
890         par.Version = *pVer;
891     }
892     else {
893         par.Version.Major = DEFAULT_API_VERSION_MAJOR;
894         par.Version.Minor = DEFAULT_API_VERSION_MINOR;
895     }
896     par.ExternalThreads = 0;
897 
898     return MFXInitEx(par, session);
899 }
900 
901 // passthrough functions to implementation
MFXMemory_GetSurfaceForVPP(mfxSession session,mfxFrameSurface1 ** surface)902 mfxStatus MFXMemory_GetSurfaceForVPP(mfxSession session, mfxFrameSurface1 **surface) {
903     mfxStatus sts = MFX_ERR_INVALID_HANDLE;
904 
905     if (!session)
906         return MFX_ERR_INVALID_HANDLE;
907 
908     struct _mfxSession *pHandle = (struct _mfxSession *)session;
909 
910     mfxFunctionPointer pFunc;
911     pFunc = pHandle->callVideoTable2[eMFXMemory_GetSurfaceForVPP];
912     if (pFunc) {
913         session = pHandle->session;
914         sts = (*(mfxStatus(MFX_CDECL *)(mfxSession, mfxFrameSurface1 **))pFunc)(session, surface);
915     }
916 
917     return sts;
918 }
919 
MFXMemory_GetSurfaceForVPPOut(mfxSession session,mfxFrameSurface1 ** surface)920 mfxStatus MFXMemory_GetSurfaceForVPPOut(mfxSession session, mfxFrameSurface1 **surface) {
921     mfxStatus sts = MFX_ERR_INVALID_HANDLE;
922 
923     if (!session)
924         return MFX_ERR_INVALID_HANDLE;
925 
926     struct _mfxSession *pHandle = (struct _mfxSession *)session;
927 
928     mfxFunctionPointer pFunc;
929     pFunc = pHandle->callVideoTable2[eMFXMemory_GetSurfaceForVPPOut];
930     if (pFunc) {
931         session = pHandle->session;
932         sts = (*(mfxStatus(MFX_CDECL *)(mfxSession, mfxFrameSurface1 **))pFunc)(session, surface);
933     }
934 
935     return sts;
936 }
937 
MFXMemory_GetSurfaceForEncode(mfxSession session,mfxFrameSurface1 ** surface)938 mfxStatus MFXMemory_GetSurfaceForEncode(mfxSession session, mfxFrameSurface1 **surface) {
939     mfxStatus sts = MFX_ERR_INVALID_HANDLE;
940 
941     if (!session)
942         return MFX_ERR_INVALID_HANDLE;
943 
944     struct _mfxSession *pHandle = (struct _mfxSession *)session;
945 
946     mfxFunctionPointer pFunc;
947     pFunc = pHandle->callVideoTable2[eMFXMemory_GetSurfaceForEncode];
948     if (pFunc) {
949         session = pHandle->session;
950         sts = (*(mfxStatus(MFX_CDECL *)(mfxSession, mfxFrameSurface1 **))pFunc)(session, surface);
951     }
952 
953     return sts;
954 }
955 
MFXMemory_GetSurfaceForDecode(mfxSession session,mfxFrameSurface1 ** surface)956 mfxStatus MFXMemory_GetSurfaceForDecode(mfxSession session, mfxFrameSurface1 **surface) {
957     mfxStatus sts = MFX_ERR_INVALID_HANDLE;
958 
959     if (!session)
960         return MFX_ERR_INVALID_HANDLE;
961 
962     struct _mfxSession *pHandle = (struct _mfxSession *)session;
963 
964     mfxFunctionPointer pFunc;
965     pFunc = pHandle->callVideoTable2[eMFXMemory_GetSurfaceForDecode];
966     if (pFunc) {
967         session = pHandle->session;
968         sts = (*(mfxStatus(MFX_CDECL *)(mfxSession, mfxFrameSurface1 **))pFunc)(session, surface);
969     }
970 
971     return sts;
972 }
973 
MFXVideoDECODE_VPP_Init(mfxSession session,mfxVideoParam * decode_par,mfxVideoChannelParam ** vpp_par_array,mfxU32 num_vpp_par)974 mfxStatus MFXVideoDECODE_VPP_Init(mfxSession session,
975                                   mfxVideoParam *decode_par,
976                                   mfxVideoChannelParam **vpp_par_array,
977                                   mfxU32 num_vpp_par) {
978     mfxStatus sts = MFX_ERR_INVALID_HANDLE;
979 
980     if (!session)
981         return MFX_ERR_INVALID_HANDLE;
982 
983     struct _mfxSession *pHandle = (struct _mfxSession *)session;
984 
985     mfxFunctionPointer pFunc;
986     pFunc = pHandle->callVideoTable2[eMFXVideoDECODE_VPP_Init];
987     if (pFunc) {
988         session = pHandle->session;
989         sts =
990             (*(mfxStatus(MFX_CDECL *)(mfxSession, mfxVideoParam *, mfxVideoChannelParam **, mfxU32))
991                  pFunc)(session, decode_par, vpp_par_array, num_vpp_par);
992     }
993 
994     return sts;
995 }
996 
MFXVideoDECODE_VPP_DecodeFrameAsync(mfxSession session,mfxBitstream * bs,mfxU32 * skip_channels,mfxU32 num_skip_channels,mfxSurfaceArray ** surf_array_out)997 mfxStatus MFXVideoDECODE_VPP_DecodeFrameAsync(mfxSession session,
998                                               mfxBitstream *bs,
999                                               mfxU32 *skip_channels,
1000                                               mfxU32 num_skip_channels,
1001                                               mfxSurfaceArray **surf_array_out) {
1002     mfxStatus sts = MFX_ERR_INVALID_HANDLE;
1003 
1004     if (!session)
1005         return MFX_ERR_INVALID_HANDLE;
1006 
1007     struct _mfxSession *pHandle = (struct _mfxSession *)session;
1008 
1009     mfxFunctionPointer pFunc;
1010     pFunc = pHandle->callVideoTable2[eMFXVideoDECODE_VPP_DecodeFrameAsync];
1011     if (pFunc) {
1012         session = pHandle->session;
1013         sts     = (*(mfxStatus(
1014             MFX_CDECL *)(mfxSession, mfxBitstream *, mfxU32 *, mfxU32, mfxSurfaceArray **))
1015                    pFunc)(session, bs, skip_channels, num_skip_channels, surf_array_out);
1016     }
1017 
1018     return sts;
1019 }
1020 
MFXVideoDECODE_VPP_Reset(mfxSession session,mfxVideoParam * decode_par,mfxVideoChannelParam ** vpp_par_array,mfxU32 num_vpp_par)1021 mfxStatus MFXVideoDECODE_VPP_Reset(mfxSession session,
1022                                    mfxVideoParam *decode_par,
1023                                    mfxVideoChannelParam **vpp_par_array,
1024                                    mfxU32 num_vpp_par) {
1025     mfxStatus sts = MFX_ERR_INVALID_HANDLE;
1026 
1027     if (!session)
1028         return MFX_ERR_INVALID_HANDLE;
1029 
1030     struct _mfxSession *pHandle = (struct _mfxSession *)session;
1031 
1032     mfxFunctionPointer pFunc;
1033     pFunc = pHandle->callVideoTable2[eMFXVideoDECODE_VPP_Reset];
1034     if (pFunc) {
1035         session = pHandle->session;
1036         sts =
1037             (*(mfxStatus(MFX_CDECL *)(mfxSession, mfxVideoParam *, mfxVideoChannelParam **, mfxU32))
1038                  pFunc)(session, decode_par, vpp_par_array, num_vpp_par);
1039     }
1040 
1041     return sts;
1042 }
1043 
MFXVideoDECODE_VPP_GetChannelParam(mfxSession session,mfxVideoChannelParam * par,mfxU32 channel_id)1044 mfxStatus MFXVideoDECODE_VPP_GetChannelParam(mfxSession session,
1045                                              mfxVideoChannelParam *par,
1046                                              mfxU32 channel_id) {
1047     mfxStatus sts = MFX_ERR_INVALID_HANDLE;
1048 
1049     if (!session)
1050         return MFX_ERR_INVALID_HANDLE;
1051 
1052     struct _mfxSession *pHandle = (struct _mfxSession *)session;
1053 
1054     mfxFunctionPointer pFunc;
1055     pFunc = pHandle->callVideoTable2[eMFXVideoDECODE_VPP_GetChannelParam];
1056     if (pFunc) {
1057         session = pHandle->session;
1058         sts     = (*(mfxStatus(MFX_CDECL *)(mfxSession, mfxVideoChannelParam *, mfxU32))pFunc)(
1059             session,
1060             par,
1061             channel_id);
1062     }
1063 
1064     return sts;
1065 }
1066 
MFXVideoDECODE_VPP_Close(mfxSession session)1067 mfxStatus MFXVideoDECODE_VPP_Close(mfxSession session) {
1068     mfxStatus sts = MFX_ERR_INVALID_HANDLE;
1069 
1070     if (!session)
1071         return MFX_ERR_INVALID_HANDLE;
1072 
1073     struct _mfxSession *pHandle = (struct _mfxSession *)session;
1074 
1075     mfxFunctionPointer pFunc;
1076     pFunc = pHandle->callVideoTable2[eMFXVideoDECODE_VPP_Close];
1077     if (pFunc) {
1078         session = pHandle->session;
1079         sts     = (*(mfxStatus(MFX_CDECL *)(mfxSession))pFunc)(session);
1080     }
1081 
1082     return sts;
1083 }
1084 
MFXVideoVPP_ProcessFrameAsync(mfxSession session,mfxFrameSurface1 * in,mfxFrameSurface1 ** out)1085 mfxStatus MFXVideoVPP_ProcessFrameAsync(mfxSession session,
1086                                         mfxFrameSurface1 *in,
1087                                         mfxFrameSurface1 **out) {
1088     mfxStatus sts = MFX_ERR_INVALID_HANDLE;
1089 
1090     if (!session)
1091         return MFX_ERR_INVALID_HANDLE;
1092 
1093     struct _mfxSession *pHandle = (struct _mfxSession *)session;
1094 
1095     mfxFunctionPointer pFunc;
1096     pFunc = pHandle->callVideoTable2[eMFXVideoVPP_ProcessFrameAsync];
1097     if (pFunc) {
1098         session = pHandle->session;
1099         sts = (*(mfxStatus(MFX_CDECL *)(mfxSession, mfxFrameSurface1 *, mfxFrameSurface1 **))pFunc)(
1100             session,
1101             in,
1102             out);
1103     }
1104 
1105     return sts;
1106 }
1107 
1108 //
1109 //
1110 // implement all other calling functions.
1111 // They just call a procedure of DLL library from the table.
1112 //
1113 
1114 // define for common functions (from mfxsession.h)
1115 #undef FUNCTION
1116 #define FUNCTION(return_value, func_name, formal_param_list, actual_param_list)               \
1117     return_value func_name formal_param_list {                                                \
1118         mfxStatus mfxRes     = MFX_ERR_INVALID_HANDLE;                                        \
1119         _mfxSession *pHandle = (_mfxSession *)session;                                        \
1120         /* get the function's address and make a call */                                      \
1121         if (pHandle) {                                                                        \
1122             /* check whether it is audio session or video */                                  \
1123             int tableIndex = e##func_name;                                                    \
1124             mfxFunctionPointer pFunc;                                                         \
1125             pFunc = pHandle->callTable[tableIndex];                                           \
1126             if (pFunc) {                                                                      \
1127                 /* get the real session pointer */                                            \
1128                 session = pHandle->session;                                                   \
1129                 /* pass down the call */                                                      \
1130                 mfxRes = (*(mfxStatus(MFX_CDECL *) formal_param_list)pFunc)actual_param_list; \
1131             }                                                                                 \
1132         }                                                                                     \
1133         return mfxRes;                                                                        \
1134     }
1135 
1136 FUNCTION(mfxStatus, MFXQueryIMPL, (mfxSession session, mfxIMPL *impl), (session, impl))
1137 FUNCTION(mfxStatus, MFXQueryVersion, (mfxSession session, mfxVersion *version), (session, version))
1138 
1139 // these functions are not necessary in LOADER part of dispatcher and
1140 // need to be included only in in SOLID dispatcher or PROCTABLE part of dispatcher
1141 
1142 FUNCTION(mfxStatus, MFXDisjoinSession, (mfxSession session), (session))
1143 FUNCTION(mfxStatus, MFXSetPriority, (mfxSession session, mfxPriority priority), (session, priority))
1144 FUNCTION(mfxStatus,
1145          MFXGetPriority,
1146          (mfxSession session, mfxPriority *priority),
1147          (session, priority))
1148 
1149 #undef FUNCTION
1150 #define FUNCTION(return_value, func_name, formal_param_list, actual_param_list)               \
1151     return_value func_name formal_param_list {                                                \
1152         mfxStatus mfxRes     = MFX_ERR_INVALID_HANDLE;                                        \
1153         _mfxSession *pHandle = (_mfxSession *)session;                                        \
1154         /* get the function's address and make a call */                                      \
1155         if (pHandle) {                                                                        \
1156             mfxFunctionPointer pFunc = pHandle->callTable[e##func_name];                      \
1157             if (pFunc) {                                                                      \
1158                 /* get the real session pointer */                                            \
1159                 session = pHandle->session;                                                   \
1160                 /* pass down the call */                                                      \
1161                 mfxRes = (*(mfxStatus(MFX_CDECL *) formal_param_list)pFunc)actual_param_list; \
1162             }                                                                                 \
1163         }                                                                                     \
1164         return mfxRes;                                                                        \
1165     }
1166 
1167 #include "windows/mfx_exposed_functions_list.h"
1168