feat(encode): native QSV backend — libvpl-sys + qsv.rs (Phases 0-3 of design/native-qsv-encoder.md)

Vendored MIT VPL dispatcher (static, trimmed tree, pin 674d015b/v2.17.0) built
via cmake+bindgen behind new feature 'qsv' (pf-encode + punktfunk-host forward).
qsv.rs: dispatcher session on the capture adapter (LUID-matched), SetHandle
D3D11, AsyncDepth=1/GopRefDist=1/VDEnc/CBR + HRD-off low-latency config,
GetSurfaceForEncode + GPU CopySubresourceRegion input (zero-copy, no readback
path), bounded sync-point poll, in-place reset with teardown escalation, no-IDR
bitrate retarget (Reset + StartNewSequence=OFF), 10-bit P010 HEVC-Main10/AV1,
HDR mastering/CLL SEI-OBU at IDR + BT.2020/PQ VSI, LTR-RFI via mfxExtRefListCtrl
(AMF slot policy port, Query-gated per codec, wire-index FrameOrder pinning).
Dispatch: native-first with ffmpeg fallback + PUNKTFUNK_QSV_FFMPEG hatch;
probes (can_encode_10bit / windows_codec_support / windows_backend_is_probed)
now answer natively for QSV.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-17 19:34:18 +02:00
parent bbe4380b41
commit 55e7f3fca9
88 changed files with 29515 additions and 16 deletions
+204
View File
@@ -0,0 +1,204 @@
# ##############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
# ##############################################################################
cmake_minimum_required(VERSION 3.13.0)
set(TARGET VPL)
set(OUTPUT_NAME "vpl")
set(DLL_PREFIX "lib")
if(WIN32)
set(SOURCES
src/windows/main.cpp
src/windows/mfx_critical_section.cpp
src/windows/mfx_dispatcher.cpp
src/windows/mfx_dispatcher_log.cpp
src/windows/mfx_driver_store_loader.cpp
src/windows/mfx_dxva2_device.cpp
src/windows/mfx_function_table.cpp
src/windows/mfx_library_iterator.cpp
src/windows/mfx_load_dll.cpp
src/windows/mfx_win_reg_key.cpp
src/windows/libmfx.def)
if(BUILD_SHARED_LIBS)
configure_file(src/windows/version.rc.in src/windows/version.rc @ONLY)
list(APPEND SOURCES ${CMAKE_CURRENT_BINARY_DIR}/src/windows/version.rc)
endif()
endif()
if(UNIX)
set(SOURCES src/linux/mfxloader.cpp)
if(NOT DEFINED MFX_MODULES_DIR)
set(MFX_MODULES_DIR ${CMAKE_INSTALL_FULL_LIBDIR})
endif()
add_definitions(-DMFX_MODULES_DIR="${MFX_MODULES_DIR}")
message(STATUS "MFX_MODULES_DIR=${MFX_MODULES_DIR}")
endif()
if(BUILD_EXPERIMENTAL)
add_definitions(-DONEVPL_EXPERIMENTAL)
endif()
list(
APPEND
SOURCES
src/mfx_dispatcher_vpl.cpp
src/mfx_dispatcher_vpl_loader.cpp
src/mfx_dispatcher_vpl_config.cpp
src/mfx_dispatcher_vpl_lowlatency.cpp
src/mfx_dispatcher_vpl_log.cpp
src/mfx_dispatcher_vpl_msdk.cpp
src/mfx_config_interface/mfx_config_interface.cpp
src/mfx_config_interface/mfx_config_interface_string_api.cpp)
add_library(${TARGET} "")
# disable warnings for dispatcher library itself but not subprojects (unit
# tests)
set_target_properties(${TARGET} PROPERTIES COMPILE_DEFINITIONS
"MFX_DEPRECATED_OFF")
# optionally include the install location of dispatcher dll in the runtime
# search process
if(UNIX)
if(ENABLE_LIBDIR_IN_RUNTIME_SEARCH)
file(TO_CMAKE_PATH "${CMAKE_INSTALL_FULL_LIBDIR}" _install_libdir_search)
target_compile_definitions(
${TARGET} PRIVATE INSTALL_LIBDIR_SEARCH=\"${_install_libdir_search}\")
message(STATUS "Enabled install libdir search: ${_install_libdir_search}")
endif()
endif()
if(WIN32)
# force libxxx style sharedlib name on Windows
if(BUILD_SHARED_LIBS)
set_target_properties(${TARGET} PROPERTIES PREFIX ${DLL_PREFIX})
endif()
set(SHLIB_FILE_NAME ${DLL_PREFIX}${OUTPUT_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX})
set(SHLIB_FILE_NAME_DEBUG
${DLL_PREFIX}${OUTPUT_NAME}${CMAKE_DEBUG_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX}
)
else()
# use version script on Linux
set_target_properties(
${TARGET}
PROPERTIES
LINK_FLAGS
"-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/src/linux/libvpl.map")
set(SHLIB_FILE_NAME
${CMAKE_SHARED_LIBRARY_PREFIX}${OUTPUT_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}.${API_VERSION_MAJOR}
)
set(SHLIB_FILE_NAME_DEBUG ${SHLIB_FILE_NAME})
endif()
set(LIB_FILE_NAME
${CMAKE_STATIC_LIBRARY_PREFIX}${OUTPUT_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX})
set(IMPLIB_FILE_NAME
${CMAKE_IMPORT_LIBRARY_PREFIX}${OUTPUT_NAME}${CMAKE_IMPORT_LIBRARY_SUFFIX})
set(LIB_FILE_NAME_DEBUG
${CMAKE_STATIC_LIBRARY_PREFIX}${OUTPUT_NAME}${CMAKE_DEBUG_POSTFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}
)
set(IMPLIB_FILE_NAME_DEBUG
${CMAKE_IMPORT_LIBRARY_PREFIX}${OUTPUT_NAME}${CMAKE_DEBUG_POSTFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX}
)
set_target_properties(
${TARGET}
PROPERTIES OUTPUT_NAME ${OUTPUT_NAME} SOVERSION ${API_VERSION_MAJOR}
VERSION ${API_VERSION_MAJOR}.${API_VERSION_MINOR})
target_sources(${TARGET} PRIVATE ${SOURCES})
if(UNIX)
# require pthreads for loading legacy MSDK runtimes
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)
if(BUILD_SHARED_LIBS)
target_link_libraries(${TARGET} PRIVATE Threads::Threads)
else()
target_link_libraries(${TARGET} PUBLIC Threads::Threads)
endif()
endif()
target_link_libraries(${TARGET} PUBLIC vpl-api)
if(BUILD_SHARED_LIBS)
target_link_libraries(${TARGET} PRIVATE ${CMAKE_DL_LIBS})
else()
target_link_libraries(${TARGET} PUBLIC ${CMAKE_DL_LIBS})
endif()
target_include_directories(${TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR})
if(INSTALL_LIB)
install(
TARGETS ${TARGET}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT ${VPL_COMPONENT_LIB}
NAMELINK_SKIP
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${VPL_COMPONENT_LIB})
endif()
if(INSTALL_DEV)
install(
TARGETS ${TARGET}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT ${VPL_COMPONENT_DEV}
NAMELINK_ONLY)
if(WIN32)
install(TARGETS ${TARGET} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT ${VPL_COMPONENT_DEV})
endif()
file(RELATIVE_PATH cmake_rel_prefix ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/vpl
${CMAKE_INSTALL_PREFIX})
file(RELATIVE_PATH cmake_rel_libdir ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/vpl
${CMAKE_INSTALL_FULL_LIBDIR})
file(RELATIVE_PATH cmake_rel_incdir ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/vpl
${CMAKE_INSTALL_FULL_INCLUDEDIR})
file(RELATIVE_PATH cmake_rel_bindir ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/vpl
${CMAKE_INSTALL_FULL_BINDIR})
configure_file(cmake/VPLConfig.cmake.in cmake/VPLConfig.cmake @ONLY)
configure_file(cmake/VPLConfigVersion.cmake.in cmake/VPLConfigVersion.cmake
@ONLY)
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/cmake/VPLConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/cmake/VPLConfigVersion.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/vpl"
COMPONENT ${VPL_COMPONENT_DEV})
file(RELATIVE_PATH pc_rel_prefix ${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig
${CMAKE_INSTALL_PREFIX})
file(RELATIVE_PATH pc_rel_libdir ${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig
${CMAKE_INSTALL_FULL_LIBDIR})
file(RELATIVE_PATH pc_rel_incdir ${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig
${CMAKE_INSTALL_FULL_INCLUDEDIR})
set(pc_rel_prefix "$\{pcfiledir}/${pc_rel_prefix}")
set(pc_rel_libdir "$\{pcfiledir}/${pc_rel_libdir}")
set(pc_rel_incdir "$\{pcfiledir}/${pc_rel_incdir}")
if(CMAKE_DL_LIBS)
set(DL_LIBS "-l${CMAKE_DL_LIBS}")
endif()
if(MINGW)
# being conservative by restricting to MinGW, these are probably ok for
# WIN32 in general
set(MINGW_LIBS "-lole32 -lgdi32 -luuid")
endif()
set(VPL_PKGCONFIG_DEPENDENT_LIBS
"${DL_LIBS} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_LIBS} ${CXX_LIB}")
configure_file("pkgconfig/vpl.pc.in" "pkgconfig/vpl.pc" @ONLY)
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/vpl.pc"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
COMPONENT ${VPL_COMPONENT_DEV})
endif()
if(BUILD_TESTS)
add_subdirectory(test)
endif()
@@ -0,0 +1,146 @@
# ##############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
# ##############################################################################
# * Config file for the VPL package It defines the following variables
# VPL_<component>_FOUND VPL_IMPORTED_TARGETS
#
# VPLConfigVersion.cmake defines VPL_VERSION
option(VPL_SHARED "Use shared instead of static version of dispatcher."
@BUILD_SHARED_LIBS@)
# Initialize to default values
set(VPL_INTERFACE_VERSION @API_VERSION_MAJOR@)
get_filename_component(_vpl_config_file
"${CMAKE_CURRENT_LIST_DIR}/VPLConfig.cmake" REALPATH)
get_filename_component(_vpl_config_dir "${_vpl_config_file}" DIRECTORY)
get_filename_component(_vpl_install_prefix
"${_vpl_config_dir}/@cmake_rel_prefix@" REALPATH)
get_filename_component(VPL_LIB_DIR "${_vpl_config_dir}/@cmake_rel_libdir@"
ABSOLUTE)
get_filename_component(VPL_INCLUDE_DIR "${_vpl_config_dir}/@cmake_rel_incdir@"
ABSOLUTE)
get_filename_component(VPL_BIN_DIR "${_vpl_config_dir}/@cmake_rel_bindir@"
ABSOLUTE)
if(CMAKE_SYSTEM_NAME MATCHES Windows)
set(VPL_SHLIB_DIR ${VPL_BIN_DIR})
else()
set(VPL_SHLIB_DIR ${VPL_LIB_DIR})
endif()
if(NOT VPL_IMPORTED_TARGETS)
set(VPL_IMPORTED_TARGETS "")
endif()
if(NOT VPL_FIND_COMPONENTS)
set(VPL_FIND_COMPONENTS "dispatcher;api")
foreach(_vpl_component ${VPL_FIND_COMPONENTS})
set(VPL_FIND_REQUIRED_${_vpl_component} 1)
endforeach()
endif()
# VPL::dispatcher
set(VPL_dispatcher_FOUND 0)
get_filename_component(_dispatcher_shlib "${VPL_SHLIB_DIR}/@SHLIB_FILE_NAME@"
ABSOLUTE)
get_filename_component(_dispatcher_debug_shlib
"${VPL_SHLIB_DIR}/@SHLIB_FILE_NAME_DEBUG@" ABSOLUTE)
get_filename_component(_dispatcher_lib "${VPL_LIB_DIR}/@LIB_FILE_NAME@"
ABSOLUTE)
get_filename_component(_dispatcher_debug_lib
"${VPL_LIB_DIR}/@LIB_FILE_NAME_DEBUG@" ABSOLUTE)
get_filename_component(_dispatcher_implib "${VPL_LIB_DIR}/@LIB_FILE_NAME@"
ABSOLUTE)
get_filename_component(_dispatcher_debug_implib
"${VPL_LIB_DIR}/@LIB_FILE_NAME_DEBUG@" ABSOLUTE)
if(TARGET VPL::dispatcher)
list(APPEND VPL_IMPORTED_TARGETS VPL::dispatcher)
set(VPL_dispatcher_FOUND 1)
else()
if(VPL_SHARED)
if(EXISTS "${_dispatcher_shlib}" OR EXISTS "${_dispatcher_debug_shlib}")
list(APPEND VPL_IMPORTED_TARGETS VPL::dispatcher)
set(VPL_dispatcher_FOUND 1)
add_library(VPL::dispatcher SHARED IMPORTED)
set_target_properties(
VPL::dispatcher
PROPERTIES IMPORTED_LOCATION_RELEASE ${_dispatcher_shlib}
IMPORTED_LOCATION_RELWITHDEBINFO ${_dispatcher_shlib}
IMPORTED_LOCATION_MINSIZEREL ${_dispatcher_shlib}
IMPORTED_LOCATION_DEBUG ${_dispatcher_debug_shlib}
IMPORTED_LOCATION_RELWITHDEBRT ${_dispatcher_debug_shlib})
if(CMAKE_SYSTEM_NAME MATCHES Windows)
set_target_properties(
VPL::dispatcher
PROPERTIES IMPORTED_IMPLIB_RELEASE ${_dispatcher_implib}
IMPORTED_IMPLIB_RELWITHDEBINFO ${_dispatcher_implib}
IMPORTED_IMPLIB_MINSIZEREL ${_dispatcher_implib}
IMPORTED_IMPLIB_DEBUG ${_dispatcher_debug_implib}
IMPORTED_IMPLIB_RELWITHDEBRT ${_dispatcher_debug_implib})
endif()
elseif(VPL_FIND_REQUIRED AND VPL_FIND_REQUIRED_dispatcher)
message(STATUS "Unable to find required VPL component: dispatcher")
set(VPL_FOUND FALSE)
endif()
else()
if(EXISTS "${_dispatcher_lib}" OR EXISTS "${_dispatcher_debug_lib}")
list(APPEND VPL_IMPORTED_TARGETS VPL::dispatcher)
set(VPL_dispatcher_FOUND 1)
add_library(VPL::dispatcher STATIC IMPORTED)
set_target_properties(
VPL::dispatcher
PROPERTIES IMPORTED_LOCATION_RELEASE ${_dispatcher_lib}
IMPORTED_LOCATION_RELWITHDEBINFO ${_dispatcher_lib}
IMPORTED_LOCATION_MINSIZEREL ${_dispatcher_lib}
IMPORTED_LOCATION_DEBUG ${_dispatcher_debug_lib}
IMPORTED_LOCATION_RELWITHDEBRT ${_dispatcher_debug_lib})
if(UNIX)
# require pthreads for loading legacy MSDK runtimes
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)
target_link_libraries(VPL::dispatcher INTERFACE Threads::Threads)
endif()
target_link_libraries(VPL::dispatcher INTERFACE ${CMAKE_DL_LIBS})
elseif(VPL_FIND_REQUIRED AND VPL_FIND_REQUIRED_dispatcher)
message(STATUS "Unable to find required VPL component: dispatcher")
set(VPL_FOUND FALSE)
endif()
endif()
set_target_properties(VPL::dispatcher PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
"${VPL_INCLUDE_DIR}")
endif()
unset(_dispatcher_shlib)
# VPL::api
set(VPL_api_FOUND 0)
if(EXISTS ${VPL_INCLUDE_DIR})
if(NOT TARGET VPL::api)
add_library(VPL::api INTERFACE IMPORTED)
set_target_properties(VPL::api PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
"${VPL_INCLUDE_DIR}")
endif()
list(APPEND VPL_IMPORTED_TARGETS VPL::api)
set(VPL_api_FOUND 1)
endif()
# VPL::cppapi
set(VPL_cppapi_FOUND 0)
if(EXISTS ${VPL_INCLUDE_DIR})
if(NOT TARGET VPL::cppapi)
add_library(VPL::cppapi INTERFACE IMPORTED)
set_target_properties(VPL::cppapi PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
"${VPL_INCLUDE_DIR}")
endif()
list(APPEND VPL_IMPORTED_TARGETS VPL::cppapi)
set(VPL_cppapi_FOUND 1)
endif()
@@ -0,0 +1,17 @@
# ##############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
# ##############################################################################
set(PACKAGE_VERSION "@API_VERSION_MAJOR@.@API_VERSION_MINOR@")
# Check whether the requested PACKAGE_FIND_VERSION is compatible
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()
@@ -0,0 +1,12 @@
prefix=@pc_rel_prefix@
libdir=@pc_rel_libdir@
includedir=@pc_rel_incdir@
Name: Intel(R) Video Processing Library
Description: Accelerated video decode, encode, and frame processing capabilities on Intel(R) GPUs
Version: @API_VERSION_MAJOR@.@API_VERSION_MINOR@
URL: https://github.com/intel/libvpl
Libs: -L${libdir} -l@OUTPUT_NAME@ @VPL_PKGCONFIG_DEPENDENT_LIBS@
Libs.private: @VPL_PKGCONFIG_PRIVATE_LIBS@
Cflags: -I${includedir} -I${includedir}/vpl
@@ -0,0 +1,448 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#ifndef LIBVPL_SRC_LINUX_DEVICE_IDS_H_
#define LIBVPL_SRC_LINUX_DEVICE_IDS_H_
// Tables from:
// https://github.com/Intel-Media-SDK/MediaSDK/blob/master/_studio/shared/src/libmfx_core_vaapi.cpp
// https://github.com/Intel-Media-SDK/MediaSDK/blob/master/_studio/shared/include/mfxstructures-int.h
#include <algorithm>
#include <fstream>
#include <string>
#include <vector>
#include "vpl/mfxvideo.h"
enum eMFXHWType {
MFX_HW_UNKNOWN = 0,
MFX_HW_SNB = 0x300000,
MFX_HW_IVB = 0x400000,
MFX_HW_HSW = 0x500000,
MFX_HW_HSW_ULT = 0x500001,
MFX_HW_VLV = 0x600000,
MFX_HW_BDW = 0x700000,
MFX_HW_CHT = 0x800000,
MFX_HW_SCL = 0x900000,
MFX_HW_APL = 0x1000000,
MFX_HW_KBL = 0x1100000,
MFX_HW_GLK = MFX_HW_KBL + 1,
MFX_HW_CFL = MFX_HW_KBL + 2,
MFX_HW_CNL = 0x1200000,
MFX_HW_ICL = 0x1400000,
MFX_HW_ICL_LP = MFX_HW_ICL + 1,
MFX_HW_JSL = 0x1500001,
MFX_HW_EHL = 0x1500002,
};
enum eMFXGTConfig { MFX_GT_UNKNOWN = 0, MFX_GT1 = 1, MFX_GT2 = 2, MFX_GT3 = 3, MFX_GT4 = 4 };
typedef struct {
unsigned int device_id;
eMFXHWType platform;
eMFXGTConfig config;
} mfx_device_item;
// list of legal dev ID for Intel's graphics
static const mfx_device_item listLegalDevIDs[] = {
/*IVB*/
{ 0x0156, MFX_HW_IVB, MFX_GT1 }, /* GT1 mobile */
{ 0x0166, MFX_HW_IVB, MFX_GT2 }, /* GT2 mobile */
{ 0x0152, MFX_HW_IVB, MFX_GT1 }, /* GT1 desktop */
{ 0x0162, MFX_HW_IVB, MFX_GT2 }, /* GT2 desktop */
{ 0x015a, MFX_HW_IVB, MFX_GT1 }, /* GT1 server */
{ 0x016a, MFX_HW_IVB, MFX_GT2 }, /* GT2 server */
/*HSW*/
{ 0x0402, MFX_HW_HSW, MFX_GT1 }, /* GT1 desktop */
{ 0x0412, MFX_HW_HSW, MFX_GT2 }, /* GT2 desktop */
{ 0x0422, MFX_HW_HSW, MFX_GT2 }, /* GT2 desktop */
{ 0x041e, MFX_HW_HSW, MFX_GT2 }, /* Core i3-4130 */
{ 0x040a, MFX_HW_HSW, MFX_GT1 }, /* GT1 server */
{ 0x041a, MFX_HW_HSW, MFX_GT2 }, /* GT2 server */
{ 0x042a, MFX_HW_HSW, MFX_GT2 }, /* GT2 server */
{ 0x0406, MFX_HW_HSW, MFX_GT1 }, /* GT1 mobile */
{ 0x0416, MFX_HW_HSW, MFX_GT2 }, /* GT2 mobile */
{ 0x0426, MFX_HW_HSW, MFX_GT2 }, /* GT2 mobile */
{ 0x0C02, MFX_HW_HSW, MFX_GT1 }, /* SDV GT1 desktop */
{ 0x0C12, MFX_HW_HSW, MFX_GT2 }, /* SDV GT2 desktop */
{ 0x0C22, MFX_HW_HSW, MFX_GT2 }, /* SDV GT2 desktop */
{ 0x0C0A, MFX_HW_HSW, MFX_GT1 }, /* SDV GT1 server */
{ 0x0C1A, MFX_HW_HSW, MFX_GT2 }, /* SDV GT2 server */
{ 0x0C2A, MFX_HW_HSW, MFX_GT2 }, /* SDV GT2 server */
{ 0x0C06, MFX_HW_HSW, MFX_GT1 }, /* SDV GT1 mobile */
{ 0x0C16, MFX_HW_HSW, MFX_GT2 }, /* SDV GT2 mobile */
{ 0x0C26, MFX_HW_HSW, MFX_GT2 }, /* SDV GT2 mobile */
{ 0x0A02, MFX_HW_HSW, MFX_GT1 }, /* ULT GT1 desktop */
{ 0x0A12, MFX_HW_HSW, MFX_GT2 }, /* ULT GT2 desktop */
{ 0x0A22, MFX_HW_HSW, MFX_GT2 }, /* ULT GT2 desktop */
{ 0x0A0A, MFX_HW_HSW, MFX_GT1 }, /* ULT GT1 server */
{ 0x0A1A, MFX_HW_HSW, MFX_GT2 }, /* ULT GT2 server */
{ 0x0A2A, MFX_HW_HSW, MFX_GT2 }, /* ULT GT2 server */
{ 0x0A06, MFX_HW_HSW, MFX_GT1 }, /* ULT GT1 mobile */
{ 0x0A16, MFX_HW_HSW, MFX_GT2 }, /* ULT GT2 mobile */
{ 0x0A26, MFX_HW_HSW, MFX_GT2 }, /* ULT GT2 mobile */
{ 0x0D02, MFX_HW_HSW, MFX_GT1 }, /* CRW GT1 desktop */
{ 0x0D12, MFX_HW_HSW, MFX_GT2 }, /* CRW GT2 desktop */
{ 0x0D22, MFX_HW_HSW, MFX_GT2 }, /* CRW GT2 desktop */
{ 0x0D0A, MFX_HW_HSW, MFX_GT1 }, /* CRW GT1 server */
{ 0x0D1A, MFX_HW_HSW, MFX_GT2 }, /* CRW GT2 server */
{ 0x0D2A, MFX_HW_HSW, MFX_GT2 }, /* CRW GT2 server */
{ 0x0D06, MFX_HW_HSW, MFX_GT1 }, /* CRW GT1 mobile */
{ 0x0D16, MFX_HW_HSW, MFX_GT2 }, /* CRW GT2 mobile */
{ 0x0D26, MFX_HW_HSW, MFX_GT2 }, /* CRW GT2 mobile */
/* this dev IDs added per HSD 5264859 request */
{ 0x040B, MFX_HW_HSW, MFX_GT1 },
/*HASWELL_B_GT1 */ /* Reserved */
{ 0x041B, MFX_HW_HSW, MFX_GT2 }, /*HASWELL_B_GT2*/
{ 0x042B, MFX_HW_HSW, MFX_GT3 }, /*HASWELL_B_GT3*/
{ 0x040E, MFX_HW_HSW, MFX_GT1 },
/*HASWELL_E_GT1*/ /* Reserved */
{ 0x041E, MFX_HW_HSW, MFX_GT2 }, /*HASWELL_E_GT2*/
{ 0x042E, MFX_HW_HSW, MFX_GT3 }, /*HASWELL_E_GT3*/
{ 0x0C0B, MFX_HW_HSW, MFX_GT1 },
/*HASWELL_SDV_B_GT1*/ /* Reserved */
{ 0x0C1B, MFX_HW_HSW, MFX_GT2 }, /*HASWELL_SDV_B_GT2*/
{ 0x0C2B, MFX_HW_HSW, MFX_GT3 }, /*HASWELL_SDV_B_GT3*/
{ 0x0C0E, MFX_HW_HSW, MFX_GT1 },
/*HASWELL_SDV_B_GT1*/ /* Reserved */
{ 0x0C1E, MFX_HW_HSW, MFX_GT2 }, /*HASWELL_SDV_B_GT2*/
{ 0x0C2E, MFX_HW_HSW, MFX_GT3 }, /*HASWELL_SDV_B_GT3*/
{ 0x0A0B, MFX_HW_HSW, MFX_GT1 },
/*HASWELL_ULT_B_GT1*/ /* Reserved */
{ 0x0A1B, MFX_HW_HSW, MFX_GT2 }, /*HASWELL_ULT_B_GT2*/
{ 0x0A2B, MFX_HW_HSW, MFX_GT3 }, /*HASWELL_ULT_B_GT3*/
{ 0x0A0E, MFX_HW_HSW, MFX_GT1 },
/*HASWELL_ULT_E_GT1*/ /* Reserved */
{ 0x0A1E, MFX_HW_HSW, MFX_GT2 }, /*HASWELL_ULT_E_GT2*/
{ 0x0A2E, MFX_HW_HSW, MFX_GT3 }, /*HASWELL_ULT_E_GT3*/
{ 0x0D0B, MFX_HW_HSW, MFX_GT1 },
/*HASWELL_CRW_B_GT1*/ /* Reserved */
{ 0x0D1B, MFX_HW_HSW, MFX_GT2 }, /*HASWELL_CRW_B_GT2*/
{ 0x0D2B, MFX_HW_HSW, MFX_GT3 }, /*HASWELL_CRW_B_GT3*/
{ 0x0D0E, MFX_HW_HSW, MFX_GT1 },
/*HASWELL_CRW_E_GT1*/ /* Reserved */
{ 0x0D1E, MFX_HW_HSW, MFX_GT2 }, /*HASWELL_CRW_E_GT2*/
{ 0x0D2E, MFX_HW_HSW, MFX_GT3 }, /*HASWELL_CRW_E_GT3*/
/* VLV */
{ 0x0f30, MFX_HW_VLV, MFX_GT1 }, /* VLV mobile */
{ 0x0f31, MFX_HW_VLV, MFX_GT1 }, /* VLV mobile */
{ 0x0f32, MFX_HW_VLV, MFX_GT1 }, /* VLV mobile */
{ 0x0f33, MFX_HW_VLV, MFX_GT1 }, /* VLV mobile */
{ 0x0157, MFX_HW_VLV, MFX_GT1 },
{ 0x0155, MFX_HW_VLV, MFX_GT1 },
/* BDW */
/*GT3: */
{ 0x162D, MFX_HW_BDW, MFX_GT3 },
{ 0x162A, MFX_HW_BDW, MFX_GT3 },
/*GT2: */
{ 0x161D, MFX_HW_BDW, MFX_GT2 },
{ 0x161A, MFX_HW_BDW, MFX_GT2 },
/* GT1: */
{ 0x160D, MFX_HW_BDW, MFX_GT1 },
{ 0x160A, MFX_HW_BDW, MFX_GT1 },
/* BDW-ULT */
/* (16x2 - ULT, 16x6 - ULT, 16xB - Iris, 16xE - ULX) */
/*GT3: */
{ 0x162E, MFX_HW_BDW, MFX_GT3 },
{ 0x162B, MFX_HW_BDW, MFX_GT3 },
{ 0x1626, MFX_HW_BDW, MFX_GT3 },
{ 0x1622, MFX_HW_BDW, MFX_GT3 },
{ 0x1636, MFX_HW_BDW, MFX_GT3 }, /* ULT */
{ 0x163B, MFX_HW_BDW, MFX_GT3 }, /* Iris */
{ 0x163E, MFX_HW_BDW, MFX_GT3 }, /* ULX */
{ 0x1632, MFX_HW_BDW, MFX_GT3 }, /* ULT */
{ 0x163A, MFX_HW_BDW, MFX_GT3 }, /* Server */
{ 0x163D, MFX_HW_BDW, MFX_GT3 }, /* Workstation */
/* GT2: */
{ 0x161E, MFX_HW_BDW, MFX_GT2 },
{ 0x161B, MFX_HW_BDW, MFX_GT2 },
{ 0x1616, MFX_HW_BDW, MFX_GT2 },
{ 0x1612, MFX_HW_BDW, MFX_GT2 },
/* GT1: */
{ 0x160E, MFX_HW_BDW, MFX_GT1 },
{ 0x160B, MFX_HW_BDW, MFX_GT1 },
{ 0x1606, MFX_HW_BDW, MFX_GT1 },
{ 0x1602, MFX_HW_BDW, MFX_GT1 },
/* CHT */
{ 0x22b0, MFX_HW_CHT, MFX_GT1 },
{ 0x22b1, MFX_HW_CHT, MFX_GT1 },
{ 0x22b2, MFX_HW_CHT, MFX_GT1 },
{ 0x22b3, MFX_HW_CHT, MFX_GT1 },
/* SCL */
/* GT1F */
{ 0x1902, MFX_HW_SCL, MFX_GT1 }, // DT, 2x1F, 510
{ 0x1906, MFX_HW_SCL, MFX_GT1 }, // U-ULT, 2x1F, 510
{ 0x190A, MFX_HW_SCL, MFX_GT1 }, // Server, 4x1F
{ 0x190B, MFX_HW_SCL, MFX_GT1 },
{ 0x190E, MFX_HW_SCL, MFX_GT1 }, // Y-ULX 2x1F
/*GT1.5*/
{ 0x1913, MFX_HW_SCL, MFX_GT1 }, // U-ULT, 2x1.5
{ 0x1915, MFX_HW_SCL, MFX_GT1 }, // Y-ULX, 2x1.5
{ 0x1917, MFX_HW_SCL, MFX_GT1 }, // DT, 2x1.5
/* GT2 */
{ 0x1912, MFX_HW_SCL, MFX_GT2 }, // DT, 2x2, 530
{ 0x1916, MFX_HW_SCL, MFX_GT2 }, // U-ULD 2x2, 520
{ 0x191A, MFX_HW_SCL, MFX_GT2 }, // 2x2,4x2, Server
{ 0x191B, MFX_HW_SCL, MFX_GT2 }, // DT, 2x2, 530
{ 0x191D, MFX_HW_SCL, MFX_GT2 }, // 4x2, WKS, P530
{ 0x191E, MFX_HW_SCL, MFX_GT2 }, // Y-ULX, 2x2, P510,515
{ 0x1921, MFX_HW_SCL, MFX_GT2 }, // U-ULT, 2x2F, 540
/* GT3 */
{ 0x1923, MFX_HW_SCL, MFX_GT3 }, // U-ULT, 2x3, 535
{ 0x1926, MFX_HW_SCL, MFX_GT3 }, // U-ULT, 2x3, 540 (15W)
{ 0x1927, MFX_HW_SCL, MFX_GT3 }, // U-ULT, 2x3e, 550 (28W)
{ 0x192A, MFX_HW_SCL, MFX_GT3 }, // Server, 2x3
{ 0x192B, MFX_HW_SCL, MFX_GT3 }, // Halo 3e
{ 0x192D, MFX_HW_SCL, MFX_GT3 },
/* GT4e*/
{ 0x1932, MFX_HW_SCL, MFX_GT4 }, // DT
{ 0x193A, MFX_HW_SCL, MFX_GT4 }, // SRV
{ 0x193B, MFX_HW_SCL, MFX_GT4 }, // Halo
{ 0x193D, MFX_HW_SCL, MFX_GT4 }, // WKS
/* APL */
{ 0x0A84, MFX_HW_APL, MFX_GT1 },
{ 0x0A85, MFX_HW_APL, MFX_GT1 },
{ 0x0A86, MFX_HW_APL, MFX_GT1 },
{ 0x0A87, MFX_HW_APL, MFX_GT1 },
{ 0x1A84, MFX_HW_APL, MFX_GT1 },
{ 0x1A85, MFX_HW_APL, MFX_GT1 },
{ 0x5A84, MFX_HW_APL, MFX_GT1 },
{ 0x5A85, MFX_HW_APL, MFX_GT1 },
/* KBL */
{ 0x5902, MFX_HW_KBL, MFX_GT1 }, // DT GT1
{ 0x5906, MFX_HW_KBL, MFX_GT1 }, // ULT GT1
{ 0x5908, MFX_HW_KBL, MFX_GT1 }, // HALO GT1F
{ 0x590A, MFX_HW_KBL, MFX_GT1 }, // SERV GT1
{ 0x590B, MFX_HW_KBL, MFX_GT1 }, // HALO GT1
{ 0x590E, MFX_HW_KBL, MFX_GT1 }, // ULX GT1
{ 0x5912, MFX_HW_KBL, MFX_GT2 }, // DT GT2
{ 0x5913, MFX_HW_KBL, MFX_GT1 }, // ULT GT1 5
{ 0x5915, MFX_HW_KBL, MFX_GT1 }, // ULX GT1 5
{ 0x5916, MFX_HW_KBL, MFX_GT2 }, // ULT GT2
{ 0x5917, MFX_HW_KBL, MFX_GT2 }, // ULT GT2 R
{ 0x591A, MFX_HW_KBL, MFX_GT2 }, // SERV GT2
{ 0x591B, MFX_HW_KBL, MFX_GT2 }, // HALO GT2
{ 0x591C, MFX_HW_KBL, MFX_GT2 }, // ULX GT2
{ 0x591D, MFX_HW_KBL, MFX_GT2 }, // WRK GT2
{ 0x591E, MFX_HW_KBL, MFX_GT2 }, // ULX GT2
{ 0x5921, MFX_HW_KBL, MFX_GT2 }, // ULT GT2F
{ 0x5923, MFX_HW_KBL, MFX_GT3 }, // ULT GT3
{ 0x5926, MFX_HW_KBL, MFX_GT3 }, // ULT GT3 15W
{ 0x5927, MFX_HW_KBL, MFX_GT3 }, // ULT GT3 28W
{ 0x592A, MFX_HW_KBL, MFX_GT3 }, // SERV GT3
{ 0x592B, MFX_HW_KBL, MFX_GT3 }, // HALO GT3
{ 0x5932, MFX_HW_KBL, MFX_GT4 }, // DT GT4
{ 0x593A, MFX_HW_KBL, MFX_GT4 }, // SERV GT4
{ 0x593B, MFX_HW_KBL, MFX_GT4 }, // HALO GT4
{ 0x593D, MFX_HW_KBL, MFX_GT4 }, // WRK GT4
{ 0x87C0, MFX_HW_KBL, MFX_GT2 }, // ULX GT2
/* GLK */
{ 0x3184, MFX_HW_GLK, MFX_GT1 },
{ 0x3185, MFX_HW_GLK, MFX_GT1 },
/* CFL */
{ 0x3E90, MFX_HW_CFL, MFX_GT1 },
{ 0x3E91, MFX_HW_CFL, MFX_GT2 },
{ 0x3E92, MFX_HW_CFL, MFX_GT2 },
{ 0x3E93, MFX_HW_CFL, MFX_GT1 },
{ 0x3E94, MFX_HW_CFL, MFX_GT2 },
{ 0x3E96, MFX_HW_CFL, MFX_GT2 },
{ 0x3E98, MFX_HW_CFL, MFX_GT2 },
{ 0x3E99, MFX_HW_CFL, MFX_GT1 },
{ 0x3E9A, MFX_HW_CFL, MFX_GT2 },
{ 0x3E9C, MFX_HW_CFL, MFX_GT1 },
{ 0x3E9B, MFX_HW_CFL, MFX_GT2 },
{ 0x3EA5, MFX_HW_CFL, MFX_GT3 },
{ 0x3EA6, MFX_HW_CFL, MFX_GT3 },
{ 0x3EA7, MFX_HW_CFL, MFX_GT3 },
{ 0x3EA8, MFX_HW_CFL, MFX_GT3 },
{ 0x3EA9, MFX_HW_CFL, MFX_GT2 },
{ 0x87CA, MFX_HW_CFL, MFX_GT2 },
/* WHL */
{ 0x3EA0, MFX_HW_CFL, MFX_GT2 },
{ 0x3EA1, MFX_HW_CFL, MFX_GT1 },
{ 0x3EA2, MFX_HW_CFL, MFX_GT3 },
{ 0x3EA3, MFX_HW_CFL, MFX_GT2 },
{ 0x3EA4, MFX_HW_CFL, MFX_GT1 },
/* CML GT1 */
{ 0x9b21, MFX_HW_CFL, MFX_GT1 },
{ 0x9baa, MFX_HW_CFL, MFX_GT1 },
{ 0x9bab, MFX_HW_CFL, MFX_GT1 },
{ 0x9bac, MFX_HW_CFL, MFX_GT1 },
{ 0x9ba0, MFX_HW_CFL, MFX_GT1 },
{ 0x9ba5, MFX_HW_CFL, MFX_GT1 },
{ 0x9ba8, MFX_HW_CFL, MFX_GT1 },
{ 0x9ba4, MFX_HW_CFL, MFX_GT1 },
{ 0x9ba2, MFX_HW_CFL, MFX_GT1 },
/* CML GT2 */
{ 0x9b41, MFX_HW_CFL, MFX_GT2 },
{ 0x9bca, MFX_HW_CFL, MFX_GT2 },
{ 0x9bcb, MFX_HW_CFL, MFX_GT2 },
{ 0x9bcc, MFX_HW_CFL, MFX_GT2 },
{ 0x9bc0, MFX_HW_CFL, MFX_GT2 },
{ 0x9bc5, MFX_HW_CFL, MFX_GT2 },
{ 0x9bc8, MFX_HW_CFL, MFX_GT2 },
{ 0x9bc4, MFX_HW_CFL, MFX_GT2 },
{ 0x9bc2, MFX_HW_CFL, MFX_GT2 },
{ 0x9bc6, MFX_HW_CFL, MFX_GT2 },
{ 0x9be6, MFX_HW_CFL, MFX_GT2 },
{ 0x9bf6, MFX_HW_CFL, MFX_GT2 },
/* CNL */
{ 0x5A51, MFX_HW_CNL, MFX_GT2 },
{ 0x5A52, MFX_HW_CNL, MFX_GT2 },
{ 0x5A5A, MFX_HW_CNL, MFX_GT2 },
{ 0x5A40, MFX_HW_CNL, MFX_GT2 },
{ 0x5A42, MFX_HW_CNL, MFX_GT2 },
{ 0x5A4A, MFX_HW_CNL, MFX_GT2 },
{ 0x5A4C, MFX_HW_CNL, MFX_GT1 },
{ 0x5A50, MFX_HW_CNL, MFX_GT2 },
{ 0x5A54, MFX_HW_CNL, MFX_GT1 },
{ 0x5A59, MFX_HW_CNL, MFX_GT2 },
{ 0x5A5C, MFX_HW_CNL, MFX_GT1 },
{ 0x5A41, MFX_HW_CNL, MFX_GT2 },
{ 0x5A44, MFX_HW_CNL, MFX_GT1 },
{ 0x5A49, MFX_HW_CNL, MFX_GT2 },
/* ICL LP */
{ 0xFF05, MFX_HW_ICL_LP, MFX_GT1 },
{ 0x8A50, MFX_HW_ICL_LP, MFX_GT2 },
{ 0x8A51, MFX_HW_ICL_LP, MFX_GT2 },
{ 0x8A52, MFX_HW_ICL_LP, MFX_GT2 },
{ 0x8A53, MFX_HW_ICL_LP, MFX_GT2 },
{ 0x8A54, MFX_HW_ICL_LP, MFX_GT1 },
{ 0x8A56, MFX_HW_ICL_LP, MFX_GT1 },
{ 0x8A57, MFX_HW_ICL_LP, MFX_GT1 },
{ 0x8A58, MFX_HW_ICL_LP, MFX_GT1 },
{ 0x8A59, MFX_HW_ICL_LP, MFX_GT1 },
{ 0x8A5A, MFX_HW_ICL_LP, MFX_GT1 },
{ 0x8A5B, MFX_HW_ICL_LP, MFX_GT1 },
{ 0x8A5C, MFX_HW_ICL_LP, MFX_GT1 },
{ 0x8A5D, MFX_HW_ICL_LP, MFX_GT1 },
{ 0x8A70, MFX_HW_ICL_LP, MFX_GT1 },
{ 0x8A71, MFX_HW_ICL_LP, MFX_GT1 }, // GT05, but 1 ok in this context
/* JSL */
{ 0x4E51, MFX_HW_JSL, MFX_GT2 },
{ 0x4E55, MFX_HW_JSL, MFX_GT2 },
{ 0x4E61, MFX_HW_JSL, MFX_GT2 },
{ 0x4E71, MFX_HW_JSL, MFX_GT2 },
/* EHL */
{ 0x4500, MFX_HW_EHL, MFX_GT2 },
{ 0x4541, MFX_HW_EHL, MFX_GT2 },
{ 0x4551, MFX_HW_EHL, MFX_GT2 },
{ 0x4555, MFX_HW_EHL, MFX_GT2 },
{ 0x4569, MFX_HW_EHL, MFX_GT2 },
{ 0x4571, MFX_HW_EHL, MFX_GT2 },
};
typedef struct {
unsigned int vendor_id;
unsigned int device_id;
eMFXHWType platform;
} Device;
static inline eMFXHWType get_platform(unsigned int device_id) {
for (unsigned i = 0; i < sizeof(listLegalDevIDs) / sizeof(listLegalDevIDs[0]); ++i) {
if (listLegalDevIDs[i].device_id == device_id) {
return listLegalDevIDs[i].platform;
}
}
return MFX_HW_UNKNOWN;
}
static mfxStatus get_devices(std::vector<Device> &allDevices) {
const char *dir = "/sys/class/drm";
const char *device_id_file = "/device/device";
const char *vendor_id_file = "/device/vendor";
int i = 0;
for (; i < 64; ++i) {
Device device;
std::string path = std::string(dir) + "/renderD" + std::to_string(128 + i) + vendor_id_file;
std::string line;
std::ifstream dev_str;
dev_str.open(path);
if (!dev_str.is_open()) {
continue;
}
std::getline(dev_str, line);
dev_str.close();
try {
device.vendor_id = std::stoul(line, 0, 16);
}
catch (std::invalid_argument &) {
continue;
}
catch (std::out_of_range &) {
continue;
}
// Filter out non-Intel devices
if (device.vendor_id != 0x8086)
continue;
path = std::string(dir) + "/renderD" + std::to_string(128 + i) + device_id_file;
dev_str.open(path);
if (!dev_str.is_open()) {
continue;
}
std::getline(dev_str, line);
dev_str.close();
try {
device.device_id = std::stoul(line, 0, 16);
}
catch (std::invalid_argument &) {
continue;
}
catch (std::out_of_range &) {
continue;
}
device.platform = get_platform(device.device_id);
allDevices.emplace_back(device);
}
// sort by platform, unknown will appear at beginning
std::sort(allDevices.begin(), allDevices.end(), [](const Device &a, const Device &b) {
return a.platform < b.platform;
});
if (allDevices.size() == 0)
return MFX_ERR_NOT_FOUND;
return MFX_ERR_NONE;
}
#endif // LIBVPL_SRC_LINUX_DEVICE_IDS_H_
@@ -0,0 +1,81 @@
LIBVPL_2.0 {
global:
MFXInit;
MFXClose;
MFXQueryIMPL;
MFXQueryVersion;
MFXJoinSession;
MFXDisjoinSession;
MFXCloneSession;
MFXSetPriority;
MFXGetPriority;
MFXVideoCORE_SetFrameAllocator;
MFXVideoCORE_SetHandle;
MFXVideoCORE_GetHandle;
MFXVideoCORE_QueryPlatform;
MFXVideoCORE_SyncOperation;
MFXVideoENCODE_Query;
MFXVideoENCODE_QueryIOSurf;
MFXVideoENCODE_Init;
MFXVideoENCODE_Reset;
MFXVideoENCODE_Close;
MFXVideoENCODE_GetVideoParam;
MFXVideoENCODE_GetEncodeStat;
MFXVideoENCODE_EncodeFrameAsync;
MFXVideoDECODE_Query;
MFXVideoDECODE_DecodeHeader;
MFXVideoDECODE_QueryIOSurf;
MFXVideoDECODE_Init;
MFXVideoDECODE_Reset;
MFXVideoDECODE_Close;
MFXVideoDECODE_GetVideoParam;
MFXVideoDECODE_GetDecodeStat;
MFXVideoDECODE_SetSkipMode;
MFXVideoDECODE_GetPayload;
MFXVideoDECODE_DecodeFrameAsync;
MFXVideoVPP_Query;
MFXVideoVPP_QueryIOSurf;
MFXVideoVPP_Init;
MFXVideoVPP_Reset;
MFXVideoVPP_Close;
MFXVideoVPP_GetVideoParam;
MFXVideoVPP_GetVPPStat;
MFXVideoVPP_RunFrameVPPAsync;
MFXInitEx;
MFXLoad;
MFXUnload;
MFXCreateConfig;
MFXSetConfigFilterProperty;
MFXEnumImplementations;
MFXCreateSession;
MFXDispReleaseImplDescription;
MFXMemory_GetSurfaceForVPP;
MFXMemory_GetSurfaceForEncode;
MFXMemory_GetSurfaceForDecode;
local:
*;
};
LIBVPL_2.1 {
global:
MFXMemory_GetSurfaceForVPPOut;
MFXVideoDECODE_VPP_Init;
MFXVideoDECODE_VPP_DecodeFrameAsync;
MFXVideoDECODE_VPP_Reset;
MFXVideoDECODE_VPP_GetChannelParam;
MFXVideoDECODE_VPP_Close;
MFXVideoVPP_ProcessFrameAsync;
local:
*;
} LIBVPL_2.0;
@@ -0,0 +1,842 @@
/*############################################################################
# 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"
// internal implementation of mfxConfigInterface
#include "src/mfx_config_interface/mfx_config_interface.h"
#include "src/linux/device_ids.h"
#include "src/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,
eMFXVideoCORE_GetHandle,
#include "src/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) },
{ eMFXVideoCORE_GetHandle, "MFXVideoCORE_GetHandle", VERSION(1, 0) },
#include "src/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 Intel® Video Processing Library (Intel® VPL) 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 Intel® VPL
libs.emplace_back(ONEVPLHW);
libs.emplace_back(MFX_MODULES_DIR "/" ONEVPLHW);
}
// use MSDK (fallback if Intel® VPL is not installed)
libs.emplace_back(LIBMFXHW);
libs.emplace_back(MFX_MODULES_DIR "/" LIBMFXHW);
}
// add SW lib (Intel® VPL 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);
}
// implement as a non-passthrough function so that we can catch dispatcher-level interface query requests
mfxStatus MFXVideoCORE_GetHandle(mfxSession session, mfxHandleType type, mfxHDL *hdl) {
if (!session)
return MFX_ERR_INVALID_HANDLE;
MFX::LoaderCtx *loader = (MFX::LoaderCtx *)session;
// first check if handle type points to an interface implemented inside the dispatcher
if (type == MFX_HANDLE_CONFIG_INTERFACE) {
if (!hdl)
return MFX_ERR_NULL_PTR;
*hdl = (mfxHDL)(&(MFX_CONFIG_INTERFACE::g_dispatcher_mfxConfigInterface));
return MFX_ERR_NONE;
}
// passthrough to runtime
auto proc =
(decltype(MFXVideoCORE_GetHandle) *)loader->getFunction(MFX::eMFXVideoCORE_GetHandle);
if (!proc) {
return MFX_ERR_INVALID_HANDLE;
}
return (*proc)(loader->getSession(), type, hdl);
}
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 "src/linux/mfxvideo_functions.h" // NOLINT(build/include)
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,30 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#ifndef LIBVPL_SRC_LINUX_MFXLOADER_H_
#define LIBVPL_SRC_LINUX_MFXLOADER_H_
#include <limits.h>
#include <list>
#include <sstream>
#include <string>
#include "vpl/mfxvideo.h"
inline bool operator<(const mfxVersion &lhs, const mfxVersion &rhs) {
return (lhs.Major < rhs.Major || (lhs.Major == rhs.Major && lhs.Minor < rhs.Minor));
}
inline bool operator<=(const mfxVersion &lhs, const mfxVersion &rhs) {
return (lhs < rhs || (lhs.Major == rhs.Major && lhs.Minor == rhs.Minor));
}
inline bool operator==(mfxGUID const &l, mfxGUID const &r) {
return std::equal(l.Data, l.Data + 16, r.Data);
}
#endif // LIBVPL_SRC_LINUX_MFXLOADER_H_
@@ -0,0 +1,176 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
//
// WARNING:
// this file doesn't contain an include guard by design.
// The file may be included into a source file many times.
// That is why this header doesn't contain any include directive.
// Please, do no try to fix it.
//
// NOLINT(build/header_guard)
// Use define API_VERSION to set the API of functions listed further
// When new functions are added new section with functions declarations must be started with updated define
//
// API version 1.0 functions
//
// API version where a function is added. Minor value should precedes the major value
#define API_VERSION \
{ \
{ 0, 1 } \
}
FUNCTION(mfxStatus, MFXQueryIMPL, (mfxSession session, mfxIMPL *impl), (session, impl))
FUNCTION(mfxStatus, MFXQueryVersion, (mfxSession session, mfxVersion *version), (session, version))
// CORE interface functions
FUNCTION(mfxStatus,
MFXVideoCORE_SetFrameAllocator,
(mfxSession session, mfxFrameAllocator *allocator),
(session, allocator))
FUNCTION(mfxStatus,
MFXVideoCORE_SetHandle,
(mfxSession session, mfxHandleType type, mfxHDL hdl),
(session, type, hdl))
FUNCTION(mfxStatus,
MFXVideoCORE_SyncOperation,
(mfxSession session, mfxSyncPoint syncp, mfxU32 wait),
(session, syncp, wait))
// ENCODE interface functions
FUNCTION(mfxStatus,
MFXVideoENCODE_Query,
(mfxSession session, mfxVideoParam *in, mfxVideoParam *out),
(session, in, out))
FUNCTION(mfxStatus,
MFXVideoENCODE_QueryIOSurf,
(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request),
(session, par, request))
FUNCTION(mfxStatus, MFXVideoENCODE_Init, (mfxSession session, mfxVideoParam *par), (session, par))
FUNCTION(mfxStatus, MFXVideoENCODE_Reset, (mfxSession session, mfxVideoParam *par), (session, par))
FUNCTION(mfxStatus, MFXVideoENCODE_Close, (mfxSession session), (session))
FUNCTION(mfxStatus,
MFXVideoENCODE_GetVideoParam,
(mfxSession session, mfxVideoParam *par),
(session, par))
FUNCTION(mfxStatus,
MFXVideoENCODE_GetEncodeStat,
(mfxSession session, mfxEncodeStat *stat),
(session, stat))
FUNCTION(mfxStatus,
MFXVideoENCODE_EncodeFrameAsync,
(mfxSession session,
mfxEncodeCtrl *ctrl,
mfxFrameSurface1 *surface,
mfxBitstream *bs,
mfxSyncPoint *syncp),
(session, ctrl, surface, bs, syncp))
// DECODE interface functions
FUNCTION(mfxStatus,
MFXVideoDECODE_Query,
(mfxSession session, mfxVideoParam *in, mfxVideoParam *out),
(session, in, out))
FUNCTION(mfxStatus,
MFXVideoDECODE_DecodeHeader,
(mfxSession session, mfxBitstream *bs, mfxVideoParam *par),
(session, bs, par))
FUNCTION(mfxStatus,
MFXVideoDECODE_QueryIOSurf,
(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request),
(session, par, request))
FUNCTION(mfxStatus, MFXVideoDECODE_Init, (mfxSession session, mfxVideoParam *par), (session, par))
FUNCTION(mfxStatus, MFXVideoDECODE_Reset, (mfxSession session, mfxVideoParam *par), (session, par))
FUNCTION(mfxStatus, MFXVideoDECODE_Close, (mfxSession session), (session))
FUNCTION(mfxStatus,
MFXVideoDECODE_GetVideoParam,
(mfxSession session, mfxVideoParam *par),
(session, par))
FUNCTION(mfxStatus,
MFXVideoDECODE_GetDecodeStat,
(mfxSession session, mfxDecodeStat *stat),
(session, stat))
FUNCTION(mfxStatus,
MFXVideoDECODE_SetSkipMode,
(mfxSession session, mfxSkipMode mode),
(session, mode))
FUNCTION(mfxStatus,
MFXVideoDECODE_GetPayload,
(mfxSession session, mfxU64 *ts, mfxPayload *payload),
(session, ts, payload))
FUNCTION(mfxStatus,
MFXVideoDECODE_DecodeFrameAsync,
(mfxSession session,
mfxBitstream *bs,
mfxFrameSurface1 *surface_work,
mfxFrameSurface1 **surface_out,
mfxSyncPoint *syncp),
(session, bs, surface_work, surface_out, syncp))
// VPP interface functions
FUNCTION(mfxStatus,
MFXVideoVPP_Query,
(mfxSession session, mfxVideoParam *in, mfxVideoParam *out),
(session, in, out))
FUNCTION(mfxStatus,
MFXVideoVPP_QueryIOSurf,
(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request),
(session, par, request))
FUNCTION(mfxStatus, MFXVideoVPP_Init, (mfxSession session, mfxVideoParam *par), (session, par))
FUNCTION(mfxStatus, MFXVideoVPP_Reset, (mfxSession session, mfxVideoParam *par), (session, par))
FUNCTION(mfxStatus, MFXVideoVPP_Close, (mfxSession session), (session))
FUNCTION(mfxStatus,
MFXVideoVPP_GetVideoParam,
(mfxSession session, mfxVideoParam *par),
(session, par))
FUNCTION(mfxStatus, MFXVideoVPP_GetVPPStat, (mfxSession session, mfxVPPStat *stat), (session, stat))
FUNCTION(mfxStatus,
MFXVideoVPP_RunFrameVPPAsync,
(mfxSession session,
mfxFrameSurface1 *in,
mfxFrameSurface1 *out,
mfxExtVppAuxData *aux,
mfxSyncPoint *syncp),
(session, in, out, aux, syncp))
#undef API_VERSION
//
// API version 1.1 functions
//
#define API_VERSION \
{ \
{ 1, 1 } \
}
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 API_VERSION
#define API_VERSION \
{ \
{ 19, 1 } \
}
FUNCTION(mfxStatus,
MFXVideoCORE_QueryPlatform,
(mfxSession session, mfxPlatform *platform),
(session, platform))
#undef API_VERSION
@@ -0,0 +1,145 @@
---
Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: true
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: false
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: None
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: true
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: false
ColumnLimit: 150
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentPPDirectives: BeforeHash
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Right
RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- 'c++'
- 'C++'
CanonicalDelimiter: ''
BasedOnStyle: google
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
CanonicalDelimiter: ''
BasedOnStyle: google
ReflowComments: false
SortIncludes: true
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 1
UseTab: Never
...
@@ -0,0 +1,110 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#include "src/mfx_config_interface/mfx_config_interface.h"
namespace MFX_CONFIG_INTERFACE {
// leave table formatting alone
// clang-format off
// Dispatcher-level implementation of mfxConfigInterface.
// Current implementation is stateless (string API only) so set Context to a special key.
// We could replace Context with pointer to mfxSession (or some object within mfxSession)
// if future extensions require access to the session state.
// The application is not permitted to modify or dereference Context (see struct definition)
// so we can set this to whatever we need.
const mfxConfigInterface g_dispatcher_mfxConfigInterface = {
MFX_CONFIG_INTERFACE_CONTEXT, // Context
{ { 0, 1 } }, // Version
MFX_CONFIG_INTERFACE::ExtSetParameter, // SetParameter (callback function)
{}, // reserved
};
// end table formatting
// clang-format on
// callback function - set mfxConfigInterface::SetParameter to this
// this has to be static since it's returned as function pointer, so cast session to _mfxSession
// to access session-specific state (current implementation is stateless)
mfxStatus ExtSetParameter(struct mfxConfigInterface *config_interface,
const mfxU8 *key,
const mfxU8 *value,
mfxStructureType struct_type,
mfxHDL structure,
mfxExtBuffer *ext_buffer) {
if (struct_type == MFX_STRUCTURE_TYPE_VIDEO_PARAM) {
return SetParameter(key, value, (mfxVideoParam *)structure, ext_buffer);
}
return MFX_ERR_UNSUPPORTED;
}
// validate key and value input strings
mfxStatus ValidateKVPair(const mfxU8 *key, const mfxU8 *value, KVPair &kvStr) {
mfxU32 lengthKey, lengthValue;
// manually check length of key string
for (lengthKey = 0; lengthKey < MAX_PARAM_STRING_LENGTH; lengthKey++) {
if (!key[lengthKey])
break;
}
if (lengthKey == 0 || lengthKey == MAX_PARAM_STRING_LENGTH)
return MFX_ERR_INVALID_VIDEO_PARAM;
// manually check length of value string
for (lengthValue = 0; lengthValue < MAX_PARAM_STRING_LENGTH; lengthValue++) {
if (!value[lengthValue])
break;
}
if (lengthValue == 0 || lengthValue == MAX_PARAM_STRING_LENGTH)
return MFX_ERR_INVALID_VIDEO_PARAM;
kvStr.first = (const char *)key;
kvStr.second = (const char *)value;
return MFX_ERR_NONE;
}
mfxStatus SetParameter(const mfxU8 *key, const mfxU8 *value, mfxVideoParam *videoParam, mfxExtBuffer *extBuf) {
if (!key || !value || !videoParam || !extBuf)
return MFX_ERR_NULL_PTR;
*extBuf = {}; // clear extBuf, will be filled in if new extBuf is required from caller
mfxStatus sts = MFX_ERR_NOT_FOUND; // default if no valid parameters
// validate C-style key and value strings
// output is a pair of std::string's in kvStr
KVPair kvStr;
sts = ValidateKVPair(key, value, kvStr);
if (sts != MFX_ERR_NONE)
return sts;
if (IsExtBuf(kvStr)) {
mfxExtBuffer extBufRequired = {};
// key maps to a parameter in an extension buffer
sts = UpdateExtBufParam(kvStr, videoParam, &extBufRequired);
// if required extension buffer is not attached, we request the app to allocate it
// and then call the SetParameter function again
if (sts == MFX_ERR_MORE_EXTBUFFER) {
extBuf->BufferId = extBufRequired.BufferId;
extBuf->BufferSz = extBufRequired.BufferSz;
}
return sts;
}
// key maps to a parameter in mfxVideoParam
sts = UpdateVideoParam(kvStr, videoParam);
return sts;
}
} // namespace MFX_CONFIG_INTERFACE
@@ -0,0 +1,50 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#ifndef LIBVPL_SRC_MFX_CONFIG_INTERFACE_MFX_CONFIG_INTERFACE_H_
#define LIBVPL_SRC_MFX_CONFIG_INTERFACE_MFX_CONFIG_INTERFACE_H_
#include <algorithm>
#include <list>
#include <map>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include "vpl/mfxvideo.h"
// special key to indicate Context is not a real context, as it is a stateless interface
#define MFX_CONFIG_INTERFACE_CONTEXT ((mfxHDL)(-1))
namespace MFX_CONFIG_INTERFACE {
// dispatcher returns this interface from call to MFXVideoCORE_GetHandle(type = MFX_HANDLE_CONFIG_INTERFACE)
extern const mfxConfigInterface g_dispatcher_mfxConfigInterface;
// string K-V pairs, each key may only have a single value
typedef std::pair<std::string, std::string> KVPair;
mfxStatus MFX_CDECL ExtSetParameter(struct mfxConfigInterface *config_interface,
const mfxU8 *key,
const mfxU8 *value,
mfxStructureType struct_type,
mfxHDL structure,
mfxExtBuffer *ext_buffer);
mfxStatus SetParameter(const mfxU8 *key, const mfxU8 *value, mfxVideoParam *videoParam, mfxExtBuffer *extBuf);
mfxStatus UpdateVideoParam(const KVPair &kvStr, mfxVideoParam *videoParam);
mfxStatus UpdateExtBufParam(const KVPair &kvStr, mfxVideoParam *videoParam, mfxExtBuffer *extBufRequired);
bool IsExtBuf(const KVPair &kvStr);
mfxStatus ValidateKVPair(const mfxU8 *key, const mfxU8 *value, KVPair &kvStr);
mfxStatus SetExtBufParam(mfxExtBuffer *extBufActual, KVPair &kvStrParsed);
mfxStatus GetExtBufType(const KVPair &kvStr, mfxExtBuffer *extBufHeader, KVPair &kvStrParsed);
}; // namespace MFX_CONFIG_INTERFACE
#endif // LIBVPL_SRC_MFX_CONFIG_INTERFACE_MFX_CONFIG_INTERFACE_H_
@@ -0,0 +1,229 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#include "src/mfx_dispatcher_vpl.h"
// exported functions for API >= 2.0
// create unique loader context
mfxLoader MFXLoad() {
LoaderCtxVPL *loaderCtx;
try {
std::unique_ptr<LoaderCtxVPL> pLoaderCtx;
pLoaderCtx.reset(new LoaderCtxVPL{});
// initialize logging if appropriate environment variables are set
pLoaderCtx->InitDispatcherLog();
loaderCtx = (LoaderCtxVPL *)pLoaderCtx.release();
}
catch (...) {
return nullptr;
}
return (mfxLoader)loaderCtx;
}
// unload libraries, destroy all created mfxConfig objects, free other memory
void MFXUnload(mfxLoader loader) {
try {
if (!loader)
return;
LoaderCtxVPL *loaderCtx = (LoaderCtxVPL *)loader;
loaderCtx->UnloadAllLibraries();
loaderCtx->FreeConfigFilters();
delete loaderCtx;
}
catch (...) {
// nothing to return
}
}
// create config context
// each loader may have more than one config context
mfxConfig MFXCreateConfig(mfxLoader loader) {
try {
if (!loader)
return nullptr;
LoaderCtxVPL *loaderCtx = (LoaderCtxVPL *)loader;
ConfigCtxVPL *configCtx;
DispatcherLogVPL *dispLog = loaderCtx->GetLogger();
DISP_LOG_FUNCTION(dispLog);
configCtx = loaderCtx->AddConfigFilter();
return (mfxConfig)(configCtx);
}
catch (...) {
return nullptr;
}
}
// set a config property to use in enumerating implementations
mfxStatus MFXSetConfigFilterProperty(mfxConfig config, const mfxU8 *name, mfxVariant value) {
try {
if (!config)
return MFX_ERR_NULL_PTR;
ConfigCtxVPL *configCtx = (ConfigCtxVPL *)config;
LoaderCtxVPL *loaderCtx = configCtx->m_parentLoader;
if (!loaderCtx)
return MFX_ERR_NULL_PTR; // should never happen - always set during MFXCreateConfig()
DispatcherLogVPL *dispLog = loaderCtx->GetLogger();
DISP_LOG_FUNCTION(dispLog);
mfxStatus sts = configCtx->SetFilterProperty(name, value);
if (sts)
return sts;
loaderCtx->m_bNeedUpdateValidImpls = true;
sts = loaderCtx->UpdateLowLatency();
if (sts)
return sts;
#ifdef ONEVPL_EXPERIMENTAL
sts = loaderCtx->UpdatePropsQuery();
#endif
return sts;
}
catch (...) {
return MFX_ERR_UNKNOWN;
}
}
// iterate over available implementations
// capabilities are returned in idesc
mfxStatus MFXEnumImplementations(mfxLoader loader,
mfxU32 i,
mfxImplCapsDeliveryFormat format,
mfxHDL *idesc) {
try {
if (!loader || !idesc)
return MFX_ERR_NULL_PTR;
LoaderCtxVPL *loaderCtx = (LoaderCtxVPL *)loader;
DispatcherLogVPL *dispLog = loaderCtx->GetLogger();
DISP_LOG_FUNCTION(dispLog);
mfxStatus sts = MFX_ERR_NONE;
// load and query all libraries
if (loaderCtx->m_bNeedFullQuery) {
// if a session was already created in low-latency mode, unload all implementations
// before running full load and query
if (loaderCtx->m_bLowLatency && !loaderCtx->m_bNeedLowLatencyQuery) {
loaderCtx->UnloadAllLibraries();
}
sts = loaderCtx->FullLoadAndQuery();
if (sts)
return MFX_ERR_NOT_FOUND;
}
// update list of valid libraries based on updated set of
// mfxConfig properties
if (loaderCtx->m_bNeedUpdateValidImpls) {
sts = loaderCtx->UpdateValidImplList();
if (sts)
return MFX_ERR_NOT_FOUND;
}
sts = loaderCtx->QueryImpl(i, format, idesc);
return sts;
}
catch (...) {
return MFX_ERR_UNKNOWN;
}
}
// create a new session with implementation i
mfxStatus MFXCreateSession(mfxLoader loader, mfxU32 i, mfxSession *session) {
try {
if (!loader || !session)
return MFX_ERR_NULL_PTR;
LoaderCtxVPL *loaderCtx = (LoaderCtxVPL *)loader;
DispatcherLogVPL *dispLog = loaderCtx->GetLogger();
DISP_LOG_FUNCTION(dispLog);
mfxStatus sts = MFX_ERR_NONE;
if (loaderCtx->m_bLowLatency) {
DISP_LOG_MESSAGE(dispLog, "message: low latency mode enabled");
if (loaderCtx->m_bNeedLowLatencyQuery) {
// load low latency libraries
sts = loaderCtx->LoadLibsLowLatency();
if (sts != MFX_ERR_NONE)
return MFX_ERR_NOT_FOUND;
// run limited query operations for low latency init
sts = loaderCtx->QueryLibraryCaps();
if (sts != MFX_ERR_NONE)
return MFX_ERR_NOT_FOUND;
}
}
else {
DISP_LOG_MESSAGE(dispLog, "message: low latency mode disabled");
// load and query all libraries
if (loaderCtx->m_bNeedFullQuery) {
sts = loaderCtx->FullLoadAndQuery();
if (sts)
return MFX_ERR_NOT_FOUND;
}
// update list of valid libraries based on updated set of
// mfxConfig properties
if (loaderCtx->m_bNeedUpdateValidImpls) {
sts = loaderCtx->UpdateValidImplList();
if (sts)
return MFX_ERR_NOT_FOUND;
}
}
sts = loaderCtx->CreateSession(i, session);
return sts;
}
catch (...) {
return MFX_ERR_UNKNOWN;
}
}
// release memory associated with implementation description hdl
mfxStatus MFXDispReleaseImplDescription(mfxLoader loader, mfxHDL hdl) {
try {
if (!loader)
return MFX_ERR_NULL_PTR;
LoaderCtxVPL *loaderCtx = (LoaderCtxVPL *)loader;
DispatcherLogVPL *dispLog = loaderCtx->GetLogger();
DISP_LOG_FUNCTION(dispLog);
mfxStatus sts = loaderCtx->ReleaseImpl(hdl);
return sts;
}
catch (...) {
return MFX_ERR_UNKNOWN;
}
}
@@ -0,0 +1,669 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#ifndef LIBVPL_SRC_MFX_DISPATCHER_VPL_H_
#define LIBVPL_SRC_MFX_DISPATCHER_VPL_H_
#include <algorithm>
#include <cstdlib>
#include <list>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
#include "vpl/mfxdispatcher.h"
#include "vpl/mfxvideo.h"
#include "./mfx_dispatcher_vpl_log.h"
#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
// use wide char on Windows
#define MAKE_STRING(x) L##x
typedef std::wstring STRING_TYPE;
typedef wchar_t CHAR_TYPE;
#else
#include <dirent.h>
#include <dlfcn.h>
#include <string.h>
#include <unistd.h>
// use standard char on Linux
#define MAKE_STRING(x) x
typedef std::string STRING_TYPE;
typedef char CHAR_TYPE;
#endif
#if defined(_WIN32) || defined(_WIN64)
#if defined _M_IX86
// Windows x86
#define MSDK_LIB_NAME L"libmfxhw32."
#else
// Windows x64
#define MSDK_LIB_NAME L"libmfxhw64."
#endif
#define ONEVPL_PRIORITY_PATH_VAR L"ONEVPL_PRIORITY_PATH"
#elif defined(__linux__)
// Linux x64
#define MSDK_LIB_NAME "libmfxhw64."
#define ONEVPL_PRIORITY_PATH_VAR "ONEVPL_PRIORITY_PATH"
#endif
#define MSDK_MIN_VERSION_MAJOR 1
#define MSDK_MIN_VERSION_MINOR 0
#define MAX_MSDK_ACCEL_MODES 16 // see mfxcommon.h --> mfxAccelerationMode
#define MAX_WINDOWS_ADAPTER_ID 3 // check adapterID in range [0,3]
#define MAX_NUM_IMPL_MSDK 4
#define MAX_VPL_SEARCH_PATH 4096
#define MAX_ENV_VAR_LEN 32768
#define DEVICE_ID_UNKNOWN 0xffffffff
#define ADAPTER_IDX_UNKNOWN 0xffffffff
#define TAB_SIZE(type, tab) (sizeof(tab) / sizeof(type))
#define MAKE_MFX_VERSION(major, minor) \
{ \
{ (minor), (major) } \
}
// internal function to load dll by full path, fail if unsuccessful
mfxStatus MFXInitEx2(mfxVersion version,
mfxInitializationParam vplParam,
mfxIMPL hwImpl,
mfxSession *session,
mfxU16 *deviceID,
CHAR_TYPE *dllName);
typedef void(MFX_CDECL *VPLFunctionPtr)(void);
extern const mfxIMPL msdkImplTab[MAX_NUM_IMPL_MSDK];
enum LibType {
LibTypeUnknown = -1,
LibTypeVPL = 0,
LibTypeMSDK,
NumLibTypes
};
enum VPLFunctionIdx {
// 2.0
IdxMFXQueryImplsDescription = 0,
IdxMFXReleaseImplDescription,
IdxMFXMemory_GetSurfaceForVPP,
IdxMFXMemory_GetSurfaceForEncode,
IdxMFXMemory_GetSurfaceForDecode,
IdxMFXInitialize,
// 2.1
IdxMFXMemory_GetSurfaceForVPPOut,
IdxMFXVideoDECODE_VPP_Init,
IdxMFXVideoDECODE_VPP_DecodeFrameAsync,
IdxMFXVideoDECODE_VPP_Reset,
IdxMFXVideoDECODE_VPP_GetChannelParam,
IdxMFXVideoDECODE_VPP_Close,
IdxMFXVideoVPP_ProcessFrameAsync,
NumVPLFunctions
};
enum VPLOptionalFunctionIdx {
// 2.15
IdxMFXQueryImplsProperties = 0,
NumVPLOptionalFunctions
};
// select MSDK functions for 1.x style caps query
enum MSDKCompatFunctionIdx {
IdxMFXInitEx = 0,
IdxMFXClose,
NumMSDKFunctions
};
// both Windows and Linux use char* for function names
struct VPLFunctionDesc {
const char *pName;
mfxVersion apiVersion;
};
// DX adapter info
struct DXGI1DeviceInfo {
mfxU32 vendorID;
mfxU32 deviceID;
mfxU64 luid;
};
// priority of runtime loading
enum LibPriority {
LIB_PRIORITY_SPECIAL = 0, // highest priority regardless of other priority rules
LIB_PRIORITY_01 = 1,
LIB_PRIORITY_02 = 2,
LIB_PRIORITY_03 = 3,
LIB_PRIORITY_04 = 4,
LIB_PRIORITY_05 = 5,
LIB_PRIORITY_9999 = 9999, // lowest priority for 2.x libs
LIB_PRIORITY_LEGACY_DRIVERSTORE = 10000,
LIB_PRIORITY_LEGACY,
};
enum CfgPropState {
CFG_PROP_STATE_NOT_SET = 0,
CFG_PROP_STATE_SUPPORTED,
CFG_PROP_STATE_UNSUPPORTED,
};
enum PropRanges {
PROP_RANGE_DEC_W = 0,
PROP_RANGE_DEC_H,
PROP_RANGE_ENC_W,
PROP_RANGE_ENC_H,
PROP_RANGE_VPP_W,
PROP_RANGE_VPP_H,
NUM_PROP_RANGES
};
// must match eProp_TotalProps, is checked with static_assert in _config.cpp
// (should throw error at compile time if !=)
#ifdef ONEVPL_EXPERIMENTAL
#define NUM_TOTAL_FILTER_PROPS 62
#else
#define NUM_TOTAL_FILTER_PROPS 58
#endif
// typedef child structures for easier reading
typedef struct mfxDecoderDescription::decoder DecCodec;
typedef struct mfxDecoderDescription::decoder::decprofile DecProfile;
typedef struct mfxDecoderDescription::decoder::decprofile::decmemdesc DecMemDesc;
typedef struct mfxEncoderDescription::encoder EncCodec;
typedef struct mfxEncoderDescription::encoder::encprofile EncProfile;
typedef struct mfxEncoderDescription::encoder::encprofile::encmemdesc EncMemDesc;
typedef struct mfxVPPDescription::filter VPPFilter;
typedef struct mfxVPPDescription::filter::memdesc VPPMemDesc;
typedef struct mfxVPPDescription::filter::memdesc::format VPPFormat;
// flattened version of single enc/dec/vpp configs
// each struct contains all _settable_ props
// i.e. not implied values like NumCodecs
struct DecConfig {
mfxU32 CodecID;
mfxU16 MaxcodecLevel;
mfxU32 Profile;
mfxResourceType MemHandleType;
mfxRange32U Width;
mfxRange32U Height;
mfxU32 ColorFormat;
};
struct EncConfig {
mfxU32 CodecID;
mfxU16 MaxcodecLevel;
mfxU16 BiDirectionalPrediction;
mfxU32 Profile;
mfxResourceType MemHandleType;
mfxRange32U Width;
mfxRange32U Height;
mfxU32 ColorFormat;
};
struct VPPConfig {
mfxU32 FilterFourCC;
mfxU16 MaxDelayInFrames;
mfxResourceType MemHandleType;
mfxRange32U Width;
mfxRange32U Height;
mfxU32 InFormat;
mfxU32 OutFormat;
};
struct SurfaceConfig {
mfxU32 SurfaceType;
mfxU32 SurfaceComponent;
mfxU32 SurfaceFlags;
};
// special props which are passed in via MFXSetConfigProperty()
// these are updated with every call to ValidateConfig() and may
// be used in MFXCreateSession()
struct SpecialConfig {
bool bIsSet_deviceHandleType;
mfxHandleType deviceHandleType;
bool bIsSet_deviceHandle;
mfxHDL deviceHandle;
bool bIsSet_accelerationMode;
mfxAccelerationMode accelerationMode;
bool bIsSet_ApiVersion;
mfxVersion ApiVersion;
bool bIsSet_dxgiAdapterIdx;
mfxU32 dxgiAdapterIdx;
bool bIsSet_NumThread;
mfxU32 NumThread;
bool bIsSet_DeviceCopy;
mfxU16 DeviceCopy;
bool bIsSet_ExtBuffer;
std::vector<mfxExtBuffer *> ExtBuffers;
};
struct mfxVariantWrapper : mfxVariant {
public:
bool bPropsQuery = false;
};
// config class implementation
class ConfigCtxVPL {
public:
ConfigCtxVPL();
~ConfigCtxVPL();
// set a single filter property (KV pair)
mfxStatus SetFilterProperty(const mfxU8 *name, mfxVariant value);
static bool CheckLowLatencyConfig(std::list<ConfigCtxVPL *> configCtxList,
SpecialConfig *specialConfig);
#ifdef ONEVPL_EXPERIMENTAL
static bool UpdatePropsQueryConfig(std::list<ConfigCtxVPL *> configCtxList,
std::vector<mfxQueryProperty> &queryProps);
#endif
// compare library caps vs. set of configuration filters
static mfxStatus ValidateConfig(const mfxImplDescription *libImplDesc,
const mfxImplementedFunctions *libImplFuncs,
const mfxExtendedDeviceId *libImplExtDevID,
#ifdef ONEVPL_EXPERIMENTAL
const mfxSurfaceTypesSupported *libImplSurfTypes,
#endif
std::list<ConfigCtxVPL *> configCtxList,
LibType libType,
SpecialConfig *specialConfig);
// parse deviceID for x86 devices
static bool ParseDeviceIDx86(mfxChar *cDeviceID, mfxU32 &deviceID, mfxU32 &adapterIdx);
// loader object this config is associated with - needed to
// rebuild valid implementation list after each calling
// MFXSetConfigFilterProperty()
class LoaderCtxVPL *m_parentLoader;
private:
static __inline std::string GetNextProp(std::list<std::string> &s) {
if (s.empty())
return "";
std::string t = s.front();
s.pop_front();
return t;
}
mfxStatus ValidateAndSetProp(mfxI32 idx, mfxVariant value);
mfxStatus SetFilterPropertyDec(std::list<std::string> &propParsedString, mfxVariant value);
mfxStatus SetFilterPropertyEnc(std::list<std::string> &propParsedString, mfxVariant value);
mfxStatus SetFilterPropertyVPP(std::list<std::string> &propParsedString, mfxVariant value);
mfxStatus SetFilterPropertySurface(std::list<std::string> &propParsedString, mfxVariant value);
static mfxStatus GetFlatDescriptionsDec(const mfxImplDescription *libImplDesc,
std::list<DecConfig> &decConfigList);
static mfxStatus GetFlatDescriptionsEnc(const mfxImplDescription *libImplDesc,
std::list<EncConfig> &encConfigList);
static mfxStatus GetFlatDescriptionsVPP(const mfxImplDescription *libImplDesc,
std::list<VPPConfig> &vppConfigList);
#ifdef ONEVPL_EXPERIMENTAL
static mfxStatus GetFlatDescriptionsSurface(const mfxSurfaceTypesSupported *libSurfaceTypes,
std::list<SurfaceConfig> &surfaceConfigList);
#endif
static mfxStatus CheckPropsGeneral(const mfxVariant cfgPropsAll[],
const mfxImplDescription *libImplDesc);
static mfxStatus CheckPropsDec(const mfxVariant cfgPropsAll[],
std::list<DecConfig> decConfigList);
static mfxStatus CheckPropsEnc(const mfxVariant cfgPropsAll[],
std::list<EncConfig> encConfigList);
static mfxStatus CheckPropsVPP(const mfxVariant cfgPropsAll[],
std::list<VPPConfig> vppConfigList);
static mfxStatus CheckPropString(const mfxChar *implString, const std::string filtString);
static mfxStatus CheckPropsExtDevID(const mfxVariant cfgPropsAll[],
const mfxExtendedDeviceId *libImplExtDevID);
#ifdef ONEVPL_EXPERIMENTAL
static mfxStatus CheckPropsSurface(const mfxVariant cfgPropsAll[],
std::list<SurfaceConfig> surfaceConfigList);
#endif
mfxVariantWrapper m_propVar[NUM_TOTAL_FILTER_PROPS];
// special containers for properties which are passed by pointer
// (save a copy of the whole object based on property name)
mfxRange32U m_propRange32U[NUM_PROP_RANGES];
std::string m_implName;
std::string m_implLicense;
std::string m_implKeywords;
std::string m_deviceIdStr;
std::string m_implFunctionName;
mfxU8 m_extDevLUID8U[8];
std::string m_extDevNameStr;
std::vector<mfxU8> m_extBuf;
__inline bool SetExtBuf(mfxExtBuffer *extBuf) {
if (!extBuf)
return false;
mfxU32 BufferSz = extBuf->BufferSz;
if (BufferSz > 0) {
m_extBuf.resize(BufferSz);
std::copy((mfxU8 *)extBuf, (mfxU8 *)extBuf + BufferSz, m_extBuf.begin());
return true;
}
return false;
}
__inline bool GetExtBuf(mfxExtBuffer **extBuf) {
if (!extBuf)
return false;
*extBuf = nullptr;
if (!m_extBuf.empty()) {
*extBuf = (mfxExtBuffer *)m_extBuf.data();
return true;
}
return false;
}
__inline void ClearExtBuf() {
m_extBuf.clear();
}
};
// MSDK compatibility loader implementation
class LoaderCtxMSDK {
public:
LoaderCtxMSDK();
~LoaderCtxMSDK();
// public function to be called the dispatcher
// do not allocate any new memory here, so no need for a matching Release functions
mfxStatus QueryMSDKCaps(STRING_TYPE libNameFull,
mfxImplDescription **implDesc,
mfxImplementedFunctions **implFuncs,
mfxU32 adapterID,
bool bSkipD3D9Check);
static mfxStatus QueryAPIVersion(STRING_TYPE libNameFull, mfxVersion *msdkVersion);
static mfxStatus QueryExtDeviceID(mfxExtendedDeviceId *extDeviceID,
mfxU32 adapterID,
mfxU16 deviceID,
mfxU64 luid);
// required by MFXCreateSession
mfxIMPL m_msdkAdapter;
mfxIMPL m_msdkAdapterD3D9;
mfxU16 m_deviceID;
mfxU64 m_luid;
mfxExtendedDeviceId m_extDeviceID;
private:
// session management
mfxStatus OpenSession(mfxSession *session,
STRING_TYPE libNameFull,
mfxAccelerationMode accelMode,
mfxIMPL hwImpl);
void CloseSession(mfxSession *session);
// utility functions
static mfxAccelerationMode CvtAccelType(mfxIMPL implType, mfxIMPL implMethod);
static mfxStatus GetDefaultAccelType(mfxU32 adapterID, mfxIMPL *implDefault, mfxU64 *luid);
static mfxStatus CheckD3D9Support(mfxU64 luid, STRING_TYPE libNameFull, mfxIMPL *implD3D9);
static mfxStatus GetRenderNodeDescription(mfxU32 adapterID, mfxU32 &vendorID, mfxU16 &deviceID);
// internal state variables
STRING_TYPE m_libNameFull;
mfxImplDescription m_id; // base description struct
mfxAccelerationMode m_accelMode[MAX_MSDK_ACCEL_MODES];
mfxU16 m_loaderDeviceID;
__inline bool IsVersionSupported(mfxVersion reqVersion, mfxVersion actualVersion) {
if (actualVersion.Major > reqVersion.Major) {
return true;
}
else if ((actualVersion.Major == reqVersion.Major) &&
(actualVersion.Minor >= reqVersion.Minor)) {
return true;
}
return false;
}
};
struct LibInfo {
// during search store candidate file names
// and priority based on rules in spec
STRING_TYPE libNameFull;
mfxU32 libPriority;
LibType libType;
// if valid library, store file handle
// and table of exported functions
void *hModuleVPL;
VPLFunctionPtr vplFuncTable[NumVPLFunctions]; // NOLINT
// optional functions which RT may or may not export
VPLFunctionPtr vplOptionalFuncTable[NumVPLOptionalFunctions]; // NOLINT
// loader context for legacy MSDK
LoaderCtxMSDK msdkCtx[MAX_NUM_IMPL_MSDK];
// API version of legacy MSDK
mfxVersion msdkVersion;
// user-friendly version of path for MFX_IMPLCAPS_IMPLPATH query
mfxChar implCapsPath[MAX_VPL_SEARCH_PATH];
// avoid warnings
LibInfo()
: libNameFull(),
libPriority(0),
libType(LibTypeUnknown),
hModuleVPL(nullptr),
vplFuncTable(),
vplOptionalFuncTable(),
msdkCtx(),
msdkVersion(),
implCapsPath() {}
virtual ~LibInfo() {}
private:
// make this class non-copyable
LibInfo(const LibInfo &);
LibInfo &operator=(const LibInfo &);
};
struct ImplInfo {
// library containing this implementation
LibInfo *libInfo;
// description of implementation
mfxHDL implDesc;
// list of implemented functions
mfxHDL implFuncs;
mfxHDL implExtDeviceID;
#ifdef ONEVPL_EXPERIMENTAL
mfxHDL implSurfTypes;
#endif
// used for session initialization with this implementation
mfxInitializationParam vplParam;
mfxVersion version;
// if MSDK library, index of corresponding adapter (i.e. which LoaderCtxMSDK)
mfxU32 msdkImplIdx;
// adapter index in multi-adapter systems
mfxU32 adapterIdx;
// local index for libraries with more than one implementation
mfxU32 libImplIdx;
// index of valid libraries - updates with every call to MFXSetConfigFilterProperty()
mfxI32 validImplIdx;
// avoid warnings
ImplInfo()
: libInfo(nullptr),
implDesc(nullptr),
implFuncs(nullptr),
implExtDeviceID(nullptr),
#ifdef ONEVPL_EXPERIMENTAL
implSurfTypes(nullptr),
#endif
vplParam(),
version(),
msdkImplIdx(0),
adapterIdx(ADAPTER_IDX_UNKNOWN),
libImplIdx(0),
validImplIdx(-1) {
}
};
// loader class implementation
class LoaderCtxVPL {
public:
LoaderCtxVPL();
~LoaderCtxVPL();
// manage library implementations
mfxStatus BuildListOfCandidateLibs();
mfxU32 CheckValidLibraries();
mfxStatus QueryLibraryCaps();
mfxStatus UnloadAllLibraries();
// query capabilities of each implementation
mfxStatus FullLoadAndQuery();
mfxStatus QueryImpl(mfxU32 idx, mfxImplCapsDeliveryFormat format, mfxHDL *idesc);
mfxStatus ReleaseImpl(mfxHDL idesc);
// update list of valid implementations based on current filter props
mfxStatus UpdateValidImplList(void);
mfxStatus PrioritizeImplList(void);
// create mfxSession
mfxStatus CreateSession(mfxU32 idx, mfxSession *session);
// manage configuration filters
ConfigCtxVPL *AddConfigFilter();
mfxStatus FreeConfigFilters();
// manage logging
mfxStatus InitDispatcherLog();
DispatcherLogVPL *GetLogger();
// low latency initialization
mfxStatus LoadLibsLowLatency();
mfxStatus UpdateLowLatency();
bool m_bLowLatency;
bool m_bNeedUpdateValidImpls;
bool m_bNeedFullQuery;
bool m_bNeedLowLatencyQuery;
bool m_bPriorityPathEnabled;
#ifdef ONEVPL_EXPERIMENTAL
bool m_bEnablePropsQuery;
mfxStatus UpdatePropsQuery();
#endif
private:
// helper functions
mfxStatus LoadSingleLibrary(LibInfo *libInfo);
mfxStatus UnloadSingleLibrary(LibInfo *libInfo);
mfxStatus UnloadSingleImplementation(ImplInfo *implInfo);
VPLFunctionPtr GetFunctionAddr(void *hModuleVPL, const char *pName);
mfxU32 GetSearchPathsDriverStore(std::list<STRING_TYPE> &searchDirs, LibType libType);
mfxU32 GetSearchPathsSystemDefault(std::list<STRING_TYPE> &searchDirs);
mfxU32 GetSearchPathsCurrentExe(std::list<STRING_TYPE> &searchDirs);
mfxU32 GetSearchPathsCurrentDir(std::list<STRING_TYPE> &searchDirs);
mfxU32 GetSearchPathsLegacy(std::list<STRING_TYPE> &searchDirs);
#if defined INSTALL_LIBDIR_SEARCH
mfxU32 GetSearchPathsInstallDir(std::list<STRING_TYPE> &searchDirs);
#endif
mfxU32 ParseEnvSearchPaths(const CHAR_TYPE *envVarName, std::list<STRING_TYPE> &searchDirs);
mfxU32 ParseLegacySearchPaths(std::list<STRING_TYPE> &searchDirs);
mfxStatus SearchDirForLibs(STRING_TYPE searchDir,
std::list<LibInfo *> &libInfoList,
mfxU32 priority,
bool bLoadVPLOnly = false);
mfxU32 LoadAPIExports(LibInfo *libInfo, LibType libType);
mfxStatus ValidateAPIExports(VPLFunctionPtr *vplFuncTable, mfxVersion reportedVersion);
bool IsValidX86GPU(ImplInfo *implInfo, mfxU32 &deviceID, mfxU32 &adapterIdx);
mfxStatus UpdateImplPath(LibInfo *libInfo);
mfxStatus LoadLibsFromDriverStore(mfxU32 numAdapters,
const std::vector<DXGI1DeviceInfo> &adapterInfo,
LibType libType);
mfxStatus LoadLibsFromSystemDir(LibType libType);
mfxStatus LoadLibsFromMultipleDirs(LibType libType);
LibInfo *AddSingleLibrary(STRING_TYPE libPath, LibType libType);
mfxStatus QuerySessionLowLatency(LibInfo *libInfo, mfxU32 adapterID, mfxVersion *ver);
std::list<LibInfo *> m_libInfoList;
std::list<ImplInfo *> m_implInfoList;
std::list<ConfigCtxVPL *> m_configCtxList;
std::vector<DXGI1DeviceInfo> m_gpuAdapterInfo;
#ifdef ONEVPL_EXPERIMENTAL
std::vector<mfxQueryProperty> m_queryProps;
#endif
SpecialConfig m_specialConfig;
mfxU32 m_implIdxNext;
bool m_bKeepCapsUntilUnload;
CHAR_TYPE m_envVar[MAX_ENV_VAR_LEN];
// logger object - enabled with ONEVPL_DISPATCHER_LOG environment variable
DispatcherLogVPL m_dispLog;
};
#endif // LIBVPL_SRC_MFX_DISPATCHER_VPL_H_
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,63 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#include "src/mfx_dispatcher_vpl_log.h"
DispatcherLogVPL::DispatcherLogVPL() : m_logLevel(0), m_logFileName(), m_logFile(nullptr) {}
DispatcherLogVPL::~DispatcherLogVPL() {
if (!m_logFileName.empty() && m_logFile)
fclose(m_logFile);
m_logFile = nullptr;
}
mfxStatus DispatcherLogVPL::Init(mfxU32 logLevel, const std::string &logFileName) {
// avoid leaking file handle if Init is accidentally called more than once
if (m_logFile)
return MFX_ERR_UNSUPPORTED;
m_logLevel = logLevel;
m_logFileName = logFileName;
// append to file if it already exists, otherwise create a new one
// m_logFile will be closed in dtor
if (m_logLevel) {
if (m_logFileName.empty()) {
m_logFile = stdout;
}
else {
#if defined(_WIN32) || defined(_WIN64)
fopen_s(&m_logFile, m_logFileName.c_str(), "a");
#else
m_logFile = fopen(m_logFileName.c_str(), "a");
#endif
if (!m_logFile) {
m_logFile = stdout;
fprintf(m_logFile,
"Warning - unable to create logfile %s\n",
m_logFileName.c_str());
fprintf(m_logFile, "Log output will be sent to stdout\n");
m_logFileName.clear();
}
}
}
return MFX_ERR_NONE;
}
mfxStatus DispatcherLogVPL::LogMessage(const char *msg, ...) {
if (!m_logLevel || !m_logFile)
return MFX_ERR_NONE;
va_list args;
va_start(args, msg);
vfprintf(m_logFile, msg, args);
va_end(args);
fprintf(m_logFile, "\n");
return MFX_ERR_NONE;
}
@@ -0,0 +1,85 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#ifndef LIBVPL_SRC_MFX_DISPATCHER_VPL_LOG_H_
#define LIBVPL_SRC_MFX_DISPATCHER_VPL_LOG_H_
/* Intel® Video Processing Library (Intel® VPL) Dispatcher Debug Log
* The debug output of the dispatcher is controlled with the ONEVPL_DISPATCHER_LOG environment variable.
* To enable log output, set the ONEVPL_DISPATCHER_LOG environment variable value equals to "ON".
*
* By default, Intel® VPL dispatcher prints all log messages to the console.
* To redirect log output to the desired file, set the ONEVPL_DISPATCHER_LOG_FILE environmental
* variable with the file name of the log file.
*/
#include <stdarg.h>
#include <stdio.h>
#include <string>
#include "vpl/mfxdispatcher.h"
#include "vpl/mfxvideo.h"
#ifndef __FUNC_NAME__
#if defined(_WIN32) || defined(_WIN64)
#define __FUNC_NAME__ __FUNCTION__
#else
#define __FUNC_NAME__ __PRETTY_FUNCTION__
#endif
#endif
class DispatcherLogVPL {
public:
DispatcherLogVPL();
~DispatcherLogVPL();
mfxStatus Init(mfxU32 logLevel, const std::string &logFileName);
mfxStatus LogMessage(const char *msdk, ...);
mfxU32 m_logLevel;
private:
std::string m_logFileName;
FILE *m_logFile;
DispatcherLogVPL(const DispatcherLogVPL &other);
DispatcherLogVPL &operator=(const DispatcherLogVPL &other);
};
class DispatcherLogVPLFunction {
public:
DispatcherLogVPLFunction(DispatcherLogVPL *dispLog, const char *fnName)
: m_dispLog(),
m_fnName() {
m_dispLog = dispLog;
if (m_dispLog && m_dispLog->m_logLevel) {
m_fnName = fnName;
m_dispLog->LogMessage("function: %s (enter)", m_fnName.c_str());
}
}
~DispatcherLogVPLFunction() {
if (m_dispLog && m_dispLog->m_logLevel)
m_dispLog->LogMessage("function: %s (return)", m_fnName.c_str());
}
private:
DispatcherLogVPL *m_dispLog;
std::string m_fnName;
DispatcherLogVPLFunction(const DispatcherLogVPLFunction &other);
DispatcherLogVPLFunction &operator=(const DispatcherLogVPLFunction &other);
};
#define DISP_LOG_FUNCTION(dispLog) DispatcherLogVPLFunction _dispLogFn(dispLog, __FUNC_NAME__);
#define DISP_LOG_MESSAGE(dispLog, ...) \
{ \
if (dispLog) { \
(dispLog)->LogMessage(__VA_ARGS__); \
} \
}
#endif // LIBVPL_SRC_MFX_DISPATCHER_VPL_LOG_H_
@@ -0,0 +1,432 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#include "src/mfx_dispatcher_vpl.h"
#if defined(_WIN32) || defined(_WIN64)
#include "src/mfx_dispatcher_vpl_win.h"
#if defined _M_IX86
// Windows x86
#define LIB_ONEVPL L"libmfx32-gen.dll"
#define LIB_MSDK L"libmfxhw32.dll"
#else
// Windows x64
#define LIB_ONEVPL L"libmfx64-gen.dll"
#define LIB_MSDK L"libmfxhw64.dll"
#endif
#elif defined(__linux__)
// Linux x64
#define LIB_ONEVPL "libmfx-gen.so.1.2"
#define LIB_MSDK "libmfxhw64.so.1"
#endif
//Intel® Video Processing Library (Intel® VPL) low latency dispatcher
// For Windows:
// Intel® VPL - load from Driver Store, look only for libmfx64-gen.dll (32)
// MSDK - load from Driver Store, look only for libmfxhw64.dll (32)
// MSDK - fallback, load from %windir%\system32 or %windir%\syswow64
// For Linux:
// Intel® VPL - load from system paths in LoadLibsFromMultipleDirs(), look only for libmfx-gen.so.1.2
// MSDK - load from system paths in LoadLibsFromMultipleDirs(), look only for libmfxhw64.so.1
// library names
static const CHAR_TYPE *libNameVPL = LIB_ONEVPL;
static const CHAR_TYPE *libNameMSDK = LIB_MSDK;
// required exports
static const char *reqFuncVPL = "MFXInitialize";
static const char *reqFuncMSDK = "MFXInitEx";
LibInfo *LoaderCtxVPL::AddSingleLibrary(STRING_TYPE libPath, LibType libType) {
LibInfo *libInfo = nullptr;
#if defined(_WIN32) || defined(_WIN64)
// try to open library
mfxModuleHandle hLib = MFX::mfx_dll_load(libPath.c_str());
if (!hLib)
return nullptr;
// check for required entrypoint function
const char *reqFunc = (libType == LibTypeVPL ? reqFuncVPL : reqFuncMSDK);
VPLFunctionPtr pProc = (VPLFunctionPtr)MFX::mfx_dll_get_addr(hLib, reqFunc);
MFX::mfx_dll_free(hLib);
// entrypoint function missing - invalid library
if (!pProc)
return nullptr;
#else
// try to open library
void *hLib = dlopen(libPath.c_str(), RTLD_LOCAL | RTLD_NOW);
if (!hLib)
return nullptr;
// check for required entrypoint function
const char *reqFunc = (libType == LibTypeVPL ? reqFuncVPL : reqFuncMSDK);
VPLFunctionPtr pProc = (VPLFunctionPtr)dlsym(hLib, reqFunc);
dlclose(hLib);
// entrypoint function missing - invalid library
if (!pProc)
return nullptr;
#endif
// create new LibInfo and add to list
libInfo = new (std::nothrow) LibInfo;
if (!libInfo)
return nullptr;
libInfo->libNameFull = libPath;
libInfo->libType = libType;
libInfo->libPriority = (libType == LibTypeVPL ? LIB_PRIORITY_01 : LIB_PRIORITY_LEGACY);
return libInfo;
}
mfxStatus LoaderCtxVPL::LoadLibsFromDriverStore(mfxU32 numAdapters,
const std::vector<DXGI1DeviceInfo> &adapterInfo,
LibType libType) {
#if defined(_WIN32) || defined(_WIN64)
mfxStatus sts = MFX_ERR_NONE;
mfxI32 storageID = MFX::MFX_UNKNOWN_KEY;
const CHAR_TYPE *libName = nullptr;
if (libType == LibTypeVPL) {
storageID = MFX::MFX_DRIVER_STORE_ONEVPL;
libName = libNameVPL;
}
else if (libType == LibTypeMSDK) {
storageID = MFX::MFX_DRIVER_STORE;
libName = libNameMSDK;
}
else {
return MFX_ERR_UNSUPPORTED;
}
// get path to Windows driver store
STRING_TYPE libPath;
mfxU32 adapterID;
for (adapterID = 0; adapterID < numAdapters; adapterID++) {
// get driver store path for this adapter
libPath.clear();
sts = MFX::MFXLibraryIterator::GetDriverStoreDir(libPath,
MAX_VPL_SEARCH_PATH,
adapterInfo[adapterID].deviceID,
storageID);
if (sts != MFX_ERR_NONE || libPath.size() == 0)
continue;
// try to open library
libPath += libName;
LibInfo *libInfo = AddSingleLibrary(libPath, libType);
// if successful, add to list and return (stop at first
if (libInfo) {
m_libInfoList.push_back(libInfo);
return MFX_ERR_NONE;
}
}
return MFX_ERR_UNSUPPORTED;
#else
// Linux - not supported
return MFX_ERR_UNSUPPORTED;
#endif
}
mfxStatus LoaderCtxVPL::LoadLibsFromSystemDir(LibType libType) {
#if defined(_WIN32) || defined(_WIN64)
const CHAR_TYPE *libName = nullptr;
if (libType == LibTypeVPL) {
libName = libNameVPL;
}
else if (libType == LibTypeMSDK) {
libName = libNameMSDK;
}
else {
return MFX_ERR_UNSUPPORTED;
}
// get path to Windows system dir
STRING_TYPE libPath;
libPath.clear();
std::list<STRING_TYPE> winSysDir;
ParseEnvSearchPaths(L"windir", winSysDir);
// should resolve to a single directory, otherwise something went wrong
if (winSysDir.size() == 1) {
#if defined _M_IX86
libPath = winSysDir.front() + L"\\syswow64\\";
#else
libPath = winSysDir.front() + L"\\system32\\";
#endif
}
else {
return MFX_ERR_UNSUPPORTED;
}
// try to open library
libPath += libName;
LibInfo *libInfo = AddSingleLibrary(libPath, libType);
// if successful, add to list and return (stop at first
if (libInfo) {
m_libInfoList.push_back(libInfo);
return MFX_ERR_NONE;
}
return MFX_ERR_UNSUPPORTED;
#else
// Linux - not supported
return MFX_ERR_UNSUPPORTED;
#endif
}
mfxStatus LoaderCtxVPL::LoadLibsFromMultipleDirs(LibType libType) {
#ifdef __linux__
// clang-format off
// standard paths for RT installation on Linux
std::vector<std::string> llSearchDir = {
"/usr/lib/x86_64-linux-gnu",
"/lib",
"/usr/lib",
"/lib64",
"/usr/lib64",
};
// clang-format on
const CHAR_TYPE *libName = nullptr;
if (libType == LibTypeVPL) {
libName = libNameVPL;
}
else if (libType == LibTypeMSDK) {
libName = libNameMSDK;
// additional search directories for MSDK
llSearchDir.push_back("/opt/intel/mediasdk/lib");
llSearchDir.push_back("/opt/intel/mediasdk/lib64");
}
else {
return MFX_ERR_UNSUPPORTED;
}
for (const auto &searchDir : llSearchDir) {
STRING_TYPE libPath;
libPath = searchDir;
libPath += "/";
libPath += libName;
// try to open library
LibInfo *libInfo = AddSingleLibrary(libPath, libType);
// if successful, add to list and return (stop at first success)
if (libInfo) {
m_libInfoList.push_back(libInfo);
return MFX_ERR_NONE;
}
}
return MFX_ERR_UNSUPPORTED;
#else
return MFX_ERR_UNSUPPORTED;
#endif
}
mfxStatus LoaderCtxVPL::LoadLibsLowLatency() {
DISP_LOG_FUNCTION(&m_dispLog);
#if defined(_WIN32) || defined(_WIN64)
mfxStatus sts = MFX_ERR_NONE;
// check driver store
mfxU32 numAdapters = 0;
std::vector<DXGI1DeviceInfo> adapterInfo;
bool bEnumSuccess = MFX::DXGI1Device::GetAdapterList(adapterInfo);
numAdapters = (mfxU32)adapterInfo.size();
// error - no graphics adapters found
if (!bEnumSuccess || numAdapters == 0)
return MFX_ERR_UNSUPPORTED;
// try loading Intel® VPL from driver store
sts = LoadLibsFromDriverStore(numAdapters, adapterInfo, LibTypeVPL);
if (sts == MFX_ERR_NONE) {
LibInfo *libInfo = m_libInfoList.back();
sts = LoadSingleLibrary(libInfo);
if (sts == MFX_ERR_NONE) {
LoadAPIExports(libInfo, LibTypeVPL);
m_bNeedLowLatencyQuery = false;
return MFX_ERR_NONE;
}
UnloadSingleLibrary(libInfo); // failed - unload and move to next location
}
// try loading MSDK from driver store
sts = LoadLibsFromDriverStore(numAdapters, adapterInfo, LibTypeMSDK);
if (sts == MFX_ERR_NONE) {
LibInfo *libInfo = m_libInfoList.back();
sts = LoadSingleLibrary(libInfo);
if (sts == MFX_ERR_NONE) {
mfxU32 numFunctions = LoadAPIExports(libInfo, LibTypeMSDK);
if (numFunctions == NumMSDKFunctions) {
mfxVariant var = {};
var.Type = MFX_VARIANT_TYPE_PTR;
var.Data.Ptr = (mfxHDL) "mfxhw64";
auto it = m_configCtxList.begin();
while (it != m_configCtxList.end()) {
ConfigCtxVPL *config = (*it);
sts = config->SetFilterProperty((const mfxU8 *)"mfxImplDescription.ImplName",
var);
if (sts != MFX_ERR_NONE)
return MFX_ERR_UNSUPPORTED;
it++;
}
m_bNeedLowLatencyQuery = false;
return MFX_ERR_NONE;
}
}
UnloadSingleLibrary(libInfo); // failed - unload and move to next location
}
// try loading MSDK from sysdir %windir%\system32 and %windir%\syswow64
sts = LoadLibsFromSystemDir(LibTypeMSDK);
if (sts == MFX_ERR_NONE) {
LibInfo *libInfo = m_libInfoList.front();
sts = LoadSingleLibrary(libInfo);
if (sts == MFX_ERR_NONE) {
mfxU32 numFunctions = LoadAPIExports(libInfo, LibTypeMSDK);
if (numFunctions == NumMSDKFunctions) {
mfxVariant var = {};
var.Type = MFX_VARIANT_TYPE_PTR;
var.Data.Ptr = (mfxHDL) "mfxhw64";
auto it = m_configCtxList.begin();
while (it != m_configCtxList.end()) {
ConfigCtxVPL *config = (*it);
sts = config->SetFilterProperty((const mfxU8 *)"mfxImplDescription.ImplName",
var);
if (sts != MFX_ERR_NONE)
return MFX_ERR_UNSUPPORTED;
it++;
}
m_bNeedLowLatencyQuery = false;
return MFX_ERR_NONE;
}
}
UnloadSingleLibrary(libInfo); // failed - unload and move to next location
}
return MFX_ERR_UNSUPPORTED;
#else
mfxStatus sts = MFX_ERR_NONE;
// try loading Intel® VPL from Linux system directories
sts = LoadLibsFromMultipleDirs(LibTypeVPL);
if (sts == MFX_ERR_NONE) {
LibInfo *libInfo = m_libInfoList.back();
sts = LoadSingleLibrary(libInfo);
if (sts == MFX_ERR_NONE) {
LoadAPIExports(libInfo, LibTypeVPL);
m_bNeedLowLatencyQuery = false;
return MFX_ERR_NONE;
}
UnloadSingleLibrary(libInfo); // failed - unload and move to next location
}
// try loading MSDK from Linux system directories
sts = LoadLibsFromMultipleDirs(LibTypeMSDK);
if (sts == MFX_ERR_NONE) {
LibInfo *libInfo = m_libInfoList.back();
sts = LoadSingleLibrary(libInfo);
if (sts == MFX_ERR_NONE) {
mfxU32 numFunctions = LoadAPIExports(libInfo, LibTypeMSDK);
if (numFunctions == NumMSDKFunctions) {
mfxVariant var = {};
var.Type = MFX_VARIANT_TYPE_PTR;
var.Data.Ptr = (mfxHDL) "mfxhw64";
auto it = m_configCtxList.begin();
while (it != m_configCtxList.end()) {
ConfigCtxVPL *config = (*it);
sts = config->SetFilterProperty((const mfxU8 *)"mfxImplDescription.ImplName",
var);
if (sts != MFX_ERR_NONE)
return MFX_ERR_UNSUPPORTED;
it++;
}
m_bNeedLowLatencyQuery = false;
return MFX_ERR_NONE;
}
}
UnloadSingleLibrary(libInfo); // failed - unload and move to next location
}
return MFX_ERR_UNSUPPORTED;
#endif
}
// try creating a session in order to get runtime API version
mfxStatus LoaderCtxVPL::QuerySessionLowLatency(LibInfo *libInfo,
mfxU32 adapterID,
mfxVersion *ver) {
mfxStatus sts;
mfxSession session = nullptr;
mfxVersion reqVersion;
if (libInfo->libType == LibTypeVPL) {
reqVersion.Major = 2;
reqVersion.Minor = 0;
}
else {
reqVersion.Major = 1;
reqVersion.Minor = 0;
}
// set acceleration mode
mfxInitializationParam vplParam = {};
vplParam.AccelerationMode = m_specialConfig.accelerationMode;
// set adapter ID for both MSDK and Intel® VPL
vplParam.VendorImplID = adapterID;
mfxIMPL hwImpl = msdkImplTab[adapterID];
mfxU16 deviceID;
sts = MFXInitEx2(reqVersion,
vplParam,
hwImpl,
&session,
&deviceID,
(CHAR_TYPE *)libInfo->libNameFull.c_str());
if (sts == MFX_ERR_NONE) {
sts = MFXQueryVersion(session, ver);
MFXClose(session);
}
return sts;
}
@@ -0,0 +1,594 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#include <fstream>
#include "src/mfx_dispatcher_vpl.h"
#if defined(_WIN32) || defined(_WIN64)
#include "src/mfx_dispatcher_vpl_win.h"
#endif
#ifdef __linux__
#include <pthread.h>
#define strncpy_s(dst, size, src, cnt) strncpy((dst), (src), (cnt)) // NOLINT
#endif
// leave table formatting alone
// clang-format off
static const mfxChar strImplName[MFX_IMPL_NAME_LEN] = "mfxhw64";
static const mfxChar strLicense[MFX_STRFIELD_LEN] = "";
#if defined _M_IX86
static const mfxChar strKeywords[MFX_STRFIELD_LEN] = "MSDK,x86";
#else
static const mfxChar strKeywords[MFX_STRFIELD_LEN] = "MSDK,x64";
#endif
// also used in main loader routine
const mfxIMPL msdkImplTab[MAX_NUM_IMPL_MSDK] = {
MFX_IMPL_HARDWARE,
MFX_IMPL_HARDWARE2,
MFX_IMPL_HARDWARE3,
MFX_IMPL_HARDWARE4,
};
// not relevant for 1.x runtimes (no internal memory management)
#define NUM_POOL_POLICIES_MSDK 0
static const mfxPoolPolicyDescription PoolPolicies = {
{{ 0, 1 }}, // struct Version
{}, // reserved
NUM_POOL_POLICIES_MSDK, // NumPoolPolicies
nullptr,
};
// 1.x function names should match list in enum eFunc
static const mfxChar* msdkImplFuncsNames[] = {
"MFXInit",
"MFXClose",
"MFXQueryIMPL",
"MFXQueryVersion",
"MFXJoinSession",
"MFXDisjoinSession",
"MFXCloneSession",
"MFXSetPriority",
"MFXGetPriority",
"MFXInitEx",
"MFXVideoCORE_SetFrameAllocator",
"MFXVideoCORE_SetHandle",
"MFXVideoCORE_GetHandle",
"MFXVideoCORE_SyncOperation",
"MFXVideoENCODE_Query",
"MFXVideoENCODE_QueryIOSurf",
"MFXVideoENCODE_Init",
"MFXVideoENCODE_Reset",
"MFXVideoENCODE_Close",
"MFXVideoENCODE_GetVideoParam",
"MFXVideoENCODE_GetEncodeStat",
"MFXVideoENCODE_EncodeFrameAsync",
"MFXVideoDECODE_Query",
"MFXVideoDECODE_DecodeHeader",
"MFXVideoDECODE_QueryIOSurf",
"MFXVideoDECODE_Init",
"MFXVideoDECODE_Reset",
"MFXVideoDECODE_Close",
"MFXVideoDECODE_GetVideoParam",
"MFXVideoDECODE_GetDecodeStat",
"MFXVideoDECODE_SetSkipMode",
"MFXVideoDECODE_GetPayload",
"MFXVideoDECODE_DecodeFrameAsync",
"MFXVideoVPP_Query",
"MFXVideoVPP_QueryIOSurf",
"MFXVideoVPP_Init",
"MFXVideoVPP_Reset",
"MFXVideoVPP_Close",
"MFXVideoVPP_GetVideoParam",
"MFXVideoVPP_GetVPPStat",
"MFXVideoVPP_RunFrameVPPAsync",
"MFXVideoCORE_QueryPlatform",
};
static const mfxImplementedFunctions msdkImplFuncs = {
sizeof(msdkImplFuncsNames) / sizeof(mfxChar*),
(mfxChar**)msdkImplFuncsNames
};
#ifdef __linux__
// optional extBuf to limit threads created in MSDK session creation
// to enable, set vplParam.NumExtParam and vplParam.ExtParam before calling MFXInitEx2()
static const mfxExtThreadsParam extThreadParam = {
{MFX_EXTBUFF_THREADS_PARAM, sizeof(mfxExtThreadsParam)},
2,
0,
0,
{},
};
static const mfxExtBuffer* extParams[1] = {
(mfxExtBuffer *)&extThreadParam,
};
#endif
// end table formatting
// clang-format on
LoaderCtxMSDK::LoaderCtxMSDK()
: m_msdkAdapter(),
m_msdkAdapterD3D9(),
m_deviceID(0),
m_luid(0),
m_extDeviceID(),
m_libNameFull(),
m_id(),
m_accelMode(),
m_loaderDeviceID(0) {}
LoaderCtxMSDK::~LoaderCtxMSDK() {}
mfxStatus LoaderCtxMSDK::OpenSession(mfxSession *session,
STRING_TYPE libNameFull,
mfxAccelerationMode accelMode,
mfxIMPL hwImpl) {
// require API 1.0 or later (both MFXInit and MFXInitEx supported)
mfxVersion reqVersion;
reqVersion.Major = MSDK_MIN_VERSION_MAJOR;
reqVersion.Minor = MSDK_MIN_VERSION_MINOR;
// set acceleration mode - will be mapped to 1.x API
mfxInitializationParam vplParam = {};
vplParam.AccelerationMode = accelMode;
#ifdef __linux__
vplParam.ExtParam = (mfxExtBuffer **)&extParams;
vplParam.NumExtParam = 1;
#else
vplParam.ExtParam = nullptr;
vplParam.NumExtParam = 0;
#endif
return MFXInitEx2(reqVersion,
vplParam,
hwImpl,
session,
&m_loaderDeviceID,
(CHAR_TYPE *)libNameFull.c_str());
}
// safe to call more than once (sets/checks for null session)
void LoaderCtxMSDK::CloseSession(mfxSession *session) {
if (*session)
MFXClose(*session);
*session = nullptr;
}
// map mfxIMPL (1.x) to mfxAccelerationMode (2.x)
mfxAccelerationMode LoaderCtxMSDK::CvtAccelType(mfxIMPL implType, mfxIMPL implMethod) {
if (implType == MFX_IMPL_HARDWARE) {
switch (implMethod) {
case MFX_IMPL_VIA_D3D9:
return MFX_ACCEL_MODE_VIA_D3D9;
case MFX_IMPL_VIA_D3D11:
return MFX_ACCEL_MODE_VIA_D3D11;
case MFX_IMPL_VIA_VAAPI:
return MFX_ACCEL_MODE_VIA_VAAPI;
}
}
return MFX_ACCEL_MODE_NA;
}
mfxStatus LoaderCtxMSDK::GetDefaultAccelType(mfxU32 adapterID, mfxIMPL *implDefault, mfxU64 *luid) {
#ifdef __linux__
// VAAPI only
*implDefault = MFX_IMPL_VIA_VAAPI;
*luid = 0;
return MFX_ERR_NONE;
#else
// Windows - D3D11 only
mfxU32 VendorID = 0, DeviceID = 0;
mfxIMPL implTest;
mfxStatus sts;
// check whether adapterID supports D3D11 and has correct VendorID
implTest = MFX_IMPL_VIA_D3D11;
sts = MFX::SelectImplementationType(adapterID, &implTest, &VendorID, &DeviceID, luid);
if (sts != MFX_ERR_NONE || VendorID != 0x8086) {
implTest = MFX_IMPL_UNSUPPORTED;
return MFX_ERR_UNSUPPORTED;
}
*implDefault = implTest;
return MFX_ERR_NONE;
#endif
}
mfxStatus LoaderCtxMSDK::QueryAPIVersion(STRING_TYPE libNameFull, mfxVersion *msdkVersion) {
mfxStatus sts;
mfxSession session = nullptr;
mfxVersion reqVersion;
reqVersion.Major = MSDK_MIN_VERSION_MAJOR;
reqVersion.Minor = MSDK_MIN_VERSION_MINOR;
// try creating a session with each adapter in order to get MSDK API version
// stop with first successful session creation
for (mfxU32 adapterID = 0; adapterID < MAX_NUM_IMPL_MSDK; adapterID++) {
// try HW session, default acceleration mode
mfxIMPL hwImpl = msdkImplTab[adapterID];
mfxIMPL implDefault = MFX_IMPL_UNSUPPORTED;
mfxU64 luid;
// if not a valid HW device, try next adapter
sts = GetDefaultAccelType(adapterID, &implDefault, &luid);
if (sts != MFX_ERR_NONE)
continue;
// set acceleration mode - will be mapped to 1.x API
mfxInitializationParam vplParam = {};
vplParam.AccelerationMode =
(mfxAccelerationMode)CvtAccelType(MFX_IMPL_HARDWARE, implDefault & 0xFF00);
#ifdef __linux__
vplParam.ExtParam = (mfxExtBuffer **)&extParams;
vplParam.NumExtParam = 1;
#else
vplParam.ExtParam = nullptr;
vplParam.NumExtParam = 0;
#endif
mfxU16 deviceID;
sts = MFXInitEx2(reqVersion,
vplParam,
hwImpl,
&session,
&deviceID,
(CHAR_TYPE *)libNameFull.c_str());
if (sts == MFX_ERR_NONE) {
sts = MFXQueryVersion(session, msdkVersion);
MFXClose(session);
if (sts == MFX_ERR_NONE)
return sts;
}
}
return MFX_ERR_UNSUPPORTED;
}
mfxStatus LoaderCtxMSDK::QueryMSDKCaps(STRING_TYPE libNameFull,
mfxImplDescription **implDesc,
mfxImplementedFunctions **implFuncs,
mfxU32 adapterID,
bool bSkipD3D9Check) {
#ifdef DISABLE_MSDK_COMPAT
// disable support for legacy MSDK
return MFX_ERR_UNSUPPORTED;
#endif
mfxStatus sts;
mfxSession session = nullptr;
m_libNameFull = libNameFull;
m_deviceID = 0;
#ifdef __linux__
// require pthreads to be linked in for MSDK RT to load
pthread_key_t pkey;
if (pthread_key_create(&pkey, NULL) == 0) {
pthread_key_delete(pkey);
}
mfxU32 vendorID = 0;
mfxU16 deviceID = 0;
sts = GetRenderNodeDescription(adapterID, vendorID, deviceID);
if (sts != MFX_ERR_NONE)
return MFX_ERR_UNSUPPORTED;
// on Linux read deviceID from the render node path
m_deviceID = deviceID;
#endif
// try HW session, default acceleration mode
mfxIMPL hwImpl = msdkImplTab[adapterID];
mfxIMPL implDefault = MFX_IMPL_UNSUPPORTED;
sts = GetDefaultAccelType(adapterID, &implDefault, &m_luid);
if (sts != MFX_ERR_NONE)
return MFX_ERR_UNSUPPORTED;
sts = OpenSession(&session,
m_libNameFull,
(mfxAccelerationMode)CvtAccelType(MFX_IMPL_HARDWARE, implDefault & 0xFF00),
hwImpl);
// adapter unsupported
if (sts != MFX_ERR_NONE)
return MFX_ERR_UNSUPPORTED;
// return list of implemented functions
*implFuncs = (mfxImplementedFunctions *)(&msdkImplFuncs);
// clear new 2.0 style description struct
memset(&m_id, 0, sizeof(mfxImplDescription));
*implDesc = &m_id;
// fill in top-level capabilities
m_id.Version.Version = MFX_IMPLDESCRIPTION_VERSION;
m_id.Impl = MFX_IMPL_TYPE_HARDWARE;
// query API version
sts = MFXQueryVersion(session, &m_id.ApiVersion);
if (sts != MFX_ERR_NONE) {
CloseSession(&session);
return sts;
}
// set default acceleration mode
m_id.AccelerationMode = CvtAccelType(MFX_IMPL_HARDWARE, implDefault & 0xFF00);
// fill in acceleration description struct
mfxAccelerationModeDescription *accelDesc = &(m_id.AccelerationModeDescription);
accelDesc->Version.Version = MFX_ACCELERATIONMODESCRIPTION_VERSION;
// fill in mode description with just the single (default) mode
accelDesc->NumAccelerationModes = 1;
accelDesc->Mode = m_accelMode;
accelDesc->Mode[0] = m_id.AccelerationMode;
// return HW accelerator - required by MFXCreateSession
m_msdkAdapter = hwImpl;
// map MFX HW number to VendorImplID
m_id.VendorImplID = 0;
switch (hwImpl) {
case MFX_IMPL_HARDWARE:
m_id.VendorImplID = 0;
break;
case MFX_IMPL_HARDWARE2:
m_id.VendorImplID = 1;
break;
case MFX_IMPL_HARDWARE3:
m_id.VendorImplID = 2;
break;
case MFX_IMPL_HARDWARE4:
m_id.VendorImplID = 3;
break;
}
// fill in strings
strncpy_s(m_id.ImplName, sizeof(m_id.ImplName), strImplName, sizeof(strImplName));
m_id.ImplName[sizeof(m_id.ImplName) - 1] = 0;
strncpy_s(m_id.License, sizeof(m_id.License), strLicense, sizeof(strLicense));
m_id.License[sizeof(m_id.License) - 1] = 0;
strncpy_s(m_id.Keywords, sizeof(m_id.Keywords), strKeywords, sizeof(strKeywords));
m_id.Keywords[sizeof(m_id.Keywords) - 1] = 0;
m_id.VendorID = 0x8086;
m_id.NumExtParam = 0;
// fill in pool policies
m_id.PoolPolicies = PoolPolicies;
// fill in device description
mfxDeviceDescription *Dev = &(m_id.Dev);
memset(Dev, 0, sizeof(mfxDeviceDescription)); // initially empty
Dev->MediaAdapterType = MFX_MEDIA_UNKNOWN;
// query for underlying deviceID (requires API >= 1.19)
// for Linux, we may already have the deviceID from parsing render node path earlier
if (m_deviceID == 0) {
if (IsVersionSupported(MAKE_MFX_VERSION(1, 19), m_id.ApiVersion)) {
mfxPlatform platform = {};
sts = MFXVideoCORE_QueryPlatform(session, &platform);
if (sts == MFX_ERR_NONE)
m_deviceID = platform.DeviceId;
// mfxPlatform::MediaAdapterType was added in API 1.31
if (IsVersionSupported(MAKE_MFX_VERSION(1, 31), m_id.ApiVersion)) {
Dev->MediaAdapterType = platform.MediaAdapterType;
}
}
}
// if QueryPlatform did not return deviceID, we may have received
// it from the loader (MFXInitEx2)
if (m_deviceID == 0)
m_deviceID = m_loaderDeviceID;
// store DeviceID as "DevID" (hex) / "AdapterIdx" (dec) to match GPU RT
Dev->Version.Version = MFX_DEVICEDESCRIPTION_VERSION;
snprintf(Dev->DeviceID, sizeof(Dev->DeviceID), "%x/%d", m_deviceID, m_id.VendorImplID);
Dev->NumSubDevices = 0;
CloseSession(&session);
#if defined(_WIN32) || defined(_WIN64)
if (bSkipD3D9Check == false) {
mfxIMPL implD3D9;
m_msdkAdapterD3D9 = MFX_IMPL_UNSUPPORTED;
sts = CheckD3D9Support(m_luid, libNameFull, &implD3D9);
if (sts == MFX_ERR_NONE) {
m_msdkAdapterD3D9 = implD3D9;
accelDesc->Mode[accelDesc->NumAccelerationModes] = MFX_ACCEL_MODE_VIA_D3D9;
accelDesc->NumAccelerationModes++;
}
}
#endif
return MFX_ERR_NONE;
}
mfxStatus LoaderCtxMSDK::CheckD3D9Support(mfxU64 luid, STRING_TYPE libNameFull, mfxIMPL *implD3D9) {
#if defined(_WIN32) || defined(_WIN64)
mfxU32 VendorID = 0, DeviceID = 0;
mfxIMPL implTest = MFX_IMPL_VIA_D3D9;
mfxStatus sts;
mfxSession session = nullptr;
mfxVersion reqVersion;
reqVersion.Major = MSDK_MIN_VERSION_MAJOR;
reqVersion.Minor = MSDK_MIN_VERSION_MINOR;
*implD3D9 = MFX_IMPL_UNSUPPORTED;
mfxU32 idx;
for (idx = 0; idx < MAX_NUM_IMPL_MSDK; idx++) {
mfxU64 luidD3D9 = 0;
sts = MFX::SelectImplementationType(idx, &implTest, &VendorID, &DeviceID, &luidD3D9);
if (sts != MFX_ERR_NONE || VendorID != 0x8086 || luid != luidD3D9)
continue;
// matching LUID - try creating a D3D9 session
mfxInitializationParam vplParam = {};
vplParam.AccelerationMode = MFX_ACCEL_MODE_VIA_D3D9;
// thread limit not enabled on Windows
vplParam.ExtParam = nullptr;
vplParam.NumExtParam = 0;
mfxU16 deviceID;
sts = MFXInitEx2(reqVersion,
vplParam,
msdkImplTab[idx],
&session,
&deviceID,
(CHAR_TYPE *)libNameFull.c_str());
if (sts == MFX_ERR_NONE) {
*implD3D9 = msdkImplTab[idx];
MFXClose(session);
return MFX_ERR_NONE;
}
break; // D3D9 not supported
}
// this adapter (input luid) does not support D3D9
return MFX_ERR_UNSUPPORTED;
#else
return MFX_ERR_UNSUPPORTED;
#endif
}
mfxU32 read_device_file(std::string &path) {
mfxU32 result = 0;
std::string line;
std::ifstream dev_str(path);
if (!dev_str.is_open()) {
return 0;
}
std::getline(dev_str, line);
dev_str.close();
try {
result = std::stoul(line, 0, 16);
}
catch (std::invalid_argument &) {
return 0;
}
catch (std::out_of_range &) {
return 0;
}
return result;
}
mfxStatus LoaderCtxMSDK::GetRenderNodeDescription(mfxU32 adapterID,
mfxU32 &vendorID,
mfxU16 &deviceID) {
vendorID = 0;
deviceID = 0;
#if defined(__linux__)
mfxU32 DRMRenderNodeNum = 128 + adapterID;
std::string nodeStr = std::to_string(DRMRenderNodeNum);
std::string vendorPath = "/sys/class/drm/renderD" + nodeStr + "/device/vendor";
std::string devPath = "/sys/class/drm/renderD" + nodeStr + "/device/device";
vendorID = read_device_file(vendorPath);
if (vendorID != 0x8086)
return MFX_ERR_UNSUPPORTED;
deviceID = read_device_file(devPath);
if (deviceID == 0)
return MFX_ERR_UNSUPPORTED;
return MFX_ERR_NONE;
#else
return MFX_ERR_UNSUPPORTED;
#endif
}
// avoid confusing #ifdef indentation
// clang-format off
mfxStatus LoaderCtxMSDK::QueryExtDeviceID(mfxExtendedDeviceId *extDeviceID,
mfxU32 adapterID,
mfxU16 deviceID,
mfxU64 luid) {
// fill extended device ID struct (API >= 2.6)
memset(extDeviceID, 0, sizeof(mfxExtendedDeviceId));
// common properties
extDeviceID->Version.Version = MFX_EXTENDEDDEVICEID_VERSION;
extDeviceID->VendorID = 0x8086;
extDeviceID->DeviceID = deviceID;
// default - no PCI info
// additional dependencies required to obtain these props
extDeviceID->PCIDomain = 0xFFFFFFFF;
extDeviceID->PCIBus = 0xFFFFFFFF;
extDeviceID->PCIDevice = 0xFFFFFFFF;
extDeviceID->PCIFunction = 0xFFFFFFFF;
// default - no LUID
extDeviceID->LUIDDeviceNodeMask = 0;
extDeviceID->LUIDValid = 0;
for (mfxU32 idx = 0; idx < 8; idx++)
extDeviceID->DeviceLUID[idx] = 0;
// default - no DRM node
extDeviceID->DRMRenderNodeNum = 0;
extDeviceID->DRMPrimaryNodeNum = 0x7FFFFFFF;
// default - no PCI RevisionID
extDeviceID->RevisionID = 0xFFFF;
snprintf(extDeviceID->DeviceName, sizeof(extDeviceID->DeviceName), "%s", strImplName);
#if defined(_WIN32) || defined(_WIN64)
// fill in Windows-specific properties
if (luid) {
extDeviceID->LUIDDeviceNodeMask = 1;
extDeviceID->LUIDValid = 1;
// map 64-bit LUID into mfxU8[8]
mfxU64 luidArr = luid;
for (mfxU32 idx = 0; idx < 8; idx++) {
extDeviceID->DeviceLUID[idx] = mfxU8((luidArr)&0xFF);
luidArr >>= 8;
}
}
#elif defined(__linux__)
extDeviceID->DRMPrimaryNodeNum = adapterID;
extDeviceID->DRMRenderNodeNum = 128 + adapterID;
#endif
return MFX_ERR_NONE;
}
// clang-format on
@@ -0,0 +1,19 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#ifndef LIBVPL_SRC_MFX_DISPATCHER_VPL_WIN_H_
#define LIBVPL_SRC_MFX_DISPATCHER_VPL_WIN_H_
// headers for Windows legacy dispatcher
#if defined(_WIN32) || defined(_WIN64)
#include "windows/mfx_dispatcher.h"
#include "windows/mfx_dispatcher_defs.h"
#include "windows/mfx_dxva2_device.h"
#include "windows/mfx_library_iterator.h"
#include "windows/mfx_load_dll.h"
#endif
#endif // LIBVPL_SRC_MFX_DISPATCHER_VPL_WIN_H_
@@ -0,0 +1,76 @@
EXPORTS
MFXInit
MFXClose
MFXQueryIMPL
MFXQueryVersion
MFXJoinSession
MFXDisjoinSession
MFXCloneSession
MFXSetPriority
MFXGetPriority
MFXVideoCORE_SetFrameAllocator
MFXVideoCORE_SetHandle
MFXVideoCORE_GetHandle
MFXVideoCORE_QueryPlatform
MFXVideoCORE_SyncOperation
MFXVideoENCODE_Query
MFXVideoENCODE_QueryIOSurf
MFXVideoENCODE_Init
MFXVideoENCODE_Reset
MFXVideoENCODE_Close
MFXVideoENCODE_GetVideoParam
MFXVideoENCODE_GetEncodeStat
MFXVideoENCODE_EncodeFrameAsync
MFXVideoDECODE_Query
MFXVideoDECODE_DecodeHeader
MFXVideoDECODE_QueryIOSurf
MFXVideoDECODE_Init
MFXVideoDECODE_Reset
MFXVideoDECODE_Close
MFXVideoDECODE_GetVideoParam
MFXVideoDECODE_GetDecodeStat
MFXVideoDECODE_SetSkipMode
MFXVideoDECODE_GetPayload
MFXVideoDECODE_DecodeFrameAsync
MFXVideoVPP_Query
MFXVideoVPP_QueryIOSurf
MFXVideoVPP_Init
MFXVideoVPP_Reset
MFXVideoVPP_Close
MFXVideoVPP_GetVideoParam
MFXVideoVPP_GetVPPStat
MFXVideoVPP_RunFrameVPPAsync
MFXInitEx
MFXQueryAdapters
MFXQueryAdaptersNumber
MFXQueryAdaptersDecode
MFXLoad
MFXUnload
MFXCreateConfig
MFXSetConfigFilterProperty
MFXEnumImplementations
MFXCreateSession
MFXDispReleaseImplDescription
MFXMemory_GetSurfaceForVPP
MFXMemory_GetSurfaceForEncode
MFXMemory_GetSurfaceForDecode
MFXMemory_GetSurfaceForVPPOut
MFXVideoDECODE_VPP_Init
MFXVideoDECODE_VPP_DecodeFrameAsync
MFXVideoDECODE_VPP_Reset
MFXVideoDECODE_VPP_GetChannelParam
MFXVideoDECODE_VPP_Close
MFXVideoVPP_ProcessFrameAsync
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,49 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#include "src/windows/mfx_critical_section.h"
#include <windows.h>
// SDK re-declares the following functions with different call declarator.
// We don't need them. Just redefine them to nothing.
#define _interlockedbittestandset fake_set
#define _interlockedbittestandreset fake_reset
#define _interlockedbittestandset64 fake_set64
#define _interlockedbittestandreset64 fake_reset64
#include <intrin.h>
#define MFX_WAIT() SwitchToThread()
// static section of the file
namespace {
enum { MFX_SC_IS_FREE = 0, MFX_SC_IS_TAKEN = 1 };
} // namespace
namespace MFX {
mfxU32 mfxInterlockedCas32(mfxCriticalSection *pCSection,
mfxU32 value_to_exchange,
mfxU32 value_to_compare) {
return _InterlockedCompareExchange(pCSection, value_to_exchange, value_to_compare);
}
mfxU32 mfxInterlockedXchg32(mfxCriticalSection *pCSection, mfxU32 value) {
return _InterlockedExchange(pCSection, value);
}
void mfxEnterCriticalSection(mfxCriticalSection *pCSection) {
while (MFX_SC_IS_TAKEN == mfxInterlockedCas32(pCSection, MFX_SC_IS_TAKEN, MFX_SC_IS_FREE)) {
MFX_WAIT();
}
} // void mfxEnterCriticalSection(mfxCriticalSection *pCSection)
void mfxLeaveCriticalSection(mfxCriticalSection *pCSection) {
mfxInterlockedXchg32(pCSection, MFX_SC_IS_FREE);
} // void mfxLeaveCriticalSection(mfxCriticalSection *pCSection)
} // namespace MFX
@@ -0,0 +1,48 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#ifndef LIBVPL_SRC_WINDOWS_MFX_CRITICAL_SECTION_H_
#define LIBVPL_SRC_WINDOWS_MFX_CRITICAL_SECTION_H_
#include "vpl/mfxdefs.h"
namespace MFX {
// Just set "critical section" instance to zero for initialization.
typedef volatile mfxL32 mfxCriticalSection;
// Enter the global critical section.
void mfxEnterCriticalSection(mfxCriticalSection *pCSection);
// Leave the global critical section.
void mfxLeaveCriticalSection(mfxCriticalSection *pCSection);
class MFXAutomaticCriticalSection {
public:
// Constructor
explicit MFXAutomaticCriticalSection(mfxCriticalSection *pCSection) {
m_pCSection = pCSection;
mfxEnterCriticalSection(m_pCSection);
}
// Destructor
~MFXAutomaticCriticalSection() {
mfxLeaveCriticalSection(m_pCSection);
}
protected:
// Pointer to a critical section
mfxCriticalSection *m_pCSection;
private:
// unimplemented by intent to make this class non-copyable
MFXAutomaticCriticalSection(const MFXAutomaticCriticalSection &);
void operator=(const MFXAutomaticCriticalSection &);
};
} // namespace MFX
#endif // LIBVPL_SRC_WINDOWS_MFX_CRITICAL_SECTION_H_
@@ -0,0 +1,594 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#include "src/windows/mfx_dispatcher.h"
#include "src/windows/mfx_dispatcher_log.h"
#include "src/windows/mfx_load_dll.h"
#include <assert.h>
#include <string.h>
#include <windows.h>
#include <algorithm>
#include "src/windows/mfx_dxva2_device.h"
#include "src/windows/mfx_vector.h"
#include "src/windows/mfxvideo++.h"
#include "vpl/mfxadapter.h"
#if _MSC_VER
#pragma warning(disable : 4355)
#endif
MFX_DISP_HANDLE::MFX_DISP_HANDLE(const mfxVersion requiredVersion)
: _mfxSession(),
apiVersion(requiredVersion) {
actualApiVersion.Version = 0;
implType = MFX_LIB_SOFTWARE;
impl = MFX_IMPL_SOFTWARE;
loadStatus = MFX_ERR_NOT_FOUND;
dispVersion.Major = MFX_DISPATCHER_VERSION_MAJOR;
dispVersion.Minor = MFX_DISPATCHER_VERSION_MINOR;
storageID = 0;
implInterface = MFX_IMPL_HARDWARE_ANY;
hModule = (mfxModuleHandle)0;
} // MFX_DISP_HANDLE::MFX_DISP_HANDLE(const mfxVersion requiredVersion)
MFX_DISP_HANDLE::~MFX_DISP_HANDLE(void) {
Close();
} // MFX_DISP_HANDLE::~MFX_DISP_HANDLE(void)
mfxStatus MFX_DISP_HANDLE::Close(void) {
mfxStatus mfxRes;
mfxRes = UnLoadSelectedDLL();
// need to reset dispatcher state after unloading dll
if (MFX_ERR_NONE == mfxRes) {
implType = MFX_LIB_SOFTWARE;
impl = MFX_IMPL_SOFTWARE;
loadStatus = MFX_ERR_NOT_FOUND;
dispVersion.Major = MFX_DISPATCHER_VERSION_MAJOR;
dispVersion.Minor = MFX_DISPATCHER_VERSION_MINOR;
*static_cast<_mfxSession *>(this) = _mfxSession();
hModule = (mfxModuleHandle)0;
}
return mfxRes;
} // mfxStatus MFX_DISP_HANDLE::Close(void)
mfxStatus MFX_DISP_HANDLE::LoadSelectedDLL(const wchar_t *pPath,
eMfxImplType reqImplType,
mfxIMPL reqImpl,
mfxIMPL reqImplInterface,
mfxInitParam &par,
mfxInitializationParam &vplParam,
bool bCloneSession) {
mfxStatus mfxRes = MFX_ERR_NONE;
// check error(s)
if ((MFX_LIB_SOFTWARE != reqImplType) && (MFX_LIB_HARDWARE != reqImplType)) {
DISPATCHER_LOG_ERROR(
(("implType == %s, should be either MFX_LIB_SOFTWARE or MFX_LIB_HARDWARE\n"),
DispatcherLog_GetMFXImplString(reqImplType).c_str()));
loadStatus = MFX_ERR_ABORTED;
return loadStatus;
}
// only exact types of implementation is allowed
if ((MFX_IMPL_SOFTWARE != reqImpl) && (MFX_IMPL_HARDWARE != reqImpl) &&
(MFX_IMPL_HARDWARE2 != reqImpl) && (MFX_IMPL_HARDWARE3 != reqImpl) &&
(MFX_IMPL_HARDWARE4 != reqImpl)) {
DISPATCHER_LOG_ERROR((("invalid implementation impl == %s\n"),
DispatcherLog_GetMFXImplString(impl).c_str()));
loadStatus = MFX_ERR_ABORTED;
return loadStatus;
}
// close the handle before initialization
Close();
// save the library's type
this->implType = reqImplType;
this->impl = reqImpl;
this->implInterface = reqImplInterface;
{
assert(hModule == (mfxModuleHandle)0);
DISPATCHER_LOG_BLOCK(("invoking LoadLibrary(%S)\n", pPath));
// load the DLL into the memory
hModule = MFX::mfx_dll_load(pPath);
if (hModule) {
int i;
DISPATCHER_LOG_OPERATION({
wchar_t modulePath[1024];
GetModuleFileNameW((HMODULE)hModule,
modulePath,
sizeof(modulePath) / sizeof(modulePath[0]));
DISPATCHER_LOG_INFO((("loaded module %S\n"), modulePath))
});
// load video functions: pointers to exposed functions
for (i = 0; i < eVideoFuncTotal; i += 1) {
mfxFunctionPointer pProc =
(mfxFunctionPointer)MFX::mfx_dll_get_addr(hModule, APIFunc[i].pName);
if (pProc) {
// function exists in the library,
// save the pointer.
callTable[i] = pProc;
}
else {
// The library doesn't contain the function
DISPATCHER_LOG_WRN((("Can't find API function \"%s\"\n"), APIFunc[i].pName));
if (apiVersion.Version >= APIFunc[i].apiVersion.Version) {
DISPATCHER_LOG_ERROR((("\"%s\" is required for API %u.%u\n"),
APIFunc[i].pName,
apiVersion.Major,
apiVersion.Minor));
mfxRes = MFX_ERR_UNSUPPORTED;
break;
}
}
}
// if version >= 2.0, load these functions as well
if (apiVersion.Major >= 2) {
for (i = 0; i < eVideoFunc2Total; i += 1) {
mfxFunctionPointer pProc =
(mfxFunctionPointer)MFX::mfx_dll_get_addr(hModule, APIVideoFunc2[i].pName);
if (pProc) {
// function exists in the library,
// save the pointer.
callVideoTable2[i] = pProc;
}
else {
// The library doesn't contain the function
DISPATCHER_LOG_WRN(
(("Can't find API function \"%s\"\n"), APIVideoFunc2[i].pName));
if (apiVersion.Version >= APIVideoFunc2[i].apiVersion.Version) {
DISPATCHER_LOG_ERROR((("\"%s\" is required for API %u.%u\n"),
APIVideoFunc2[i].pName,
apiVersion.Major,
apiVersion.Minor));
mfxRes = MFX_ERR_UNSUPPORTED;
break;
}
}
}
}
}
else {
DISPATCHER_LOG_WRN((("can't find DLL: GetLastErr()=0x%x\n"), GetLastError()))
mfxRes = MFX_ERR_UNSUPPORTED;
}
}
if (bCloneSession == true) {
loadStatus = mfxRes;
return mfxRes;
}
// initialize the loaded DLL
if (MFX_ERR_NONE == mfxRes) {
mfxVersion version(apiVersion);
if (version.Major >= 2) {
// for API >= 2.0 call MFXInitialize instead of MFXInitEx
int tableIndex = eMFXInitialize;
mfxFunctionPointer pFunc = callVideoTable2[tableIndex];
// filled-in mfxInitializationParam must be provided for MFXInitialize path
mfxRes =
(*(mfxStatus(MFX_CDECL *)(mfxInitializationParam, mfxSession *))pFunc)(vplParam,
&session);
}
else {
// Call old-style MFXInit init for older libraries
bool callOldInit =
!callTable[eMFXInitEx]; // if true call eMFXInit, if false - eMFXInitEx
int tableIndex = (callOldInit) ? eMFXInit : eMFXInitEx;
mfxFunctionPointer pFunc = callTable[tableIndex];
if (callOldInit) {
DISPATCHER_LOG_BLOCK(("MFXInit(%s,ver=%u.%u,session=0x%p)\n",
DispatcherLog_GetMFXImplString(impl | implInterface).c_str(),
apiVersion.Major,
apiVersion.Minor,
&session));
mfxRes = (*(mfxStatus(MFX_CDECL *)(mfxIMPL, mfxVersion *, mfxSession *))pFunc)(
impl | implInterface,
&version,
&session);
}
else {
DISPATCHER_LOG_BLOCK(("MFXInitEx(%s,ver=%u.%u,ExtThreads=%d,session=0x%p)\n",
DispatcherLog_GetMFXImplString(impl | implInterface).c_str(),
apiVersion.Major,
apiVersion.Minor,
par.ExternalThreads,
&session));
mfxInitParam initPar = par;
// adjusting user parameters
initPar.Implementation = impl | implInterface;
initPar.Version = version;
mfxRes =
(*(mfxStatus(MFX_CDECL *)(mfxInitParam, mfxSession *))pFunc)(initPar, &session);
}
}
if (MFX_ERR_NONE != mfxRes) {
DISPATCHER_LOG_WRN((("library can't be load. MFXInit returned %s \n"),
DispatcherLog_GetMFXStatusString(mfxRes)))
}
else {
mfxRes = MFXQueryVersion((mfxSession)this, &actualApiVersion);
if (MFX_ERR_NONE != mfxRes) {
DISPATCHER_LOG_ERROR(
(("MFXQueryVersion returned: %d, skipped this library\n"), mfxRes))
}
else {
DISPATCHER_LOG_INFO((("MFXQueryVersion returned API: %d.%d\n"),
actualApiVersion.Major,
actualApiVersion.Minor))
//special hook for applications that uses sink api to get loaded library path
DISPATCHER_LOG_LIBRARY(("%p", hModule));
DISPATCHER_LOG_INFO(("library loaded successfully\n"))
}
}
}
loadStatus = mfxRes;
return mfxRes;
} // mfxStatus MFX_DISP_HANDLE::LoadSelectedDLL(const wchar_t* pPath, eMfxImplType reqImplType, mfxIMPL reqImpl, mfxIMPL reqImplInterface, mfxInitParam& par, mfxInitializationParam &vplParam)
mfxStatus MFX_DISP_HANDLE::UnLoadSelectedDLL(void) {
mfxStatus mfxRes = MFX_ERR_NONE;
// close the loaded DLL
if (session) {
/* check whether it is audio session or video */
int tableIndex = eMFXClose;
mfxFunctionPointer pFunc;
pFunc = callTable[tableIndex];
mfxRes = (*(mfxStatus(MFX_CDECL *)(mfxSession))pFunc)(session);
if (MFX_ERR_NONE == mfxRes) {
session = (mfxSession)0;
}
DISPATCHER_LOG_INFO((("MFXClose(0x%x) returned %d\n"), session, mfxRes));
// actually, the return value is required to pass outside only.
}
// it is possible, that there is an active child session.
// can't unload library in that case.
if ((MFX_ERR_UNDEFINED_BEHAVIOR != mfxRes) && (hModule)) {
// unload the library.
if (!MFX::mfx_dll_free(hModule)) {
mfxRes = MFX_ERR_UNDEFINED_BEHAVIOR;
}
hModule = (mfxModuleHandle)0;
}
return mfxRes;
} // mfxStatus MFX_DISP_HANDLE::UnLoadSelectedDLL(void)
MFX_DISP_HANDLE_EX::MFX_DISP_HANDLE_EX(const mfxVersion requiredVersion)
: MFX_DISP_HANDLE(requiredVersion),
mediaAdapterType(MFX_MEDIA_UNKNOWN) {}
#if (defined(_WIN64) || defined(_WIN32)) && (MFX_VERSION >= 1031)
static mfxStatus InitDummySession(mfxU32 adapter_n, MFXVideoSession &dummy_session) {
mfxInitParam initPar;
memset(&initPar, 0, sizeof(initPar));
initPar.Version.Major = 1;
initPar.Version.Minor = 0;
switch (adapter_n) {
case 0:
initPar.Implementation = MFX_IMPL_HARDWARE;
break;
case 1:
initPar.Implementation = MFX_IMPL_HARDWARE2;
break;
case 2:
initPar.Implementation = MFX_IMPL_HARDWARE3;
break;
case 3:
initPar.Implementation = MFX_IMPL_HARDWARE4;
break;
default:
// try searching on all display adapters
initPar.Implementation = MFX_IMPL_HARDWARE_ANY;
break;
}
initPar.Implementation |= MFX_IMPL_VIA_D3D11;
return dummy_session.InitEx(initPar);
}
static inline bool is_iGPU(const mfxAdapterInfo &adapter_info) {
return adapter_info.Platform.MediaAdapterType == MFX_MEDIA_INTEGRATED;
}
static inline bool is_dGPU(const mfxAdapterInfo &adapter_info) {
return adapter_info.Platform.MediaAdapterType == MFX_MEDIA_DISCRETE;
}
// This function implies that iGPU has higher priority
static inline mfxI32 iGPU_priority(const void *ll, const void *rr) {
const mfxAdapterInfo &l = *(reinterpret_cast<const mfxAdapterInfo *>(ll));
const mfxAdapterInfo &r = *(reinterpret_cast<const mfxAdapterInfo *>(rr));
if ((is_iGPU(l) && is_iGPU(r)) || (is_dGPU(l) && is_dGPU(r)))
return 0;
if (is_iGPU(l) && is_dGPU(r))
return -1;
// The only combination left is_dGPU(l) && is_iGPU(r))
return 1;
}
static void RearrangeInPriorityOrder(const mfxComponentInfo &info,
MFX::MFXVector<mfxAdapterInfo> &vec) {
(void)info;
{
// Move iGPU to top priority
qsort(vec.data(), vec.size(), sizeof(mfxAdapterInfo), &iGPU_priority);
}
}
static mfxStatus PrepareAdaptersInfo(const mfxComponentInfo *info,
MFX::MFXVector<mfxAdapterInfo> &vec,
mfxAdaptersInfo &adapters) {
// No suitable adapters on system to handle user's workload
if (vec.empty()) {
adapters.NumActual = 0;
return MFX_ERR_NOT_FOUND;
}
if (info) {
RearrangeInPriorityOrder(*info, vec);
}
mfxU32 num_to_copy = (std::min)(mfxU32(vec.size()), adapters.NumAlloc);
for (mfxU32 i = 0; i < num_to_copy; ++i) {
adapters.Adapters[i] = vec[i];
}
adapters.NumActual = num_to_copy;
if (vec.size() > adapters.NumAlloc) {
return MFX_WRN_OUT_OF_RANGE;
}
return MFX_ERR_NONE;
}
static inline bool QueryAdapterInfo(mfxU32 adapter_n, mfxU32 &VendorID, mfxU32 &DeviceID) {
MFX::DXVA2Device dxvaDevice;
if (!dxvaDevice.InitDXGI1(adapter_n))
return false;
VendorID = dxvaDevice.GetVendorID();
DeviceID = dxvaDevice.GetDeviceID();
return true;
}
static inline mfxU32 MakeVersion(mfxU16 major, mfxU16 minor) {
return major * 1000 + minor;
}
mfxStatus MFXQueryAdaptersDecode(mfxBitstream *bitstream,
mfxU32 codec_id,
mfxAdaptersInfo *adapters) {
if (!adapters || !bitstream)
return MFX_ERR_NULL_PTR;
MFX::MFXVector<mfxAdapterInfo> obtained_info;
mfxU32 adapter_n = 0, VendorID, DeviceID;
mfxComponentInfo input_info;
memset(&input_info, 0, sizeof(input_info));
input_info.Type = mfxComponentType::MFX_COMPONENT_DECODE;
input_info.Requirements.mfx.CodecId = codec_id;
for (;;) {
if (!QueryAdapterInfo(adapter_n, VendorID, DeviceID))
break;
++adapter_n;
if (VendorID != INTEL_VENDOR_ID)
continue;
// Check if requested capabilities are supported
MFXVideoSession dummy_session;
mfxStatus sts = InitDummySession(adapter_n - 1, dummy_session);
if (sts != MFX_ERR_NONE) {
continue;
}
mfxVideoParam stream_params, out;
memset(&out, 0, sizeof(out));
memset(&stream_params, 0, sizeof(stream_params));
out.mfx.CodecId = stream_params.mfx.CodecId = codec_id;
sts = MFXVideoDECODE_DecodeHeader(dummy_session.operator mfxSession(),
bitstream,
&stream_params);
if (sts != MFX_ERR_NONE) {
continue;
}
sts = MFXVideoDECODE_Query(dummy_session.operator mfxSession(), &stream_params, &out);
if (sts !=
MFX_ERR_NONE) // skip MFX_ERR_UNSUPPORTED as well as MFX_WRN_INCOMPATIBLE_VIDEO_PARAM
continue;
mfxAdapterInfo info;
memset(&info, 0, sizeof(info));
//WA for initialization when application built w/ new API, but lib w/ old one.
mfxVersion apiVersion;
sts = dummy_session.QueryVersion(&apiVersion);
if (sts != MFX_ERR_NONE)
continue;
mfxU32 version = MakeVersion(apiVersion.Major, apiVersion.Minor);
if (version >= 1019) {
sts = MFXVideoCORE_QueryPlatform(dummy_session.operator mfxSession(), &info.Platform);
if (sts != MFX_ERR_NONE) {
continue;
}
}
else {
// for API versions greater than 1.19 Device id is set inside QueryPlatform call
info.Platform.DeviceId = static_cast<mfxU16>(DeviceID);
}
info.Number = adapter_n - 1;
obtained_info.push_back(info);
}
return PrepareAdaptersInfo(&input_info, obtained_info, *adapters);
}
mfxStatus MFXQueryAdapters(mfxComponentInfo *input_info, mfxAdaptersInfo *adapters) {
if (!adapters)
return MFX_ERR_NULL_PTR;
MFX::MFXVector<mfxAdapterInfo> obtained_info;
//obtained_info.reserve(adapters->NumAdaptersAlloc);
mfxU32 adapter_n = 0, VendorID, DeviceID;
for (;;) {
if (!QueryAdapterInfo(adapter_n, VendorID, DeviceID))
break;
++adapter_n;
if (VendorID != INTEL_VENDOR_ID)
continue;
// Check if requested capabilities are supported
MFXVideoSession dummy_session;
mfxStatus sts = InitDummySession(adapter_n - 1, dummy_session);
if (sts != MFX_ERR_NONE) {
continue;
}
// If input_info is NULL just return all Intel adapters and information about them
if (input_info) {
mfxVideoParam out;
memset(&out, 0, sizeof(out));
switch (input_info->Type) {
case mfxComponentType::MFX_COMPONENT_ENCODE: {
out.mfx.CodecId = input_info->Requirements.mfx.CodecId;
sts = MFXVideoENCODE_Query(dummy_session.operator mfxSession(),
&input_info->Requirements,
&out);
} break;
case mfxComponentType::MFX_COMPONENT_DECODE: {
out.mfx.CodecId = input_info->Requirements.mfx.CodecId;
sts = MFXVideoDECODE_Query(dummy_session.operator mfxSession(),
&input_info->Requirements,
&out);
} break;
case mfxComponentType::MFX_COMPONENT_VPP: {
sts = MFXVideoVPP_Query(dummy_session.operator mfxSession(),
&input_info->Requirements,
&out);
} break;
default:
sts = MFX_ERR_UNSUPPORTED;
}
}
if (sts !=
MFX_ERR_NONE) // skip MFX_ERR_UNSUPPORTED as well as MFX_WRN_INCOMPATIBLE_VIDEO_PARAM
continue;
mfxAdapterInfo info;
memset(&info, 0, sizeof(info));
//WA for initialization when application built w/ new API, but lib w/ old one.
mfxVersion apiVersion;
sts = dummy_session.QueryVersion(&apiVersion);
if (sts != MFX_ERR_NONE)
continue;
mfxU32 version = MakeVersion(apiVersion.Major, apiVersion.Minor);
if (version >= 1019) {
sts = MFXVideoCORE_QueryPlatform(dummy_session.operator mfxSession(), &info.Platform);
if (sts != MFX_ERR_NONE) {
continue;
}
}
else {
// for API versions greater than 1.19 Device id is set inside QueryPlatform call
info.Platform.DeviceId = static_cast<mfxU16>(DeviceID);
}
info.Number = adapter_n - 1;
obtained_info.push_back(info);
}
return PrepareAdaptersInfo(input_info, obtained_info, *adapters);
}
mfxStatus MFXQueryAdaptersNumber(mfxU32 *num_adapters) {
if (!num_adapters)
return MFX_ERR_NULL_PTR;
mfxU32 intel_adapter_count = 0, VendorID, DeviceID;
for (mfxU32 cur_adapter = 0;; ++cur_adapter) {
if (!QueryAdapterInfo(cur_adapter, VendorID, DeviceID))
break;
if (VendorID == INTEL_VENDOR_ID)
++intel_adapter_count;
}
*num_adapters = intel_adapter_count;
return MFX_ERR_NONE;
}
#endif // (defined(_WIN64) || defined(_WIN32)) && (MFX_VERSION >= 1031)
@@ -0,0 +1,218 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#ifndef LIBVPL_SRC_WINDOWS_MFX_DISPATCHER_H_
#define LIBVPL_SRC_WINDOWS_MFX_DISPATCHER_H_
#include <stddef.h>
#include <algorithm>
#include "vpl/mfxdispatcher.h"
#include "vpl/mfxvideo.h"
#include "src/windows/mfx_dispatcher_defs.h"
// internal implementation of mfxConfigInterface
#include "src/mfx_config_interface/mfx_config_interface.h"
#define INTEL_VENDOR_ID 0x8086
mfxStatus MFXQueryVersion(mfxSession session, mfxVersion *version);
enum {
// to avoid code changing versions are just inherited
// from the API header file.
DEFAULT_API_VERSION_MAJOR = MFX_VERSION_MAJOR,
DEFAULT_API_VERSION_MINOR = MFX_VERSION_MINOR
};
enum { VPL_MINIMUM_VERSION_MAJOR = 2, VPL_MINIMUM_VERSION_MINOR = 0 };
//
// declare functions' integer identifiers.
//
#undef FUNCTION
#define FUNCTION(return_value, func_name, formal_param_list, actual_param_list) e##func_name,
enum eFunc {
eMFXInit,
eMFXClose,
eMFXQueryIMPL,
eMFXQueryVersion,
eMFXVideoCORE_GetHandle,
eMFXJoinSession,
eMFXDisjoinSession,
eMFXCloneSession,
eMFXSetPriority,
eMFXGetPriority,
eMFXInitEx,
#include "src/windows/mfx_exposed_functions_list.h"
eVideoFuncTotal
};
enum ePluginFunc {
eMFXVideoUSER_Load,
eMFXVideoUSER_LoadByPath,
eMFXVideoUSER_UnLoad,
eMFXAudioUSER_Load,
eMFXAudioUSER_UnLoad,
ePluginFuncTotal
};
enum eVideoFunc2 {
// 2.0
eMFXQueryImplsDescription,
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,
eVideoFunc2Total
};
// declare max buffer length for regsitry key name
enum { MFX_MAX_REGISTRY_KEY_NAME = 256 };
// declare the maximum DLL path
enum { MFX_MAX_DLL_PATH = 1024 };
// declare library's implementation types
enum eMfxImplType {
MFX_LIB_HARDWARE = 0,
MFX_LIB_SOFTWARE = 1,
MFX_LIB_PSEUDO = 2,
MFX_LIB_IMPL_TYPES
};
// declare dispatcher's version
enum { MFX_DISPATCHER_VERSION_MAJOR = 1, MFX_DISPATCHER_VERSION_MINOR = 3 };
struct _mfxSession {
// A real handle from MFX engine passed to a called function
mfxSession session;
mfxFunctionPointer callTable[eVideoFuncTotal]; // NOLINT(runtime/arrays)
mfxFunctionPointer callPlugInsTable[ePluginFuncTotal]; // NOLINT(runtime/arrays)
mfxFunctionPointer callVideoTable2[eVideoFunc2Total]; // NOLINT(runtime/arrays)
// Current library's implementation (exact implementation)
mfxIMPL impl;
};
// declare a dispatcher's handle
struct MFX_DISP_HANDLE : public _mfxSession {
// Default constructor
explicit MFX_DISP_HANDLE(const mfxVersion requiredVersion);
// Destructor
~MFX_DISP_HANDLE(void);
// Load the library's module
mfxStatus LoadSelectedDLL(const wchar_t *pPath,
eMfxImplType implType,
mfxIMPL impl,
mfxIMPL implInterface,
mfxInitParam &par,
mfxInitializationParam &vplParam,
bool bCloneSession = false);
// Unload the library's module
mfxStatus UnLoadSelectedDLL(void);
// Close the handle
mfxStatus Close(void);
// NOTE: changing order of struct's members can make different version of
// dispatchers incompatible. Think of different modules (e.g. MFT filters)
// within a single application.
//
// FOR THIS IMPLEMENTATION: order should not matter. Dispatcher is now built
// as a DLL and installed in %WINDIR%\system32. Thus all applications on the
// system should use same dispatcher. Even if an app loads a different
// dispatcher version, initializing an mfxSession with one library then
// using it in a different library is not a supported use case.
// Library's implementation type (hardware or software)
eMfxImplType implType;
// Current library's VIA interface
mfxIMPL implInterface;
// Dispatcher's version. If version is 1.1 or lower, then old dispatcher's
// architecture is used. Otherwise it means current dispatcher's version.
mfxVersion dispVersion;
// Required API version of session initialized
const mfxVersion apiVersion;
// Actual library API version
mfxVersion actualApiVersion;
// Status of loaded dll
mfxStatus loadStatus;
// Resgistry subkey name for windows version
wchar_t subkeyName[MFX_MAX_REGISTRY_KEY_NAME];
// Storage ID for windows version
int storageID;
// Library's module handle
mfxModuleHandle hModule;
private:
// Declare assignment operator and copy constructor to prevent occasional assignment
MFX_DISP_HANDLE(const MFX_DISP_HANDLE &);
MFX_DISP_HANDLE &operator=(const MFX_DISP_HANDLE &);
};
// This struct extends MFX_DISP_HANDLE, we cannot extend MFX_DISP_HANDLE itself due to possible compatibility issues
// This struct was added in dispatcher version 1.3
// Check dispatcher handle's version when you cast session struct which came from outside of MSDK API function to this
struct MFX_DISP_HANDLE_EX : public MFX_DISP_HANDLE {
explicit MFX_DISP_HANDLE_EX(const mfxVersion requiredVersion);
mfxU16 mediaAdapterType;
mfxU16 reserved[10];
};
// declare comparison operator
inline bool operator==(const mfxVersion &one, const mfxVersion &two) {
return (one.Version == two.Version);
}
inline bool operator<(const mfxVersion &one, const mfxVersion &two) {
return (one.Major < two.Major) || ((one.Major == two.Major) && (one.Minor < two.Minor));
}
inline bool operator<=(const mfxVersion &one, const mfxVersion &two) {
return (one == two) || (one < two);
}
inline bool operator==(mfxGUID const &l, mfxGUID const &r) {
return std::equal(l.Data, l.Data + 16, r.Data);
}
//
// declare a table with functions descriptions
//
typedef struct FUNCTION_DESCRIPTION {
// Literal function's name
const char *pName;
// API version when function appeared first time
mfxVersion apiVersion;
} FUNCTION_DESCRIPTION;
extern const FUNCTION_DESCRIPTION APIFunc[eVideoFuncTotal];
extern const FUNCTION_DESCRIPTION APIVideoFunc2[eVideoFunc2Total];
#endif // LIBVPL_SRC_WINDOWS_MFX_DISPATCHER_H_
@@ -0,0 +1,37 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#pragma once
#include <cstdio>
#include <cstring>
#include "vpl/mfxdefs.h"
#if defined(MFX_DISPATCHER_LOG)
#include <string.h>
#include <string>
#endif
#define MAX_PLUGIN_PATH 4096
#define MAX_PLUGIN_NAME 4096
#if _MSC_VER < 1400
#define wcscpy_s(to, to_size, from) \
(void)(to_size); \
wcscpy(to, from)
#define wcscat_s(to, to_size, from) \
(void)(to_size); \
wcscat(to, from)
#endif
// declare library module's handle
typedef void *mfxModuleHandle;
typedef void(MFX_CDECL *mfxFunctionPointer)(void);
// Tracer uses lib loading from Program Files logic (via Dispatch reg key) to make dispatcher load tracer dll.
// With DriverStore loading put at 1st place, dispatcher loads real lib before it finds tracer dll.
// This workaround explicitly checks tracer presence in Dispatch reg key and loads tracer dll before the search for lib in all other places.
#define MFX_TRACER_WA_FOR_DS 1
@@ -0,0 +1,366 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#if defined(MFX_DISPATCHER_LOG)
#include "src/windows/mfx_dispatcher_log.h"
#include <windows.h>
#include "vpl/mfxstructures.h"
#if defined(DISPATCHER_LOG_REGISTER_EVENT_PROVIDER)
#include <evntprov.h>
#include <winmeta.h>
#endif
#include <stdarg.h>
#include <algorithm>
#include <sstream>
#include <string>
struct CodeStringTable {
int code;
const char *string;
} LevelStrings[] = { { DL_INFO, "INFO: " }, { DL_WRN, "WARNING:" }, { DL_ERROR, "ERROR: " } };
#define DEFINE_CODE(code) \
{ code, #code }
static CodeStringTable StringsOfImpl[] = {
DEFINE_CODE(MFX_IMPL_AUTO), DEFINE_CODE(MFX_IMPL_SOFTWARE),
DEFINE_CODE(MFX_IMPL_HARDWARE), DEFINE_CODE(MFX_IMPL_AUTO_ANY),
DEFINE_CODE(MFX_IMPL_HARDWARE_ANY), DEFINE_CODE(MFX_IMPL_HARDWARE2),
DEFINE_CODE(MFX_IMPL_HARDWARE3), DEFINE_CODE(MFX_IMPL_HARDWARE4),
DEFINE_CODE(MFX_IMPL_UNSUPPORTED)
};
static CodeStringTable StringsOfImplVIA[] = {
DEFINE_CODE(MFX_IMPL_VIA_ANY),
DEFINE_CODE(MFX_IMPL_VIA_D3D9),
DEFINE_CODE(MFX_IMPL_VIA_D3D11),
};
static CodeStringTable StringsOfStatus[] = {
DEFINE_CODE(MFX_ERR_NONE),
DEFINE_CODE(MFX_ERR_UNKNOWN),
DEFINE_CODE(MFX_ERR_NULL_PTR),
DEFINE_CODE(MFX_ERR_UNSUPPORTED),
DEFINE_CODE(MFX_ERR_MEMORY_ALLOC),
DEFINE_CODE(MFX_ERR_NOT_ENOUGH_BUFFER),
DEFINE_CODE(MFX_ERR_INVALID_HANDLE),
DEFINE_CODE(MFX_ERR_LOCK_MEMORY),
DEFINE_CODE(MFX_ERR_NOT_INITIALIZED),
DEFINE_CODE(MFX_ERR_NOT_FOUND),
DEFINE_CODE(MFX_ERR_MORE_DATA),
DEFINE_CODE(MFX_ERR_MORE_SURFACE),
DEFINE_CODE(MFX_ERR_ABORTED),
DEFINE_CODE(MFX_ERR_DEVICE_LOST),
DEFINE_CODE(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM),
DEFINE_CODE(MFX_ERR_INVALID_VIDEO_PARAM),
DEFINE_CODE(MFX_ERR_UNDEFINED_BEHAVIOR),
DEFINE_CODE(MFX_ERR_DEVICE_FAILED),
DEFINE_CODE(MFX_WRN_IN_EXECUTION),
DEFINE_CODE(MFX_WRN_DEVICE_BUSY),
DEFINE_CODE(MFX_WRN_VIDEO_PARAM_CHANGED),
DEFINE_CODE(MFX_WRN_PARTIAL_ACCELERATION),
DEFINE_CODE(MFX_WRN_INCOMPATIBLE_VIDEO_PARAM),
DEFINE_CODE(MFX_WRN_VALUE_NOT_CHANGED),
DEFINE_CODE(MFX_WRN_OUT_OF_RANGE),
};
#define CODE_TO_STRING(code, array) CodeToString(code, array, sizeof(array) / sizeof(array[0]))
const char *CodeToString(int code, CodeStringTable array[], int len) {
for (int i = 0; i < len; i++) {
if (array[i].code == code)
return array[i].string;
}
return "undef";
}
std::string DispatcherLog_GetMFXImplString(int impl) {
std::string str1 = CODE_TO_STRING(impl & ~(-MFX_IMPL_VIA_ANY), StringsOfImpl);
std::string str2 = CODE_TO_STRING(impl & (-MFX_IMPL_VIA_ANY), StringsOfImplVIA);
return str1 + (str2 == "undef" ? "" : "|" + str2);
}
const char *DispatcherLog_GetMFXStatusString(int sts) {
return CODE_TO_STRING(sts, StringsOfStatus);
}
//////////////////////////////////////////////////////////////////////////
void DispatcherLogBracketsHelper::Write(const char *str, ...) {
va_list argsptr;
va_start(argsptr, str);
DispatchLog::get().Write(m_level, m_opcode, str, argsptr);
va_end(argsptr);
}
void DispatchLogBlockHelper::Write(const char *str, ...) {
va_list argsptr;
va_start(argsptr, str);
DispatchLog::get().Write(m_level, DL_EVENT_START, str, argsptr);
va_end(argsptr);
}
DispatchLogBlockHelper::~DispatchLogBlockHelper() {
DispatchLog::get().Write(m_level, DL_EVENT_STOP, NULL, NULL);
}
//////////////////////////////////////////////////////////////////////////
DispatchLog::DispatchLog() : m_DispatcherLogSink(DL_SINK_PRINTF) {}
void DispatchLog::SetSink(int nSink, IMsgHandler *pHandler) {
DetachAllSinks();
AttachSink(nSink, pHandler);
}
void DispatchLog::AttachSink(int nsink, IMsgHandler *pHandler) {
m_DispatcherLogSink |= nsink;
if (NULL != pHandler)
m_Recepients.push_back(pHandler);
}
void DispatchLog::DetachSink(int nsink, IMsgHandler *pHandler) {
if (nsink & DL_SINK_IMsgHandler) {
m_Recepients.remove(pHandler);
}
m_DispatcherLogSink &= ~nsink;
}
void DispatchLog::ExchangeSink(int nsink, IMsgHandler *oldHdl, IMsgHandler *newHdl) {
if (nsink & DL_SINK_IMsgHandler) {
std::list<IMsgHandler *>::iterator it =
std::find(m_Recepients.begin(), m_Recepients.end(), oldHdl);
//cannot exchange in that case
if (m_Recepients.end() == it)
return;
*it = newHdl;
}
}
void DispatchLog::DetachAllSinks() {
m_Recepients.clear();
m_DispatcherLogSink = DL_SINK_NULL;
}
void DispatchLog::Write(int level, int opcode, const char *msg, va_list argptr) {
int sinkTable[] = {
DL_SINK_PRINTF,
DL_SINK_IMsgHandler,
};
for (size_t i = 0; i < sizeof(sinkTable) / sizeof(sinkTable[0]); i++) {
switch (m_DispatcherLogSink & sinkTable[i]) {
case DL_SINK_NULL:
break;
case DL_SINK_PRINTF: {
char msg_formated[8048] = { 0 };
if (NULL != msg && level != DL_LOADED_LIBRARY) {
#if _MSC_VER >= 1400
vsprintf_s(msg_formated,
sizeof(msg_formated) / sizeof(msg_formated[0]),
msg,
argptr);
#else
vsnprintf(msg_formated,
sizeof(msg_formated) / sizeof(msg_formated[0]),
msg,
argptr);
#endif
//TODO(XX): improve this , add opcode handling
printf("%s %s", CODE_TO_STRING(level, LevelStrings), msg_formated);
}
break;
}
case DL_SINK_IMsgHandler: {
std::list<IMsgHandler *>::iterator it;
for (it = m_Recepients.begin(); it != m_Recepients.end(); ++it) {
(*it)->Write(level, opcode, msg, argptr);
}
break;
}
}
}
}
#if defined(DISPATCHER_LOG_REGISTER_EVENT_PROVIDER)
class ETWHandler : public IMsgHandler {
public:
explicit ETWHandler(const wchar_t *guid_str)
: m_bUseFormatter(DISPATCHER_LOG_USE_FORMATING),
m_EventHandle(),
m_bProviderEnable() {
GUID rguid = GUID_NULL;
if (FAILED(CLSIDFromString(guid_str, &rguid))) {
return;
}
EventRegister(&rguid, NULL, NULL, &m_EventHandle);
m_bProviderEnable = 0 != EventProviderEnabled(m_EventHandle, 1, 0);
}
~ETWHandler() {
if (m_EventHandle) {
EventUnregister(m_EventHandle);
}
}
virtual void Write(int level, int opcode, const char *msg, va_list argptr) {
//event not registered
if (0 == m_EventHandle) {
return;
}
if (!m_bProviderEnable) {
return;
}
if (level == DL_LOADED_LIBRARY) {
return;
}
char msg_formated[1024];
EVENT_DESCRIPTOR descriptor;
EVENT_DATA_DESCRIPTOR data_descriptor;
EventDescZero(&descriptor);
descriptor.Opcode = (UCHAR)opcode;
descriptor.Level = (UCHAR)level;
if (m_bUseFormatter) {
if (NULL != msg) {
#if _MSC_VER >= 1400
vsprintf_s(msg_formated,
sizeof(msg_formated) / sizeof(msg_formated[0]),
msg,
argptr);
#else
vsnprintf(msg_formated,
sizeof(msg_formated) / sizeof(msg_formated[0]),
msg,
argptr);
#endif
EventDataDescCreate(&data_descriptor,
msg_formated,
(ULONG)(strlen(msg_formated) + 1));
}
else {
EventDataDescCreate(&data_descriptor, NULL, 0);
}
}
else {
//TODO(XX): non formated events supports under zbb
}
EventWrite(m_EventHandle, &descriptor, 1, &data_descriptor);
}
protected:
//we may not use formatter in some cases described in dispatch_log macro
//it significantly increases performance by eliminating any vsprintf operations
bool m_bUseFormatter;
//consumer is attached, dispatcher trace to reduce formating overhead
//submits event only if consumer attached
bool m_bProviderEnable;
REGHANDLE m_EventHandle;
};
//
IMsgHandler *ETWHandlerFactory::GetSink(const wchar_t *sguid) {
_storage_type::iterator it;
it = m_storage.find(sguid);
if (it == m_storage.end()) {
ETWHandler *handler = new ETWHandler(sguid);
_storage_type::_Pairib it_bool =
m_storage.insert(_storage_type::value_type(sguid, handler));
it = it_bool.first;
}
return it->second;
}
ETWHandlerFactory::~ETWHandlerFactory() {
for
each (_storage_type::value_type val in m_storage) {
delete val.second;
}
}
class EventRegistrator : public IMsgHandler {
const wchar_t *m_sguid;
public:
explicit EventRegistrator(const wchar_t *sguid = DISPATCHER_LOG_EVENT_GUID) : m_sguid(sguid) {
DispatchLog::get().AttachSink(DL_SINK_IMsgHandler, this);
}
virtual void Write(int level, int opcode, const char *msg, va_list argptr) {
//we cannot call attach sink since we may have been called from iteration
//we axchanging preserve that placeholding
IMsgHandler *pSink = NULL;
DispatchLog::get().ExchangeSink(DL_SINK_IMsgHandler,
this,
pSink = ETWHandlerFactory::get().GetSink(m_sguid));
//need to call only once here all next calls will be done inside dispatcherlog
if (NULL != pSink) {
pSink->Write(level, opcode, msg, argptr);
}
}
};
#endif
template <class TSink>
class SinkRegistrator {};
#if defined(DISPATCHER_LOG_REGISTER_EVENT_PROVIDER)
template <>
class SinkRegistrator<ETWHandlerFactory> {
public:
explicit SinkRegistrator(const wchar_t *sguid = DISPATCHER_LOG_EVENT_GUID) {
DispatchLog::get().AttachSink(DL_SINK_IMsgHandler, ETWHandlerFactory::get().GetSink(sguid));
}
};
#endif
#if defined(DISPATCHER_LOG_REGISTER_FILE_WRITER)
template <>
class SinkRegistrator<FileSink> {
public:
SinkRegistrator() {
DispatchLog::get().AttachSink(DL_SINK_IMsgHandler, &FileSink::get(DISPACTHER_LOG_FW_PATH));
}
};
void FileSink::Write(int level, int /*opcode*/, const char *msg, va_list argptr) {
if (NULL != m_hdl && NULL != msg) {
fprintf(m_hdl, "%s", CODE_TO_STRING(level, LevelStrings));
vfprintf(m_hdl, msg, argptr);
}
}
#endif
//////////////////////////////////////////////////////////////////////////
//singletons initialization section
#ifdef DISPATCHER_LOG_REGISTER_EVENT_PROVIDER
static SinkRegistrator<ETWHandlerFactory> g_registrator1;
#endif
#ifdef DISPATCHER_LOG_REGISTER_FILE_WRITER
static SinkRegistrator<FileSink> g_registrator2;
#endif
#endif //(MFX_DISPATCHER_LOG)
@@ -0,0 +1,225 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#ifndef LIBVPL_SRC_WINDOWS_MFX_DISPATCHER_LOG_H_
#define LIBVPL_SRC_WINDOWS_MFX_DISPATCHER_LOG_H_
//////////////////////////////////////////////////////////////////////////
//dispatcher log (DL) level
#define DL_INFO 1
#define DL_WRN 2
#define DL_ERROR 4
#define DL_LOADED_LIBRARY 8
//////////////////////////////////////////////////////////////////////////
//opcodes used only in events
enum { DL_EVENT_START = 1, DL_EVENT_STOP, DL_EVENT_MSG };
//////////////////////////////////////////////////////////////////////////
#define DL_SINK_NULL 0
#define DL_SINK_PRINTF 1
#define DL_SINK_IMsgHandler 2
#define MFXFOURCCTYPE() "%c%c%c%c"
#define ZERO_OR_SPACE(value) ((0 == (value)) ? '0' : (value))
#define MFXU32TOFOURCC(mfxu32) \
ZERO_OR_SPACE((char)(mfxu32 & 0xFF)), ZERO_OR_SPACE((char)((mfxu32 >> 8) & 0xFF)), \
ZERO_OR_SPACE((char)((mfxu32 >> 16) & 0xFF)), ZERO_OR_SPACE((char)((mfxu32 >> 24) & 0xFF))
#define MFXGUIDTYPE() "%X-%X-%X-%X-%X-%X-%X-%X-%X-%X-%X-%X-%X-%X-%X-%X"
#define MFXGUIDTOHEX(guid) \
(guid)->Data[0], (guid)->Data[1], (guid)->Data[2], (guid)->Data[3], (guid)->Data[4], \
(guid)->Data[5], (guid)->Data[6], (guid)->Data[7], (guid)->Data[8], (guid)->Data[9], \
(guid)->Data[10], (guid)->Data[11], (guid)->Data[12], (guid)->Data[13], (guid)->Data[14], \
(guid)->Data[15]
#if defined(MFX_DISPATCHER_LOG)
//---------------------------setup section------------------------
//using of formating instead of variadic macro with NULL end,
//leads to more flexibility in format, however constructing string
//with vsprintf_s is a time wasting
#define DISPATCHER_LOG_USE_FORMATING 1
//creates unique object, event guid registration, factories on heap
//heap reduce stack allocation and reduce reservation time at startup
//is a vital if mediasdk wont use
#define DISPATCHER_LOG_HEAP_SINGLETONES
// guid for all dispatcher events
#define DISPATCHER_LOG_EVENT_GUID L"{EB0538CC-4FEE-484d-ACEE-1182E9F37A57}"
//puts a sink into listeners list
//#define DISPATCHER_LOG_REGISTER_EVENT_PROVIDER
//puts a sink into listeners list
//#define DISPATCHER_LOG_REGISTER_FILE_WRITER
#define DISPACTHER_LOG_FW_PATH "c:\\dispatcher.log"
#include <stdarg.h>
#include <stdio.h>
//callback interface for intercept logging messages
class IMsgHandler {
public:
virtual ~IMsgHandler() {}
virtual void Write(int level, int opcode, const char *msg, va_list argptr) = 0;
};
#if DISPATCHER_LOG_USE_FORMATING
#define DISPATCHER_LOG(lvl, opcode, str) \
{ \
DispatcherLogBracketsHelper wrt(lvl, opcode); \
wrt.Write str; \
}
#else
#define DISPATCHER_LOG_VA_ARGS(...) wrt.Write(__VA_ARGS__, NULL)
//WARNING: don't use types that occupy more that 4 bytes in memory
//WARNING: don't use %s in format specifier
#define DISPATCHER_LOG(lvl, opcode, str) \
{ \
DispatcherLogBracketsHelper wrt(lvl, opcode); \
DISPATCHER_LOG_VA_ARGS str; \
}
#endif //DISPATCHER_LOG_USE_FORMATING
#define DISPATCHER_LOG_OPERATION(operation) operation
#define __name_from_line(name, line) name##line
#define _name_from_line(name, line) __name_from_line(name, line)
#define name_from_line(name) _name_from_line(name, __LINE__)
#define DISPATCHER_LOG_AUTO(lvl, msg) \
DispatchLogBlockHelper name_from_line(__auto_log_)(lvl); \
name_from_line(__auto_log_).Write msg;
#include <list>
#include <map>
#include <memory>
#include <string>
template <class T>
class DSSingleTone {
public:
template <class TParam1>
inline static T &get(TParam1 par1) {
T *pstored;
if (NULL == (pstored = store_or_load())) {
return *store_or_load(new T(par1));
}
return *pstored;
}
inline static T &get() {
T *pstored;
if (NULL == (pstored = store_or_load())) {
return *store_or_load(new T());
}
return *pstored;
}
private:
//if obj == NULL, then it load
//if obj != NULL then it store obj
inline static T *store_or_load(T *obj = NULL) {
static std::unique_ptr<T> instance;
if (NULL != obj) {
instance.reset(obj);
}
return instance.get();
}
};
class DispatchLog : public DSSingleTone<DispatchLog> {
friend class DSSingleTone<DispatchLog>;
std::list<IMsgHandler *> m_Recepients;
int m_DispatcherLogSink;
public:
//sets current sink
void SetSink(int nsink, IMsgHandler *pHandler);
void AttachSink(int nsink, IMsgHandler *pHandler);
void DetachSink(int nsink, IMsgHandler *pHandler);
void ExchangeSink(int nsink, IMsgHandler *pOld, IMsgHandler *pNew);
void DetachAllSinks();
void Write(int level, int opcode, const char *msg, va_list argptr);
protected:
DispatchLog();
};
//allows to push arguments on the stack without declaring them as function parameters
struct DispatcherLogBracketsHelper {
int m_level;
int m_opcode;
DispatcherLogBracketsHelper(int level, int opcode) : m_level(level), m_opcode(opcode) {}
void Write(const char *str, ...);
};
//auto log on ctor dtor
struct DispatchLogBlockHelper {
int m_level;
void Write(const char *str, ...);
explicit DispatchLogBlockHelper(int level) : m_level(level) {}
~DispatchLogBlockHelper();
};
//----utility sinks-----
#if defined(DISPATCHER_LOG_REGISTER_EVENT_PROVIDER)
class ETWHandlerFactory : public DSSingleTone<ETWHandlerFactory> {
friend class DSSingleTone<ETWHandlerFactory>;
typedef std::map<std::wstring, IMsgHandler *> _storage_type;
_storage_type m_storage;
public:
~ETWHandlerFactory();
IMsgHandler *GetSink(const wchar_t *sguid = DISPATCHER_LOG_EVENT_GUID);
protected:
ETWHandlerFactory() {}
};
#endif
#if defined(DISPATCHER_LOG_REGISTER_FILE_WRITER)
class FileSink : public DSSingleTone<FileSink>, public IMsgHandler {
friend class DSSingleTone<FileSink>;
public:
virtual void Write(int level, int opcode, const char *msg, va_list argptr);
FileSink() : m_hdl(NULL) {}
~FileSink() {
if (NULL != m_hdl)
fclose(m_hdl);
}
private:
FILE *m_hdl;
explicit FileSink(const std::string &log_file) {
fopen_s(&m_hdl, log_file.c_str(), "a");
}
};
#endif
//-----utility functions
//since they are not called outside of macro we can define them here
std::string DispatcherLog_GetMFXImplString(int impl);
const char *DispatcherLog_GetMFXStatusString(int sts);
#else // !defined(MFX_DISPATCHER_LOG)
#define DISPATCHER_LOG(level, opcode, message)
#define DISPATCHER_LOG_AUTO(level, message)
#define DISPATCHER_LOG_OPERATION(operation)
#endif // !defined(MFX_DISPATCHER_LOG)
#define DISPATCHER_LOG_INFO(msg) DISPATCHER_LOG(DL_INFO, DL_EVENT_MSG, msg)
#define DISPATCHER_LOG_WRN(msg) DISPATCHER_LOG(DL_WRN, DL_EVENT_MSG, msg)
#define DISPATCHER_LOG_ERROR(msg) DISPATCHER_LOG(DL_ERROR, DL_EVENT_MSG, msg)
#define DISPATCHER_LOG_LIBRARY(msg) DISPATCHER_LOG(DL_LOADED_LIBRARY, DL_EVENT_MSG, msg)
#define DISPATCHER_LOG_BLOCK(msg) DISPATCHER_LOG_AUTO(DL_INFO, msg)
#endif // LIBVPL_SRC_WINDOWS_MFX_DISPATCHER_LOG_H_
@@ -0,0 +1,192 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#include <tchar.h>
#include "src/windows/mfx_dispatcher_log.h"
#include "src/windows/mfx_driver_store_loader.h"
#include "src/windows/mfx_load_dll.h"
#include "src/windows/mfx_vector.h"
namespace MFX {
inline bool IsIntelDeviceInstanceID(const wchar_t *DeviceID) {
return wcsstr(DeviceID, L"VEN_8086") || wcsstr(DeviceID, L"ven_8086");
}
inline bool ExctractDeviceID(const wchar_t *descrString, mfxU32 &deviceID) {
const wchar_t *begin = wcsstr(descrString, L"DEV_");
if (!begin) {
begin = wcsstr(descrString, L"dev_");
if (!begin) {
DISPATCHER_LOG_WRN(("exctracting device id: failed to find device id substring\n"));
return false;
}
}
begin += wcslen(L"DEV_");
deviceID = wcstoul(begin, NULL, 16);
if (!deviceID) {
DISPATCHER_LOG_WRN(("exctracting device id: failed to convert device id str to int\n"));
return false;
}
return true;
}
DriverStoreLoader::DriverStoreLoader(void)
: m_moduleCfgMgr(NULL),
m_pCM_Get_Device_ID_List_Size(NULL),
m_pCM_Get_Device_ID_List(NULL),
m_pCM_Locate_DevNode(NULL),
m_pCM_Open_DevNode_Key(NULL) {}
DriverStoreLoader::~DriverStoreLoader(void) {}
bool DriverStoreLoader::GetDriverStorePath(wchar_t *path,
DWORD dwPathSize,
mfxU32 deviceID,
const wchar_t *driverKey) {
if (path == NULL || dwPathSize == 0) {
return false;
}
// Obtain a PnP handle to the Intel graphics adapter
CONFIGRET result = CR_SUCCESS;
ULONG DeviceIDListSize = 0;
MFXVector<WCHAR> DeviceIDList;
wchar_t DisplayGUID[40];
DEVINST DeviceInst;
DISPATCHER_LOG_INFO(("Looking for MediaSDK in DriverStore\n"));
if (!LoadCfgMgr() || !LoadCmFuncs()) {
return false;
}
if (StringFromGUID2(GUID_DEVCLASS_DISPLAY, DisplayGUID, _countof(DisplayGUID)) == 0) {
DISPATCHER_LOG_WRN(("Couldn't prepare string from GUID\n"));
return false;
}
do {
result =
m_pCM_Get_Device_ID_List_Size(&DeviceIDListSize,
DisplayGUID,
CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
if (result != CR_SUCCESS) {
break;
}
try {
DeviceIDList.resize(DeviceIDListSize);
}
catch (...) {
return false;
}
result = m_pCM_Get_Device_ID_List(DisplayGUID,
DeviceIDList.data(),
DeviceIDListSize,
CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
} while (result == CR_BUFFER_SMALL);
if (result != CR_SUCCESS) {
return false;
}
//Look for MediaSDK record
wchar_t *begin = DeviceIDList.data();
wchar_t *end = begin + DeviceIDList.size();
size_t len = 0;
for (; (begin < end) && (len = wcslen(begin)) > 0; begin += len + 1) {
if (IsIntelDeviceInstanceID(begin)) {
mfxU32 curDeviceID = 0;
if (!ExctractDeviceID(begin, curDeviceID) || curDeviceID != deviceID) {
continue;
}
result = m_pCM_Locate_DevNode(&DeviceInst, begin, CM_LOCATE_DEVNODE_NORMAL);
if (result != CR_SUCCESS) {
continue;
}
HKEY hKey_sw;
result = m_pCM_Open_DevNode_Key(DeviceInst,
KEY_READ,
0,
RegDisposition_OpenExisting,
&hKey_sw,
CM_REGISTRY_SOFTWARE);
if (result != CR_SUCCESS) {
continue;
}
ULONG nError;
DWORD pathSize = dwPathSize;
nError = RegQueryValueExW(hKey_sw, driverKey, 0, NULL, (LPBYTE)path, &pathSize);
RegCloseKey(hKey_sw);
if (ERROR_SUCCESS == nError) {
if (path[wcslen(path) - 1] != '/' && path[wcslen(path) - 1] != '\\') {
wcscat_s(path, MFX_MAX_DLL_PATH, L"\\");
}
DISPATCHER_LOG_INFO(("DriverStore path is found\n"));
return true;
}
}
}
DISPATCHER_LOG_INFO(("DriverStore path isn't found\n"));
return false;
} // bool DriverStoreLoader::GetDriverStorePath(wchar_t * path, DWORD dwPathSize, wchar_t *driverKey)
bool DriverStoreLoader::LoadCfgMgr() {
if (!m_moduleCfgMgr) {
m_moduleCfgMgr = mfx_dll_load(L"cfgmgr32.dll");
if (!m_moduleCfgMgr) {
DISPATCHER_LOG_WRN(("cfgmgr32.dll couldn't be loaded\n"));
return false;
}
}
return true;
} // bool DriverStoreLoader::LoadCfgMgr()
bool DriverStoreLoader::LoadCmFuncs() {
if (!m_pCM_Get_Device_ID_List || !m_pCM_Get_Device_ID_List_Size || !m_pCM_Locate_DevNode ||
!m_pCM_Open_DevNode_Key) {
m_pCM_Get_Device_ID_List =
(Func_CM_Get_Device_ID_ListW)mfx_dll_get_addr((HMODULE)m_moduleCfgMgr,
"CM_Get_Device_ID_ListW");
m_pCM_Get_Device_ID_List_Size =
(Func_CM_Get_Device_ID_List_SizeW)mfx_dll_get_addr((HMODULE)m_moduleCfgMgr,
"CM_Get_Device_ID_List_SizeW");
m_pCM_Locate_DevNode = (Func_CM_Locate_DevNodeW)mfx_dll_get_addr((HMODULE)m_moduleCfgMgr,
"CM_Locate_DevNodeW");
m_pCM_Open_DevNode_Key = (Func_CM_Open_DevNode_Key)mfx_dll_get_addr((HMODULE)m_moduleCfgMgr,
"CM_Open_DevNode_Key");
if (!m_pCM_Get_Device_ID_List || !m_pCM_Get_Device_ID_List_Size || !m_pCM_Locate_DevNode ||
!m_pCM_Open_DevNode_Key) {
DISPATCHER_LOG_WRN(("One of cfgmgr32.dll function isn't found\n"));
return false;
}
}
return true;
} // bool DriverStoreLoader::LoadCmFuncs()
} // namespace MFX
@@ -0,0 +1,75 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#ifndef LIBVPL_SRC_WINDOWS_MFX_DRIVER_STORE_LOADER_H_
#define LIBVPL_SRC_WINDOWS_MFX_DRIVER_STORE_LOADER_H_
#include <windows.h>
#include <cfgmgr32.h>
// support building in MinGW environments with older versions of cfgmgr32
#ifdef __MINGW32__
#if !defined(CM_GETIDLIST_FILTER_PRESENT)
#define CM_GETIDLIST_FILTER_PRESENT 0x00000100
#endif
#if !defined(CM_GETIDLIST_FILTER_CLASS)
#define CM_GETIDLIST_FILTER_CLASS 0x00000200
#endif
#endif
#include <devguid.h>
#include "src/windows/mfx_dispatcher_defs.h"
namespace MFX {
typedef CONFIGRET(WINAPI *Func_CM_Get_Device_ID_List_SizeW)(PULONG pulLen,
PCWSTR pszFilter,
ULONG ulFlags);
typedef CONFIGRET(WINAPI *Func_CM_Get_Device_ID_ListW)(PCWSTR pszFilter,
PZZWSTR Buffer,
ULONG BufferLen,
ULONG ulFlags);
typedef CONFIGRET(WINAPI *Func_CM_Locate_DevNodeW)(PDEVINST pdnDevInst,
DEVINSTID_W pDeviceID,
ULONG ulFlags);
typedef CONFIGRET(WINAPI *Func_CM_Open_DevNode_Key)(DEVINST dnDevNode,
REGSAM samDesired,
ULONG ulHardwareProfile,
REGDISPOSITION Disposition,
PHKEY phkDevice,
ULONG ulFlags);
class DriverStoreLoader {
public:
DriverStoreLoader(void);
~DriverStoreLoader(void);
bool GetDriverStorePath(wchar_t *path,
DWORD dwPathSize,
mfxU32 deviceID,
const wchar_t *driverKey);
protected:
bool LoadCfgMgr();
bool LoadCmFuncs();
mfxModuleHandle m_moduleCfgMgr;
Func_CM_Get_Device_ID_List_SizeW m_pCM_Get_Device_ID_List_Size;
Func_CM_Get_Device_ID_ListW m_pCM_Get_Device_ID_List;
Func_CM_Locate_DevNodeW m_pCM_Locate_DevNode;
Func_CM_Open_DevNode_Key m_pCM_Open_DevNode_Key;
private:
// unimplemented by intent to make this class non-copyable
DriverStoreLoader(const DriverStoreLoader &);
void operator=(const DriverStoreLoader &);
};
} // namespace MFX
#endif // LIBVPL_SRC_WINDOWS_MFX_DRIVER_STORE_LOADER_H_
@@ -0,0 +1,553 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#define INITGUID
#include <d3d9.h>
#include <dxgi.h>
#include "src/windows/mfx_dxva2_device.h"
#include "src/windows/mfx_load_dll.h"
using namespace MFX;
// convert LUID to mfxU64
mfxU64 LUIDtomfxU64(LUID luid) {
return (((mfxU64)luid.HighPart << 32) | ((mfxU64)luid.LowPart));
}
DXDevice::DXDevice(void) {
m_hModule = (HMODULE)0;
m_numAdapters = 0;
m_vendorID = 0;
m_deviceID = 0;
m_driverVersion = 0;
m_luid = {};
} // DXDevice::DXDevice(void)
DXDevice::~DXDevice(void) {
Close();
// free DX library only when device is destroyed
UnloadDLLModule();
} // DXDevice::~DXDevice(void)
mfxU32 DXDevice::GetVendorID(void) const {
return m_vendorID;
} // mfxU32 DXDevice::GetVendorID(void) const
mfxU32 DXDevice::GetDeviceID(void) const {
return m_deviceID;
} // mfxU32 DXDevice::GetDeviceID(void) const
mfxU64 DXDevice::GetDriverVersion(void) const {
return m_driverVersion;
} // mfxU64 DXDevice::GetDriverVersion(void) const
mfxU64 DXDevice::GetLUID(void) const {
return m_luid;
} // mfxU64 DXDevice::GetLUID(void) const
mfxU32 DXDevice::GetAdapterCount(void) const {
return m_numAdapters;
} // mfxU32 DXDevice::GetAdapterCount(void) const
void DXDevice::Close(void) {
m_numAdapters = 0;
m_vendorID = 0;
m_deviceID = 0;
m_luid = {};
} // void DXDevice::Close(void)
void DXDevice::LoadDLLModule(const wchar_t *pModuleName) {
// unload the module if it is required
UnloadDLLModule();
#if !defined(MEDIASDK_UWP_DISPATCHER)
DWORD prevErrorMode = 0;
// set the silent error mode
#if (_WIN32_WINNT >= 0x0600)
SetThreadErrorMode(SEM_FAILCRITICALERRORS, &prevErrorMode);
#else
prevErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
#endif
#endif // !defined(MEDIASDK_UWP_DISPATCHER)
// load specified library
m_hModule = LoadLibraryExW(pModuleName, NULL, 0);
#if !defined(MEDIASDK_UWP_DISPATCHER)
// set the previous error mode
#if (_WIN32_WINNT >= 0x0600)
SetThreadErrorMode(prevErrorMode, NULL);
#else
SetErrorMode(prevErrorMode);
#endif
#endif // !defined(MEDIASDK_UWP_DISPATCHER)
} // void LoadDLLModule(const wchar_t *pModuleName)
void DXDevice::UnloadDLLModule(void) {
if (m_hModule) {
FreeLibrary(m_hModule);
m_hModule = (HMODULE)0;
}
} // void DXDevice::UnloaDLLdModule(void)
#ifdef MFX_D3D9_ENABLED
D3D9Device::D3D9Device(void) {
m_pD3D9 = (void *)0;
m_pD3D9Ex = (void *)0;
} // D3D9Device::D3D9Device(void)
D3D9Device::~D3D9Device(void) {
Close();
} // D3D9Device::~D3D9Device(void)
void D3D9Device::Close(void) {
// release the interfaces
if (m_pD3D9Ex) {
((IDirect3D9Ex *)m_pD3D9Ex)->Release();
}
// release the interfaces
if (m_pD3D9) {
((IDirect3D9 *)m_pD3D9)->Release();
}
m_pD3D9 = (void *)0;
m_pD3D9Ex = (void *)0;
} // void D3D9Device::Close(void)
typedef IDirect3D9 *(WINAPI *D3DCreateFunctionPtr_t)(UINT);
typedef HRESULT(WINAPI *D3DExCreateFunctionPtr_t)(UINT, IDirect3D9Ex **);
bool D3D9Device::Init(const mfxU32 adapterNum) {
// close the device before initialization
Close();
// load the library
if (NULL == m_hModule) {
LoadDLLModule(L"d3d9.dll");
}
if (m_hModule) {
D3DCreateFunctionPtr_t pFunc;
// load address of procedure to create D3D device
pFunc = (D3DCreateFunctionPtr_t)GetProcAddress(m_hModule, "Direct3DCreate9");
if (pFunc) {
D3DADAPTER_IDENTIFIER9 adapterIdent;
IDirect3D9 *pD3D9;
HRESULT hRes;
// create D3D object
m_pD3D9 = pFunc(D3D_SDK_VERSION);
if (NULL == m_pD3D9) {
DXVA2DEVICE_TRACE(("FAIL: Direct3DCreate9(%d) : GetLastError()=0x%x",
D3D_SDK_VERSION,
GetLastError()));
return false;
}
// cast the interface
pD3D9 = (IDirect3D9 *)m_pD3D9;
m_numAdapters = pD3D9->GetAdapterCount();
if (adapterNum >= m_numAdapters) {
return false;
}
// get the card's parameters
hRes = pD3D9->GetAdapterIdentifier(adapterNum, 0, &adapterIdent);
if (D3D_OK != hRes) {
DXVA2DEVICE_TRACE(("FAIL: GetAdapterIdentifier(%d) = 0x%x \n", adapterNum, hRes));
return false;
}
m_vendorID = adapterIdent.VendorId;
m_deviceID = adapterIdent.DeviceId;
m_driverVersion = (mfxU64)adapterIdent.DriverVersion.QuadPart;
// load LUID
IDirect3D9Ex *pD3D9Ex;
D3DExCreateFunctionPtr_t pFuncEx;
LUID d3d9LUID;
// find the appropriate function
pFuncEx = (D3DExCreateFunctionPtr_t)GetProcAddress(m_hModule, "Direct3DCreate9Ex");
if (NULL == pFuncEx) {
// the extended interface is not supported
return true;
}
// create extended interface
hRes = pFuncEx(D3D_SDK_VERSION, &pD3D9Ex);
if (FAILED(hRes)) {
// can't create extended interface
return true;
}
m_pD3D9Ex = pD3D9Ex;
// obtain D3D9 device LUID
hRes = pD3D9Ex->GetAdapterLUID(adapterNum, &d3d9LUID);
if (FAILED(hRes)) {
// can't get LUID
return true;
}
// copy the LUID
m_luid = LUIDtomfxU64(d3d9LUID);
}
else {
DXVA2DEVICE_TRACE_OPERATION({
wchar_t path[1024];
DWORD lastErr = GetLastError();
GetModuleFileNameW(m_hModule, path, sizeof(path) / sizeof(path[0]));
DXVA2DEVICE_TRACE((
"FAIL: invoking GetProcAddress(Direct3DCreate9) in %S : GetLastError()==0x%x\n",
path,
lastErr));
});
return false;
}
}
else {
DXVA2DEVICE_TRACE(
("FAIL: invoking LoadLibrary(\"d3d9.dll\") : GetLastError()==0x%x\n", GetLastError()));
return false;
}
return true;
} // bool D3D9Device::Init(const mfxU32 adapterNum)
#endif //MFX_D3D9_ENABLED
typedef HRESULT(WINAPI *DXGICreateFactoryFunc)(REFIID riid, void **ppFactory);
DXGI1Device::DXGI1Device(void) {
m_pDXGIFactory1 = (void *)0;
m_pDXGIAdapter1 = (void *)0;
} // DXGI1Device::DXGI1Device(void)
DXGI1Device::~DXGI1Device(void) {
Close();
} // DXGI1Device::~DXGI1Device(void)
void DXGI1Device::Close(void) {
// release the interfaces
if (m_pDXGIAdapter1) {
((IDXGIAdapter1 *)m_pDXGIAdapter1)->Release();
}
if (m_pDXGIFactory1) {
((IDXGIFactory1 *)m_pDXGIFactory1)->Release();
}
m_pDXGIFactory1 = (void *)0;
m_pDXGIAdapter1 = (void *)0;
} // void DXGI1Device::Close(void)
bool DXGI1Device::Init(const mfxU32 adapterNum) {
// release the object before initialization
Close();
IDXGIFactory1 *pFactory = NULL;
IDXGIAdapter1 *pAdapter = NULL;
DXGI_ADAPTER_DESC1 desc = { 0 };
mfxU32 curAdapter = 0;
mfxU32 maxAdapters = 0;
HRESULT hRes = E_FAIL;
DXGICreateFactoryFunc pFunc = NULL;
// load up the library if it is not loaded
if (NULL == m_hModule) {
LoadDLLModule(L"dxgi.dll");
}
if (m_hModule) {
// load address of procedure to create DXGI 1.1 factory
pFunc = (DXGICreateFactoryFunc)GetProcAddress(m_hModule, "CreateDXGIFactory1");
}
if (NULL == pFunc) {
return false;
}
// create the factory
#if _MSC_VER >= 1400
hRes = pFunc(__uuidof(IDXGIFactory1), (void **)(&pFactory));
#else
hRes = pFunc(IID_IDXGIFactory1, (void **)(&pFactory));
#endif
if (FAILED(hRes)) {
return false;
}
m_pDXGIFactory1 = pFactory;
// get the number of adapters
curAdapter = 0;
maxAdapters = 0;
do {
// get the required adapted
hRes = pFactory->EnumAdapters1(curAdapter, &pAdapter);
if (FAILED(hRes)) {
break;
}
// if it is the required adapter, save the interface
if (curAdapter == adapterNum) {
m_pDXGIAdapter1 = pAdapter;
}
else {
pAdapter->Release();
}
// get the next adapter
curAdapter += 1;
} while (SUCCEEDED(hRes));
maxAdapters = curAdapter;
m_numAdapters = maxAdapters;
// there is no required adapter
if (adapterNum >= maxAdapters) {
return false;
}
pAdapter = (IDXGIAdapter1 *)m_pDXGIAdapter1;
// get the adapter's parameters
hRes = pAdapter->GetDesc1(&desc);
if (FAILED(hRes)) {
return false;
}
// save the parameters
m_vendorID = desc.VendorId;
m_deviceID = desc.DeviceId;
m_luid = LUIDtomfxU64(desc.AdapterLuid);
return true;
} // bool DXGI1Device::Init(const mfxU32 adapterNum)
bool DXGI1Device::GetAdapterList(std::vector<DXGI1DeviceInfo> &adapterInfo) {
mfxModuleHandle hModule = MFX::mfx_dll_load(L"dxgi.dll");
if (!hModule)
return false;
DXGICreateFactoryFunc pFactoryFunc = NULL;
pFactoryFunc = (DXGICreateFactoryFunc)MFX::mfx_dll_get_addr(hModule, "CreateDXGIFactory1");
if (pFactoryFunc == NULL)
return false;
IDXGIFactory1 *pFactory = NULL;
IDXGIAdapter1 *pAdapter = NULL;
HRESULT hRes = pFactoryFunc(__uuidof(IDXGIFactory1), (void **)(&pFactory));
if (FAILED(hRes))
return false;
bool bEnumSuccess = false;
mfxU32 curAdapter = 0;
while (pFactory->EnumAdapters1(curAdapter, &pAdapter) == S_OK) {
curAdapter++;
DXGI_ADAPTER_DESC1 desc = {};
DXGI1DeviceInfo devInfo = {};
if (pAdapter->GetDesc1(&desc) == S_OK) {
// save minimal descriptive info
devInfo.vendorID = desc.VendorId;
devInfo.deviceID = desc.DeviceId;
devInfo.luid = LUIDtomfxU64(desc.AdapterLuid);
// add to list
adapterInfo.emplace_back(devInfo);
// at least one valid adapter found
bEnumSuccess = true;
}
pAdapter->Release();
}
pFactory->Release();
mfx_dll_free(hModule);
return bEnumSuccess;
}
DXVA2Device::DXVA2Device(void) {
m_numAdapters = 0;
m_vendorID = 0;
m_deviceID = 0;
m_driverVersion = 0;
m_luid = {};
} // DXVA2Device::DXVA2Device(void)
DXVA2Device::~DXVA2Device(void) {
Close();
} // DXVA2Device::~DXVA2Device(void)
void DXVA2Device::Close(void) {
m_numAdapters = 0;
m_vendorID = 0;
m_deviceID = 0;
m_driverVersion = 0;
} // void DXVA2Device::Close(void)
#ifdef MFX_D3D9_ENABLED
bool DXVA2Device::InitD3D9(const mfxU32 adapterNum) {
D3D9Device d3d9Device;
bool bRes;
// release the object before initialization
Close();
// create 'old fashion' device
bRes = d3d9Device.Init(adapterNum);
if (false == bRes) {
return false;
}
m_numAdapters = d3d9Device.GetAdapterCount();
// check if the application is under Remote Desktop
if ((0 == d3d9Device.GetVendorID()) || (0 == d3d9Device.GetDeviceID())) {
// get the required parameters alternative way and ...
UseAlternativeWay(&d3d9Device);
}
else {
// save the parameters and ...
m_vendorID = d3d9Device.GetVendorID();
m_deviceID = d3d9Device.GetDeviceID();
m_driverVersion = d3d9Device.GetDriverVersion();
m_luid = d3d9Device.GetLUID();
}
// ... say goodbye
return true;
} // bool InitD3D9(const mfxU32 adapterNum)
#else // MFX_D3D9_ENABLED
bool DXVA2Device::InitD3D9(const mfxU32 adapterNum) {
(void)adapterNum;
return false;
}
#endif // MFX_D3D9_ENABLED
bool DXVA2Device::InitDXGI1(const mfxU32 adapterNum) {
DXGI1Device dxgi1Device;
bool bRes;
// release the object before initialization
Close();
// create modern DXGI device
bRes = dxgi1Device.Init(adapterNum);
if (false == bRes) {
return false;
}
// save the parameters and ...
m_vendorID = dxgi1Device.GetVendorID();
m_deviceID = dxgi1Device.GetDeviceID();
m_numAdapters = dxgi1Device.GetAdapterCount();
m_luid = dxgi1Device.GetLUID();
// ... say goodbye
return true;
} // bool DXVA2Device::InitDXGI1(const mfxU32 adapterNum)
#ifdef MFX_D3D9_ENABLED
void DXVA2Device::UseAlternativeWay(const D3D9Device *pD3D9Device) {
mfxU64 d3d9LUID = pD3D9Device->GetLUID();
mfxU64 kInvalidLUID = {};
// work only with valid LUIDs
if (kInvalidLUID == d3d9LUID) {
return;
}
DXGI1Device dxgi1Device;
mfxU32 curDevice = 0;
bool bRes = false;
do {
// initialize the next DXGI1 or DXGI device
bRes = dxgi1Device.Init(curDevice);
if (false == bRes) {
// there is no more devices
break;
}
// is it required device ?
if (d3d9LUID == dxgi1Device.GetLUID()) {
m_vendorID = dxgi1Device.GetVendorID();
m_deviceID = dxgi1Device.GetDeviceID();
m_driverVersion = dxgi1Device.GetDriverVersion();
m_luid = dxgi1Device.GetLUID();
return;
}
// get the next device
curDevice += 1;
} while (bRes);
dxgi1Device.Close();
// we need to match a DXGI(1) device to the D3D9 device
} // void DXVA2Device::UseAlternativeWay(const D3D9Device *pD3D9Device)
#endif // MFX_D3D9_ENABLED
mfxU32 DXVA2Device::GetVendorID(void) const {
return m_vendorID;
} // mfxU32 DXVA2Device::GetVendorID(void) const
mfxU32 DXVA2Device::GetDeviceID(void) const {
return m_deviceID;
} // mfxU32 DXVA2Device::GetDeviceID(void) const
mfxU64 DXVA2Device::GetDriverVersion(void) const {
return m_driverVersion;
} // mfxU64 DXVA2Device::GetDriverVersion(void) const
mfxU32 DXVA2Device::GetAdapterCount(void) const {
return m_numAdapters;
} // mfxU32 DXVA2Device::GetAdapterCount(void) const
mfxU64 DXVA2Device::GetLUID(void) const {
return m_luid;
} // mfxU64 DXVA2Device::GetLUID(void) const
@@ -0,0 +1,202 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#ifndef LIBVPL_SRC_WINDOWS_MFX_DXVA2_DEVICE_H_
#define LIBVPL_SRC_WINDOWS_MFX_DXVA2_DEVICE_H_
#include <windows.h>
#include <vector>
#include "src/mfx_dispatcher_vpl.h"
#define TOSTRING(L) #L
#define STRINGIFY(L) TOSTRING(L)
#if defined(MEDIASDK_UWP_DISPATCHER)
#if defined(MFX_D3D9_ENABLED) && !defined(MFX_FORCE_D3D9_ENABLED)
#undef MFX_D3D9_ENABLED
#pragma message("\n\nATTENTION:\nin file\n\t" __FILE__ \
" (" STRINGIFY(__LINE__) "):\nUsing of D3D9 disabled for UWP!\n\n")
#endif
#if defined(MFX_FORCE_D3D9_ENABLED)
#define MFX_D3D9_ENABLED
#endif
#else
#define MFX_D3D9_ENABLED
#endif
#include "vpl/mfxdefs.h"
#ifdef DXVA2DEVICE_LOG
#include <stdio.h>
#define DXVA2DEVICE_TRACE(expr) printf expr;
#define DXVA2DEVICE_TRACE_OPERATION(expr) expr;
#else
#define DXVA2DEVICE_TRACE(expr)
#define DXVA2DEVICE_TRACE_OPERATION(expr)
#endif
namespace MFX {
// compare LUIDs
inline bool operator==(const LUID &lhs, const LUID &rhs) {
return (lhs.LowPart == rhs.LowPart && lhs.HighPart == rhs.HighPart);
}
class DXDevice {
public:
// Default constructor
DXDevice(void);
// Destructor
virtual ~DXDevice(void) = 0;
// Initialize device using DXGI 1.1 or VAAPI interface
virtual bool Init(const mfxU32 adapterNum) = 0;
// Obtain graphic card's parameter
mfxU32 GetVendorID(void) const;
mfxU32 GetDeviceID(void) const;
mfxU64 GetDriverVersion(void) const;
mfxU64 GetLUID(void) const;
// Provide the number of available adapters
mfxU32 GetAdapterCount(void) const;
// Close the object
virtual void Close(void);
// Load the required DLL module
void LoadDLLModule(const wchar_t *pModuleName);
protected:
// Free DLL module
void UnloadDLLModule(void);
// Handle to the DLL library
HMODULE m_hModule;
// Number of adapters available
mfxU32 m_numAdapters;
// Vendor ID
mfxU32 m_vendorID;
// Device ID
mfxU32 m_deviceID;
// x.x.x.x each x of two bytes
mfxU64 m_driverVersion;
// LUID
mfxU64 m_luid;
private:
// unimplemented by intent to make this class and its descendants non-copyable
DXDevice(const DXDevice &);
void operator=(const DXDevice &);
};
#ifdef MFX_D3D9_ENABLED
class D3D9Device : public DXDevice {
public:
// Default constructor
D3D9Device(void);
// Destructor
virtual ~D3D9Device(void);
// Initialize device using D3D v9 interface
virtual bool Init(const mfxU32 adapterNum);
// Close the object
virtual void Close(void);
protected:
// Pointer to the D3D v9 interface
void *m_pD3D9;
// Pointer to the D3D v9 extended interface
void *m_pD3D9Ex;
private:
D3D9Device(const D3D9Device &other);
D3D9Device &operator=(const D3D9Device &other);
};
#endif // MFX_D3D9_ENABLED
class DXGI1Device : public DXDevice {
public:
// Default constructor
DXGI1Device(void);
// Destructor
virtual ~DXGI1Device(void);
// Initialize device
virtual bool Init(const mfxU32 adapterNum);
// Close the object
virtual void Close(void);
// lightweight method to get list of adapters
static bool GetAdapterList(std::vector<DXGI1DeviceInfo> &adapterInfo);
protected:
// Pointer to the DXGI1 factory
void *m_pDXGIFactory1;
// Pointer to the current DXGI1 adapter
void *m_pDXGIAdapter1;
private:
DXGI1Device(const DXGI1Device &other);
DXGI1Device &operator=(const DXGI1Device &other);
};
class DXVA2Device {
public:
// Default constructor
DXVA2Device(void);
// Destructor
~DXVA2Device(void);
// Initialize device using D3D v9 interface
bool InitD3D9(const mfxU32 adapterNum);
// Initialize device using DXGI 1.1 interface
bool InitDXGI1(const mfxU32 adapterNum);
// Obtain graphic card's parameter
mfxU32 GetVendorID(void) const;
mfxU32 GetDeviceID(void) const;
mfxU64 GetDriverVersion(void) const;
mfxU64 GetLUID(void) const;
// Provide the number of available adapters
mfxU32 GetAdapterCount(void) const;
void Close(void);
protected:
#ifdef MFX_D3D9_ENABLED
// Get vendor & device IDs by alternative way (D3D9 in Remote Desktop sessions)
void UseAlternativeWay(const D3D9Device *pD3D9Device);
#endif // MFX_D3D9_ENABLED
// Number of adapters available
mfxU32 m_numAdapters;
// Vendor ID
mfxU32 m_vendorID;
// Device ID
mfxU32 m_deviceID;
//x.x.x.x
mfxU64 m_driverVersion;
// LUID
mfxU64 m_luid;
private:
// unimplemented by intent to make this class non-copyable
DXVA2Device(const DXVA2Device &);
void operator=(const DXVA2Device &);
};
} // namespace MFX
#endif // LIBVPL_SRC_WINDOWS_MFX_DXVA2_DEVICE_H_
@@ -0,0 +1,155 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
//
// WARNING:
// this file doesn't contain an include guard by design.
// The file may be included into a source file many times.
// That is why this header doesn't contain any include directive.
// Please, do no try to fix it.
//
// NOLINT(build/header_guard)
// Use define API_VERSION to set the API of functions listed further
// When new functions are added new section with functions declarations must be started with updated define
//
// API version 1.0 functions
//
// API version where a function is added. Minor value should precedes the major value
#define API_VERSION \
{ \
{ 0, 1 } \
}
// CORE interface functions
FUNCTION(mfxStatus,
MFXVideoCORE_SetFrameAllocator,
(mfxSession session, mfxFrameAllocator *allocator),
(session, allocator))
FUNCTION(mfxStatus,
MFXVideoCORE_SetHandle,
(mfxSession session, mfxHandleType type, mfxHDL hdl),
(session, type, hdl))
FUNCTION(mfxStatus,
MFXVideoCORE_SyncOperation,
(mfxSession session, mfxSyncPoint syncp, mfxU32 wait),
(session, syncp, wait))
// ENCODE interface functions
FUNCTION(mfxStatus,
MFXVideoENCODE_Query,
(mfxSession session, mfxVideoParam *in, mfxVideoParam *out),
(session, in, out))
FUNCTION(mfxStatus,
MFXVideoENCODE_QueryIOSurf,
(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request),
(session, par, request))
FUNCTION(mfxStatus, MFXVideoENCODE_Init, (mfxSession session, mfxVideoParam *par), (session, par))
FUNCTION(mfxStatus, MFXVideoENCODE_Reset, (mfxSession session, mfxVideoParam *par), (session, par))
FUNCTION(mfxStatus, MFXVideoENCODE_Close, (mfxSession session), (session))
FUNCTION(mfxStatus,
MFXVideoENCODE_GetVideoParam,
(mfxSession session, mfxVideoParam *par),
(session, par))
FUNCTION(mfxStatus,
MFXVideoENCODE_GetEncodeStat,
(mfxSession session, mfxEncodeStat *stat),
(session, stat))
FUNCTION(mfxStatus,
MFXVideoENCODE_EncodeFrameAsync,
(mfxSession session,
mfxEncodeCtrl *ctrl,
mfxFrameSurface1 *surface,
mfxBitstream *bs,
mfxSyncPoint *syncp),
(session, ctrl, surface, bs, syncp))
// DECODE interface functions
FUNCTION(mfxStatus,
MFXVideoDECODE_Query,
(mfxSession session, mfxVideoParam *in, mfxVideoParam *out),
(session, in, out))
FUNCTION(mfxStatus,
MFXVideoDECODE_DecodeHeader,
(mfxSession session, mfxBitstream *bs, mfxVideoParam *par),
(session, bs, par))
FUNCTION(mfxStatus,
MFXVideoDECODE_QueryIOSurf,
(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request),
(session, par, request))
FUNCTION(mfxStatus, MFXVideoDECODE_Init, (mfxSession session, mfxVideoParam *par), (session, par))
FUNCTION(mfxStatus, MFXVideoDECODE_Reset, (mfxSession session, mfxVideoParam *par), (session, par))
FUNCTION(mfxStatus, MFXVideoDECODE_Close, (mfxSession session), (session))
FUNCTION(mfxStatus,
MFXVideoDECODE_GetVideoParam,
(mfxSession session, mfxVideoParam *par),
(session, par))
FUNCTION(mfxStatus,
MFXVideoDECODE_GetDecodeStat,
(mfxSession session, mfxDecodeStat *stat),
(session, stat))
FUNCTION(mfxStatus,
MFXVideoDECODE_SetSkipMode,
(mfxSession session, mfxSkipMode mode),
(session, mode))
FUNCTION(mfxStatus,
MFXVideoDECODE_GetPayload,
(mfxSession session, mfxU64 *ts, mfxPayload *payload),
(session, ts, payload))
FUNCTION(mfxStatus,
MFXVideoDECODE_DecodeFrameAsync,
(mfxSession session,
mfxBitstream *bs,
mfxFrameSurface1 *surface_work,
mfxFrameSurface1 **surface_out,
mfxSyncPoint *syncp),
(session, bs, surface_work, surface_out, syncp))
// VPP interface functions
FUNCTION(mfxStatus,
MFXVideoVPP_Query,
(mfxSession session, mfxVideoParam *in, mfxVideoParam *out),
(session, in, out))
FUNCTION(mfxStatus,
MFXVideoVPP_QueryIOSurf,
(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request),
(session, par, request))
FUNCTION(mfxStatus, MFXVideoVPP_Init, (mfxSession session, mfxVideoParam *par), (session, par))
FUNCTION(mfxStatus, MFXVideoVPP_Reset, (mfxSession session, mfxVideoParam *par), (session, par))
FUNCTION(mfxStatus, MFXVideoVPP_Close, (mfxSession session), (session))
FUNCTION(mfxStatus,
MFXVideoVPP_GetVideoParam,
(mfxSession session, mfxVideoParam *par),
(session, par))
FUNCTION(mfxStatus, MFXVideoVPP_GetVPPStat, (mfxSession session, mfxVPPStat *stat), (session, stat))
FUNCTION(mfxStatus,
MFXVideoVPP_RunFrameVPPAsync,
(mfxSession session,
mfxFrameSurface1 *in,
mfxFrameSurface1 *out,
mfxExtVppAuxData *aux,
mfxSyncPoint *syncp),
(session, in, out, aux, syncp))
#undef API_VERSION
#define API_VERSION \
{ \
{ 19, 1 } \
}
FUNCTION(mfxStatus,
MFXVideoCORE_QueryPlatform,
(mfxSession session, mfxPlatform *platform),
(session, platform))
#undef API_VERSION
@@ -0,0 +1,115 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#include "src/windows/mfx_dispatcher.h"
//
// implement a table with functions names
//
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
#undef FUNCTION
#define FUNCTION(return_value, func_name, formal_param_list, actual_param_list) \
{ #func_name, API_VERSION },
const FUNCTION_DESCRIPTION APIFunc[eVideoFuncTotal] = {
{ "MFXInit", { { 0, 1 } } },
{ "MFXClose", { { 0, 1 } } },
{ "MFXQueryIMPL", { { 0, 1 } } },
{ "MFXQueryVersion", { { 0, 1 } } },
{ "MFXVideoCORE_GetHandle", { { 0, 1 } } },
{ "MFXJoinSession", { { 1, 1 } } },
{ "MFXDisjoinSession", { { 1, 1 } } },
{ "MFXCloneSession", { { 1, 1 } } },
{ "MFXSetPriority", { { 1, 1 } } },
{ "MFXGetPriority", { { 1, 1 } } },
{ "MFXInitEx", { { 14, 1 } } },
#include "src/windows/mfx_exposed_functions_list.h"
};
// new functions for API >= 2.0
const FUNCTION_DESCRIPTION APIVideoFunc2[eVideoFunc2Total] = {
{ "MFXQueryImplsDescription", { { 0, 2 } } },
{ "MFXReleaseImplDescription", { { 0, 2 } } },
{ "MFXMemory_GetSurfaceForVPP", { { 0, 2 } } },
{ "MFXMemory_GetSurfaceForEncode", { { 0, 2 } } },
{ "MFXMemory_GetSurfaceForDecode", { { 0, 2 } } },
{ "MFXInitialize", { { 0, 2 } } },
{ "MFXMemory_GetSurfaceForVPPOut", { { 1, 2 } } },
{ "MFXVideoDECODE_VPP_Init", { { 1, 2 } } },
{ "MFXVideoDECODE_VPP_DecodeFrameAsync", { { 1, 2 } } },
{ "MFXVideoDECODE_VPP_Reset", { { 1, 2 } } },
{ "MFXVideoDECODE_VPP_GetChannelParam", { { 1, 2 } } },
{ "MFXVideoDECODE_VPP_Close", { { 1, 2 } } },
{ "MFXVideoVPP_ProcessFrameAsync", { { 1, 2 } } },
};
// static section of the file
namespace {
//
// declare pseudo-functions.
// they are used as default values for call-tables.
//
mfxStatus pseudoMFXInit(mfxIMPL impl, mfxVersion *ver, mfxSession *session) {
// touch unreferenced parameters
(void)impl;
(void)ver;
(void)session;
return MFX_ERR_UNKNOWN;
} // mfxStatus pseudoMFXInit(mfxIMPL impl, mfxVersion *ver, mfxSession *session)
mfxStatus pseudoMFXClose(mfxSession session) {
// touch unreferenced parameters
(void)session;
return MFX_ERR_UNKNOWN;
} // mfxStatus pseudoMFXClose(mfxSession session)
mfxStatus pseudoMFXJoinSession(mfxSession session, mfxSession child_session) {
// touch unreferenced parameters
(void)session;
(void)child_session;
return MFX_ERR_UNKNOWN;
} // mfxStatus pseudoMFXJoinSession(mfxSession session, mfxSession child_session)
mfxStatus pseudoMFXCloneSession(mfxSession session, mfxSession *clone) {
// touch unreferenced parameters
(void)session;
(void)clone;
return MFX_ERR_UNKNOWN;
} // mfxStatus pseudoMFXCloneSession(mfxSession session, mfxSession *clone)
void SuppressWarnings(...) {
// this functions is suppose to suppress warnings.
// Actually it does nothing.
} // void SuppressWarnings(...)
#undef FUNCTION
#define FUNCTION(return_value, func_name, formal_param_list, actual_param_list) \
return_value pseudo##func_name formal_param_list { \
SuppressWarnings actual_param_list; \
return MFX_ERR_UNKNOWN; \
}
#include "src/windows/mfx_exposed_functions_list.h" // NOLINT(build/include)
} // namespace
@@ -0,0 +1,646 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#include "src/windows/mfx_library_iterator.h"
#include "src/windows/mfx_dispatcher.h"
#include "src/windows/mfx_dispatcher_log.h"
#include "src/windows/mfx_dxva2_device.h"
#include "src/windows/mfx_load_dll.h"
#include <tchar.h>
#include <windows.h>
#include <vector>
namespace MFX {
enum { MFX_MAX_MERIT = 0x7fffffff };
//
// declare registry keys
//
const wchar_t rootDispPath[] = L"Software\\Intel\\MediaSDK\\Dispatch";
const wchar_t vendorIDKeyName[] = L"VendorID";
const wchar_t deviceIDKeyName[] = L"DeviceID";
const wchar_t meritKeyName[] = L"Merit";
const wchar_t pathKeyName[] = L"Path";
const wchar_t apiVersionName[] = L"APIVersion";
mfxStatus SelectImplementationType(const mfxU32 adapterNum,
mfxIMPL *pImplInterface,
mfxU32 *pVendorID,
mfxU32 *pDeviceID,
mfxU64 *pLUID) {
if (NULL == pImplInterface) {
return MFX_ERR_NULL_PTR;
}
mfxIMPL impl_via = *pImplInterface;
DXVA2Device dxvaDevice;
if (MFX_IMPL_VIA_D3D9 == impl_via) {
// try to create the Direct3D 9 device and find right adapter
if (!dxvaDevice.InitD3D9(adapterNum)) {
DISPATCHER_LOG_INFO((("dxvaDevice.InitD3D9(%d) Failed "), adapterNum));
return MFX_ERR_UNSUPPORTED;
}
}
else if (MFX_IMPL_VIA_D3D11 == impl_via) {
// try to open DXGI 1.1 device to get hardware ID
if (!dxvaDevice.InitDXGI1(adapterNum)) {
DISPATCHER_LOG_INFO((("dxvaDevice.InitDXGI1(%d) Failed "), adapterNum));
return MFX_ERR_UNSUPPORTED;
}
}
else if (MFX_IMPL_VIA_ANY == impl_via) {
// try the Direct3D 9 device
if (dxvaDevice.InitD3D9(adapterNum)) {
*pImplInterface = MFX_IMPL_VIA_D3D9; // store value for GetImplementationType() call
}
// else try to open DXGI 1.1 device to get hardware ID
else if (dxvaDevice.InitDXGI1(adapterNum)) {
*pImplInterface = MFX_IMPL_VIA_D3D11; // store value for GetImplementationType() call
}
else {
DISPATCHER_LOG_INFO((("Unsupported adapter %d "), adapterNum));
return MFX_ERR_UNSUPPORTED;
}
}
else {
DISPATCHER_LOG_ERROR((("Unknown implementation type %d "), *pImplInterface));
return MFX_ERR_UNSUPPORTED;
}
// obtain card's parameters
if (pVendorID && pDeviceID) {
*pVendorID = dxvaDevice.GetVendorID();
*pDeviceID = dxvaDevice.GetDeviceID();
}
if (pLUID) {
*pLUID = dxvaDevice.GetLUID();
}
return MFX_ERR_NONE;
}
mfxStatus SelectImplementationType(const mfxU32 adapterNum,
mfxIMPL *pImplInterface,
mfxU32 *pVendorID,
mfxU32 *pDeviceID) {
// do not return LUID
return SelectImplementationType(adapterNum, pImplInterface, pVendorID, pDeviceID, nullptr);
}
MFXLibraryIterator::MFXLibraryIterator(void)
#if !defined(MEDIASDK_UWP_DISPATCHER)
: m_baseRegKey()
#endif
{
m_implType = MFX_LIB_PSEUDO;
m_implInterface = MFX_IMPL_UNSUPPORTED;
m_vendorID = 0;
m_deviceID = 0;
m_lastLibIndex = 0;
m_lastLibMerit = MFX_MAX_MERIT;
m_bIsSubKeyValid = 0;
m_StorageID = 0;
m_SubKeyName[0] = 0;
m_driverStoreDir[0] = 0;
} // MFXLibraryIterator::MFXLibraryIterator(void)
MFXLibraryIterator::~MFXLibraryIterator(void) {
Release();
} // MFXLibraryIterator::~MFXLibraryIterator(void)
void MFXLibraryIterator::Release(void) {
m_implType = MFX_LIB_PSEUDO;
m_implInterface = MFX_IMPL_UNSUPPORTED;
m_vendorID = 0;
m_deviceID = 0;
m_lastLibIndex = 0;
m_lastLibMerit = MFX_MAX_MERIT;
m_SubKeyName[0] = 0;
} // void MFXLibraryIterator::Release(void)
DECLSPEC_NOINLINE HMODULE GetThisDllModuleHandle() {
HMODULE hDll = NULL;
GetModuleHandleExW(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
reinterpret_cast<LPCWSTR>(&GetThisDllModuleHandle),
&hDll);
return hDll;
}
// wchar_t* sImplPath must be allocated with size not less then msdk_disp_path_len
bool GetImplPath(int storageID, wchar_t *sImplPath) {
HMODULE hModule = NULL;
sImplPath[0] = L'\0';
switch (storageID) {
case MFX_APP_FOLDER:
hModule = 0;
break;
case MFX_PATH_MSDK_FOLDER:
hModule = GetThisDllModuleHandle();
HMODULE exeModule = GetModuleHandleW(NULL);
//It should works only if Dispatcher is linked with Dynamic Linked Library
if (!hModule || !exeModule || hModule == exeModule)
return false;
break;
}
DWORD nSize = 0;
DWORD allocSize = msdk_disp_path_len;
nSize = GetModuleFileNameW(hModule, &sImplPath[0], allocSize);
if (nSize == 0 || nSize == allocSize) {
// nSize == 0 meanse that system can't get this info for hModule
// nSize == allocSize buffer is too small
return false;
}
// for any case because WinXP implementation of GetModuleFileName does not add \0 to the end of string
sImplPath[nSize] = L'\0';
wchar_t *dirSeparator = wcsrchr(sImplPath, L'\\');
if (dirSeparator != NULL && dirSeparator < (sImplPath + msdk_disp_path_len)) {
*++dirSeparator = 0;
}
return true;
}
mfxStatus MFXLibraryIterator::Init(eMfxImplType implType,
mfxIMPL implInterface,
const mfxU32 adapterNum,
int storageID) {
// check error(s)
if ((MFX_LIB_SOFTWARE != implType) && (MFX_LIB_HARDWARE != implType)) {
return MFX_ERR_UNSUPPORTED;
}
// release the object before initialization
Release();
m_StorageID = storageID;
m_lastLibIndex = 0;
m_implType = implType;
m_implInterface = implInterface != 0 ? implInterface : MFX_IMPL_VIA_ANY;
// for HW impl check impl interface, check adapter, obtain deviceID and vendorID
if (m_implType != MFX_LIB_SOFTWARE) {
mfxStatus mfxRes =
MFX::SelectImplementationType(adapterNum, &m_implInterface, &m_vendorID, &m_deviceID);
if (MFX_ERR_NONE != mfxRes) {
return mfxRes;
}
}
#if !defined(MEDIASDK_UWP_DISPATCHER)
if (storageID == MFX_CURRENT_USER_KEY || storageID == MFX_LOCAL_MACHINE_KEY ||
storageID == MFX_CURRENT_USER_KEY_ONEVPL || storageID == MFX_LOCAL_MACHINE_KEY_ONEVPL) {
return InitRegistry(storageID);
}
#if defined(MFX_TRACER_WA_FOR_DS)
if (storageID == MFX_TRACER) {
return InitRegistryTracer();
}
#endif
#endif
if (storageID == MFX_DRIVER_STORE) {
m_driverStoreDir[0] = 0;
if (!m_driverStoreLoader.GetDriverStorePath(m_driverStoreDir,
sizeof(m_driverStoreDir),
m_deviceID,
L"DriverStorePathForMediaSDK")) {
return MFX_ERR_UNSUPPORTED;
}
}
else if (storageID == MFX_DRIVER_STORE_ONEVPL || storageID == MFX_DRIVER_STORE_ONEVPL_MFXINIT) {
// get path to runtime directory only (without library name)
m_driverStoreDir[0] = 0;
if (!m_driverStoreLoader.GetDriverStorePath(m_driverStoreDir,
sizeof(m_driverStoreDir),
m_deviceID,
L"DriverStorePathForVPL")) {
return MFX_ERR_UNSUPPORTED;
}
}
else if (!GetImplPath(storageID, m_driverStoreDir)) {
return MFX_ERR_UNSUPPORTED;
}
// only need the path for Intel® Video Processing Library (Intel® VPL) loader
if (storageID == MFX_DRIVER_STORE_ONEVPL || storageID == MFX_CURRENT_USER_KEY_ONEVPL ||
storageID == MFX_LOCAL_MACHINE_KEY_ONEVPL) {
return MFX_ERR_NONE;
}
return InitFolder(implType, m_driverStoreDir, storageID);
} // mfxStatus MFXLibraryIterator::Init(eMfxImplType implType, const mfxU32 adapterNum, int storageID)
mfxStatus MFXLibraryIterator::InitRegistry(int storageID) {
#if !defined(MEDIASDK_UWP_DISPATCHER)
HKEY rootHKey;
bool bRes;
// open required registry key
switch (storageID) {
case MFX_LOCAL_MACHINE_KEY:
case MFX_LOCAL_MACHINE_KEY_ONEVPL:
rootHKey = HKEY_LOCAL_MACHINE;
break;
default:
rootHKey = HKEY_CURRENT_USER;
break;
}
bRes = m_baseRegKey.Open(rootHKey, rootDispPath, KEY_READ);
if (false == bRes) {
DISPATCHER_LOG_WRN(
(("Can't open %s\\%S : RegOpenKeyExA()==0x%x\n"),
(MFX_LOCAL_MACHINE_KEY == storageID) ? ("HKEY_LOCAL_MACHINE") : ("HKEY_CURRENT_USER"),
rootDispPath,
GetLastError()))
return MFX_ERR_UNKNOWN;
}
DISPATCHER_LOG_INFO(
(("Inspecting %s\\%S\n"),
(MFX_LOCAL_MACHINE_KEY == storageID) ? ("HKEY_LOCAL_MACHINE") : ("HKEY_CURRENT_USER"),
rootDispPath))
return MFX_ERR_NONE;
#else
(void)storageID;
return MFX_ERR_UNSUPPORTED;
#endif // #if !defined(MEDIASDK_UWP_DISPATCHER)
} // mfxStatus MFXLibraryIterator::InitRegistry(int storageID)
#if defined(MFX_TRACER_WA_FOR_DS)
mfxStatus MFXLibraryIterator::InitRegistryTracer() {
#if !defined(MEDIASDK_UWP_DISPATCHER)
const wchar_t tracerRegKeyPath[] = L"Software\\Intel\\MediaSDK\\Dispatch\\tracer";
if (!m_baseRegKey.Open(HKEY_LOCAL_MACHINE, tracerRegKeyPath, KEY_READ) &&
!m_baseRegKey.Open(HKEY_CURRENT_USER, tracerRegKeyPath, KEY_READ)) {
DISPATCHER_LOG_WRN(("can't find tracer registry key\n"))
return MFX_ERR_UNKNOWN;
}
DISPATCHER_LOG_INFO(("found tracer registry key\n"))
return MFX_ERR_NONE;
#else
return MFX_ERR_UNSUPPORTED;
#endif // #if !defined(MEDIASDK_UWP_DISPATCHER)
} // mfxStatus MFXLibraryIterator::InitRegistryTracer()
#endif
mfxStatus MFXLibraryIterator::InitFolder(eMfxImplType implType,
const wchar_t *path,
const int storageID) {
const int maxPathLen = sizeof(m_path) / sizeof(m_path[0]);
m_path[0] = 0;
wcscpy_s(m_path, maxPathLen, path);
size_t pathLen = wcslen(m_path);
if (storageID == MFX_APP_FOLDER) {
// we looking for runtime in application folder, it should be named libmfxsw64 or libmfxsw32
mfx_get_default_dll_name(m_path + pathLen, msdk_disp_path_len - pathLen, MFX_LIB_SOFTWARE);
}
else if (storageID == MFX_DRIVER_STORE_ONEVPL_MFXINIT) {
mfx_get_default_vpl_dll_name(m_path + pathLen, msdk_disp_path_len - pathLen);
}
else {
mfx_get_default_dll_name(m_path + pathLen, msdk_disp_path_len - pathLen, implType);
}
return MFX_ERR_NONE;
} // mfxStatus MFXLibraryIterator::InitFolder(eMfxImplType implType, const wchar_t * path, const int storageID)
mfxStatus MFXLibraryIterator::SelectDLLVersion(wchar_t *pPath,
size_t pathSize,
eMfxImplType *pImplType,
mfxVersion minVersion) {
UNREFERENCED_PARAMETER(minVersion);
if (m_StorageID == MFX_APP_FOLDER) {
if (m_lastLibIndex != 0)
return MFX_ERR_NOT_FOUND;
if (m_vendorID != INTEL_VENDOR_ID)
return MFX_ERR_UNKNOWN;
m_lastLibIndex = 1;
wcscpy_s(pPath, pathSize, m_path);
*pImplType = MFX_LIB_SOFTWARE;
return MFX_ERR_NONE;
}
if (m_StorageID == MFX_PATH_MSDK_FOLDER || m_StorageID == MFX_DRIVER_STORE ||
m_StorageID == MFX_DRIVER_STORE_ONEVPL_MFXINIT) {
if (m_lastLibIndex != 0)
return MFX_ERR_NOT_FOUND;
if (m_vendorID != INTEL_VENDOR_ID)
return MFX_ERR_UNKNOWN;
m_lastLibIndex = 1;
wcscpy_s(pPath, pathSize, m_path);
// do not change impl type
return MFX_ERR_NONE;
}
#if !defined(MEDIASDK_UWP_DISPATCHER)
#if defined(MFX_TRACER_WA_FOR_DS)
if (m_StorageID == MFX_TRACER) {
if (m_lastLibIndex != 0)
return MFX_ERR_NOT_FOUND;
if (m_vendorID != INTEL_VENDOR_ID)
return MFX_ERR_UNKNOWN;
m_lastLibIndex = 1;
if (m_baseRegKey.Query(pathKeyName, REG_SZ, (LPBYTE)pPath, (DWORD *)&pathSize)) {
DISPATCHER_LOG_INFO((("loaded %S : %S\n"), pathKeyName, pPath));
}
else {
DISPATCHER_LOG_WRN(
(("error querying %S : RegQueryValueExA()==0x%x\n"), pathKeyName, GetLastError()));
}
return MFX_ERR_NONE;
}
#endif
wchar_t libPath[MFX_MAX_DLL_PATH] = L"";
DWORD libIndex = 0;
DWORD libMerit = 0;
DWORD index;
bool enumRes;
// main query cycle
index = 0;
m_bIsSubKeyValid = false;
do {
WinRegKey subKey;
wchar_t subKeyName[MFX_MAX_REGISTRY_KEY_NAME] = { 0 };
DWORD subKeyNameSize = sizeof(subKeyName) / sizeof(subKeyName[0]);
// query next value name
enumRes = m_baseRegKey.EnumKey(index, subKeyName, &subKeyNameSize);
if (!enumRes) {
DISPATCHER_LOG_WRN((("no more subkeys : RegEnumKeyExA()==0x%x\n"), GetLastError()))
}
else {
DISPATCHER_LOG_INFO((("found subkey: %S\n"), subKeyName))
bool bRes;
// open the sub key
bRes = subKey.Open(m_baseRegKey, subKeyName, KEY_READ);
if (!bRes) {
DISPATCHER_LOG_WRN((("error opening key %S :RegOpenKeyExA()==0x%x\n"),
subKeyName,
GetLastError()));
}
else {
DISPATCHER_LOG_INFO((("opened key: %S\n"), subKeyName));
mfxU32 vendorID = 0, deviceID = 0, merit = 0;
DWORD size;
// query vendor and device IDs
size = sizeof(vendorID);
bRes = subKey.Query(vendorIDKeyName, REG_DWORD, (LPBYTE)&vendorID, &size);
DISPATCHER_LOG_OPERATION({
if (bRes) {
DISPATCHER_LOG_INFO((("loaded %S : 0x%x\n"), vendorIDKeyName, vendorID));
}
else {
DISPATCHER_LOG_WRN((("querying %S : RegQueryValueExA()==0x%x\n"),
vendorIDKeyName,
GetLastError()));
}
})
if (bRes) {
size = sizeof(deviceID);
bRes = subKey.Query(deviceIDKeyName, REG_DWORD, (LPBYTE)&deviceID, &size);
DISPATCHER_LOG_OPERATION({
if (bRes) {
DISPATCHER_LOG_INFO(
(("loaded %S : 0x%x\n"), deviceIDKeyName, deviceID));
}
else {
DISPATCHER_LOG_WRN((("querying %S : RegQueryValueExA()==0x%x\n"),
deviceIDKeyName,
GetLastError()));
}
})
}
// query merit value
if (bRes) {
size = sizeof(merit);
bRes = subKey.Query(meritKeyName, REG_DWORD, (LPBYTE)&merit, &size);
DISPATCHER_LOG_OPERATION({
if (bRes) {
DISPATCHER_LOG_INFO((("loaded %S : %d\n"), meritKeyName, merit));
}
else {
DISPATCHER_LOG_WRN((("querying %S : RegQueryValueExA()==0x%x\n"),
meritKeyName,
GetLastError()));
}
})
}
// if the library fits required parameters,
// query the library's path
if (bRes) {
// compare device's and library's IDs
if (MFX_LIB_HARDWARE == m_implType) {
if (m_vendorID != vendorID) {
bRes = false;
DISPATCHER_LOG_WRN((("%S conflict, actual = 0x%x : required = 0x%x\n"),
vendorIDKeyName,
m_vendorID,
vendorID));
}
if (bRes && m_deviceID != deviceID) {
bRes = false;
DISPATCHER_LOG_WRN((("%S conflict, actual = 0x%x : required = 0x%x\n"),
deviceIDKeyName,
m_deviceID,
deviceID));
}
}
DISPATCHER_LOG_OPERATION({
if (bRes) {
if (!(((m_lastLibMerit > merit) ||
((m_lastLibMerit == merit) && (m_lastLibIndex < index))) &&
(libMerit < merit))) {
DISPATCHER_LOG_WRN((
("merit conflict: lastMerit = 0x%x, requiredMerit = 0x%x, libraryMerit = 0x%x, lastindex = %d, index = %d\n"),
m_lastLibMerit,
merit,
libMerit,
m_lastLibIndex,
index));
}
}
})
if ((bRes) &&
((m_lastLibMerit > merit) ||
((m_lastLibMerit == merit) && (m_lastLibIndex < index))) &&
(libMerit < merit)) {
wchar_t tmpPath[MFX_MAX_DLL_PATH];
DWORD tmpPathSize = sizeof(tmpPath);
bRes = subKey.Query(pathKeyName, REG_SZ, (LPBYTE)tmpPath, &tmpPathSize);
if (!bRes) {
DISPATCHER_LOG_WRN((("error querying %S : RegQueryValueExA()==0x%x\n"),
pathKeyName,
GetLastError()));
}
else {
DISPATCHER_LOG_INFO((("loaded %S : %S\n"), pathKeyName, tmpPath));
wcscpy_s(libPath, sizeof(libPath) / sizeof(libPath[0]), tmpPath);
wcscpy_s(m_SubKeyName,
sizeof(m_SubKeyName) / sizeof(m_SubKeyName[0]),
subKeyName);
libMerit = merit;
libIndex = index;
// set the library's type
if ((0 == vendorID) || (0 == deviceID)) {
*pImplType = MFX_LIB_SOFTWARE;
DISPATCHER_LOG_INFO((("Library type is MFX_LIB_SOFTWARE\n")));
}
else {
*pImplType = MFX_LIB_HARDWARE;
DISPATCHER_LOG_INFO((("Library type is MFX_LIB_HARDWARE\n")));
}
}
}
}
}
}
// advance key index
index += 1;
} while (enumRes);
// if the library's path was successfully read,
// the merit variable holds valid value
if (0 == libMerit) {
return MFX_ERR_NOT_FOUND;
}
wcscpy_s(pPath, pathSize, libPath);
m_lastLibIndex = libIndex;
m_lastLibMerit = libMerit;
m_bIsSubKeyValid = true;
#endif
return MFX_ERR_NONE;
} // mfxStatus MFXLibraryIterator::SelectDLLVersion(wchar_t *pPath, size_t pathSize, eMfxImplType *pImplType, mfxVersion minVersion)
mfxIMPL MFXLibraryIterator::GetImplementationType() {
return m_implInterface;
} // mfxIMPL MFXLibraryIterator::GetImplementationType()
bool MFXLibraryIterator::GetSubKeyName(wchar_t *subKeyName, size_t length) const {
wcscpy_s(subKeyName, length, m_SubKeyName);
return m_bIsSubKeyValid;
}
// lightweight implementation that takes deviceID as an argument, avoiding need to init the adapter
mfxStatus MFXLibraryIterator::GetDriverStoreDir(std::wstring &driverStoreDir,
size_t length,
mfxU32 deviceID,
int storageID) {
wchar_t wcDir[MFX_MAX_DLL_PATH];
wcDir[0] = 0;
DriverStoreLoader dsLoader;
if (storageID == MFX_DRIVER_STORE_ONEVPL) {
// pass size of wcDir in bytes (see implementation of GetDriverStorePath)
if (!dsLoader.GetDriverStorePath(wcDir, sizeof(wcDir), deviceID, L"DriverStorePathForVPL"))
return MFX_ERR_UNSUPPORTED;
}
else if (storageID == MFX_DRIVER_STORE) {
if (!dsLoader.GetDriverStorePath(wcDir,
sizeof(wcDir),
deviceID,
L"DriverStorePathForMediaSDK"))
return MFX_ERR_UNSUPPORTED;
}
if (wcslen(wcDir) == 0)
return MFX_ERR_UNSUPPORTED;
// return path to driverStorDir
driverStoreDir = wcDir;
return MFX_ERR_NONE;
}
mfxStatus MFXLibraryIterator::GetRegkeyDir(std::wstring &regDir, size_t length, int storageID) {
mfxStatus sts = MFX_ERR_UNSUPPORTED;
MFX::MFXLibraryIterator libIterator;
wchar_t wRegDir[MFX_MAX_DLL_PATH];
regDir.clear();
sts = libIterator.Init(MFX_LIB_HARDWARE, MFX_IMPL_VIA_D3D11, 0, storageID);
if (sts)
return MFX_ERR_UNSUPPORTED;
eMfxImplType implType = MFX_LIB_HARDWARE;
mfxVersion ver = { 0, 1 };
sts =
libIterator.SelectDLLVersion(wRegDir, sizeof(wRegDir) / sizeof(wRegDir[0]), &implType, ver);
if (sts)
return MFX_ERR_UNSUPPORTED;
// remove DLL name - only need the path
std::wstring s = wRegDir;
size_t f = s.find_last_of('\\');
if (f == std::string::npos)
return MFX_ERR_UNSUPPORTED;
regDir = s.substr(0, f);
return MFX_ERR_NONE;
}
} // namespace MFX
@@ -0,0 +1,145 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#ifndef LIBVPL_SRC_WINDOWS_MFX_LIBRARY_ITERATOR_H_
#define LIBVPL_SRC_WINDOWS_MFX_LIBRARY_ITERATOR_H_
#include <string>
#include "vpl/mfxvideo.h"
#if !defined(MEDIASDK_UWP_DISPATCHER)
#include "mfx_win_reg_key.h"
#endif
#include "src/windows/mfx_dispatcher.h"
#include "src/windows/mfx_driver_store_loader.h"
namespace MFX {
// declare desired storage ID
enum {
#if defined(MFX_TRACER_WA_FOR_DS)
MFX_UNKNOWN_KEY = -1,
MFX_TRACER = 0,
MFX_DRIVER_STORE_ONEVPL_MFXINIT = 1,
MFX_DRIVER_STORE = 2,
MFX_CURRENT_USER_KEY = 3,
MFX_LOCAL_MACHINE_KEY = 4,
MFX_APP_FOLDER = 5,
MFX_PATH_MSDK_FOLDER = 6,
MFX_STORAGE_ID_FIRST = MFX_TRACER,
MFX_STORAGE_ID_LAST = MFX_PATH_MSDK_FOLDER,
#else
MFX_UNKNOWN_KEY = -1,
MFX_DRIVER_STORE = 0,
MFX_CURRENT_USER_KEY = 1,
MFX_LOCAL_MACHINE_KEY = 2,
MFX_APP_FOLDER = 3,
MFX_PATH_MSDK_FOLDER = 4,
MFX_STORAGE_ID_FIRST = MFX_DRIVER_STORE,
MFX_STORAGE_ID_LAST = MFX_PATH_MSDK_FOLDER,
#endif
MFX_DRIVER_STORE_ONEVPL = 1001,
MFX_CURRENT_USER_KEY_ONEVPL = 1002,
MFX_LOCAL_MACHINE_KEY_ONEVPL = 1003,
};
// Try to initialize using given implementation type. Select appropriate type automatically in case of MFX_IMPL_VIA_ANY.
// Params: adapterNum - in, pImplInterface - in/out, pVendorID - out, pDeviceID - out, pLUID - out (optional)
mfxStatus SelectImplementationType(const mfxU32 adapterNum,
mfxIMPL *pImplInterface,
mfxU32 *pVendorID,
mfxU32 *pDeviceID);
mfxStatus SelectImplementationType(const mfxU32 adapterNum,
mfxIMPL *pImplInterface,
mfxU32 *pVendorID,
mfxU32 *pDeviceID,
mfxU64 *pLUID);
bool GetImplPath(int storageID, wchar_t *sImplPath);
const mfxU32 msdk_disp_path_len = 1024;
class MFXLibraryIterator {
public:
// Default constructor
MFXLibraryIterator(void);
// Destructor
~MFXLibraryIterator(void);
// Initialize the iterator
mfxStatus Init(eMfxImplType implType,
mfxIMPL implInterface,
const mfxU32 adapterNum,
int storageID);
// Get the next library path
mfxStatus SelectDLLVersion(wchar_t *pPath,
size_t pathSize,
eMfxImplType *pImplType,
mfxVersion minVersion);
// Return interface type on which Intel adapter was found (if any): D3D9 or D3D11
mfxIMPL GetImplementationType();
// Retrun registry subkey name on which dll was selected after sucesfull call to selectDllVesion
bool GetSubKeyName(wchar_t *subKeyName, size_t length) const;
int GetStorageID() const {
return m_StorageID;
}
static mfxStatus GetDriverStoreDir(std::wstring &driverStoreDir,
size_t length,
mfxU32 deviceID,
int storageID);
static mfxStatus GetRegkeyDir(std::wstring &regDir, size_t length, int storageID);
protected:
// Release the iterator
void Release(void);
// Initialize the registry iterator
mfxStatus InitRegistry(int storageID);
#if defined(MFX_TRACER_WA_FOR_DS)
// Initialize the registry iterator for searching for tracer
mfxStatus InitRegistryTracer();
#endif
// Initialize the app/module folder iterator
mfxStatus InitFolder(eMfxImplType implType, const wchar_t *path, const int storageID);
eMfxImplType m_implType; // Required library implementation
mfxIMPL m_implInterface; // Required interface (D3D9, D3D11)
mfxU32 m_vendorID; // (mfxU32) property of used graphic card
mfxU32 m_deviceID; // (mfxU32) property of used graphic card
bool m_bIsSubKeyValid;
wchar_t m_SubKeyName[MFX_MAX_REGISTRY_KEY_NAME]; // registry subkey for selected module loaded
int m_StorageID;
#if !defined(MEDIASDK_UWP_DISPATCHER)
WinRegKey m_baseRegKey; // (WinRegKey) main registry key
#endif
mfxU32 m_lastLibIndex; // (mfxU32) index of previously returned library
mfxU32 m_lastLibMerit; // (mfxU32) merit of previously returned library
wchar_t m_path[msdk_disp_path_len]; //NOLINT(runtime/arrays)
wchar_t m_driverStoreDir[msdk_disp_path_len]; //NOLINT(runtime/arrays)
DriverStoreLoader m_driverStoreLoader; // for loading MediaSDK from DriverStore
private:
// unimplemented by intent to make this class non-copyable
MFXLibraryIterator(const MFXLibraryIterator &);
void operator=(const MFXLibraryIterator &);
};
} // namespace MFX
#endif // LIBVPL_SRC_WINDOWS_MFX_LIBRARY_ITERATOR_H_
@@ -0,0 +1,196 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#include "src/windows/mfx_load_dll.h"
#include "src/windows/mfx_dispatcher.h"
#include <string.h>
#include <wchar.h>
#include <windows.h>
#if defined(_WIN64)
const wchar_t *const defaultDLLName[2] = { L"libmfxhw64.dll", L"libvplswref64.dll" };
const wchar_t *const defaultAudioDLLName[2] = { L"libmfxaudiosw64.dll", L"libmfxaudiosw64.dll" };
const wchar_t *const defaultOneVPLDLLName = { L"libmfx64-gen.dll" };
const wchar_t *const defaultPluginDLLName[2] = { L"mfxplugin64_hw.dll", L"mfxplugin64_sw.dll" };
#if defined(MEDIASDK_UWP_DISPATCHER)
const wchar_t *const IntelGFXAPIDLLName = { L"intel_gfx_api-x64.dll" };
#endif
#elif defined(_WIN32)
const wchar_t *const defaultDLLName[2] = { L"libmfxhw32.dll", L"libvplswref32.dll" };
const wchar_t *const defaultAudioDLLName[2] = { L"libmfxaudiosw32.dll", L"libmfxaudiosw32.dll" };
const wchar_t *const defaultOneVPLDLLName = { L"libmfx32-gen.dll" };
const wchar_t *const defaultPluginDLLName[2] = { L"mfxplugin32_hw.dll", L"mfxplugin32_sw.dll" };
#if defined(MEDIASDK_UWP_DISPATCHER)
const wchar_t *const IntelGFXAPIDLLName = { L"intel_gfx_api-x86.dll" };
#endif
#endif // (defined(_WIN64))
namespace MFX {
mfxStatus mfx_get_default_dll_name(wchar_t *pPath, size_t pathSize, eMfxImplType implType) {
if (!pPath) {
return MFX_ERR_NULL_PTR;
}
// there are only 2 implementation with default DLL names
#if _MSC_VER >= 1400
return 0 == wcscpy_s(pPath, pathSize, defaultDLLName[implType & 1]) ? MFX_ERR_NONE
: MFX_ERR_UNKNOWN;
#else
wcscpy(pPath, defaultDLLName[implType & 1]);
return MFX_ERR_NONE;
#endif
} // mfxStatus mfx_get_default_dll_name(wchar_t *pPath, size_t pathSize, eMfxImplType implType)
mfxStatus mfx_get_default_vpl_dll_name(wchar_t *pPath, size_t pathSize) {
if (!pPath) {
return MFX_ERR_NULL_PTR;
}
// there are only 2 implementation with default DLL names
#if _MSC_VER >= 1400
return 0 == wcscpy_s(pPath, pathSize, defaultOneVPLDLLName) ? MFX_ERR_NONE : MFX_ERR_UNKNOWN;
#else
wcscpy(pPath, defaultOneVPLDLLName);
return MFX_ERR_NONE;
#endif
} // mfxStatus mfx_get_default_vpl_dll_name(wchar_t *pPath, size_t pathSize, eMfxImplType implType)
#if defined(MEDIASDK_UWP_DISPATCHER)
mfxStatus mfx_get_default_intel_gfx_api_dll_name(wchar_t *pPath, size_t pathSize) {
if (!pPath) {
return MFX_ERR_NULL_PTR;
}
#if _MSC_VER >= 1400
return 0 == wcscpy_s(pPath, pathSize, IntelGFXAPIDLLName) ? MFX_ERR_NONE : MFX_ERR_UNKNOWN;
#else
wcscpy(pPath, IntelGFXAPIDLLName);
return MFX_ERR_NONE;
#endif
} // mfx_get_default_intel_gfx_api_dll_name(wchar_t *pPath, size_t pathSize)
#endif
mfxStatus mfx_get_default_plugin_name(wchar_t *pPath, size_t pathSize, eMfxImplType implType) {
if (!pPath) {
return MFX_ERR_NULL_PTR;
}
// there are only 2 implementation with default DLL names
#if _MSC_VER >= 1400
return 0 == wcscpy_s(pPath, pathSize, defaultPluginDLLName[implType & 1]) ? MFX_ERR_NONE
: MFX_ERR_UNKNOWN;
#else
wcscpy(pPath, defaultPluginDLLName[implType & 1]);
return MFX_ERR_NONE;
#endif
}
mfxStatus mfx_get_default_audio_dll_name(wchar_t *pPath, size_t pathSize, eMfxImplType implType) {
if (!pPath) {
return MFX_ERR_NULL_PTR;
}
// there are only 2 implementation with default DLL names
#if _MSC_VER >= 1400
return 0 == wcscpy_s(pPath, pathSize, defaultAudioDLLName[implType & 1]) ? MFX_ERR_NONE
: MFX_ERR_UNKNOWN;
#else
wcscpy(pPath, defaultAudioDLLName[implType & 1]);
return MFX_ERR_NONE;
#endif
} // mfxStatus mfx_get_default_audio_dll_name(wchar_t *pPath, size_t pathSize, eMfxImplType implType)
mfxModuleHandle mfx_dll_load(const wchar_t *pFileName) {
mfxModuleHandle hModule = (mfxModuleHandle)0;
// check error(s)
if (NULL == pFileName) {
return NULL;
}
#if !defined(MEDIASDK_UWP_DISPATCHER)
// set the silent error mode
DWORD prevErrorMode = 0;
#if (_WIN32_WINNT >= 0x0600)
SetThreadErrorMode(SEM_FAILCRITICALERRORS, &prevErrorMode);
#else
prevErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
#endif
#endif // !defined(MEDIASDK_UWP_DISPATCHER)
// load the library's module
#if !defined(MEDIASDK_ARM_LOADER)
hModule = LoadLibraryExW(pFileName, NULL, 0);
#endif
#if !defined(MEDIASDK_UWP_DISPATCHER)
// set the previous error mode
#if (_WIN32_WINNT >= 0x0600)
SetThreadErrorMode(prevErrorMode, NULL);
#else
SetErrorMode(prevErrorMode);
#endif
#endif // !defined(MEDIASDK_UWP_DISPATCHER)
return hModule;
} // mfxModuleHandle mfx_dll_load(const wchar_t *pFileName)
mfxFunctionPointer mfx_dll_get_addr(mfxModuleHandle handle, const char *pFunctionName) {
if (NULL == handle) {
return NULL;
}
return (mfxFunctionPointer)GetProcAddress((HMODULE)handle, pFunctionName);
} // mfxFunctionPointer mfx_dll_get_addr(mfxModuleHandle handle, const char *pFunctionName)
bool mfx_dll_free(mfxModuleHandle handle) {
if (NULL == handle) {
return true;
}
BOOL bRes = FreeLibrary((HMODULE)handle);
return !!bRes;
} // bool mfx_dll_free(mfxModuleHandle handle)
#if !defined(MEDIASDK_UWP_DISPATCHER)
mfxModuleHandle mfx_get_dll_handle(const wchar_t *pFileName) {
mfxModuleHandle hModule = (mfxModuleHandle)0;
// check error(s)
if (NULL == pFileName) {
return NULL;
}
// set the silent error mode
DWORD prevErrorMode = 0;
#if (_WIN32_WINNT >= 0x0600)
SetThreadErrorMode(SEM_FAILCRITICALERRORS, &prevErrorMode);
#else
prevErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
#endif
// load the library's module
GetModuleHandleExW(0, pFileName, (HMODULE *)&hModule);
// set the previous error mode
#if (_WIN32_WINNT >= 0x0600)
SetThreadErrorMode(prevErrorMode, NULL);
#else
SetErrorMode(prevErrorMode);
#endif
return hModule;
}
#endif //!defined(MEDIASDK_UWP_DISPATCHER)
} // namespace MFX
@@ -0,0 +1,36 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#ifndef LIBVPL_SRC_WINDOWS_MFX_LOAD_DLL_H_
#define LIBVPL_SRC_WINDOWS_MFX_LOAD_DLL_H_
#include "src/windows/mfx_dispatcher.h"
namespace MFX {
//
// declare DLL loading routines
//
mfxStatus mfx_get_rt_dll_name(wchar_t *pPath, size_t pathSize);
mfxStatus mfx_get_default_dll_name(wchar_t *pPath, size_t pathSize, eMfxImplType implType);
mfxStatus mfx_get_default_vpl_dll_name(wchar_t *pPath, size_t pathSize);
mfxStatus mfx_get_default_plugin_name(wchar_t *pPath, size_t pathSize, eMfxImplType implType);
#if defined(MEDIASDK_UWP_DISPATCHER)
mfxStatus mfx_get_default_intel_gfx_api_dll_name(wchar_t *pPath, size_t pathSize);
#endif
mfxStatus mfx_get_default_audio_dll_name(wchar_t *pPath, size_t pathSize, eMfxImplType implType);
mfxModuleHandle mfx_dll_load(const wchar_t *file_name);
//increments reference counter
mfxModuleHandle mfx_get_dll_handle(const wchar_t *file_name);
mfxFunctionPointer mfx_dll_get_addr(mfxModuleHandle handle, const char *func_name);
bool mfx_dll_free(mfxModuleHandle handle);
} // namespace MFX
#endif // LIBVPL_SRC_WINDOWS_MFX_LOAD_DLL_H_
@@ -0,0 +1,159 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#pragma once
#include <exception>
#include "vpl/mfxstructures.h"
namespace MFX {
template <class T>
class iterator_tmpl {
template <class U>
friend class MFXVector;
mfxU32 mIndex;
T *mRecords;
iterator_tmpl(mfxU32 index, T *records) : mIndex(index), mRecords(records) {}
public:
iterator_tmpl() : mIndex(), mRecords() {}
bool operator==(const iterator_tmpl<T> &that) const {
return mIndex == that.mIndex;
}
bool operator!=(const iterator_tmpl<T> &that) const {
return mIndex != that.mIndex;
}
mfxU32 operator-(const iterator_tmpl<T> &that) const {
return mIndex - that.mIndex;
}
iterator_tmpl<T> &operator++() {
mIndex++;
return *this;
}
iterator_tmpl<T> &operator++(int) {
mIndex++;
return *this;
}
T &operator*() {
return mRecords[mIndex];
}
T *operator->() {
return mRecords + mIndex;
}
};
class MFXVectorRangeError : public std::exception {};
template <class T>
class MFXVector {
T *mRecords;
mfxU32 mNrecords;
public:
MFXVector() : mRecords(), mNrecords() {}
MFXVector(const MFXVector &rhs) : mRecords(), mNrecords() {
insert(end(), rhs.begin(), rhs.end());
}
MFXVector &operator=(const MFXVector &rhs) {
if (this != &rhs) {
clear();
insert(end(), rhs.begin(), rhs.end());
}
return *this;
}
virtual ~MFXVector() {
clear();
}
typedef iterator_tmpl<T> iterator;
iterator begin() const {
return iterator(0u, mRecords);
}
iterator end() const {
return iterator(mNrecords, mRecords);
}
void insert(iterator where, iterator beg_iter, iterator end_iter) {
mfxU32 elementsToInsert = (end_iter - beg_iter);
if (!elementsToInsert) {
return;
}
if (where.mIndex > mNrecords) {
throw MFXVectorRangeError();
}
T *newRecords = new T[mNrecords + elementsToInsert]();
mfxU32 i = 0;
// save left
for (; i < where.mIndex; i++) {
newRecords[i] = mRecords[i];
}
// insert
for (; beg_iter != end_iter; beg_iter++, i++) {
newRecords[i] = *beg_iter;
}
//save right
for (; i < mNrecords + elementsToInsert; i++) {
newRecords[i] = mRecords[i - elementsToInsert];
}
delete[] mRecords;
mRecords = newRecords;
mNrecords = i;
}
T &operator[](mfxU32 idx) {
return mRecords[idx];
}
void push_back(const T &obj) {
T *newRecords = new T[mNrecords + 1]();
mfxU32 i = 0;
for (; i < mNrecords; i++) {
newRecords[i] = mRecords[i];
}
newRecords[i] = obj;
delete[] mRecords;
mRecords = newRecords;
mNrecords = i + 1;
}
void erase(iterator at) {
if (at.mIndex >= mNrecords) {
throw MFXVectorRangeError();
}
mNrecords--;
mfxU32 i = at.mIndex;
for (; i != mNrecords; i++) {
mRecords[i] = mRecords[i + 1];
}
//destroy last element
mRecords[i] = T();
}
void resize(mfxU32 nSize) {
T *newRecords = new T[nSize]();
for (mfxU32 i = 0; i < mNrecords; i++) {
newRecords[i] = mRecords[i];
}
delete[] mRecords;
mRecords = newRecords;
mNrecords = nSize;
}
mfxU32 size() const {
return mNrecords;
}
void clear() {
delete[] mRecords;
mRecords = 0;
mNrecords = 0;
}
bool empty() {
return !mRecords;
}
T *data() const {
return mRecords;
}
};
} // namespace MFX
@@ -0,0 +1,201 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#if !defined(MEDIASDK_UWP_DISPATCHER)
#include "src/windows/mfx_win_reg_key.h"
#include "src/windows/mfx_dispatcher_log.h"
#define TRACE_WINREG_ERROR(str, ...) DISPATCHER_LOG_ERROR((("[WINREG]: " str), __VA_ARGS__))
namespace MFX {
WinRegKey::WinRegKey(void) {
m_hKey = (HKEY)0;
} // WinRegKey::WinRegKey(void)
WinRegKey::~WinRegKey(void) {
Release();
} // WinRegKey::~WinRegKey(void)
void WinRegKey::Release(void) {
// close the opened key
if (m_hKey) {
RegCloseKey(m_hKey);
}
m_hKey = (HKEY)0;
} // void WinRegKey::Release(void)
bool WinRegKey::Open(HKEY hRootKey, const wchar_t *pSubKey, REGSAM samDesired) {
LONG lRes;
HKEY hTemp;
//
// All operation are performed in this order by intention.
// It makes possible to reopen the keys, using itself as a base.
//
// try to the open registry key
lRes = RegOpenKeyExW(hRootKey, pSubKey, 0, samDesired, &hTemp);
if (ERROR_SUCCESS != lRes) {
DISPATCHER_LOG_OPERATION(SetLastError(lRes));
TRACE_WINREG_ERROR("Opening key \"%s\\%S\" : RegOpenKeyExW()==0x%x\n",
(HKEY_LOCAL_MACHINE == hRootKey) ? ("HKEY_LOCAL_MACHINE")
: (HKEY_CURRENT_USER == hRootKey) ? ("HKEY_CURRENT_USER")
: "UNSUPPORTED_KEY",
pSubKey,
GetLastError());
return false;
}
// release the object before initialization
Release();
// save the handle
m_hKey = hTemp;
return true;
} // bool WinRegKey::Open(HKEY hRootKey, const wchar_t *pSubKey, REGSAM samDesired)
bool WinRegKey::Open(WinRegKey &rootKey, const wchar_t *pSubKey, REGSAM samDesired) {
return Open(rootKey.m_hKey, pSubKey, samDesired);
} // bool WinRegKey::Open(WinRegKey &rootKey, const wchar_t *pSubKey, REGSAM samDesired)
bool WinRegKey::QueryValueSize(const wchar_t *pValueName, DWORD type, LPDWORD pcbData) {
DWORD keyType = type;
LONG lRes;
// query the value
lRes = RegQueryValueExW(m_hKey, pValueName, NULL, &keyType, 0, pcbData);
if (ERROR_SUCCESS != lRes) {
DISPATCHER_LOG_OPERATION(SetLastError(lRes));
TRACE_WINREG_ERROR("Querying \"%S\" : RegQueryValueExA()==0x%x\n",
pValueName,
GetLastError());
return false;
}
return true;
}
bool WinRegKey::Query(const wchar_t *pValueName, DWORD type, LPBYTE pData, LPDWORD pcbData) {
DWORD keyType = type;
LONG lRes;
DWORD dstSize = (pcbData) ? (*pcbData) : (0);
// According to docs for RegQueryValueExW: "The lpcbData parameter can be NULL only if lpData is NULL."
if (pData && !pcbData)
return false;
// query the value
lRes = RegQueryValueExW(m_hKey, pValueName, NULL, &keyType, pData, pcbData);
if (ERROR_SUCCESS != lRes) {
DISPATCHER_LOG_OPERATION(SetLastError(lRes));
TRACE_WINREG_ERROR("Querying \"%S\" : RegQueryValueExA()==0x%x\n",
pValueName,
GetLastError());
return false;
}
// check the type
if (keyType != type) {
TRACE_WINREG_ERROR("Querying \"%S\" : expectedType=%d, returned=%d\n",
pValueName,
type,
keyType);
return false;
}
// terminate the string only if pointers not NULL
if ((REG_SZ == type || REG_EXPAND_SZ == type) && NULL != pData && NULL != pcbData) {
wchar_t *pString = (wchar_t *)pData;
size_t NullEndingSizeBytes = sizeof(wchar_t); // size of string termination null character
if (dstSize < NullEndingSizeBytes) {
TRACE_WINREG_ERROR("Querying \"%S\" : buffer is too small for null-terminated string",
pValueName);
return false;
}
size_t maxStringLengthBytes = dstSize - NullEndingSizeBytes;
size_t maxStringIndex = dstSize / sizeof(wchar_t) - 1;
size_t lastIndex =
(maxStringLengthBytes < *pcbData) ? (maxStringIndex) : (*pcbData) / sizeof(wchar_t);
pString[lastIndex] = (wchar_t)0;
}
else if (REG_MULTI_SZ == type && NULL != pData && NULL != pcbData) {
wchar_t *pString = (wchar_t *)pData;
size_t NullEndingSizeBytes =
sizeof(wchar_t) * 2; // size of string termination null characters
if (dstSize < NullEndingSizeBytes) {
TRACE_WINREG_ERROR(
"Querying \"%S\" : buffer is too small for multi-line null-terminated string",
pValueName);
return false;
}
size_t maxStringLengthBytes = dstSize - NullEndingSizeBytes;
size_t maxStringIndex = dstSize / sizeof(wchar_t) - 1;
size_t lastIndex =
(maxStringLengthBytes < *pcbData) ? (maxStringIndex) : (*pcbData) / sizeof(wchar_t) + 1;
// last 2 bytes should be 0 in case of REG_MULTI_SZ
pString[lastIndex] = pString[lastIndex - 1] = (wchar_t)0;
}
return true;
} // bool WinRegKey::Query(const wchar_t *pValueName, DWORD type, LPBYTE pData, LPDWORD pcbData)
bool WinRegKey::EnumValue(DWORD index, wchar_t *pValueName, LPDWORD pcchValueName, LPDWORD pType) {
LONG lRes;
// enum the values
lRes = RegEnumValueW(m_hKey, index, pValueName, pcchValueName, 0, pType, NULL, NULL);
if (ERROR_SUCCESS != lRes) {
DISPATCHER_LOG_OPERATION(SetLastError(lRes));
return false;
}
return true;
} // bool WinRegKey::EnumValue(DWORD index, wchar_t *pValueName, LPDWORD pcchValueName, LPDWORD pType)
bool WinRegKey::EnumKey(DWORD index, wchar_t *pValueName, LPDWORD pcchValueName) {
LONG lRes;
// enum the keys
lRes = RegEnumKeyExW(m_hKey, index, pValueName, pcchValueName, NULL, NULL, NULL, NULL);
if (ERROR_SUCCESS != lRes) {
DISPATCHER_LOG_OPERATION(SetLastError(lRes));
TRACE_WINREG_ERROR("EnumKey with index=%d: RegEnumKeyExW()==0x%x\n", index, GetLastError());
return false;
}
return true;
} // bool WinRegKey::EnumKey(DWORD index, wchar_t *pValueName, LPDWORD pcchValueName)
bool WinRegKey::QueryInfo(LPDWORD lpcSubkeys) {
LONG lRes;
lRes = RegQueryInfoKeyW(m_hKey, NULL, 0, 0, lpcSubkeys, 0, 0, 0, 0, 0, 0, 0);
if (ERROR_SUCCESS != lRes) {
TRACE_WINREG_ERROR("RegQueryInfoKeyW()==0x%x\n", lRes);
return false;
}
return true;
} //bool QueryInfo(LPDWORD lpcSubkeys);
} // namespace MFX
#endif // #if !defined(MEDIASDK_UWP_DISPATCHER)
@@ -0,0 +1,99 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#ifndef LIBVPL_SRC_WINDOWS_MFX_WIN_REG_KEY_H_
#define LIBVPL_SRC_WINDOWS_MFX_WIN_REG_KEY_H_
#include <windows.h>
#include "src/windows/mfx_dispatcher_log.h"
#include "vpl/mfxcommon.h"
#if !defined(MEDIASDK_UWP_DISPATCHER)
namespace MFX {
template <class T>
struct RegKey {};
template <>
struct RegKey<bool> {
enum { type = REG_DWORD };
};
template <>
struct RegKey<mfxU32> {
enum { type = REG_DWORD };
};
template <>
struct RegKey<mfxVersion> {
enum { type = REG_DWORD };
};
template <>
struct RegKey<char *> {
enum { type = REG_SZ };
};
template <>
struct RegKey<wchar_t *> {
enum { type = REG_SZ };
};
class WinRegKey {
public:
// Default constructor
WinRegKey(void);
// Destructor
~WinRegKey(void);
// Open a registry key
bool Open(HKEY hRootKey, const wchar_t *pSubKey, REGSAM samDesired);
bool Open(WinRegKey &rootKey, const wchar_t *pSubKey, REGSAM samDesired);
// Query value
bool QueryInfo(LPDWORD lpcSubkeys);
bool QueryValueSize(const wchar_t *pValueName, DWORD type, LPDWORD pcbData);
bool Query(const wchar_t *pValueName, DWORD type, LPBYTE pData, LPDWORD pcbData);
bool Query(const wchar_t *pValueName, wchar_t *pData, mfxU32 &nData) {
DWORD dw = (DWORD)nData;
if (!Query(pValueName, RegKey<wchar_t *>::type, (LPBYTE)pData, &dw)) {
return false;
}
nData = dw;
return true;
}
// Enumerate value names
bool EnumValue(DWORD index, wchar_t *pValueName, LPDWORD pcchValueName, LPDWORD pType);
bool EnumKey(DWORD index, wchar_t *pValueName, LPDWORD pcchValueName);
protected:
// Release the object
void Release(void);
HKEY m_hKey; // (HKEY) handle to the opened key
private:
// unimplemented by intent to make this class non-copyable
WinRegKey(const WinRegKey &);
void operator=(const WinRegKey &);
};
template <class T>
inline bool QueryKey(WinRegKey &key, const wchar_t *pValueName, T &data) {
DWORD size = sizeof(data);
return key.Query(pValueName, RegKey<T>::type, (LPBYTE)&data, &size);
}
template <>
inline bool QueryKey<bool>(WinRegKey &key, const wchar_t *pValueName, bool &data) {
mfxU32 value = 0;
bool bRes = QueryKey(key, pValueName, value);
data = (1 == value);
return bRes;
}
} // namespace MFX
#endif // #if !defined(MEDIASDK_UWP_DISPATCHER)
#endif // LIBVPL_SRC_WINDOWS_MFX_WIN_REG_KEY_H_
@@ -0,0 +1,231 @@
/*############################################################################
# Copyright (C) Intel Corporation
#
# SPDX-License-Identifier: MIT
############################################################################*/
#ifndef LIBVPL_SRC_WINDOWS_MFXVIDEO___H_
#define LIBVPL_SRC_WINDOWS_MFXVIDEO___H_
#include "vpl/mfxvideo.h"
class MFXVideoSession {
public:
MFXVideoSession(void) {
m_session = (mfxSession)0;
}
virtual ~MFXVideoSession(void) {
Close();
}
virtual mfxStatus Init(mfxIMPL impl, mfxVersion *ver) {
return MFXInit(impl, ver, &m_session);
}
virtual mfxStatus InitEx(mfxInitParam par) {
return MFXInitEx(par, &m_session);
}
virtual mfxStatus Close(void) {
mfxStatus mfxRes;
mfxRes = MFXClose(m_session);
m_session = (mfxSession)0;
return mfxRes;
}
virtual mfxStatus QueryIMPL(mfxIMPL *impl) {
return MFXQueryIMPL(m_session, impl);
}
virtual mfxStatus QueryVersion(mfxVersion *version) {
return MFXQueryVersion(m_session, version);
}
virtual mfxStatus JoinSession(mfxSession child_session) {
return MFXJoinSession(m_session, child_session);
}
virtual mfxStatus DisjoinSession() {
return MFXDisjoinSession(m_session);
}
virtual mfxStatus CloneSession(mfxSession *clone) {
return MFXCloneSession(m_session, clone);
}
virtual mfxStatus SetPriority(mfxPriority priority) {
return MFXSetPriority(m_session, priority);
}
virtual mfxStatus GetPriority(mfxPriority *priority) {
return MFXGetPriority(m_session, priority);
}
virtual mfxStatus SetFrameAllocator(mfxFrameAllocator *allocator) {
return MFXVideoCORE_SetFrameAllocator(m_session, allocator);
}
virtual mfxStatus SetHandle(mfxHandleType type, mfxHDL hdl) {
return MFXVideoCORE_SetHandle(m_session, type, hdl);
}
virtual mfxStatus GetHandle(mfxHandleType type, mfxHDL *hdl) {
return MFXVideoCORE_GetHandle(m_session, type, hdl);
}
virtual mfxStatus QueryPlatform(mfxPlatform *platform) {
return MFXVideoCORE_QueryPlatform(m_session, platform);
}
virtual mfxStatus SyncOperation(mfxSyncPoint syncp, mfxU32 wait) {
return MFXVideoCORE_SyncOperation(m_session, syncp, wait);
}
virtual operator mfxSession(void) {
return m_session;
}
protected:
mfxSession m_session; // (mfxSession) handle to the owning session
private:
MFXVideoSession(const MFXVideoSession &);
void operator=(MFXVideoSession &);
};
class MFXVideoENCODE {
public:
explicit MFXVideoENCODE(mfxSession session) {
m_session = session;
}
virtual ~MFXVideoENCODE(void) {
Close();
}
virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) {
return MFXVideoENCODE_Query(m_session, in, out);
}
virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest *request) {
return MFXVideoENCODE_QueryIOSurf(m_session, par, request);
}
virtual mfxStatus Init(mfxVideoParam *par) {
return MFXVideoENCODE_Init(m_session, par);
}
virtual mfxStatus Reset(mfxVideoParam *par) {
return MFXVideoENCODE_Reset(m_session, par);
}
virtual mfxStatus Close(void) {
return MFXVideoENCODE_Close(m_session);
}
virtual mfxStatus GetVideoParam(mfxVideoParam *par) {
return MFXVideoENCODE_GetVideoParam(m_session, par);
}
virtual mfxStatus GetEncodeStat(mfxEncodeStat *stat) {
return MFXVideoENCODE_GetEncodeStat(m_session, stat);
}
virtual mfxStatus EncodeFrameAsync(mfxEncodeCtrl *ctrl,
mfxFrameSurface1 *surface,
mfxBitstream *bs,
mfxSyncPoint *syncp) {
return MFXVideoENCODE_EncodeFrameAsync(m_session, ctrl, surface, bs, syncp);
}
protected:
mfxSession m_session; // (mfxSession) handle to the owning session
private:
MFXVideoENCODE(const MFXVideoENCODE &other);
MFXVideoENCODE &operator=(const MFXVideoENCODE &other);
};
class MFXVideoDECODE {
public:
explicit MFXVideoDECODE(mfxSession session) {
m_session = session;
}
virtual ~MFXVideoDECODE(void) {
Close();
}
virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) {
return MFXVideoDECODE_Query(m_session, in, out);
}
virtual mfxStatus DecodeHeader(mfxBitstream *bs, mfxVideoParam *par) {
return MFXVideoDECODE_DecodeHeader(m_session, bs, par);
}
virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest *request) {
return MFXVideoDECODE_QueryIOSurf(m_session, par, request);
}
virtual mfxStatus Init(mfxVideoParam *par) {
return MFXVideoDECODE_Init(m_session, par);
}
virtual mfxStatus Reset(mfxVideoParam *par) {
return MFXVideoDECODE_Reset(m_session, par);
}
virtual mfxStatus Close(void) {
return MFXVideoDECODE_Close(m_session);
}
virtual mfxStatus GetVideoParam(mfxVideoParam *par) {
return MFXVideoDECODE_GetVideoParam(m_session, par);
}
virtual mfxStatus GetDecodeStat(mfxDecodeStat *stat) {
return MFXVideoDECODE_GetDecodeStat(m_session, stat);
}
virtual mfxStatus GetPayload(mfxU64 *ts, mfxPayload *payload) {
return MFXVideoDECODE_GetPayload(m_session, ts, payload);
}
virtual mfxStatus SetSkipMode(mfxSkipMode mode) {
return MFXVideoDECODE_SetSkipMode(m_session, mode);
}
virtual mfxStatus DecodeFrameAsync(mfxBitstream *bs,
mfxFrameSurface1 *surface_work,
mfxFrameSurface1 **surface_out,
mfxSyncPoint *syncp) {
return MFXVideoDECODE_DecodeFrameAsync(m_session, bs, surface_work, surface_out, syncp);
}
protected:
mfxSession m_session; // (mfxSession) handle to the owning session
private:
MFXVideoDECODE(const MFXVideoDECODE &other);
MFXVideoDECODE &operator=(const MFXVideoDECODE &other);
};
class MFXVideoVPP {
public:
explicit MFXVideoVPP(mfxSession session) {
m_session = session;
}
virtual ~MFXVideoVPP(void) {
Close();
}
virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) {
return MFXVideoVPP_Query(m_session, in, out);
}
virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest request[2]) {
return MFXVideoVPP_QueryIOSurf(m_session, par, request);
}
virtual mfxStatus Init(mfxVideoParam *par) {
return MFXVideoVPP_Init(m_session, par);
}
virtual mfxStatus Reset(mfxVideoParam *par) {
return MFXVideoVPP_Reset(m_session, par);
}
virtual mfxStatus Close(void) {
return MFXVideoVPP_Close(m_session);
}
virtual mfxStatus GetVideoParam(mfxVideoParam *par) {
return MFXVideoVPP_GetVideoParam(m_session, par);
}
virtual mfxStatus GetVPPStat(mfxVPPStat *stat) {
return MFXVideoVPP_GetVPPStat(m_session, stat);
}
virtual mfxStatus RunFrameVPPAsync(mfxFrameSurface1 *in,
mfxFrameSurface1 *out,
mfxExtVppAuxData *aux,
mfxSyncPoint *syncp) {
return MFXVideoVPP_RunFrameVPPAsync(m_session, in, out, aux, syncp);
}
protected:
mfxSession m_session; // (mfxSession) handle to the owning session
private:
MFXVideoVPP(const MFXVideoVPP &other);
MFXVideoVPP &operator=(const MFXVideoVPP &other);
};
#endif // LIBVPL_SRC_WINDOWS_MFXVIDEO___H_
@@ -0,0 +1,30 @@
#include "winver.h"
#define VER_FILEVERSION @API_VERSION_MAJOR@,@API_VERSION_MINOR@,0,0
#define VER_FILEVERSION_STR "@API_VERSION_MAJOR@.@API_VERSION_MINOR@.0.0\0"
#define VER_PRODUCTVERSION @CMAKE_PROJECT_VERSION_MAJOR@,@CMAKE_PROJECT_VERSION_MINOR@,0,0
#define VER_PRODUCTVERSION_STR "@CMAKE_PROJECT_VERSION_MAJOR@.@CMAKE_PROJECT_VERSION_MINOR@\0"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
PRODUCTVERSION VER_PRODUCTVERSION
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", "Intel\0"
VALUE "FileDescription", "Intel® VPL Dispatcher\0"
VALUE "FileVersion", VER_FILEVERSION_STR
// Copyright year is the first publication date. Subsequent dates are optional
VALUE "LegalCopyright", "Copyright (C) 2021 Intel Corporation\0"
VALUE "ProductName", "VPL\0"
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END