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