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