mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-03-16 13:37:05 -04:00
938 lines
30 KiB
C++
938 lines
30 KiB
C++
/* ****************************************************************************** *\
|
|
|
|
Copyright (C) 2012-2015 Intel Corporation. All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
- Redistributions of source code must retain the above copyright notice,
|
|
this list of conditions and the following disclaimer.
|
|
- Redistributions in binary form must reproduce the above copyright notice,
|
|
this list of conditions and the following disclaimer in the documentation
|
|
and/or other materials provided with the distribution.
|
|
- Neither the name of Intel Corporation nor the names of its contributors
|
|
may be used to endorse or promote products derived from this software
|
|
without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR
|
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
File Name: main.cpp
|
|
|
|
\* ****************************************************************************** */
|
|
|
|
#include "mfx_dispatcher.h"
|
|
#include "mfx_load_dll.h"
|
|
#include "mfx_dispatcher_log.h"
|
|
#include "mfx_library_iterator.h"
|
|
#include "mfx_critical_section.h"
|
|
|
|
#include <string.h> /* for memset on Linux */
|
|
#include <memory>
|
|
#include <stdlib.h> /* for qsort on Linux */
|
|
#include "mfx_load_plugin.h"
|
|
#include "mfx_plugin_hive.h"
|
|
|
|
// module-local definitions
|
|
namespace
|
|
{
|
|
|
|
const
|
|
struct
|
|
{
|
|
// instance implementation type
|
|
eMfxImplType implType;
|
|
// real implementation
|
|
mfxIMPL impl;
|
|
// adapter numbers
|
|
mfxU32 adapterID;
|
|
|
|
} implTypes[] =
|
|
{
|
|
// MFX_IMPL_AUTO case
|
|
{MFX_LIB_HARDWARE, MFX_IMPL_HARDWARE, 0},
|
|
{MFX_LIB_SOFTWARE, MFX_IMPL_SOFTWARE, 0},
|
|
|
|
// MFX_IMPL_ANY case
|
|
{MFX_LIB_HARDWARE, MFX_IMPL_HARDWARE, 0},
|
|
{MFX_LIB_HARDWARE, MFX_IMPL_HARDWARE2, 1},
|
|
{MFX_LIB_HARDWARE, MFX_IMPL_HARDWARE3, 2},
|
|
{MFX_LIB_HARDWARE, MFX_IMPL_HARDWARE4, 3},
|
|
{MFX_LIB_SOFTWARE, MFX_IMPL_SOFTWARE, 0},
|
|
{MFX_LIB_SOFTWARE, MFX_IMPL_SOFTWARE | MFX_IMPL_AUDIO, 0}
|
|
};
|
|
|
|
const
|
|
struct
|
|
{
|
|
// start index in implTypes table for specified implementation
|
|
mfxU32 minIndex;
|
|
// last index in implTypes table for specified implementation
|
|
mfxU32 maxIndex;
|
|
|
|
} implTypesRange[] =
|
|
{
|
|
{0, 1}, // MFX_IMPL_AUTO
|
|
{1, 1}, // MFX_IMPL_SOFTWARE
|
|
{0, 0}, // MFX_IMPL_HARDWARE
|
|
{2, 6}, // MFX_IMPL_AUTO_ANY
|
|
{2, 5}, // MFX_IMPL_HARDWARE_ANY
|
|
{3, 3}, // MFX_IMPL_HARDWARE2
|
|
{4, 4}, // MFX_IMPL_HARDWARE3
|
|
{5, 5}, // MFX_IMPL_HARDWARE4
|
|
{2, 6}, // MFX_IMPL_RUNTIME, same as MFX_IMPL_HARDWARE_ANY
|
|
{7, 7} // MFX_IMPL_AUDIO
|
|
};
|
|
|
|
MFX::mfxCriticalSection dispGuard = 0;
|
|
|
|
} // namespace
|
|
|
|
using namespace MFX;
|
|
//
|
|
// Implement DLL exposed functions. MFXInit and MFXClose have to do
|
|
// slightly more than other. They require to be implemented explicitly.
|
|
// All other functions are implemented implicitly.
|
|
//
|
|
|
|
typedef MFXVector<MFX_DISP_HANDLE*> HandleVector;
|
|
typedef MFXVector<mfxStatus> StatusVector;
|
|
|
|
struct VectorHandleGuard
|
|
{
|
|
VectorHandleGuard(HandleVector& aVector): m_vector(aVector) {}
|
|
~VectorHandleGuard()
|
|
{
|
|
HandleVector::iterator it = m_vector.begin(),
|
|
et = m_vector.end();
|
|
for ( ; it != et; ++it)
|
|
{
|
|
delete *it;
|
|
}
|
|
}
|
|
|
|
HandleVector& m_vector;
|
|
private:
|
|
void operator=(const VectorHandleGuard&);
|
|
};
|
|
|
|
|
|
int HandleSort (const void * plhs, const void * prhs)
|
|
{
|
|
const MFX_DISP_HANDLE * lhs = *(const MFX_DISP_HANDLE **)plhs;
|
|
const MFX_DISP_HANDLE * rhs = *(const MFX_DISP_HANDLE **)prhs;
|
|
|
|
if (lhs->actualApiVersion < rhs->actualApiVersion)
|
|
{
|
|
return -1;
|
|
}
|
|
if (rhs->actualApiVersion < lhs->actualApiVersion)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
// if versions are equal prefer library with HW
|
|
if (lhs->loadStatus == MFX_WRN_PARTIAL_ACCELERATION && rhs->loadStatus == MFX_ERR_NONE)
|
|
{
|
|
return 1;
|
|
}
|
|
if (lhs->loadStatus == MFX_ERR_NONE && rhs->loadStatus == MFX_WRN_PARTIAL_ACCELERATION)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
mfxStatus MFXInit(mfxIMPL impl, mfxVersion *pVer, mfxSession *session)
|
|
{
|
|
mfxInitParam par = {};
|
|
|
|
par.Implementation = impl;
|
|
if (pVer)
|
|
{
|
|
par.Version = *pVer;
|
|
}
|
|
else
|
|
{
|
|
par.Version.Major = DEFAULT_API_VERSION_MAJOR;
|
|
par.Version.Minor = DEFAULT_API_VERSION_MINOR;
|
|
}
|
|
par.ExternalThreads = 0;
|
|
|
|
return MFXInitEx(par, session);
|
|
}
|
|
|
|
mfxStatus MFXInitEx(mfxInitParam par, mfxSession *session)
|
|
{
|
|
MFX::MFXAutomaticCriticalSection guard(&dispGuard);
|
|
|
|
DISPATCHER_LOG_BLOCK( ("MFXInitEx (impl=%s, pVer=%d.%d, ExternalThreads=%d session=0x%p\n"
|
|
, DispatcherLog_GetMFXImplString(par.Implementation).c_str()
|
|
, par.Version.Major
|
|
, par.Version.Minor
|
|
, par.ExternalThreads
|
|
, session));
|
|
|
|
mfxStatus mfxRes;
|
|
HandleVector allocatedHandle;
|
|
VectorHandleGuard handleGuard(allocatedHandle);
|
|
|
|
MFX_DISP_HANDLE *pHandle;
|
|
msdk_disp_char dllName[MFX_MAX_DLL_PATH];
|
|
MFX::MFXLibraryIterator libIterator;
|
|
// there iterators are used only if the caller specified implicit type like AUTO
|
|
mfxU32 curImplIdx, maxImplIdx;
|
|
// particular implementation value
|
|
mfxIMPL curImpl;
|
|
// implementation method masked from the input parameter
|
|
// special case for audio library
|
|
const mfxIMPL implMethod = (par.Implementation & MFX_IMPL_AUDIO) ? (sizeof(implTypesRange) / sizeof(implTypesRange[0]) - 1) : (par.Implementation & (MFX_IMPL_VIA_ANY - 1));
|
|
|
|
// implementation interface masked from the input parameter
|
|
mfxIMPL implInterface = par.Implementation & -MFX_IMPL_VIA_ANY;
|
|
mfxIMPL implInterfaceOrig = implInterface;
|
|
mfxVersion requiredVersion = {{MFX_VERSION_MINOR, MFX_VERSION_MAJOR}};
|
|
|
|
// check error(s)
|
|
if (NULL == session)
|
|
{
|
|
return MFX_ERR_NULL_PTR;
|
|
}
|
|
if (((MFX_IMPL_AUTO > implMethod) || (MFX_IMPL_RUNTIME < implMethod)) && !(par.Implementation & MFX_IMPL_AUDIO))
|
|
{
|
|
return MFX_ERR_UNSUPPORTED;
|
|
}
|
|
|
|
// set the minimal required version
|
|
requiredVersion = par.Version;
|
|
|
|
try
|
|
{
|
|
// reset the session value
|
|
*session = 0;
|
|
|
|
// allocate the dispatching handle and call-table
|
|
pHandle = new MFX_DISP_HANDLE(requiredVersion);
|
|
}
|
|
catch(...)
|
|
{
|
|
return MFX_ERR_MEMORY_ALLOC;
|
|
}
|
|
|
|
DISPATCHER_LOG_INFO((("Required API version is %u.%u\n"), requiredVersion.Major, requiredVersion.Minor));
|
|
|
|
// Load HW library or RT from system location
|
|
curImplIdx = implTypesRange[implMethod].minIndex;
|
|
maxImplIdx = implTypesRange[implMethod].maxIndex;
|
|
mfxU32 hwImplIdx = 0;
|
|
do
|
|
{
|
|
int currentStorage = MFX::MFX_STORAGE_ID_FIRST;
|
|
implInterface = implInterfaceOrig;
|
|
do
|
|
{
|
|
// initialize the library iterator
|
|
mfxRes = libIterator.Init(implTypes[curImplIdx].implType,
|
|
implInterface,
|
|
implTypes[curImplIdx].adapterID,
|
|
currentStorage);
|
|
|
|
// look through the list of installed SDK version,
|
|
// looking for a suitable library with higher merit value.
|
|
if (MFX_ERR_NONE == mfxRes)
|
|
{
|
|
|
|
if (
|
|
MFX_LIB_HARDWARE == implTypes[curImplIdx].implType
|
|
&& (!implInterface
|
|
|| MFX_IMPL_VIA_ANY == implInterface))
|
|
{
|
|
implInterface = libIterator.GetImplementationType();
|
|
}
|
|
|
|
do
|
|
{
|
|
eMfxImplType implType;
|
|
|
|
// select a desired DLL
|
|
mfxRes = libIterator.SelectDLLVersion(dllName,
|
|
sizeof(dllName) / sizeof(dllName[0]),
|
|
&implType,
|
|
pHandle->apiVersion);
|
|
if (MFX_ERR_NONE != mfxRes)
|
|
{
|
|
break;
|
|
}
|
|
DISPATCHER_LOG_INFO((("loading library %S\n"), MSDK2WIDE(dllName)));
|
|
if (MFX_LIB_HARDWARE == implTypes[curImplIdx].implType)
|
|
hwImplIdx = curImplIdx;
|
|
// try to load the selected DLL
|
|
curImpl = implTypes[curImplIdx].impl;
|
|
mfxRes = pHandle->LoadSelectedDLL(dllName, implType, curImpl, implInterface, par);
|
|
// unload the failed DLL
|
|
if (MFX_ERR_NONE != mfxRes)
|
|
{
|
|
pHandle->Close();
|
|
}
|
|
else
|
|
{
|
|
libIterator.GetSubKeyName(pHandle->subkeyName, sizeof(pHandle->subkeyName)/sizeof(pHandle->subkeyName[0])) ;
|
|
pHandle->storageID = libIterator.GetStorageID();
|
|
allocatedHandle.push_back(pHandle);
|
|
pHandle = new MFX_DISP_HANDLE(requiredVersion);
|
|
}
|
|
|
|
} while (MFX_ERR_NONE != mfxRes);
|
|
}
|
|
|
|
// select another registry key
|
|
currentStorage += 1;
|
|
|
|
} while ((MFX_ERR_NONE != mfxRes) && (MFX::MFX_STORAGE_ID_LAST >= currentStorage));
|
|
|
|
} while ((MFX_ERR_NONE != mfxRes) && (++curImplIdx <= maxImplIdx));
|
|
|
|
|
|
curImplIdx = implTypesRange[implMethod].minIndex;
|
|
maxImplIdx = implTypesRange[implMethod].maxIndex;
|
|
|
|
// Load RT from app folder (libmfxsw64 with API >= 1.10)
|
|
do
|
|
{
|
|
implInterface = implInterfaceOrig;
|
|
// initialize the library iterator
|
|
mfxRes = libIterator.Init(implTypes[curImplIdx].implType,
|
|
implInterface,
|
|
implTypes[curImplIdx].adapterID,
|
|
MFX::MFX_APP_FOLDER);
|
|
|
|
if (MFX_ERR_NONE == mfxRes)
|
|
{
|
|
|
|
if (
|
|
MFX_LIB_HARDWARE == implTypes[curImplIdx].implType
|
|
&& (!implInterface
|
|
|| MFX_IMPL_VIA_ANY == implInterface))
|
|
{
|
|
implInterface = libIterator.GetImplementationType();
|
|
}
|
|
|
|
do
|
|
{
|
|
eMfxImplType implType;
|
|
|
|
// select a desired DLL
|
|
mfxRes = libIterator.SelectDLLVersion(dllName,
|
|
sizeof(dllName) / sizeof(dllName[0]),
|
|
&implType,
|
|
pHandle->apiVersion);
|
|
if (MFX_ERR_NONE != mfxRes)
|
|
{
|
|
break;
|
|
}
|
|
DISPATCHER_LOG_INFO((("loading library %S\n"), MSDK2WIDE(dllName)));
|
|
|
|
// try to load the selected DLL
|
|
curImpl = implTypes[curImplIdx].impl;
|
|
mfxRes = pHandle->LoadSelectedDLL(dllName, implType, curImpl, implInterface, par);
|
|
// unload the failed DLL
|
|
if (MFX_ERR_NONE != mfxRes)
|
|
{
|
|
pHandle->Close();
|
|
}
|
|
else
|
|
{
|
|
if (pHandle->actualApiVersion.Major == 1 && pHandle->actualApiVersion.Minor <= 9)
|
|
{
|
|
// this is not RT, skip it
|
|
mfxRes = MFX_ERR_ABORTED;
|
|
break;
|
|
}
|
|
pHandle->storageID = MFX::MFX_UNKNOWN_KEY;
|
|
allocatedHandle.push_back(pHandle);
|
|
pHandle = new MFX_DISP_HANDLE(requiredVersion);
|
|
}
|
|
|
|
} while (MFX_ERR_NONE != mfxRes);
|
|
}
|
|
} while ((MFX_ERR_NONE != mfxRes) && (++curImplIdx <= maxImplIdx));
|
|
|
|
// Load HW and SW libraries using legacy default DLL search mechanism
|
|
// set current library index again
|
|
curImplIdx = implTypesRange[implMethod].minIndex;
|
|
do
|
|
{
|
|
mfxU32 backupIdx = curImplIdx;
|
|
if (MFX_LIB_HARDWARE == implTypes[curImplIdx].implType)
|
|
{
|
|
curImplIdx = hwImplIdx;
|
|
}
|
|
implInterface = implInterfaceOrig;
|
|
|
|
if (par.Implementation & MFX_IMPL_AUDIO)
|
|
{
|
|
mfxRes = MFX::mfx_get_default_audio_dll_name(dllName,
|
|
sizeof(dllName) / sizeof(dllName[0]),
|
|
implTypes[curImplIdx].implType);
|
|
}
|
|
else
|
|
{
|
|
mfxRes = MFX::mfx_get_default_dll_name(dllName,
|
|
sizeof(dllName) / sizeof(dllName[0]),
|
|
implTypes[curImplIdx].implType);
|
|
}
|
|
|
|
if (MFX_ERR_NONE == mfxRes)
|
|
{
|
|
DISPATCHER_LOG_INFO((("loading default library %S\n"), MSDK2WIDE(dllName)))
|
|
|
|
// try to load the selected DLL using default DLL search mechanism
|
|
if (MFX_LIB_HARDWARE == implTypes[curImplIdx].implType)
|
|
{
|
|
if (!implInterface)
|
|
{
|
|
implInterface = MFX_IMPL_VIA_ANY;
|
|
}
|
|
mfxRes = MFX::SelectImplementationType(implTypes[curImplIdx].adapterID, &implInterface, NULL, NULL);
|
|
}
|
|
if (MFX_ERR_NONE == mfxRes)
|
|
{
|
|
// try to load the selected DLL using default DLL search mechanism
|
|
mfxRes = pHandle->LoadSelectedDLL(dllName,
|
|
implTypes[curImplIdx].implType,
|
|
implTypes[curImplIdx].impl,
|
|
implInterface,
|
|
par);
|
|
}
|
|
// unload the failed DLL
|
|
if ((MFX_ERR_NONE != mfxRes) &&
|
|
(MFX_WRN_PARTIAL_ACCELERATION != mfxRes))
|
|
{
|
|
pHandle->Close();
|
|
}
|
|
else
|
|
{
|
|
pHandle->storageID = MFX::MFX_UNKNOWN_KEY;
|
|
allocatedHandle.push_back(pHandle);
|
|
pHandle = new MFX_DISP_HANDLE(requiredVersion);
|
|
}
|
|
}
|
|
curImplIdx = backupIdx;
|
|
}
|
|
while ((MFX_ERR_NONE > mfxRes) && (++curImplIdx <= maxImplIdx));
|
|
delete pHandle;
|
|
|
|
if (allocatedHandle.size() == 0)
|
|
return MFX_ERR_UNSUPPORTED;
|
|
|
|
bool NeedSort = false;
|
|
HandleVector::iterator first = allocatedHandle.begin(),
|
|
it = allocatedHandle.begin(),
|
|
et = allocatedHandle.end();
|
|
for (it++; it != et; ++it)
|
|
if (HandleSort(&(*first), &(*it)) != 0)
|
|
NeedSort = true;
|
|
|
|
// select dll with version with lowest version number still greater or equal to requested
|
|
if (NeedSort)
|
|
qsort(&(*allocatedHandle.begin()), allocatedHandle.size(), sizeof(MFX_DISP_HANDLE*), &HandleSort);
|
|
|
|
HandleVector::iterator candidate = allocatedHandle.begin();
|
|
// check the final result of loading
|
|
try
|
|
{
|
|
pHandle = *candidate;
|
|
//pulling up current mediasdk version, that required to match plugin version
|
|
mfxVersion apiVerActual;
|
|
mfxStatus stsQueryVersion;
|
|
stsQueryVersion = MFXQueryVersion((mfxSession)pHandle, &apiVerActual);
|
|
if (MFX_ERR_NONE != stsQueryVersion)
|
|
{
|
|
DISPATCHER_LOG_ERROR((("MFXQueryVersion returned: %d, cannot load plugins\n"), mfxRes))
|
|
}
|
|
else
|
|
{
|
|
MFX::MFXPluginStorage & hive = pHandle->pluginHive;
|
|
|
|
HandleVector::iterator it = allocatedHandle.begin(),
|
|
et = allocatedHandle.end();
|
|
for (; it != et; ++it)
|
|
{
|
|
// Registering default plugins set
|
|
MFX::MFXDefaultPlugins defaultPugins(apiVerActual, *it, (*it)->implType);
|
|
hive.insert(hive.end(), defaultPugins.begin(), defaultPugins.end());
|
|
|
|
if ((*it)->storageID != MFX::MFX_UNKNOWN_KEY)
|
|
{
|
|
// Scan HW plugins in subkeys of registry library
|
|
MFX::MFXPluginsInHive plgsInHive((*it)->storageID, (*it)->subkeyName, apiVerActual);
|
|
hive.insert(hive.end(), plgsInHive.begin(), plgsInHive.end());
|
|
}
|
|
}
|
|
|
|
//setting up plugins records
|
|
for(int i = MFX::MFX_STORAGE_ID_FIRST; i <= MFX::MFX_STORAGE_ID_LAST; i++)
|
|
{
|
|
MFX::MFXPluginsInHive plgsInHive(i, NULL, apiVerActual);
|
|
hive.insert(hive.end(), plgsInHive.begin(), plgsInHive.end());
|
|
}
|
|
|
|
MFX::MFXPluginsInFS plgsInFS(apiVerActual);
|
|
hive.insert(hive.end(), plgsInFS.begin(), plgsInFS.end());
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
DISPATCHER_LOG_ERROR((("unknown exception while loading plugins\n")))
|
|
}
|
|
|
|
// everything is OK. Save pointers to the output variable
|
|
*candidate = 0; // keep this one safe from guard destructor
|
|
*((MFX_DISP_HANDLE **) session) = pHandle;
|
|
|
|
return pHandle->loadStatus;
|
|
|
|
} // mfxStatus MFXInit(mfxIMPL impl, mfxVersion *ver, mfxSession *session)
|
|
|
|
mfxStatus MFXClose(mfxSession session)
|
|
{
|
|
MFX::MFXAutomaticCriticalSection guard(&dispGuard);
|
|
|
|
mfxStatus mfxRes = MFX_ERR_INVALID_HANDLE;
|
|
MFX_DISP_HANDLE *pHandle = (MFX_DISP_HANDLE *) session;
|
|
|
|
// check error(s)
|
|
if (pHandle)
|
|
{
|
|
try
|
|
{
|
|
// unload the DLL library
|
|
mfxRes = pHandle->Close();
|
|
|
|
// it is possible, that there is an active child session.
|
|
// can't unload library in that case.
|
|
if (MFX_ERR_UNDEFINED_BEHAVIOR != mfxRes)
|
|
{
|
|
// release the handle
|
|
delete pHandle;
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
mfxRes = MFX_ERR_INVALID_HANDLE;
|
|
}
|
|
}
|
|
|
|
return mfxRes;
|
|
|
|
} // mfxStatus MFXClose(mfxSession session)
|
|
|
|
mfxStatus MFXJoinSession(mfxSession session, mfxSession child_session)
|
|
{
|
|
mfxStatus mfxRes = MFX_ERR_INVALID_HANDLE;
|
|
MFX_DISP_HANDLE *pHandle = (MFX_DISP_HANDLE *) session;
|
|
MFX_DISP_HANDLE *pChildHandle = (MFX_DISP_HANDLE *) child_session;
|
|
|
|
// get the function's address and make a call
|
|
if ((pHandle) && (pChildHandle) && (pHandle->apiVersion == pChildHandle->apiVersion))
|
|
{
|
|
/* check whether it is audio session or video */
|
|
int tableIndex = eMFXJoinSession;
|
|
mfxFunctionPointer pFunc;
|
|
if (pHandle->impl & MFX_IMPL_AUDIO)
|
|
{
|
|
pFunc = pHandle->callAudioTable[tableIndex];
|
|
}
|
|
else
|
|
{
|
|
pFunc = pHandle->callTable[tableIndex];
|
|
}
|
|
|
|
if (pFunc)
|
|
{
|
|
// pass down the call
|
|
mfxRes = (*(mfxStatus (MFX_CDECL *) (mfxSession, mfxSession)) pFunc) (pHandle->session,
|
|
pChildHandle->session);
|
|
}
|
|
}
|
|
|
|
return mfxRes;
|
|
|
|
} // mfxStatus MFXJoinSession(mfxSession session, mfxSession child_session)
|
|
|
|
mfxStatus MFXCloneSession(mfxSession session, mfxSession *clone)
|
|
{
|
|
mfxStatus mfxRes = MFX_ERR_INVALID_HANDLE;
|
|
MFX_DISP_HANDLE *pHandle = (MFX_DISP_HANDLE *) session;
|
|
mfxVersion apiVersion;
|
|
mfxIMPL impl;
|
|
|
|
// check error(s)
|
|
if (pHandle)
|
|
{
|
|
// initialize the clone session
|
|
apiVersion = pHandle->apiVersion;
|
|
impl = pHandle->impl | pHandle->implInterface;
|
|
mfxRes = MFXInit(impl, &apiVersion, clone);
|
|
if (MFX_ERR_NONE != mfxRes)
|
|
{
|
|
return mfxRes;
|
|
}
|
|
|
|
// join the sessions
|
|
mfxRes = MFXJoinSession(session, *clone);
|
|
if (MFX_ERR_NONE != mfxRes)
|
|
{
|
|
MFXClose(*clone);
|
|
*clone = NULL;
|
|
return mfxRes;
|
|
}
|
|
}
|
|
|
|
return mfxRes;
|
|
|
|
} // mfxStatus MFXCloneSession(mfxSession session, mfxSession *clone)
|
|
|
|
|
|
mfxStatus MFXVideoUSER_Load(mfxSession session, const mfxPluginUID *uid, mfxU32 version)
|
|
{
|
|
mfxStatus sts = MFX_ERR_NONE;
|
|
bool ErrFlag = false;
|
|
MFX_DISP_HANDLE &pHandle = *(MFX_DISP_HANDLE *) session;
|
|
if (!&pHandle)
|
|
{
|
|
DISPATCHER_LOG_ERROR((("MFXVideoUSER_Load: session=NULL\n")));
|
|
return MFX_ERR_NULL_PTR;
|
|
}
|
|
if (!uid)
|
|
{
|
|
DISPATCHER_LOG_ERROR((("MFXVideoUSER_Load: uid=NULL\n")));
|
|
return MFX_ERR_NULL_PTR;
|
|
}
|
|
DISPATCHER_LOG_INFO((("MFXVideoUSER_Load: uid="MFXGUIDTYPE()" version=%d\n")
|
|
, MFXGUIDTOHEX(uid)
|
|
, version))
|
|
size_t pluginsChecked = 0;
|
|
|
|
for (MFX::MFXPluginStorage::iterator i = pHandle.pluginHive.begin();i != pHandle.pluginHive.end(); i++, pluginsChecked++)
|
|
{
|
|
if (i->PluginUID != *uid)
|
|
{
|
|
continue;
|
|
}
|
|
//check rest in records
|
|
if (i->PluginVersion < version)
|
|
{
|
|
DISPATCHER_LOG_INFO((("MFXVideoUSER_Load: registered \"Plugin Version\" for GUID="MFXGUIDTYPE()" is %d, that is smaller that requested\n")
|
|
, MFXGUIDTOHEX(uid)
|
|
, i->PluginVersion))
|
|
continue;
|
|
}
|
|
try
|
|
{
|
|
sts = pHandle.pluginFactory.Create(*i);
|
|
if( MFX_ERR_NONE != sts)
|
|
{
|
|
ErrFlag = (ErrFlag || (sts == MFX_ERR_UNDEFINED_BEHAVIOR));
|
|
continue;
|
|
}
|
|
return MFX_ERR_NONE;
|
|
}
|
|
catch(...)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// Specified UID was not found among individually registed plugins, now try load it from default sets if any
|
|
for (MFX::MFXPluginStorage::iterator i = pHandle.pluginHive.begin();i != pHandle.pluginHive.end(); i++, pluginsChecked++)
|
|
{
|
|
if (!i->Default)
|
|
continue;
|
|
|
|
i->PluginUID = *uid;
|
|
i->PluginVersion = (mfxU16)version;
|
|
try
|
|
{
|
|
sts = pHandle.pluginFactory.Create(*i);
|
|
if( MFX_ERR_NONE != sts)
|
|
{
|
|
ErrFlag = (ErrFlag || (sts == MFX_ERR_UNDEFINED_BEHAVIOR));
|
|
continue;
|
|
}
|
|
return MFX_ERR_NONE;
|
|
}
|
|
catch(...)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
DISPATCHER_LOG_ERROR((("MFXVideoUSER_Load: cannot find registered plugin with requested UID, total plugins available=%d\n"), pHandle.pluginHive.size()));
|
|
if (ErrFlag)
|
|
return MFX_ERR_UNDEFINED_BEHAVIOR;
|
|
else
|
|
return MFX_ERR_NOT_FOUND;
|
|
}
|
|
|
|
|
|
mfxStatus MFXVideoUSER_LoadByPath(mfxSession session, const mfxPluginUID *uid, mfxU32 version, const mfxChar *path, mfxU32 len)
|
|
{
|
|
MFX_DISP_HANDLE &pHandle = *(MFX_DISP_HANDLE *) session;
|
|
if (!&pHandle)
|
|
{
|
|
DISPATCHER_LOG_ERROR((("MFXVideoUSER_LoadByPath: session=NULL\n")));
|
|
return MFX_ERR_NULL_PTR;
|
|
}
|
|
if (!uid)
|
|
{
|
|
DISPATCHER_LOG_ERROR((("MFXVideoUSER_LoadByPath: uid=NULL\n")));
|
|
return MFX_ERR_NULL_PTR;
|
|
}
|
|
|
|
DISPATCHER_LOG_INFO((("MFXVideoUSER_LoadByPath: %S uid="MFXGUIDTYPE()" version=%d\n")
|
|
, MSDK2WIDE(path)
|
|
, MFXGUIDTOHEX(uid)
|
|
, version))
|
|
|
|
PluginDescriptionRecord record;
|
|
record.sName[0] = 0;
|
|
|
|
#ifdef _WIN32
|
|
msdk_disp_char wPath[MAX_PLUGIN_PATH];
|
|
int res = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, path, len, wPath, MAX_PLUGIN_PATH);
|
|
if (!res)
|
|
{
|
|
DISPATCHER_LOG_ERROR((("MFXVideoUSER_LoadByPath: cant convert UTF-8 path to UTF-16\n")));
|
|
return MFX_ERR_NOT_FOUND;
|
|
}
|
|
msdk_disp_char_cpy_s(record.sPath, res < MAX_PLUGIN_PATH ? res : MAX_PLUGIN_PATH, wPath);
|
|
#else // Linux/Android
|
|
msdk_disp_char_cpy_s(record.sPath, len < MAX_PLUGIN_PATH ? len : MAX_PLUGIN_PATH, path);
|
|
#endif
|
|
|
|
record.PluginUID = *uid;
|
|
record.PluginVersion = (mfxU16)version;
|
|
record.Default = true;
|
|
|
|
try
|
|
{
|
|
return pHandle.pluginFactory.Create(record);
|
|
}
|
|
catch(...)
|
|
{
|
|
return MFX_ERR_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
|
|
mfxStatus MFXVideoUSER_UnLoad(mfxSession session, const mfxPluginUID *uid)
|
|
{
|
|
MFX_DISP_HANDLE &rHandle = *(MFX_DISP_HANDLE *) session;
|
|
if (!&rHandle)
|
|
{
|
|
DISPATCHER_LOG_ERROR((("MFXVideoUSER_UnLoad: session=NULL\n")));
|
|
return MFX_ERR_NULL_PTR;
|
|
}
|
|
if (!uid)
|
|
{
|
|
DISPATCHER_LOG_ERROR((("MFXVideoUSER_Load: uid=NULL\n")));
|
|
return MFX_ERR_NULL_PTR;
|
|
}
|
|
|
|
bool bDestroyed = rHandle.pluginFactory.Destroy(*uid);
|
|
if (bDestroyed)
|
|
{
|
|
DISPATCHER_LOG_INFO((("MFXVideoUSER_UnLoad : plugin with GUID="MFXGUIDTYPE()" unloaded\n"), MFXGUIDTOHEX(uid)));
|
|
} else
|
|
{
|
|
DISPATCHER_LOG_ERROR((("MFXVideoUSER_UnLoad : plugin with GUID="MFXGUIDTYPE()" not found\n"), MFXGUIDTOHEX(uid)));
|
|
}
|
|
|
|
return bDestroyed ? MFX_ERR_NONE : MFX_ERR_NOT_FOUND;
|
|
}
|
|
|
|
mfxStatus MFXAudioUSER_Load(mfxSession session, const mfxPluginUID *uid, mfxU32 version)
|
|
{
|
|
MFX_DISP_HANDLE &pHandle = *(MFX_DISP_HANDLE *) session;
|
|
if (!&pHandle)
|
|
{
|
|
DISPATCHER_LOG_ERROR((("MFXAudioUSER_Load: session=NULL\n")));
|
|
return MFX_ERR_NULL_PTR;
|
|
}
|
|
if (!uid)
|
|
{
|
|
DISPATCHER_LOG_ERROR((("MFXAudioUSER_Load: uid=NULL\n")));
|
|
return MFX_ERR_NULL_PTR;
|
|
}
|
|
DISPATCHER_LOG_INFO((("MFXAudioUSER_Load: uid="MFXGUIDTYPE()" version=%d\n")
|
|
, MFXGUIDTOHEX(uid)
|
|
, version))
|
|
size_t pluginsChecked = 0;
|
|
PluginDescriptionRecord defaultPluginRecord;
|
|
for (MFX::MFXPluginStorage::iterator i = pHandle.pluginHive.begin();i != pHandle.pluginHive.end(); i++, pluginsChecked++)
|
|
{
|
|
if (i->PluginUID != *uid)
|
|
{
|
|
if (i->Default) // PluginUID == 0 for default set
|
|
{
|
|
defaultPluginRecord = *i;
|
|
}
|
|
continue;
|
|
}
|
|
//check rest in records
|
|
if (i->PluginVersion < version)
|
|
{
|
|
DISPATCHER_LOG_INFO((("MFXAudioUSER_Load: registered \"Plugin Version\" for GUID="MFXGUIDTYPE()" is %d, that is smaller that requested\n")
|
|
, MFXGUIDTOHEX(uid)
|
|
, i->PluginVersion))
|
|
continue;
|
|
}
|
|
try {
|
|
return pHandle.pluginFactory.Create(*i);
|
|
}
|
|
catch(...) {
|
|
return MFX_ERR_UNKNOWN;
|
|
}
|
|
}
|
|
|
|
// Specified UID was not found among individually registed plugins, now try load it from default set if any
|
|
if (defaultPluginRecord.Default)
|
|
{
|
|
defaultPluginRecord.PluginUID = *uid;
|
|
defaultPluginRecord.onlyVersionRegistered = true;
|
|
defaultPluginRecord.PluginVersion = (mfxU16)version;
|
|
try {
|
|
return pHandle.pluginFactory.Create(defaultPluginRecord);
|
|
}
|
|
catch(...) {
|
|
return MFX_ERR_UNKNOWN;
|
|
}
|
|
}
|
|
|
|
DISPATCHER_LOG_ERROR((("MFXAudioUSER_Load: cannot find registered plugin with requested UID, total plugins available=%d\n"), pHandle.pluginHive.size()));
|
|
return MFX_ERR_NOT_FOUND;
|
|
}
|
|
|
|
mfxStatus MFXAudioUSER_UnLoad(mfxSession session, const mfxPluginUID *uid)
|
|
{
|
|
MFX_DISP_HANDLE &rHandle = *(MFX_DISP_HANDLE *) session;
|
|
if (!&rHandle)
|
|
{
|
|
DISPATCHER_LOG_ERROR((("MFXAudioUSER_UnLoad: session=NULL\n")));
|
|
return MFX_ERR_NULL_PTR;
|
|
}
|
|
if (!uid)
|
|
{
|
|
DISPATCHER_LOG_ERROR((("MFXAudioUSER_Load: uid=NULL\n")));
|
|
return MFX_ERR_NULL_PTR;
|
|
}
|
|
|
|
bool bDestroyed = rHandle.pluginFactory.Destroy(*uid);
|
|
if (bDestroyed)
|
|
{
|
|
DISPATCHER_LOG_INFO((("MFXAudioUSER_UnLoad : plugin with GUID="MFXGUIDTYPE()" unloaded\n"), MFXGUIDTOHEX(uid)));
|
|
} else
|
|
{
|
|
DISPATCHER_LOG_ERROR((("MFXAudioUSER_UnLoad : plugin with GUID="MFXGUIDTYPE()" not found\n"), MFXGUIDTOHEX(uid)));
|
|
}
|
|
|
|
return bDestroyed ? MFX_ERR_NONE : MFX_ERR_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// implement all other calling functions.
|
|
// They just call a procedure of DLL library from the table.
|
|
//
|
|
|
|
// define for common functions (from mfxsession.h)
|
|
#undef FUNCTION
|
|
#define FUNCTION(return_value, func_name, formal_param_list, actual_param_list) \
|
|
return_value func_name formal_param_list \
|
|
{ \
|
|
mfxStatus mfxRes = MFX_ERR_INVALID_HANDLE; \
|
|
MFX_DISP_HANDLE *pHandle = (MFX_DISP_HANDLE *) session; \
|
|
/* get the function's address and make a call */ \
|
|
if (pHandle) \
|
|
{ \
|
|
/* check whether it is audio session or video */ \
|
|
int tableIndex = e##func_name; \
|
|
mfxFunctionPointer pFunc; \
|
|
if (pHandle->impl & MFX_IMPL_AUDIO) \
|
|
{ \
|
|
pFunc = pHandle->callAudioTable[tableIndex]; \
|
|
} \
|
|
else \
|
|
{ \
|
|
pFunc = pHandle->callTable[tableIndex]; \
|
|
} \
|
|
if (pFunc) \
|
|
{ \
|
|
/* get the real session pointer */ \
|
|
session = pHandle->session; \
|
|
/* pass down the call */ \
|
|
mfxRes = (*(mfxStatus (MFX_CDECL *) formal_param_list) pFunc) actual_param_list; \
|
|
} \
|
|
} \
|
|
return mfxRes; \
|
|
}
|
|
|
|
FUNCTION(mfxStatus, MFXQueryIMPL, (mfxSession session, mfxIMPL *impl), (session, impl))
|
|
FUNCTION(mfxStatus, MFXQueryVersion, (mfxSession session, mfxVersion *version), (session, version))
|
|
FUNCTION(mfxStatus, MFXDisjoinSession, (mfxSession session), (session))
|
|
FUNCTION(mfxStatus, MFXSetPriority, (mfxSession session, mfxPriority priority), (session, priority))
|
|
FUNCTION(mfxStatus, MFXGetPriority, (mfxSession session, mfxPriority *priority), (session, priority))
|
|
|
|
#undef FUNCTION
|
|
#define FUNCTION(return_value, func_name, formal_param_list, actual_param_list) \
|
|
return_value func_name formal_param_list \
|
|
{ \
|
|
mfxStatus mfxRes = MFX_ERR_INVALID_HANDLE; \
|
|
MFX_DISP_HANDLE *pHandle = (MFX_DISP_HANDLE *) session; \
|
|
/* get the function's address and make a call */ \
|
|
if (pHandle) \
|
|
{ \
|
|
mfxFunctionPointer pFunc = pHandle->callTable[e##func_name]; \
|
|
if (pFunc) \
|
|
{ \
|
|
/* get the real session pointer */ \
|
|
session = pHandle->session; \
|
|
/* pass down the call */ \
|
|
mfxRes = (*(mfxStatus (MFX_CDECL *) formal_param_list) pFunc) actual_param_list; \
|
|
} \
|
|
} \
|
|
return mfxRes; \
|
|
}
|
|
|
|
#include "mfx_exposed_functions_list.h"
|
|
#undef FUNCTION
|
|
#define FUNCTION(return_value, func_name, formal_param_list, actual_param_list) \
|
|
return_value func_name formal_param_list \
|
|
{ \
|
|
mfxStatus mfxRes = MFX_ERR_INVALID_HANDLE; \
|
|
MFX_DISP_HANDLE *pHandle = (MFX_DISP_HANDLE *) session; \
|
|
/* get the function's address and make a call */ \
|
|
if (pHandle) \
|
|
{ \
|
|
mfxFunctionPointer pFunc = pHandle->callAudioTable[e##func_name]; \
|
|
if (pFunc) \
|
|
{ \
|
|
/* get the real session pointer */ \
|
|
session = pHandle->session; \
|
|
/* pass down the call */ \
|
|
mfxRes = (*(mfxStatus (MFX_CDECL *) formal_param_list) pFunc) actual_param_list; \
|
|
} \
|
|
} \
|
|
return mfxRes; \
|
|
}
|
|
|
|
#include "mfxaudio_exposed_functions_list.h"
|