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