mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-02 14:36:41 +00:00
810 lines
26 KiB
C++
810 lines
26 KiB
C++
/*############################################################################
|
|
# Copyright (C) Intel Corporation
|
|
#
|
|
# SPDX-License-Identifier: MIT
|
|
############################################################################*/
|
|
|
|
#include <assert.h>
|
|
#include <dlfcn.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include <algorithm>
|
|
#include <list>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "vpl/mfxvideo.h"
|
|
|
|
#include "linux/device_ids.h"
|
|
#include "linux/mfxloader.h"
|
|
|
|
namespace MFX {
|
|
|
|
#if defined(__x86_64__) || (INTPTR_MAX == INT64_MAX)
|
|
#define LIBMFXSW "libmfxsw64.so.1"
|
|
#define LIBMFXHW "libmfxhw64.so.1"
|
|
|
|
#define ONEVPLSW "libvplswref64.so.1"
|
|
#define ONEVPLHW "libmfx-gen.so.1.2"
|
|
#elif defined(__i386__) || (INTPTR_MAX == INT32_MAX)
|
|
#define LIBMFXSW "libmfxsw32.so.1"
|
|
#define LIBMFXHW "libmfxhw32.so.1"
|
|
|
|
#define ONEVPLSW "libvplswref32.so.1"
|
|
#define ONEVPLHW "libmfx-gen.so.1.2"
|
|
#else
|
|
#error Unsupported architecture
|
|
#endif
|
|
|
|
#undef FUNCTION
|
|
#define FUNCTION(return_value, func_name, formal_param_list, actual_param_list) e##func_name,
|
|
|
|
enum Function {
|
|
eMFXInit,
|
|
eMFXInitEx,
|
|
eMFXClose,
|
|
eMFXJoinSession,
|
|
#include "linux/mfxvideo_functions.h"
|
|
eFunctionsNum,
|
|
eNoMoreFunctions = eFunctionsNum
|
|
};
|
|
|
|
// new functions for API 2.x
|
|
enum Function2 {
|
|
// 2.0
|
|
eMFXQueryImplsDescription = 0,
|
|
eMFXReleaseImplDescription,
|
|
eMFXMemory_GetSurfaceForVPP,
|
|
eMFXMemory_GetSurfaceForEncode,
|
|
eMFXMemory_GetSurfaceForDecode,
|
|
eMFXInitialize,
|
|
|
|
// 2.1
|
|
eMFXMemory_GetSurfaceForVPPOut,
|
|
eMFXVideoDECODE_VPP_Init,
|
|
eMFXVideoDECODE_VPP_DecodeFrameAsync,
|
|
eMFXVideoDECODE_VPP_Reset,
|
|
eMFXVideoDECODE_VPP_GetChannelParam,
|
|
eMFXVideoDECODE_VPP_Close,
|
|
eMFXVideoVPP_ProcessFrameAsync,
|
|
|
|
eFunctionsNum2,
|
|
};
|
|
|
|
struct FunctionsTable {
|
|
Function id;
|
|
const char *name;
|
|
mfxVersion version;
|
|
};
|
|
|
|
struct FunctionsTable2 {
|
|
Function2 id;
|
|
const char *name;
|
|
mfxVersion version;
|
|
};
|
|
|
|
#define VERSION(major, minor) \
|
|
{ \
|
|
{ minor, major } \
|
|
}
|
|
|
|
#undef FUNCTION
|
|
#define FUNCTION(return_value, func_name, formal_param_list, actual_param_list) \
|
|
{ e##func_name, #func_name, API_VERSION },
|
|
|
|
static const FunctionsTable g_mfxFuncTable[] = {
|
|
{ eMFXInit, "MFXInit", VERSION(1, 0) },
|
|
{ eMFXInitEx, "MFXInitEx", VERSION(1, 14) },
|
|
{ eMFXClose, "MFXClose", VERSION(1, 0) },
|
|
{ eMFXJoinSession, "MFXJoinSession", VERSION(1, 1) },
|
|
#include "linux/mfxvideo_functions.h" // NOLINT(build/include)
|
|
{ eNoMoreFunctions }
|
|
};
|
|
|
|
static const FunctionsTable2 g_mfxFuncTable2[] = {
|
|
{ eMFXQueryImplsDescription, "MFXQueryImplsDescription", VERSION(2, 0) },
|
|
{ eMFXReleaseImplDescription, "MFXReleaseImplDescription", VERSION(2, 0) },
|
|
{ eMFXMemory_GetSurfaceForVPP, "MFXMemory_GetSurfaceForVPP", VERSION(2, 0) },
|
|
{ eMFXMemory_GetSurfaceForEncode, "MFXMemory_GetSurfaceForEncode", VERSION(2, 0) },
|
|
{ eMFXMemory_GetSurfaceForDecode, "MFXMemory_GetSurfaceForDecode", VERSION(2, 0) },
|
|
{ eMFXInitialize, "MFXInitialize", VERSION(2, 0) },
|
|
|
|
{ eMFXMemory_GetSurfaceForVPPOut, "MFXMemory_GetSurfaceForVPPOut", VERSION(2, 1) },
|
|
{ eMFXVideoDECODE_VPP_Init, "MFXVideoDECODE_VPP_Init", VERSION(2, 1) },
|
|
{ eMFXVideoDECODE_VPP_DecodeFrameAsync, "MFXVideoDECODE_VPP_DecodeFrameAsync", VERSION(2, 1) },
|
|
{ eMFXVideoDECODE_VPP_Reset, "MFXVideoDECODE_VPP_Reset", VERSION(2, 1) },
|
|
{ eMFXVideoDECODE_VPP_GetChannelParam, "MFXVideoDECODE_VPP_GetChannelParam", VERSION(2, 1) },
|
|
{ eMFXVideoDECODE_VPP_Close, "MFXVideoDECODE_VPP_Close", VERSION(2, 1) },
|
|
{ eMFXVideoVPP_ProcessFrameAsync, "MFXVideoVPP_ProcessFrameAsync", VERSION(2, 1) },
|
|
};
|
|
|
|
class LoaderCtx {
|
|
public:
|
|
mfxStatus Init(mfxInitParam &par,
|
|
mfxInitializationParam &vplParam,
|
|
mfxU16 *pDeviceID,
|
|
char *dllName,
|
|
bool bCloneSession = false);
|
|
mfxStatus Close();
|
|
|
|
inline void *getFunction(Function func) const {
|
|
return m_table[func];
|
|
}
|
|
|
|
inline void *getFunction2(Function2 func) const {
|
|
return m_table2[func];
|
|
}
|
|
|
|
inline mfxSession getSession() const {
|
|
return m_session;
|
|
}
|
|
|
|
inline mfxIMPL getImpl() const {
|
|
return m_implementation;
|
|
}
|
|
|
|
inline mfxVersion getVersion() const {
|
|
return m_version;
|
|
}
|
|
|
|
inline void *getHandle() const {
|
|
return m_dlh.get();
|
|
}
|
|
|
|
inline const char *getLibPath() const {
|
|
return m_libToLoad.c_str();
|
|
}
|
|
|
|
// special operations to set session pointer and version from MFXCloneSession()
|
|
inline void setSession(const mfxSession session) {
|
|
m_session = session;
|
|
}
|
|
|
|
inline void setVersion(const mfxVersion version) {
|
|
m_version = version;
|
|
}
|
|
|
|
private:
|
|
std::shared_ptr<void> m_dlh;
|
|
mfxVersion m_version{};
|
|
mfxIMPL m_implementation{};
|
|
mfxSession m_session = nullptr;
|
|
void *m_table[eFunctionsNum]{};
|
|
void *m_table2[eFunctionsNum2]{};
|
|
std::string m_libToLoad;
|
|
};
|
|
|
|
std::shared_ptr<void> make_dlopen(const char *filename, int flags) {
|
|
return std::shared_ptr<void>(dlopen(filename, flags), [](void *handle) {
|
|
if (handle)
|
|
dlclose(handle);
|
|
});
|
|
}
|
|
|
|
mfxStatus LoaderCtx::Init(mfxInitParam &par,
|
|
mfxInitializationParam &vplParam,
|
|
mfxU16 *pDeviceID,
|
|
char *dllName,
|
|
bool bCloneSession) {
|
|
mfxStatus mfx_res = MFX_ERR_NONE;
|
|
|
|
std::vector<std::string> libs;
|
|
std::vector<Device> devices;
|
|
eMFXHWType msdk_platform;
|
|
|
|
// query graphics device_id
|
|
// if it is found on list of legacy devices, load MSDK RT
|
|
// otherwise load oneVPL RT
|
|
mfxU16 deviceID = 0;
|
|
mfx_res = get_devices(devices);
|
|
if (mfx_res == MFX_ERR_NOT_FOUND) {
|
|
// query failed
|
|
msdk_platform = MFX_HW_UNKNOWN;
|
|
}
|
|
else {
|
|
// query succeeded:
|
|
// may be a valid platform from listLegalDevIDs[] or MFX_HW_UNKNOWN
|
|
// if underlying device_id is unrecognized (i.e. new platform)
|
|
msdk_platform = devices[0].platform;
|
|
deviceID = devices[0].device_id;
|
|
}
|
|
|
|
if (pDeviceID)
|
|
*pDeviceID = deviceID;
|
|
|
|
if (dllName) {
|
|
// attempt to load only this DLL, fail if unsuccessful
|
|
// this may also be used later by MFXCloneSession()
|
|
m_libToLoad = dllName;
|
|
libs.emplace_back(m_libToLoad);
|
|
}
|
|
else {
|
|
mfxIMPL implType = MFX_IMPL_BASETYPE(par.Implementation);
|
|
// add HW lib
|
|
if (implType == MFX_IMPL_AUTO || implType == MFX_IMPL_AUTO_ANY ||
|
|
(implType & MFX_IMPL_HARDWARE) || (implType & MFX_IMPL_HARDWARE_ANY)) {
|
|
if (msdk_platform == MFX_HW_UNKNOWN) {
|
|
// if not on list of known MSDK platforms, prefer oneVPL
|
|
libs.emplace_back(ONEVPLHW);
|
|
libs.emplace_back(MFX_MODULES_DIR "/" ONEVPLHW);
|
|
}
|
|
|
|
// use MSDK (fallback if oneVPL is not installed)
|
|
libs.emplace_back(LIBMFXHW);
|
|
libs.emplace_back(MFX_MODULES_DIR "/" LIBMFXHW);
|
|
}
|
|
|
|
// add SW lib (oneVPL only)
|
|
if (implType == MFX_IMPL_AUTO || implType == MFX_IMPL_AUTO_ANY ||
|
|
(implType & MFX_IMPL_SOFTWARE)) {
|
|
libs.emplace_back(ONEVPLSW);
|
|
libs.emplace_back(MFX_MODULES_DIR "/" ONEVPLSW);
|
|
}
|
|
}
|
|
|
|
// fail if libs is empty (invalid Implementation)
|
|
mfx_res = MFX_ERR_UNSUPPORTED;
|
|
|
|
for (auto &lib : libs) {
|
|
std::shared_ptr<void> hdl = make_dlopen(lib.c_str(), RTLD_LOCAL | RTLD_NOW);
|
|
if (hdl) {
|
|
do {
|
|
/* Loading functions table */
|
|
bool wrong_version = false;
|
|
for (int i = 0; i < eFunctionsNum; ++i) {
|
|
assert(i == g_mfxFuncTable[i].id);
|
|
m_table[i] = dlsym(hdl.get(), g_mfxFuncTable[i].name);
|
|
if (!m_table[i] && ((g_mfxFuncTable[i].version <= par.Version))) {
|
|
wrong_version = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// if version >= 2.0, load these functions as well
|
|
if (par.Version.Major >= 2) {
|
|
for (int i = 0; i < eFunctionsNum2; ++i) {
|
|
assert(i == g_mfxFuncTable2[i].id);
|
|
m_table2[i] = dlsym(hdl.get(), g_mfxFuncTable2[i].name);
|
|
if (!m_table2[i] && (g_mfxFuncTable2[i].version <= par.Version)) {
|
|
wrong_version = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (wrong_version) {
|
|
mfx_res = MFX_ERR_UNSUPPORTED;
|
|
break;
|
|
}
|
|
|
|
if (bCloneSession == true) {
|
|
// success - exit loop since caller will create session with MFXCloneSession()
|
|
mfx_res = MFX_ERR_NONE;
|
|
break;
|
|
}
|
|
|
|
if (par.Version.Major >= 2) {
|
|
// for API >= 2.0 call MFXInitialize instead of MFXInitEx
|
|
mfx_res =
|
|
((decltype(MFXInitialize) *)m_table2[eMFXInitialize])(vplParam, &m_session);
|
|
}
|
|
else {
|
|
if (m_table[eMFXInitEx]) {
|
|
// initialize with MFXInitEx if present (API >= 1.14)
|
|
mfx_res = ((decltype(MFXInitEx) *)m_table[eMFXInitEx])(par, &m_session);
|
|
}
|
|
else {
|
|
// initialize with MFXInit for API < 1.14
|
|
mfx_res = ((decltype(MFXInit) *)m_table[eMFXInit])(par.Implementation,
|
|
&(par.Version),
|
|
&m_session);
|
|
}
|
|
}
|
|
|
|
if (MFX_ERR_NONE != mfx_res) {
|
|
break;
|
|
}
|
|
|
|
// Below we just get some data and double check that we got what we have expected
|
|
// to get. Some of these checks are done inside mediasdk init function
|
|
mfx_res =
|
|
((decltype(MFXQueryVersion) *)m_table[eMFXQueryVersion])(m_session, &m_version);
|
|
if (MFX_ERR_NONE != mfx_res) {
|
|
break;
|
|
}
|
|
|
|
if (m_version < par.Version) {
|
|
mfx_res = MFX_ERR_UNSUPPORTED;
|
|
break;
|
|
}
|
|
|
|
mfx_res = ((decltype(MFXQueryIMPL) *)m_table[eMFXQueryIMPL])(m_session,
|
|
&m_implementation);
|
|
if (MFX_ERR_NONE != mfx_res) {
|
|
mfx_res = MFX_ERR_UNSUPPORTED;
|
|
break;
|
|
}
|
|
} while (false);
|
|
|
|
if (MFX_ERR_NONE == mfx_res) {
|
|
m_dlh = std::move(hdl);
|
|
break;
|
|
}
|
|
else {
|
|
Close();
|
|
}
|
|
}
|
|
}
|
|
|
|
return mfx_res;
|
|
}
|
|
|
|
mfxStatus LoaderCtx::Close() {
|
|
auto proc = (decltype(MFXClose) *)m_table[eMFXClose];
|
|
mfxStatus mfx_res = (proc) ? (*proc)(m_session) : MFX_ERR_NONE;
|
|
|
|
m_implementation = {};
|
|
m_version = {};
|
|
m_session = nullptr;
|
|
std::fill(std::begin(m_table), std::end(m_table), nullptr);
|
|
return mfx_res;
|
|
}
|
|
|
|
} // namespace MFX
|
|
|
|
// internal function - load a specific DLL, return unsupported if it fails
|
|
// vplParam is required for API >= 2.0 (load via MFXInitialize)
|
|
mfxStatus MFXInitEx2(mfxVersion version,
|
|
mfxInitializationParam vplParam,
|
|
mfxIMPL hwImpl,
|
|
mfxSession *session,
|
|
mfxU16 *deviceID,
|
|
char *dllName) {
|
|
if (!session)
|
|
return MFX_ERR_NULL_PTR;
|
|
|
|
*deviceID = 0;
|
|
|
|
// fill minimal 1.x parameters for Init to choose correct initialization path
|
|
mfxInitParam par = {};
|
|
par.Version = version;
|
|
|
|
// select first adapter if not specified
|
|
// only relevant for MSDK-via-MFXLoad path
|
|
if (!hwImpl)
|
|
hwImpl = MFX_IMPL_HARDWARE;
|
|
|
|
switch (vplParam.AccelerationMode) {
|
|
case MFX_ACCEL_MODE_NA:
|
|
par.Implementation = MFX_IMPL_SOFTWARE;
|
|
break;
|
|
case MFX_ACCEL_MODE_VIA_D3D9:
|
|
par.Implementation = hwImpl | MFX_IMPL_VIA_D3D9;
|
|
break;
|
|
case MFX_ACCEL_MODE_VIA_D3D11:
|
|
par.Implementation = hwImpl | MFX_IMPL_VIA_D3D11;
|
|
break;
|
|
case MFX_ACCEL_MODE_VIA_VAAPI:
|
|
par.Implementation = hwImpl | MFX_IMPL_VIA_VAAPI;
|
|
break;
|
|
default:
|
|
par.Implementation = hwImpl;
|
|
break;
|
|
}
|
|
|
|
// also pass extBuf array (if any) to MFXInitEx for 1.x API
|
|
par.NumExtParam = vplParam.NumExtParam;
|
|
par.ExtParam = (vplParam.NumExtParam ? vplParam.ExtParam : nullptr);
|
|
|
|
#ifdef ONEVPL_EXPERIMENTAL
|
|
// if GPUCopy is enabled via MFXSetConfigProperty(DeviceCopy), set corresponding
|
|
// flag in mfxInitParam for legacy RTs
|
|
par.GPUCopy = vplParam.DeviceCopy;
|
|
#endif
|
|
|
|
try {
|
|
std::unique_ptr<MFX::LoaderCtx> loader;
|
|
|
|
loader.reset(new MFX::LoaderCtx{});
|
|
|
|
mfxStatus mfx_res = loader->Init(par, vplParam, deviceID, dllName);
|
|
if (MFX_ERR_NONE == mfx_res) {
|
|
*session = (mfxSession)loader.release();
|
|
}
|
|
else {
|
|
*session = nullptr;
|
|
}
|
|
|
|
return mfx_res;
|
|
}
|
|
catch (...) {
|
|
return MFX_ERR_MEMORY_ALLOC;
|
|
}
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
mfxStatus MFXInit(mfxIMPL impl, mfxVersion *ver, mfxSession *session) {
|
|
mfxInitParam par{};
|
|
|
|
par.Implementation = impl;
|
|
if (ver) {
|
|
par.Version = *ver;
|
|
}
|
|
else {
|
|
par.Version = VERSION(MFX_VERSION_MAJOR, MFX_VERSION_MINOR);
|
|
}
|
|
|
|
return MFXInitEx(par, session);
|
|
}
|
|
|
|
mfxStatus MFXInitEx(mfxInitParam par, mfxSession *session) {
|
|
if (!session)
|
|
return MFX_ERR_NULL_PTR;
|
|
|
|
const mfxIMPL implMethod = par.Implementation & (MFX_IMPL_VIA_ANY - 1);
|
|
mfxInitializationParam vplParam = {};
|
|
if (implMethod == MFX_IMPL_SOFTWARE) {
|
|
vplParam.AccelerationMode = MFX_ACCEL_MODE_NA;
|
|
}
|
|
else {
|
|
vplParam.AccelerationMode = MFX_ACCEL_MODE_VIA_VAAPI;
|
|
}
|
|
|
|
try {
|
|
std::unique_ptr<MFX::LoaderCtx> loader;
|
|
|
|
loader.reset(new MFX::LoaderCtx{});
|
|
|
|
mfxStatus mfx_res = loader->Init(par, vplParam, nullptr, nullptr);
|
|
if (MFX_ERR_NONE == mfx_res) {
|
|
*session = (mfxSession)loader.release();
|
|
}
|
|
else {
|
|
*session = nullptr;
|
|
}
|
|
|
|
return mfx_res;
|
|
}
|
|
catch (...) {
|
|
return MFX_ERR_MEMORY_ALLOC;
|
|
}
|
|
}
|
|
|
|
mfxStatus MFXClose(mfxSession session) {
|
|
if (!session)
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
|
|
try {
|
|
std::unique_ptr<MFX::LoaderCtx> loader((MFX::LoaderCtx *)session);
|
|
mfxStatus mfx_res = loader->Close();
|
|
|
|
if (mfx_res == MFX_ERR_UNDEFINED_BEHAVIOR) {
|
|
// It is possible, that there is an active child session.
|
|
// Can't unload library in this case.
|
|
loader.release();
|
|
}
|
|
return mfx_res;
|
|
}
|
|
catch (...) {
|
|
return MFX_ERR_MEMORY_ALLOC;
|
|
}
|
|
}
|
|
|
|
// passthrough functions to implementation
|
|
mfxStatus MFXMemory_GetSurfaceForVPP(mfxSession session, mfxFrameSurface1 **surface) {
|
|
if (!session)
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
|
|
MFX::LoaderCtx *loader = (MFX::LoaderCtx *)session;
|
|
|
|
auto proc = (decltype(MFXMemory_GetSurfaceForVPP) *)loader->getFunction2(
|
|
MFX::eMFXMemory_GetSurfaceForVPP);
|
|
if (!proc) {
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
}
|
|
|
|
return (*proc)(loader->getSession(), surface);
|
|
}
|
|
|
|
mfxStatus MFXMemory_GetSurfaceForVPPOut(mfxSession session, mfxFrameSurface1 **surface) {
|
|
if (!session)
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
|
|
MFX::LoaderCtx *loader = (MFX::LoaderCtx *)session;
|
|
|
|
auto proc = (decltype(MFXMemory_GetSurfaceForVPPOut) *)loader->getFunction2(
|
|
MFX::eMFXMemory_GetSurfaceForVPPOut);
|
|
if (!proc) {
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
}
|
|
|
|
return (*proc)(loader->getSession(), surface);
|
|
}
|
|
|
|
mfxStatus MFXMemory_GetSurfaceForEncode(mfxSession session, mfxFrameSurface1 **surface) {
|
|
if (!session)
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
|
|
MFX::LoaderCtx *loader = (MFX::LoaderCtx *)session;
|
|
|
|
auto proc = (decltype(MFXMemory_GetSurfaceForEncode) *)loader->getFunction2(
|
|
MFX::eMFXMemory_GetSurfaceForEncode);
|
|
if (!proc) {
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
}
|
|
|
|
return (*proc)(loader->getSession(), surface);
|
|
}
|
|
|
|
mfxStatus MFXMemory_GetSurfaceForDecode(mfxSession session, mfxFrameSurface1 **surface) {
|
|
if (!session)
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
|
|
MFX::LoaderCtx *loader = (MFX::LoaderCtx *)session;
|
|
|
|
auto proc = (decltype(MFXMemory_GetSurfaceForDecode) *)loader->getFunction2(
|
|
MFX::eMFXMemory_GetSurfaceForDecode);
|
|
if (!proc) {
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
}
|
|
|
|
return (*proc)(loader->getSession(), surface);
|
|
}
|
|
|
|
mfxStatus MFXVideoDECODE_VPP_Init(mfxSession session,
|
|
mfxVideoParam *decode_par,
|
|
mfxVideoChannelParam **vpp_par_array,
|
|
mfxU32 num_vpp_par) {
|
|
if (!session)
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
|
|
MFX::LoaderCtx *loader = (MFX::LoaderCtx *)session;
|
|
|
|
auto proc =
|
|
(decltype(MFXVideoDECODE_VPP_Init) *)loader->getFunction2(MFX::eMFXVideoDECODE_VPP_Init);
|
|
if (!proc) {
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
}
|
|
|
|
return (*proc)(loader->getSession(), decode_par, vpp_par_array, num_vpp_par);
|
|
}
|
|
|
|
mfxStatus MFXVideoDECODE_VPP_DecodeFrameAsync(mfxSession session,
|
|
mfxBitstream *bs,
|
|
mfxU32 *skip_channels,
|
|
mfxU32 num_skip_channels,
|
|
mfxSurfaceArray **surf_array_out) {
|
|
if (!session)
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
|
|
MFX::LoaderCtx *loader = (MFX::LoaderCtx *)session;
|
|
|
|
auto proc = (decltype(MFXVideoDECODE_VPP_DecodeFrameAsync) *)loader->getFunction2(
|
|
MFX::eMFXVideoDECODE_VPP_DecodeFrameAsync);
|
|
if (!proc) {
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
}
|
|
|
|
return (*proc)(loader->getSession(), bs, skip_channels, num_skip_channels, surf_array_out);
|
|
}
|
|
|
|
mfxStatus MFXVideoDECODE_VPP_Reset(mfxSession session,
|
|
mfxVideoParam *decode_par,
|
|
mfxVideoChannelParam **vpp_par_array,
|
|
mfxU32 num_vpp_par) {
|
|
if (!session)
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
|
|
MFX::LoaderCtx *loader = (MFX::LoaderCtx *)session;
|
|
|
|
auto proc =
|
|
(decltype(MFXVideoDECODE_VPP_Reset) *)loader->getFunction2(MFX::eMFXVideoDECODE_VPP_Reset);
|
|
if (!proc) {
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
}
|
|
|
|
return (*proc)(loader->getSession(), decode_par, vpp_par_array, num_vpp_par);
|
|
}
|
|
|
|
mfxStatus MFXVideoDECODE_VPP_GetChannelParam(mfxSession session,
|
|
mfxVideoChannelParam *par,
|
|
mfxU32 channel_id) {
|
|
if (!session)
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
|
|
MFX::LoaderCtx *loader = (MFX::LoaderCtx *)session;
|
|
|
|
auto proc = (decltype(MFXVideoDECODE_VPP_GetChannelParam) *)loader->getFunction2(
|
|
MFX::eMFXVideoDECODE_VPP_GetChannelParam);
|
|
if (!proc) {
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
}
|
|
|
|
return (*proc)(loader->getSession(), par, channel_id);
|
|
}
|
|
|
|
mfxStatus MFXVideoDECODE_VPP_Close(mfxSession session) {
|
|
if (!session)
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
|
|
MFX::LoaderCtx *loader = (MFX::LoaderCtx *)session;
|
|
|
|
auto proc =
|
|
(decltype(MFXVideoDECODE_VPP_Close) *)loader->getFunction2(MFX::eMFXVideoDECODE_VPP_Close);
|
|
if (!proc) {
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
}
|
|
|
|
return (*proc)(loader->getSession());
|
|
}
|
|
|
|
mfxStatus MFXVideoVPP_ProcessFrameAsync(mfxSession session,
|
|
mfxFrameSurface1 *in,
|
|
mfxFrameSurface1 **out) {
|
|
if (!session)
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
|
|
MFX::LoaderCtx *loader = (MFX::LoaderCtx *)session;
|
|
|
|
auto proc = (decltype(MFXVideoVPP_ProcessFrameAsync) *)loader->getFunction2(
|
|
MFX::eMFXVideoVPP_ProcessFrameAsync);
|
|
if (!proc) {
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
}
|
|
|
|
return (*proc)(loader->getSession(), in, out);
|
|
}
|
|
|
|
mfxStatus MFXJoinSession(mfxSession session, mfxSession child_session) {
|
|
if (!session || !child_session) {
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
}
|
|
|
|
MFX::LoaderCtx *loader = (MFX::LoaderCtx *)session;
|
|
MFX::LoaderCtx *child_loader = (MFX::LoaderCtx *)child_session;
|
|
|
|
if (loader->getVersion().Version != child_loader->getVersion().Version) {
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
}
|
|
|
|
auto proc = (decltype(MFXJoinSession) *)loader->getFunction(MFX::eMFXJoinSession);
|
|
if (!proc) {
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
}
|
|
|
|
return (*proc)(loader->getSession(), child_loader->getSession());
|
|
}
|
|
|
|
static mfxStatus AllocateCloneLoader(MFX::LoaderCtx *parentLoader, MFX::LoaderCtx **cloneLoader) {
|
|
// initialization param structs are not used when bCloneSession == true
|
|
mfxInitParam par = {};
|
|
mfxInitializationParam vplParam = {};
|
|
mfxU16 deviceID = 0;
|
|
|
|
// initialization extBufs are not saved at this level
|
|
// the RT should save these when the parent session is created and may use
|
|
// them when creating the cloned session
|
|
par.NumExtParam = 0;
|
|
|
|
try {
|
|
std::unique_ptr<MFX::LoaderCtx> cl;
|
|
|
|
cl.reset(new MFX::LoaderCtx{});
|
|
|
|
mfxStatus mfx_res =
|
|
cl->Init(par, vplParam, &deviceID, (char *)parentLoader->getLibPath(), true);
|
|
if (MFX_ERR_NONE == mfx_res) {
|
|
*cloneLoader = cl.release();
|
|
}
|
|
else {
|
|
*cloneLoader = nullptr;
|
|
}
|
|
|
|
return mfx_res;
|
|
}
|
|
catch (...) {
|
|
return MFX_ERR_MEMORY_ALLOC;
|
|
}
|
|
}
|
|
|
|
mfxStatus MFXCloneSession(mfxSession session, mfxSession *clone) {
|
|
if (!session || !clone)
|
|
return MFX_ERR_INVALID_HANDLE;
|
|
|
|
MFX::LoaderCtx *loader = (MFX::LoaderCtx *)session;
|
|
mfxVersion version = loader->getVersion();
|
|
*clone = nullptr;
|
|
|
|
// initialize the clone session
|
|
// for runtimes with 1.x API, call MFXInit followed by MFXJoinSession
|
|
// for runtimes with 2.x API, use RT implementation of MFXCloneSession (passthrough)
|
|
if (version.Major == 1) {
|
|
mfxStatus mfx_res = MFXInit(loader->getImpl(), &version, clone);
|
|
if (MFX_ERR_NONE != mfx_res) {
|
|
return mfx_res;
|
|
}
|
|
|
|
// join the sessions
|
|
mfx_res = MFXJoinSession(session, *clone);
|
|
if (MFX_ERR_NONE != mfx_res) {
|
|
MFXClose(*clone);
|
|
*clone = nullptr;
|
|
return mfx_res;
|
|
}
|
|
}
|
|
else if (version.Major == 2) {
|
|
MFX::LoaderCtx *loader = (MFX::LoaderCtx *)session;
|
|
|
|
// MFXCloneSession not included in function pointer search during init
|
|
// for bwd-compat, check for it here and fail gracefully if missing
|
|
void *libHandle = loader->getHandle();
|
|
auto proc = (decltype(MFXCloneSession) *)(dlsym(libHandle, "MFXCloneSession"));
|
|
if (!proc)
|
|
return MFX_ERR_UNSUPPORTED;
|
|
|
|
// allocate new dispatcher-level session object and copy
|
|
// state from parent session (function pointer tables, impl type, etc.)
|
|
MFX::LoaderCtx *cloneLoader;
|
|
mfxStatus mfx_res = AllocateCloneLoader(loader, &cloneLoader);
|
|
if (mfx_res != MFX_ERR_NONE)
|
|
return mfx_res;
|
|
|
|
// call RT implementation of MFXCloneSession
|
|
mfxSession cloneRT;
|
|
mfx_res = (*proc)(loader->getSession(), &cloneRT);
|
|
|
|
if (mfx_res != MFX_ERR_NONE || cloneRT == NULL) {
|
|
// RT call failed, delete cloned loader (no valid session created)
|
|
delete cloneLoader;
|
|
return MFX_ERR_UNSUPPORTED;
|
|
}
|
|
cloneLoader->setSession(cloneRT);
|
|
|
|
// get version of cloned session
|
|
mfxVersion cloneVersion = {};
|
|
mfx_res = MFXQueryVersion((mfxSession)cloneLoader, &cloneVersion);
|
|
cloneLoader->setVersion(cloneVersion);
|
|
if (mfx_res != MFX_ERR_NONE) {
|
|
MFXClose((mfxSession)cloneLoader);
|
|
return mfx_res;
|
|
}
|
|
|
|
*clone = (mfxSession)cloneLoader;
|
|
}
|
|
else {
|
|
return MFX_ERR_UNSUPPORTED;
|
|
}
|
|
|
|
return MFX_ERR_NONE;
|
|
}
|
|
|
|
#undef FUNCTION
|
|
#define FUNCTION(return_value, func_name, formal_param_list, actual_param_list) \
|
|
return_value MFX_CDECL func_name formal_param_list { \
|
|
/* get the function's address and make a call */ \
|
|
if (!session) \
|
|
return MFX_ERR_INVALID_HANDLE; \
|
|
\
|
|
MFX::LoaderCtx *loader = (MFX::LoaderCtx *)session; \
|
|
\
|
|
auto proc = (decltype(func_name) *)loader->getFunction(MFX::e##func_name); \
|
|
if (!proc) \
|
|
return MFX_ERR_INVALID_HANDLE; \
|
|
\
|
|
/* get the real session pointer */ \
|
|
session = loader->getSession(); \
|
|
/* pass down the call */ \
|
|
return (*proc)actual_param_list; \
|
|
}
|
|
|
|
#include "linux/mfxvideo_functions.h" // NOLINT(build/include)
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|