From 3e4bcf06bce76e922b5ce2c034c89ef1fb4ededa Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Mon, 12 Oct 2015 01:22:01 -0700 Subject: [PATCH] obs-qsv11: Add native obs-studio QSV encoder --- plugins/CMakeLists.txt | 1 + plugins/obs-qsv11/CMakeLists.txt | 86 + plugins/obs-qsv11/QSV_Encoder.cpp | 211 +++ plugins/obs-qsv11/QSV_Encoder.h | 149 ++ plugins/obs-qsv11/QSV_Encoder_Internal.cpp | 596 +++++++ plugins/obs-qsv11/QSV_Encoder_Internal.h | 112 ++ plugins/obs-qsv11/bits/linux_defs.h | 19 + plugins/obs-qsv11/bits/windows_defs.h | 16 + plugins/obs-qsv11/common_directx11.cpp | 487 ++++++ plugins/obs-qsv11/common_directx11.h | 39 + plugins/obs-qsv11/common_utils.cpp | 306 ++++ plugins/obs-qsv11/common_utils.h | 109 ++ plugins/obs-qsv11/common_utils_windows.cpp | 104 ++ plugins/obs-qsv11/data/locale/en-US.ini | 11 + .../libmfx/include/mfx_critical_section.h | 76 + .../obs-qsv11/libmfx/include/mfx_dispatcher.h | 213 +++ .../libmfx/include/mfx_dispatcher_defs.h | 85 + .../libmfx/include/mfx_dispatcher_log.h | 306 ++++ .../libmfx/include/mfx_dxva2_device.h | 210 +++ .../include/mfx_exposed_functions_list.h | 142 ++ .../libmfx/include/mfx_library_iterator.h | 161 ++ .../obs-qsv11/libmfx/include/mfx_load_dll.h | 59 + .../libmfx/include/mfx_load_plugin.h | 93 ++ .../libmfx/include/mfx_plugin_hive.h | 132 ++ plugins/obs-qsv11/libmfx/include/mfx_vector.h | 220 +++ .../libmfx/include/mfx_win_reg_key.h | 116 ++ .../include/mfxaudio_exposed_functions_list.h | 81 + .../include/msdk/include/mfxastructures.h | 172 ++ .../libmfx/include/msdk/include/mfxaudio++.h | 113 ++ .../libmfx/include/msdk/include/mfxaudio.h | 70 + .../libmfx/include/msdk/include/mfxcommon.h | 159 ++ .../libmfx/include/msdk/include/mfxdefs.h | 153 ++ .../libmfx/include/msdk/include/mfxenc.h | 80 + .../libmfx/include/msdk/include/mfxjpeg.h | 107 ++ .../libmfx/include/msdk/include/mfxmvc.h | 109 ++ .../libmfx/include/msdk/include/mfxpak.h | 78 + .../libmfx/include/msdk/include/mfxplugin++.h | 719 +++++++++ .../libmfx/include/msdk/include/mfxplugin.h | 206 +++ .../libmfx/include/msdk/include/mfxsession.h | 60 + .../include/msdk/include/mfxstructures.h | 1379 +++++++++++++++++ .../libmfx/include/msdk/include/mfxvideo++.h | 197 +++ .../libmfx/include/msdk/include/mfxvideo.h | 112 ++ .../include/msdk/include/mfxvstructures.h | 32 + plugins/obs-qsv11/libmfx/src/main.cpp | 937 +++++++++++ .../libmfx/src/mfx_critical_section.cpp | 88 ++ .../obs-qsv11/libmfx/src/mfx_dispatcher.cpp | 349 +++++ .../libmfx/src/mfx_dispatcher_log.cpp | 449 ++++++ .../obs-qsv11/libmfx/src/mfx_dxva2_device.cpp | 558 +++++++ .../libmfx/src/mfx_function_table.cpp | 143 ++ .../libmfx/src/mfx_library_iterator.cpp | 475 ++++++ plugins/obs-qsv11/libmfx/src/mfx_load_dll.cpp | 241 +++ .../obs-qsv11/libmfx/src/mfx_load_plugin.cpp | 458 ++++++ .../obs-qsv11/libmfx/src/mfx_plugin_hive.cpp | 500 ++++++ .../obs-qsv11/libmfx/src/mfx_win_reg_key.cpp | 228 +++ plugins/obs-qsv11/obs-qsv11-plugin-main.c | 86 + plugins/obs-qsv11/obs-qsv11.c | 687 ++++++++ 56 files changed, 13085 insertions(+) create mode 100644 plugins/obs-qsv11/CMakeLists.txt create mode 100644 plugins/obs-qsv11/QSV_Encoder.cpp create mode 100644 plugins/obs-qsv11/QSV_Encoder.h create mode 100644 plugins/obs-qsv11/QSV_Encoder_Internal.cpp create mode 100644 plugins/obs-qsv11/QSV_Encoder_Internal.h create mode 100644 plugins/obs-qsv11/bits/linux_defs.h create mode 100644 plugins/obs-qsv11/bits/windows_defs.h create mode 100644 plugins/obs-qsv11/common_directx11.cpp create mode 100644 plugins/obs-qsv11/common_directx11.h create mode 100644 plugins/obs-qsv11/common_utils.cpp create mode 100644 plugins/obs-qsv11/common_utils.h create mode 100644 plugins/obs-qsv11/common_utils_windows.cpp create mode 100644 plugins/obs-qsv11/data/locale/en-US.ini create mode 100644 plugins/obs-qsv11/libmfx/include/mfx_critical_section.h create mode 100644 plugins/obs-qsv11/libmfx/include/mfx_dispatcher.h create mode 100644 plugins/obs-qsv11/libmfx/include/mfx_dispatcher_defs.h create mode 100644 plugins/obs-qsv11/libmfx/include/mfx_dispatcher_log.h create mode 100644 plugins/obs-qsv11/libmfx/include/mfx_dxva2_device.h create mode 100644 plugins/obs-qsv11/libmfx/include/mfx_exposed_functions_list.h create mode 100644 plugins/obs-qsv11/libmfx/include/mfx_library_iterator.h create mode 100644 plugins/obs-qsv11/libmfx/include/mfx_load_dll.h create mode 100644 plugins/obs-qsv11/libmfx/include/mfx_load_plugin.h create mode 100644 plugins/obs-qsv11/libmfx/include/mfx_plugin_hive.h create mode 100644 plugins/obs-qsv11/libmfx/include/mfx_vector.h create mode 100644 plugins/obs-qsv11/libmfx/include/mfx_win_reg_key.h create mode 100644 plugins/obs-qsv11/libmfx/include/mfxaudio_exposed_functions_list.h create mode 100644 plugins/obs-qsv11/libmfx/include/msdk/include/mfxastructures.h create mode 100644 plugins/obs-qsv11/libmfx/include/msdk/include/mfxaudio++.h create mode 100644 plugins/obs-qsv11/libmfx/include/msdk/include/mfxaudio.h create mode 100644 plugins/obs-qsv11/libmfx/include/msdk/include/mfxcommon.h create mode 100644 plugins/obs-qsv11/libmfx/include/msdk/include/mfxdefs.h create mode 100644 plugins/obs-qsv11/libmfx/include/msdk/include/mfxenc.h create mode 100644 plugins/obs-qsv11/libmfx/include/msdk/include/mfxjpeg.h create mode 100644 plugins/obs-qsv11/libmfx/include/msdk/include/mfxmvc.h create mode 100644 plugins/obs-qsv11/libmfx/include/msdk/include/mfxpak.h create mode 100644 plugins/obs-qsv11/libmfx/include/msdk/include/mfxplugin++.h create mode 100644 plugins/obs-qsv11/libmfx/include/msdk/include/mfxplugin.h create mode 100644 plugins/obs-qsv11/libmfx/include/msdk/include/mfxsession.h create mode 100644 plugins/obs-qsv11/libmfx/include/msdk/include/mfxstructures.h create mode 100644 plugins/obs-qsv11/libmfx/include/msdk/include/mfxvideo++.h create mode 100644 plugins/obs-qsv11/libmfx/include/msdk/include/mfxvideo.h create mode 100644 plugins/obs-qsv11/libmfx/include/msdk/include/mfxvstructures.h create mode 100644 plugins/obs-qsv11/libmfx/src/main.cpp create mode 100644 plugins/obs-qsv11/libmfx/src/mfx_critical_section.cpp create mode 100644 plugins/obs-qsv11/libmfx/src/mfx_dispatcher.cpp create mode 100644 plugins/obs-qsv11/libmfx/src/mfx_dispatcher_log.cpp create mode 100644 plugins/obs-qsv11/libmfx/src/mfx_dxva2_device.cpp create mode 100644 plugins/obs-qsv11/libmfx/src/mfx_function_table.cpp create mode 100644 plugins/obs-qsv11/libmfx/src/mfx_library_iterator.cpp create mode 100644 plugins/obs-qsv11/libmfx/src/mfx_load_dll.cpp create mode 100644 plugins/obs-qsv11/libmfx/src/mfx_load_plugin.cpp create mode 100644 plugins/obs-qsv11/libmfx/src/mfx_plugin_hive.cpp create mode 100644 plugins/obs-qsv11/libmfx/src/mfx_win_reg_key.cpp create mode 100644 plugins/obs-qsv11/obs-qsv11-plugin-main.c create mode 100644 plugins/obs-qsv11/obs-qsv11.c diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index d73838e79..879118349 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -9,6 +9,7 @@ if(WIN32) add_subdirectory(win-capture) add_subdirectory(decklink/win) add_subdirectory(win-mf) + add_subdirectory(obs-qsv11) elseif(APPLE) add_subdirectory(coreaudio-encoder) add_subdirectory(mac-avcapture) diff --git a/plugins/obs-qsv11/CMakeLists.txt b/plugins/obs-qsv11/CMakeLists.txt new file mode 100644 index 000000000..611c7aa47 --- /dev/null +++ b/plugins/obs-qsv11/CMakeLists.txt @@ -0,0 +1,86 @@ +project(obs-qsv11) + +include_directories(libmfx/include/msdk/include) +include_directories(libmfx/include) + +set(obs-qsv11_libmfx_SOURCES + libmfx/src/main.cpp + libmfx/src/mfx_critical_section.cpp + libmfx/src/mfx_dispatcher.cpp + libmfx/src/mfx_dispatcher_log.cpp + libmfx/src/mfx_dxva2_device.cpp + libmfx/src/mfx_function_table.cpp + libmfx/src/mfx_library_iterator.cpp + libmfx/src/mfx_load_dll.cpp + libmfx/src/mfx_load_plugin.cpp + libmfx/src/mfx_plugin_hive.cpp + libmfx/src/mfx_win_reg_key.cpp + ) + +set(obs-qsv11_libmfx_HEADERS + libmfx/include/msdk/include/mfxastructures.h + libmfx/include/msdk/include/mfxaudio.h + libmfx/include/msdk/include/mfxaudio++.h + libmfx/include/msdk/include/mfxcommon.h + libmfx/include/msdk/include/mfxdefs.h + libmfx/include/msdk/include/mfxjpeg.h + libmfx/include/msdk/include/mfxmvc.h + libmfx/include/msdk/include/mfxplugin.h + libmfx/include/msdk/include/mfxplugin++.h + libmfx/include/msdk/include/mfxsession.h + libmfx/include/msdk/include/mfxstructures.h + libmfx/include/msdk/include/mfxvideo.h + libmfx/include/msdk/include/mfxvideo++.h + libmfx/include/msdk/include/mfxvstructures.h + libmfx/include/mfx_critical_section.h + libmfx/include/mfx_dispatcher.h + libmfx/include/mfx_dispatcher_defs.h + libmfx/include/mfx_dispatcher_log.h + libmfx/include/mfx_dxva2_device.h + libmfx/include/mfx_exposed_functions_list.h + libmfx/include/mfx_library_iterator.h + libmfx/include/mfx_load_dll.h + libmfx/include/mfx_load_plugin.h + libmfx/include/mfx_plugin_hive.h + libmfx/include/mfx_vector.h + libmfx/include/mfx_win_reg_key.h + libmfx/include/mfxaudio_exposed_functions_list.h + ) + +set(obs-qsv11_SOURCES + common_directx11.cpp + common_utils.cpp + common_utils_windows.cpp + QSV_Encoder.cpp + QSV_Encoder_Internal.cpp + obs-qsv11.c + obs-qsv11-plugin-main.c) + +set(obs-qsv11_HEADERS + bits/linux_defs.h + bits/windows_defs.h + common_directx11.h + common_utils.h + QSV_Encoder.h + QSV_Encoder_Internal.h) + +add_library(obs-qsv11 MODULE + ${obs-qsv11_SOURCES} + ${obs-qsv11_HEADERS} + ${obs-qsv11_libmfx_SOURCES} + ${obs-qsv11_libmfx_HEADERS} + ) +target_link_libraries(obs-qsv11 + libobs + d3d11 + dxgi + ) + +target_compile_definitions(obs-qsv11 PRIVATE DX11_D3D) + +source_group("obs-qsv11\\Source Files" FILES ${obs-qsv11_SOURCES}) +source_group("obs-qsv11\\Header Files" FILES ${obs-qsv11_HEADERS}) +source_group("libmfx\\Source Files" FILES ${obs-qsv11_libmfx_SOURCES}) +source_group("libmfx\\Header Files" FILES ${obs-qsv11_libmfx_HEADERS}) + +install_obs_plugin_with_data(obs-qsv11 data) diff --git a/plugins/obs-qsv11/QSV_Encoder.cpp b/plugins/obs-qsv11/QSV_Encoder.cpp new file mode 100644 index 000000000..49ef76000 --- /dev/null +++ b/plugins/obs-qsv11/QSV_Encoder.cpp @@ -0,0 +1,211 @@ +/* + +This file is provided under a dual BSD/GPLv2 license. When using or +redistributing this file, you may do so under either license. + +GPL LICENSE SUMMARY + +Copyright(c) Oct. 2015 Intel Corporation. + +This program is free software; you can redistribute it and/or modify +it under the terms of version 2 of the GNU General Public License as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +Contact Information: + +Seung-Woo Kim, seung-woo.kim@intel.com +705 5th Ave S #500, Seattle, WA 98104 + +BSD LICENSE + +Copyright(c) Intel Corporation. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the +distribution. + +* Neither the name of Intel Corporation nor the names of its +contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +// QSV_Encoder.cpp : Defines the exported functions for the DLL application. +// + +#include "QSV_Encoder.h" +#include "QSV_Encoder_Internal.h" +#include + +QSV_Encoder_Internal *g_pEncoder = NULL; +mfxIMPL impl = MFX_IMPL_HARDWARE_ANY; +mfxVersion ver = {{0, 1}}; // for backward compatibility + +void qsv_encoder_version(unsigned short *major, unsigned short *minor) +{ + *major = ver.Major; + *minor = ver.Minor; +} + +qsv_t *qsv_encoder_open(qsv_param_t *pParams) +{ + QSV_Encoder_Internal *pEncoder = new QSV_Encoder_Internal(impl, ver); + mfxStatus sts = pEncoder->Open(pParams); + if (sts != MFX_ERR_NONE) { + delete pEncoder; + return NULL; + } + + return (qsv_t *) pEncoder; +} + +int qsv_encoder_headers(qsv_t *pContext, uint8_t **pSPS, uint8_t **pPPS, + uint16_t *pnSPS, uint16_t *pnPPS) +{ + QSV_Encoder_Internal *pEncoder = (QSV_Encoder_Internal *)pContext; + pEncoder->GetSPSPPS(pSPS, pPPS, pnSPS, pnPPS); + + return 0; +} + +int qsv_encoder_encode(qsv_t * pContext, uint64_t ts, uint8_t *pDataY, + uint8_t *pDataUV, uint32_t strideY, uint32_t strideUV, + mfxBitstream **pBS) +{ + QSV_Encoder_Internal *pEncoder = (QSV_Encoder_Internal *)pContext; + mfxStatus sts = MFX_ERR_NONE; + + if (pDataY != NULL && pDataUV != NULL) + sts = pEncoder->Encode(ts, pDataY, pDataUV, strideY, strideUV, + pBS); + + if (sts == MFX_ERR_NONE) + return 0; + else if (sts == MFX_ERR_MORE_DATA) + return 1; + else + return -1; +} + +int qsv_encoder_close(qsv_t *pContext) +{ + QSV_Encoder_Internal *pEncoder = (QSV_Encoder_Internal *)pContext; + delete pEncoder; + + return 0; +} + +/* +int qsv_param_default_preset(qsv_param_t *pParams, const char *preset, + const char *tune) +{ + return 0; +} + +int qsv_param_parse(qsv_param_t *, const char *name, const char *value) +{ + return 0; +} + +int qsv_param_apply_profile(qsv_param_t *, const char *profile) +{ + return 0; +} +*/ + +int qsv_encoder_reconfig(qsv_t *pContext, qsv_param_t *pParams) +{ + QSV_Encoder_Internal *pEncoder = (QSV_Encoder_Internal *)pContext; + mfxStatus sts = pEncoder->Reset(pParams); + + if (sts == MFX_ERR_NONE) + return 0; + else + return -1; +} + +enum qsv_cpu_platform qsv_get_cpu_platform() +{ + using std::string; + + int cpuInfo[4]; + __cpuid(cpuInfo, 0); + + string vendor; + vendor += string((char*)&cpuInfo[1], 4); + vendor += string((char*)&cpuInfo[3], 4); + vendor += string((char*)&cpuInfo[2], 4); + + if (vendor != "GenuineIntel") + return QSV_CPU_PLATFORM_UNKNOWN; + + __cpuid(cpuInfo, 1); + BYTE model = ((cpuInfo[0] >> 4) & 0xF) + ((cpuInfo[0] >> 12) & 0xF0); + BYTE family = ((cpuInfo[0] >> 8) & 0xF) + ((cpuInfo[0] >> 20) & 0xFF); + + // See Intel 64 and IA-32 Architectures Software Developer's Manual, + // Vol 3C Table 35-1 + if (family != 6) + return QSV_CPU_PLATFORM_UNKNOWN; + + switch (model) + { + case 0x1C: + case 0x26: + case 0x27: + case 0x35: + case 0x36: + return QSV_CPU_PLATFORM_BNL; + + case 0x2a: + case 0x2d: + return QSV_CPU_PLATFORM_SNB; + + case 0x3a: + case 0x3e: + return QSV_CPU_PLATFORM_IVB; + + case 0x37: + case 0x4A: + case 0x4D: + case 0x5A: + case 0x5D: + return QSV_CPU_PLATFORM_SLM; + + case 0x4C: + return QSV_CPU_PLATFORM_CHT; + + case 0x3c: + case 0x3f: + case 0x45: + case 0x46: + return QSV_CPU_PLATFORM_HSW; + } + + //assume newer revisions are at least as capable as haswell + return QSV_CPU_PLATFORM_INTEL; +} diff --git a/plugins/obs-qsv11/QSV_Encoder.h b/plugins/obs-qsv11/QSV_Encoder.h new file mode 100644 index 000000000..ffd2a693b --- /dev/null +++ b/plugins/obs-qsv11/QSV_Encoder.h @@ -0,0 +1,149 @@ +/* + +This file is provided under a dual BSD/GPLv2 license. When using or +redistributing this file, you may do so under either license. + +GPL LICENSE SUMMARY + +Copyright(c) Oct. 2015 Intel Corporation. + +This program is free software; you can redistribute it and/or modify +it under the terms of version 2 of the GNU General Public License as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +Contact Information: + +Seung-Woo Kim, seung-woo.kim@intel.com +705 5th Ave S #500, Seattle, WA 98104 + +BSD LICENSE + +Copyright(c) Intel Corporation. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the +distribution. + +* Neither the name of Intel Corporation nor the names of its +contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once + +#include +#include "mfxstructures.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct qsv_rate_control_info { + const char *name; + bool haswell_or_greater; +}; + +static const struct qsv_rate_control_info qsv_ratecontrols[] = { + {"CBR", false}, + {"VBR", false}, + {"VCM", true}, + {"CQP", false}, + {"AVBR", false}, + {"ICQ", true}, + {"LA_ICQ", true}, + {"LA", true}, + {0, false} +}; +static const char * const qsv_profile_names[] = { + "high", + "main", + "baseline", + 0 +}; +static const char * const qsv_usage_names[] = { + "quality", + "balanced", + "speed", + 0 +}; + +typedef struct qsv_t qsv_t; + +typedef struct +{ + mfxU16 nTargetUsage; /* 1 through 7, 1 being best quality and 7 + being the best speed */ + mfxU16 nWidth; /* source picture width */ + mfxU16 nHeight; /* source picture height */ + mfxU16 nAsyncDepth; + mfxU16 nFpsNum; + mfxU16 nFpsDen; + mfxU16 nTargetBitRate; + mfxU16 nMaxBitRate; + mfxU16 nCodecProfile; + mfxU16 nRateControl; + mfxU16 nAccuracy; + mfxU16 nConvergence; + mfxU16 nQPI; + mfxU16 nQPP; + mfxU16 nQPB; + mfxU16 nLADEPTH; + mfxU16 nKeyIntSec; + mfxU16 nbFrames; + mfxU16 nICQQuality; +} qsv_param_t; + +enum qsv_cpu_platform { + QSV_CPU_PLATFORM_UNKNOWN, + QSV_CPU_PLATFORM_BNL, + QSV_CPU_PLATFORM_SNB, + QSV_CPU_PLATFORM_IVB, + QSV_CPU_PLATFORM_SLM, + QSV_CPU_PLATFORM_CHT, + QSV_CPU_PLATFORM_HSW, + QSV_CPU_PLATFORM_INTEL +}; + +int qsv_encoder_close(qsv_t *); +int qsv_param_parse(qsv_param_t *, const char *name, const char *value); +int qsv_param_apply_profile(qsv_param_t *, const char *profile); +int qsv_param_default_preset(qsv_param_t *, const char *preset, + const char *tune); +int qsv_encoder_reconfig(qsv_t *, qsv_param_t *); +void qsv_encoder_version(unsigned short *major, unsigned short *minor); +qsv_t *qsv_encoder_open( qsv_param_t * ); +int qsv_encoder_encode(qsv_t *, uint64_t, uint8_t *, uint8_t *, uint32_t, + uint32_t, mfxBitstream **pBS); +int qsv_encoder_headers(qsv_t *, uint8_t **pSPS, uint8_t **pPPS, + uint16_t *pnSPS, uint16_t *pnPPS); +enum qsv_cpu_platform qsv_get_cpu_platform(); + +#ifdef __cplusplus +} +#endif diff --git a/plugins/obs-qsv11/QSV_Encoder_Internal.cpp b/plugins/obs-qsv11/QSV_Encoder_Internal.cpp new file mode 100644 index 000000000..99e4fcec9 --- /dev/null +++ b/plugins/obs-qsv11/QSV_Encoder_Internal.cpp @@ -0,0 +1,596 @@ +/* + +This file is provided under a dual BSD/GPLv2 license. When using or +redistributing this file, you may do so under either license. + +GPL LICENSE SUMMARY + +Copyright(c) Oct. 2015 Intel Corporation. + +This program is free software; you can redistribute it and/or modify +it under the terms of version 2 of the GNU General Public License as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +Contact Information: + +Seung-Woo Kim, seung-woo.kim@intel.com +705 5th Ave S #500, Seattle, WA 98104 + +BSD LICENSE + +Copyright(c) Intel Corporation. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the +distribution. + +* Neither the name of Intel Corporation nor the names of its +contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "QSV_Encoder_Internal.h" +#include "QSV_Encoder.h" +#include "mfxastructures.h" +#include "mfxvideo++.h" +#include +#include + +#define do_log(level, format, ...) \ + blog(level, "[qsv encoder: '%s'] " format, \ + "msdk_impl", ##__VA_ARGS__) + +#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__) +#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__) +#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__) + +QSV_Encoder_Internal::QSV_Encoder_Internal(mfxIMPL& impl, mfxVersion& version) : + m_pmfxENC(NULL), + m_nSPSBufferSize(100), + m_nPPSBufferSize(100), + m_nTaskPool(0), + m_pTaskPool(NULL), + m_nTaskIdx(0), + m_nFirstSyncTask(0) +{ + mfxIMPL tempImpl; + mfxStatus sts; + + m_bIsWindows8OrGreater = IsWindows8OrGreater(); + m_bUseD3D11 = false; + + if (m_bIsWindows8OrGreater) { + tempImpl = impl | MFX_IMPL_VIA_D3D11; + sts = m_session.Init(tempImpl, &version); + if (sts == MFX_ERR_NONE) { + m_session.QueryVersion(&version); + m_session.Close(); + + // Use D3D11 surface + // m_bUseD3D11 = ((version.Major > 1) || + // (version.Major == 1 && version.Minor >= 8)); + m_bUseD3D11 = true; + if (m_bUseD3D11) + blog(LOG_INFO, "\timpl: D3D11\n" + "\tsurf: D3D11"); + else + blog(LOG_INFO, "\timpl: D3D11\n" + "\tsurf: SysMem"); + + m_impl = tempImpl; + m_ver = version; + return; + } + } + + // Either windows 7 or D3D11 failed at this point. + tempImpl = impl | MFX_IMPL_VIA_D3D9; + sts = m_session.Init(tempImpl, &version); + if (sts == MFX_ERR_NONE) { + m_session.QueryVersion(&version); + m_session.Close(); + + blog(LOG_INFO, "\timpl: D3D09\n" + "\tsurf: SysMem"); + + m_impl = tempImpl; + m_ver = version; + } + +} + +QSV_Encoder_Internal::~QSV_Encoder_Internal() +{ + ClearData(); +} + +mfxStatus QSV_Encoder_Internal::Open(qsv_param_t * pParams) +{ + mfxStatus sts = MFX_ERR_NONE; + + if (m_bUseD3D11) + // Use D3D11 surface + sts = Initialize(m_impl, m_ver, &m_session, &m_mfxAllocator); + else + // Use system memory + sts = Initialize(m_impl, m_ver, &m_session, NULL); + + if (sts == MFX_ERR_NONE) + m_pmfxENC = new MFXVideoENCODE(m_session); + + InitParams(pParams); + + sts = m_pmfxENC->Query(&m_mfxEncParams, &m_mfxEncParams); + MSDK_IGNORE_MFX_STS(sts, MFX_WRN_INCOMPATIBLE_VIDEO_PARAM); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + + sts = AllocateSurfaces(); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + + sts = m_pmfxENC->Init(&m_mfxEncParams); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + + sts = GetVideoParam(); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + + sts = InitBitstream(); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + + return sts; +} + + +bool QSV_Encoder_Internal::InitParams(qsv_param_t * pParams) +{ + memset(&m_mfxEncParams, 0, sizeof(m_mfxEncParams)); + + m_mfxEncParams.mfx.CodecId = MFX_CODEC_AVC; + m_mfxEncParams.mfx.GopOptFlag = MFX_GOP_STRICT; + m_mfxEncParams.mfx.NumSlice = 1; + m_mfxEncParams.mfx.TargetUsage = pParams->nTargetUsage; + m_mfxEncParams.mfx.CodecProfile = pParams->nCodecProfile; + m_mfxEncParams.mfx.FrameInfo.FrameRateExtN = pParams->nFpsNum; + m_mfxEncParams.mfx.FrameInfo.FrameRateExtD = pParams->nFpsDen; + m_mfxEncParams.mfx.FrameInfo.FourCC = MFX_FOURCC_NV12; + m_mfxEncParams.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; + m_mfxEncParams.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; + m_mfxEncParams.mfx.FrameInfo.CropX = 0; + m_mfxEncParams.mfx.FrameInfo.CropY = 0; + m_mfxEncParams.mfx.FrameInfo.CropW = pParams->nWidth; + m_mfxEncParams.mfx.FrameInfo.CropH = pParams->nHeight; + + m_mfxEncParams.mfx.RateControlMethod = pParams->nRateControl; + + switch (pParams->nRateControl) { + case MFX_RATECONTROL_CBR: + m_mfxEncParams.mfx.TargetKbps = pParams->nTargetBitRate; + break; + case MFX_RATECONTROL_VBR: + case MFX_RATECONTROL_VCM: + m_mfxEncParams.mfx.TargetKbps = pParams->nTargetBitRate; + m_mfxEncParams.mfx.MaxKbps = pParams->nMaxBitRate; + break; + case MFX_RATECONTROL_CQP: + m_mfxEncParams.mfx.QPI = pParams->nQPI; + m_mfxEncParams.mfx.QPB = pParams->nQPB; + m_mfxEncParams.mfx.QPP = pParams->nQPP; + break; + case MFX_RATECONTROL_AVBR: + m_mfxEncParams.mfx.TargetKbps = pParams->nTargetBitRate; + m_mfxEncParams.mfx.Accuracy = pParams->nAccuracy; + m_mfxEncParams.mfx.Convergence = pParams->nConvergence; + break; + case MFX_RATECONTROL_ICQ: + m_mfxEncParams.mfx.ICQQuality = pParams->nICQQuality; + break; + case MFX_RATECONTROL_LA: + m_mfxEncParams.mfx.TargetKbps = pParams->nTargetBitRate; + break; + case MFX_RATECONTROL_LA_ICQ: + m_mfxEncParams.mfx.ICQQuality = pParams->nICQQuality; + break; + default: + break; + } + + m_mfxEncParams.AsyncDepth = pParams->nAsyncDepth; + m_mfxEncParams.mfx.GopPicSize = (mfxU16)(pParams->nKeyIntSec * + pParams->nFpsNum / (float)pParams->nFpsDen); + + static mfxExtBuffer* extendedBuffers[2]; + int iBuffers = 0; + if (pParams->nAsyncDepth == 1) { + m_mfxEncParams.mfx.NumRefFrame = 1; + // low latency, I and P frames only + m_mfxEncParams.mfx.GopRefDist = 1; + memset(&m_co, 0, sizeof(mfxExtCodingOption)); + m_co.Header.BufferId = MFX_EXTBUFF_CODING_OPTION; + m_co.Header.BufferSz = sizeof(mfxExtCodingOption); + m_co.MaxDecFrameBuffering = 1; + extendedBuffers[iBuffers++] = (mfxExtBuffer*)&m_co; + } + else + m_mfxEncParams.mfx.GopRefDist = pParams->nbFrames + 1; + + if (pParams->nRateControl == MFX_RATECONTROL_LA_ICQ || + pParams->nRateControl == MFX_RATECONTROL_LA) { + + memset(&m_co2, 0, sizeof(mfxExtCodingOption2)); + m_co2.Header.BufferId = MFX_EXTBUFF_CODING_OPTION; + m_co2.Header.BufferSz = sizeof(m_co2); + m_co2.LookAheadDepth = pParams->nLADEPTH; + extendedBuffers[iBuffers++] = (mfxExtBuffer*)& m_co2; + } + + if (iBuffers > 0) { + m_mfxEncParams.ExtParam = extendedBuffers; + m_mfxEncParams.NumExtParam = (mfxU16)iBuffers; + } + + // Width must be a multiple of 16 + // Height must be a multiple of 16 in case of frame picture and a + // multiple of 32 in case of field picture + m_mfxEncParams.mfx.FrameInfo.Width = MSDK_ALIGN16(pParams->nWidth); + m_mfxEncParams.mfx.FrameInfo.Height = MSDK_ALIGN16(pParams->nHeight); + + if (m_bUseD3D11) + m_mfxEncParams.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY; + else + m_mfxEncParams.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY; + + return true; +} + +mfxStatus QSV_Encoder_Internal::AllocateSurfaces() +{ + // Query number of required surfaces for encoder + mfxFrameAllocRequest EncRequest; + memset(&EncRequest, 0, sizeof(EncRequest)); + mfxStatus sts = m_pmfxENC->QueryIOSurf(&m_mfxEncParams, &EncRequest); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + + EncRequest.Type |= WILL_WRITE; + + // SNB hack. On some SNB, it seems to require more surfaces + EncRequest.NumFrameSuggested += m_mfxEncParams.AsyncDepth; + + // Allocate required surfaces + if (m_bUseD3D11) { + sts = m_mfxAllocator.Alloc(m_mfxAllocator.pthis, &EncRequest, + &m_mfxResponse); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + + m_nSurfNum = m_mfxResponse.NumFrameActual; + + m_pmfxSurfaces = new mfxFrameSurface1 *[m_nSurfNum]; + MSDK_CHECK_POINTER(m_pmfxSurfaces, MFX_ERR_MEMORY_ALLOC); + + for (int i = 0; i < m_nSurfNum; i++) { + m_pmfxSurfaces[i] = new mfxFrameSurface1; + memset(m_pmfxSurfaces[i], 0, sizeof(mfxFrameSurface1)); + memcpy(&(m_pmfxSurfaces[i]->Info), + &(m_mfxEncParams.mfx.FrameInfo), + sizeof(mfxFrameInfo)); + m_pmfxSurfaces[i]->Data.MemId = m_mfxResponse.mids[i]; + } + } + else { + mfxU16 width = (mfxU16)MSDK_ALIGN32(EncRequest.Info.Width); + mfxU16 height = (mfxU16)MSDK_ALIGN32(EncRequest.Info.Height); + mfxU8 bitsPerPixel = 12; + mfxU32 surfaceSize = width * height * bitsPerPixel / 8; + m_nSurfNum = EncRequest.NumFrameSuggested; + + m_pmfxSurfaces = new mfxFrameSurface1 *[m_nSurfNum]; + for (int i = 0; i < m_nSurfNum; i++) { + m_pmfxSurfaces[i] = new mfxFrameSurface1; + memset(m_pmfxSurfaces[i], 0, sizeof(mfxFrameSurface1)); + memcpy(&(m_pmfxSurfaces[i]->Info), + &(m_mfxEncParams.mfx.FrameInfo), + sizeof(mfxFrameInfo)); + + mfxU8* pSurface = (mfxU8*) new mfxU8[surfaceSize]; + m_pmfxSurfaces[i]->Data.Y = pSurface; + m_pmfxSurfaces[i]->Data.U = pSurface + width * height; + m_pmfxSurfaces[i]->Data.V = pSurface + width * height + 1; + m_pmfxSurfaces[i]->Data.Pitch = width; + } + } + + blog(LOG_INFO, "\tm_nSurfNum: %d", m_nSurfNum); + + return sts; +} + +mfxStatus QSV_Encoder_Internal::GetVideoParam() +{ + memset(&m_parameter, 0, sizeof(m_parameter)); + mfxExtCodingOptionSPSPPS opt; + memset(&m_parameter, 0, sizeof(m_parameter)); + opt.Header.BufferId = MFX_EXTBUFF_CODING_OPTION_SPSPPS; + opt.Header.BufferSz = sizeof(mfxExtCodingOptionSPSPPS); + + static mfxExtBuffer* extendedBuffers[1]; + extendedBuffers[0] = (mfxExtBuffer*)& opt; + m_parameter.ExtParam = extendedBuffers; + m_parameter.NumExtParam = 1; + + opt.SPSBuffer = m_SPSBuffer; + opt.PPSBuffer = m_PPSBuffer; + opt.SPSBufSize = 100; // m_nSPSBufferSize; + opt.PPSBufSize = 100; // m_nPPSBufferSize; + + mfxStatus sts = m_pmfxENC->GetVideoParam(&m_parameter); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + + m_nSPSBufferSize = opt.SPSBufSize; + m_nPPSBufferSize = opt.PPSBufSize; + + return sts; +} + +void QSV_Encoder_Internal::GetSPSPPS(mfxU8 **pSPSBuf, mfxU8 **pPPSBuf, + mfxU16 *pnSPSBuf, mfxU16 *pnPPSBuf) +{ + *pSPSBuf = m_SPSBuffer; + *pPPSBuf = m_PPSBuffer; + *pnSPSBuf = m_nSPSBufferSize; + *pnPPSBuf = m_nPPSBufferSize; +} + +mfxStatus QSV_Encoder_Internal::InitBitstream() +{ + m_nTaskPool = m_parameter.AsyncDepth; + m_nFirstSyncTask = 0; + + m_pTaskPool = new Task[m_nTaskPool]; + memset(m_pTaskPool, 0, sizeof(Task) * m_nTaskPool); + + for (int i = 0; i < m_nTaskPool; i++) { + m_pTaskPool[i].mfxBS.MaxLength = + m_parameter.mfx.BufferSizeInKB * 1000; + m_pTaskPool[i].mfxBS.Data = + new mfxU8[m_pTaskPool[i].mfxBS.MaxLength]; + m_pTaskPool[i].mfxBS.DataOffset = 0; + m_pTaskPool[i].mfxBS.DataLength = 0; + + MSDK_CHECK_POINTER(m_pTaskPool[i].mfxBS.Data, + MFX_ERR_MEMORY_ALLOC); + } + + memset(&m_outBitstream, 0, sizeof(mfxBitstream)); + m_outBitstream.MaxLength = m_parameter.mfx.BufferSizeInKB * 1000; + m_outBitstream.Data = new mfxU8[m_outBitstream.MaxLength]; + m_outBitstream.DataOffset = 0; + m_outBitstream.DataLength = 0; + + blog(LOG_INFO, "\tm_nTaskPool: %d", m_nTaskPool); + + return MFX_ERR_NONE; +} + +mfxStatus QSV_Encoder_Internal::LoadNV12(mfxFrameSurface1 *pSurface, + uint8_t *pDataY, uint8_t *pDataUV, uint32_t strideY, + uint32_t strideUV) +{ + mfxU16 w, h, i, pitch; + mfxU8* ptr; + mfxFrameInfo* pInfo = &pSurface->Info; + mfxFrameData* pData = &pSurface->Data; + + if (pInfo->CropH > 0 && pInfo->CropW > 0) + { + w = pInfo->CropW; + h = pInfo->CropH; + } + else + { + w = pInfo->Width; + h = pInfo->Height; + } + + pitch = pData->Pitch; + ptr = pData->Y + pInfo->CropX + pInfo->CropY * pData->Pitch; + + // load Y plane + for (i = 0; i < h; i++) + memcpy(ptr + i * pitch, pDataY + i * strideY, w); + + // load UV plane + h /= 2; + ptr = pData->UV + pInfo->CropX + (pInfo->CropY / 2) * pitch; + + for (i = 0; i < h; i++) + memcpy(ptr + i * pitch, pDataUV + i * strideUV, w); + + return MFX_ERR_NONE; +} + +int QSV_Encoder_Internal::GetFreeTaskIndex(Task* pTaskPool, mfxU16 nPoolSize) +{ + if (pTaskPool) + for (int i = 0; i < nPoolSize; i++) + if (!pTaskPool[i].syncp) + return i; + return MFX_ERR_NOT_FOUND; +} + +mfxStatus QSV_Encoder_Internal::Encode(uint64_t ts, uint8_t *pDataY, + uint8_t *pDataUV, uint32_t strideY, uint32_t strideUV, + mfxBitstream **pBS) +{ + mfxStatus sts = MFX_ERR_NONE; + *pBS = NULL; + int nTaskIdx = GetFreeTaskIndex(m_pTaskPool, m_nTaskPool); + +#if 0 + info("MSDK Encode:\n" + "\tTaskIndex: %d", + nTaskIdx); +#endif + + int nSurfIdx = GetFreeSurfaceIndex(m_pmfxSurfaces, m_nSurfNum); +#if 0 + info("MSDK Encode:\n" + "\tnSurfIdx: %d", + nSurfIdx); +#endif + + while (MFX_ERR_NOT_FOUND == nTaskIdx || MFX_ERR_NOT_FOUND == nSurfIdx) { + // No more free tasks or surfaces, need to sync + sts = m_session.SyncOperation(m_pTaskPool[m_nFirstSyncTask].syncp, + 60000); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + + mfxU8 *pTemp = m_outBitstream.Data; + memcpy(&m_outBitstream, &m_pTaskPool[m_nFirstSyncTask].mfxBS, + sizeof(mfxBitstream)); + + m_pTaskPool[m_nFirstSyncTask].mfxBS.Data = pTemp; + m_pTaskPool[m_nFirstSyncTask].mfxBS.DataLength = 0; + m_pTaskPool[m_nFirstSyncTask].mfxBS.DataOffset = 0; + m_pTaskPool[m_nFirstSyncTask].syncp = NULL; + nTaskIdx = m_nFirstSyncTask; + m_nFirstSyncTask = (m_nFirstSyncTask + 1) % m_nTaskPool; + *pBS = &m_outBitstream; + +#if 0 + info("MSDK Encode:\n" + "\tnew FirstSyncTask: %d\n" + "\tTaskIndex: %d", + m_nFirstSyncTask, + nTaskIdx); +#endif + + nSurfIdx = GetFreeSurfaceIndex(m_pmfxSurfaces, m_nSurfNum); +#if 0 + info("MSDK Encode:\n" + "\tnSurfIdx: %d", + nSurfIdx); +#endif + } + + mfxFrameSurface1 *pSurface = m_pmfxSurfaces[nSurfIdx]; + if (m_bUseD3D11) + sts = m_mfxAllocator.Lock(m_mfxAllocator.pthis, + pSurface->Data.MemId, &(pSurface->Data)); + + sts = LoadNV12(pSurface, pDataY, pDataUV, strideY, strideUV); + pSurface->Data.TimeStamp = ts; + + if (m_bUseD3D11) + sts = m_mfxAllocator.Unlock(m_mfxAllocator.pthis, + pSurface->Data.MemId, &(pSurface->Data)); + + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + + for (;;) { + // Encode a frame asychronously (returns immediately) + sts = m_pmfxENC->EncodeFrameAsync(NULL, pSurface, + &m_pTaskPool[nTaskIdx].mfxBS, + &m_pTaskPool[nTaskIdx].syncp); + + if (MFX_ERR_NONE < sts && !m_pTaskPool[nTaskIdx].syncp) { + // Repeat the call if warning and no output + if (MFX_WRN_DEVICE_BUSY == sts) + MSDK_SLEEP(1); // Wait if device is busy, then repeat the same call + } else if (MFX_ERR_NONE < sts && m_pTaskPool[nTaskIdx].syncp) { + sts = MFX_ERR_NONE; // Ignore warnings if output is available + break; + } else if (MFX_ERR_NOT_ENOUGH_BUFFER == sts) { + // Allocate more bitstream buffer memory here if needed... + break; + } else + break; + } + + return sts; +} + +mfxStatus QSV_Encoder_Internal::Drain() +{ + mfxStatus sts = MFX_ERR_NONE; + + while (m_pTaskPool[m_nFirstSyncTask].syncp) { + sts = m_session.SyncOperation(m_pTaskPool[m_nFirstSyncTask].syncp, 60000); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + + m_pTaskPool[m_nFirstSyncTask].syncp = NULL; + m_nFirstSyncTask = (m_nFirstSyncTask + 1) % m_nTaskPool; + } + + return sts; +} + +mfxStatus QSV_Encoder_Internal::ClearData() +{ + mfxStatus sts = MFX_ERR_NONE; + sts = Drain(); + + sts = m_pmfxENC->Close(); + + if (m_bUseD3D11) + m_mfxAllocator.Free(m_mfxAllocator.pthis, &m_mfxResponse); + + for (int i = 0; i < m_nSurfNum; i++) { + if (!m_bUseD3D11) + delete m_pmfxSurfaces[i]->Data.Y; + + delete m_pmfxSurfaces[i]; + } + MSDK_SAFE_DELETE_ARRAY(m_pmfxSurfaces); + + for (int i = 0; i < m_nTaskPool; i++) + delete m_pTaskPool[i].mfxBS.Data; + MSDK_SAFE_DELETE_ARRAY(m_pTaskPool); + + delete m_outBitstream.Data; + + if (m_pmfxENC != NULL) { + delete m_pmfxENC; + m_pmfxENC = NULL; + } + + if (m_bUseD3D11) + Release(); + + m_session.Close(); + + return sts; +} + +mfxStatus QSV_Encoder_Internal::Reset(qsv_param_t *pParams) +{ + mfxStatus sts = ClearData(); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + + sts = Open(pParams); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + + return sts; +} diff --git a/plugins/obs-qsv11/QSV_Encoder_Internal.h b/plugins/obs-qsv11/QSV_Encoder_Internal.h new file mode 100644 index 000000000..b2648a1a9 --- /dev/null +++ b/plugins/obs-qsv11/QSV_Encoder_Internal.h @@ -0,0 +1,112 @@ +/* + +This file is provided under a dual BSD/GPLv2 license. When using or +redistributing this file, you may do so under either license. + +GPL LICENSE SUMMARY + +Copyright(c) Oct. 2015 Intel Corporation. + +This program is free software; you can redistribute it and/or modify +it under the terms of version 2 of the GNU General Public License as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +Contact Information: + +Seung-Woo Kim, seung-woo.kim@intel.com +705 5th Ave S #500, Seattle, WA 98104 + +BSD LICENSE + +Copyright(c) Intel Corporation. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the +distribution. + +* Neither the name of Intel Corporation nor the names of its +contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#pragma once +#include "mfxastructures.h" +#include "mfxvideo++.h" +#include "QSV_Encoder.h" +#include "common_utils.h" + +class QSV_Encoder_Internal +{ +public: + QSV_Encoder_Internal(mfxIMPL& impl, mfxVersion& version); + ~QSV_Encoder_Internal(); + + mfxStatus Open(qsv_param_t * pParams); + void GetSPSPPS(mfxU8 **pSPSBuf, mfxU8 **pPPSBuf, + mfxU16 *pnSPSBuf, mfxU16 *pnPPSBuf); + mfxStatus Encode(uint64_t ts, uint8_t *pDataY, uint8_t *pDataUV, + uint32_t strideY, uint32_t strideUV, mfxBitstream + **pBS); + mfxStatus ClearData(); + mfxStatus Reset(qsv_param_t *pParams); + +protected: + bool InitParams(qsv_param_t * pParams); + mfxStatus AllocateSurfaces(); + mfxStatus GetVideoParam(); + mfxStatus InitBitstream(); + mfxStatus LoadNV12(mfxFrameSurface1 *pSurface, uint8_t *pDataY, + uint8_t *pDataUV, uint32_t strideY, uint32_t strideUV); + mfxStatus Drain(); + int GetFreeTaskIndex(Task* pTaskPool, mfxU16 nPoolSize); + +private: + mfxIMPL m_impl; + mfxVersion m_ver; + MFXVideoSession m_session; + mfxFrameAllocator m_mfxAllocator; + mfxVideoParam m_mfxEncParams; + mfxFrameAllocResponse m_mfxResponse; + mfxFrameSurface1** m_pmfxSurfaces; + mfxU16 m_nSurfNum; + MFXVideoENCODE* m_pmfxENC; + mfxU8 m_SPSBuffer[100]; + mfxU8 m_PPSBuffer[100]; + mfxU16 m_nSPSBufferSize; + mfxU16 m_nPPSBufferSize; + mfxVideoParam m_parameter; + mfxExtCodingOption2 m_co2; + mfxExtCodingOption m_co; + mfxU16 m_nTaskPool; + Task* m_pTaskPool; + int m_nTaskIdx; + int m_nFirstSyncTask; + mfxBitstream m_outBitstream; + bool m_bIsWindows8OrGreater; + bool m_bUseD3D11; +}; + diff --git a/plugins/obs-qsv11/bits/linux_defs.h b/plugins/obs-qsv11/bits/linux_defs.h new file mode 100644 index 000000000..7a46dbbfa --- /dev/null +++ b/plugins/obs-qsv11/bits/linux_defs.h @@ -0,0 +1,19 @@ +/***************************************************************************** + +INTEL CORPORATION PROPRIETARY INFORMATION +This software is supplied under the terms of a license agreement or +nondisclosure agreement with Intel Corporation and may not be copied +or disclosed except in accordance with the terms of that agreement. +Copyright(c) 2005-2014 Intel Corporation. All Rights Reserved. + +*****************************************************************************/ + +#include +#include +#include +#include + +#define MSDK_FOPEN(FH, FN, M) { FH=fopen(FN,M); } +#define MSDK_SLEEP(X) { usleep(1000*(X)); } + +typedef timespec mfxTime; diff --git a/plugins/obs-qsv11/bits/windows_defs.h b/plugins/obs-qsv11/bits/windows_defs.h new file mode 100644 index 000000000..d81cae5db --- /dev/null +++ b/plugins/obs-qsv11/bits/windows_defs.h @@ -0,0 +1,16 @@ +/***************************************************************************** + +INTEL CORPORATION PROPRIETARY INFORMATION +This software is supplied under the terms of a license agreement or +nondisclosure agreement with Intel Corporation and may not be copied +or disclosed except in accordance with the terms of that agreement. +Copyright(c) 2005-2014 Intel Corporation. All Rights Reserved. + +*****************************************************************************/ + +#include + +#define MSDK_FOPEN(FH, FN, M) { fopen_s(&FH, FN, M); } +#define MSDK_SLEEP(X) { Sleep(X); } + +typedef LARGE_INTEGER mfxTime; diff --git a/plugins/obs-qsv11/common_directx11.cpp b/plugins/obs-qsv11/common_directx11.cpp new file mode 100644 index 000000000..bd800b71e --- /dev/null +++ b/plugins/obs-qsv11/common_directx11.cpp @@ -0,0 +1,487 @@ +/***************************************************************************** + +INTEL CORPORATION PROPRIETARY INFORMATION +This software is supplied under the terms of a license agreement or +nondisclosure agreement with Intel Corporation and may not be copied +or disclosed except in accordance with the terms of that agreement. +Copyright(c) 2005-2014 Intel Corporation. All Rights Reserved. + +*****************************************************************************/ + +#include "common_directx11.h" + +#include + +ID3D11Device* g_pD3D11Device; +ID3D11DeviceContext* g_pD3D11Ctx; +IDXGIFactory2* g_pDXGIFactory; +IDXGIAdapter* g_pAdapter; + +std::map allocResponses; +std::map allocDecodeResponses; +std::map allocDecodeRefCount; + +typedef struct { + mfxMemId memId; + mfxMemId memIdStage; + mfxU16 rw; +} CustomMemId; + +const struct { + mfxIMPL impl; // actual implementation + mfxU32 adapterID; // device adapter number +} implTypes[] = { + {MFX_IMPL_HARDWARE, 0}, + {MFX_IMPL_HARDWARE2, 1}, + {MFX_IMPL_HARDWARE3, 2}, + {MFX_IMPL_HARDWARE4, 3} +}; + +// ================================================================= +// DirectX functionality required to manage DX11 device and surfaces +// + +IDXGIAdapter* GetIntelDeviceAdapterHandle(mfxSession session) +{ + mfxU32 adapterNum = 0; + mfxIMPL impl; + + MFXQueryIMPL(session, &impl); + + mfxIMPL baseImpl = MFX_IMPL_BASETYPE(impl); // Extract Media SDK base implementation type + + // get corresponding adapter number + for (mfxU8 i = 0; i < sizeof(implTypes)/sizeof(implTypes[0]); i++) { + if (implTypes[i].impl == baseImpl) { + adapterNum = implTypes[i].adapterID; + break; + } + } + + HRESULT hres = CreateDXGIFactory(__uuidof(IDXGIFactory2), (void**)(&g_pDXGIFactory) ); + if (FAILED(hres)) return NULL; + + IDXGIAdapter* adapter; + hres = g_pDXGIFactory->EnumAdapters(adapterNum, &adapter); + if (FAILED(hres)) return NULL; + + return adapter; +} + +// Create HW device context +mfxStatus CreateHWDevice(mfxSession session, mfxHDL* deviceHandle, HWND hWnd, bool bCreateSharedHandles) +{ + //Note: not using bCreateSharedHandles for DX11 -- for API consistency only + hWnd; // Window handle not required by DX11 since we do not showcase rendering. + bCreateSharedHandles; // For rendering, not used here. Just for consistencies sake. + + HRESULT hres = S_OK; + + static D3D_FEATURE_LEVEL FeatureLevels[] = { + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0 + }; + D3D_FEATURE_LEVEL pFeatureLevelsOut; + + g_pAdapter = GetIntelDeviceAdapterHandle(session); + if (NULL == g_pAdapter) + return MFX_ERR_DEVICE_FAILED; + + UINT dxFlags = 0; + //UINT dxFlags = D3D11_CREATE_DEVICE_DEBUG; + + hres = D3D11CreateDevice( g_pAdapter, + D3D_DRIVER_TYPE_UNKNOWN, + NULL, + dxFlags, + FeatureLevels, + (sizeof(FeatureLevels) / sizeof(FeatureLevels[0])), + D3D11_SDK_VERSION, + &g_pD3D11Device, + &pFeatureLevelsOut, + &g_pD3D11Ctx); + if (FAILED(hres)) + return MFX_ERR_DEVICE_FAILED; + + // turn on multithreading for the DX11 context + CComQIPtr p_mt(g_pD3D11Ctx); + if (p_mt) + p_mt->SetMultithreadProtected(true); + else + return MFX_ERR_DEVICE_FAILED; + + *deviceHandle = (mfxHDL)g_pD3D11Device; + + return MFX_ERR_NONE; +} + + +void SetHWDeviceContext(CComPtr devCtx) +{ + g_pD3D11Ctx = devCtx; + devCtx->GetDevice(&g_pD3D11Device); +} + +// Free HW device context +void CleanupHWDevice() +{ + if (g_pAdapter) + { + g_pAdapter->Release(); + g_pAdapter = NULL; + } + if (g_pD3D11Device) + { + g_pD3D11Device->Release(); + g_pD3D11Device = NULL; + } + if (g_pD3D11Ctx) + { + g_pD3D11Ctx->Release(); + g_pD3D11Ctx = NULL; + } + if (g_pDXGIFactory) + { + g_pDXGIFactory->Release(); + g_pDXGIFactory = NULL; + } +} + +CComPtr GetHWDeviceContext() +{ + return g_pD3D11Ctx; +} + +/* (Hugh) Functions currently unused */ +#if 0 +void ClearYUVSurfaceD3D(mfxMemId memId) +{ + // TBD +} + +void ClearRGBSurfaceD3D(mfxMemId memId) +{ + // TBD +} +#endif + +// +// Intel Media SDK memory allocator entrypoints.... +// +mfxStatus _simple_alloc(mfxFrameAllocRequest* request, mfxFrameAllocResponse* response) +{ + HRESULT hRes; + + // Determine surface format + DXGI_FORMAT format; + if (MFX_FOURCC_NV12 == request->Info.FourCC) + format = DXGI_FORMAT_NV12; + else if (MFX_FOURCC_RGB4 == request->Info.FourCC) + format = DXGI_FORMAT_B8G8R8A8_UNORM; + else if (MFX_FOURCC_YUY2== request->Info.FourCC) + format = DXGI_FORMAT_YUY2; + else if (MFX_FOURCC_P8 == request->Info.FourCC ) //|| MFX_FOURCC_P8_TEXTURE == request->Info.FourCC + format = DXGI_FORMAT_P8; + else + format = DXGI_FORMAT_UNKNOWN; + + if (DXGI_FORMAT_UNKNOWN == format) + return MFX_ERR_UNSUPPORTED; + + + // Allocate custom container to keep texture and stage buffers for each surface + // Container also stores the intended read and/or write operation. + CustomMemId** mids = (CustomMemId**)calloc(request->NumFrameSuggested, sizeof(CustomMemId*)); + if (!mids) return MFX_ERR_MEMORY_ALLOC; + + for (int i=0; iNumFrameSuggested; i++) { + mids[i] = (CustomMemId*)calloc(1, sizeof(CustomMemId)); + if (!mids[i]) { + return MFX_ERR_MEMORY_ALLOC; + } + mids[i]->rw = request->Type & 0xF000; // Set intended read/write operation + } + + request->Type = request->Type & 0x0FFF; + + // because P8 data (bitstream) for h264 encoder should be allocated by CreateBuffer() + // but P8 data (MBData) for MPEG2 encoder should be allocated by CreateTexture2D() + if (request->Info.FourCC == MFX_FOURCC_P8) { + D3D11_BUFFER_DESC desc = { 0 }; + + if (!request->NumFrameSuggested) return MFX_ERR_MEMORY_ALLOC; + + desc.ByteWidth = request->Info.Width * request->Info.Height; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + desc.MiscFlags = 0; + desc.StructureByteStride = 0; + + ID3D11Buffer* buffer = 0; + hRes = g_pD3D11Device->CreateBuffer(&desc, 0, &buffer); + if (FAILED(hRes)) + return MFX_ERR_MEMORY_ALLOC; + + mids[0]->memId = reinterpret_cast(buffer); + } else { + D3D11_TEXTURE2D_DESC desc = {0}; + + desc.Width = request->Info.Width; + desc.Height = request->Info.Height; + desc.MipLevels = 1; + desc.ArraySize = 1; // number of subresources is 1 in this case + desc.Format = format; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_DECODER; + desc.MiscFlags = 0; + //desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; + + if ( (MFX_MEMTYPE_FROM_VPPIN & request->Type) && + (DXGI_FORMAT_B8G8R8A8_UNORM == desc.Format) ) { + desc.BindFlags = D3D11_BIND_RENDER_TARGET; + if (desc.ArraySize > 2) + return MFX_ERR_MEMORY_ALLOC; + } + + if ( (MFX_MEMTYPE_FROM_VPPOUT & request->Type) || + (MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET & request->Type)) { + desc.BindFlags = D3D11_BIND_RENDER_TARGET; + if (desc.ArraySize > 2) + return MFX_ERR_MEMORY_ALLOC; + } + + if ( DXGI_FORMAT_P8 == desc.Format ) + desc.BindFlags = 0; + + ID3D11Texture2D* pTexture2D; + + // Create surface textures + for (size_t i = 0; i < request->NumFrameSuggested / desc.ArraySize; i++) { + hRes = g_pD3D11Device->CreateTexture2D(&desc, NULL, &pTexture2D); + + if (FAILED(hRes)) + return MFX_ERR_MEMORY_ALLOC; + + mids[i]->memId = pTexture2D; + } + + desc.ArraySize = 1; + desc.Usage = D3D11_USAGE_STAGING; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;// | D3D11_CPU_ACCESS_WRITE; + desc.BindFlags = 0; + desc.MiscFlags = 0; + //desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; + + // Create surface staging textures + for (size_t i = 0; i < request->NumFrameSuggested; i++) { + hRes = g_pD3D11Device->CreateTexture2D(&desc, NULL, &pTexture2D); + + if (FAILED(hRes)) + return MFX_ERR_MEMORY_ALLOC; + + mids[i]->memIdStage = pTexture2D; + } + } + + + response->mids = (mfxMemId*)mids; + response->NumFrameActual = request->NumFrameSuggested; + + return MFX_ERR_NONE; +} + +mfxStatus simple_alloc(mfxHDL pthis, mfxFrameAllocRequest* request, mfxFrameAllocResponse* response) +{ + mfxStatus sts = MFX_ERR_NONE; + + if (request->Type & MFX_MEMTYPE_SYSTEM_MEMORY) + return MFX_ERR_UNSUPPORTED; + + if (allocDecodeResponses.find(pthis) != allocDecodeResponses.end() && + MFX_MEMTYPE_EXTERNAL_FRAME & request->Type && + MFX_MEMTYPE_FROM_DECODE & request->Type) { + // Memory for this request was already allocated during manual allocation stage. Return saved response + // When decode acceleration device (DXVA) is created it requires a list of d3d surfaces to be passed. + // Therefore Media SDK will ask for the surface info/mids again at Init() stage, thus requiring us to return the saved response + // (No such restriction applies to Encode or VPP) + *response = allocDecodeResponses[pthis]; + allocDecodeRefCount[pthis]++; + } else { + sts = _simple_alloc(request, response); + + if (MFX_ERR_NONE == sts) { + if ( MFX_MEMTYPE_EXTERNAL_FRAME & request->Type && + MFX_MEMTYPE_FROM_DECODE & request->Type) { + // Decode alloc response handling + allocDecodeResponses[pthis] = *response; + allocDecodeRefCount[pthis]++; + } else { + // Encode and VPP alloc response handling + allocResponses[response->mids] = pthis; + } + } + } + + return sts; +} + +mfxStatus simple_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData* ptr) +{ + pthis; // To suppress warning for this unused parameter + + HRESULT hRes = S_OK; + + D3D11_TEXTURE2D_DESC desc = {0}; + D3D11_MAPPED_SUBRESOURCE lockedRect = {0}; + + CustomMemId* memId = (CustomMemId*)mid; + ID3D11Texture2D* pSurface = (ID3D11Texture2D*)memId->memId; + ID3D11Texture2D* pStage = (ID3D11Texture2D*)memId->memIdStage; + + D3D11_MAP mapType = D3D11_MAP_READ; + UINT mapFlags = D3D11_MAP_FLAG_DO_NOT_WAIT; + + if (NULL == pStage) { + hRes = g_pD3D11Ctx->Map(pSurface, 0, mapType, mapFlags, &lockedRect); + desc.Format = DXGI_FORMAT_P8; + } else { + pSurface->GetDesc(&desc); + + // copy data only in case of user wants o read from stored surface + if (memId->rw & WILL_READ) + g_pD3D11Ctx->CopySubresourceRegion(pStage, 0, 0, 0, 0, pSurface, 0, NULL); + + do { + hRes = g_pD3D11Ctx->Map(pStage, 0, mapType, mapFlags, &lockedRect); + if (S_OK != hRes && DXGI_ERROR_WAS_STILL_DRAWING != hRes) + return MFX_ERR_LOCK_MEMORY; + } while (DXGI_ERROR_WAS_STILL_DRAWING == hRes); + } + + if (FAILED(hRes)) + return MFX_ERR_LOCK_MEMORY; + + switch (desc.Format) { + case DXGI_FORMAT_NV12: + ptr->Pitch = (mfxU16)lockedRect.RowPitch; + ptr->Y = (mfxU8*)lockedRect.pData; + ptr->U = (mfxU8*)lockedRect.pData + desc.Height * lockedRect.RowPitch; + ptr->V = ptr->U + 1; + break; + case DXGI_FORMAT_B8G8R8A8_UNORM : + ptr->Pitch = (mfxU16)lockedRect.RowPitch; + ptr->B = (mfxU8*)lockedRect.pData; + ptr->G = ptr->B + 1; + ptr->R = ptr->B + 2; + ptr->A = ptr->B + 3; + break; + case DXGI_FORMAT_YUY2: + ptr->Pitch = (mfxU16)lockedRect.RowPitch; + ptr->Y = (mfxU8*)lockedRect.pData; + ptr->U = ptr->Y + 1; + ptr->V = ptr->Y + 3; + break; + case DXGI_FORMAT_P8 : + ptr->Pitch = (mfxU16)lockedRect.RowPitch; + ptr->Y = (mfxU8*)lockedRect.pData; + ptr->U = 0; + ptr->V = 0; + break; + default: + return MFX_ERR_LOCK_MEMORY; + } + + return MFX_ERR_NONE; +} + +mfxStatus simple_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData* ptr) +{ + pthis; // To suppress warning for this unused parameter + + CustomMemId* memId = (CustomMemId*)mid; + ID3D11Texture2D* pSurface = (ID3D11Texture2D*)memId->memId; + ID3D11Texture2D* pStage = (ID3D11Texture2D*)memId->memIdStage; + + if (NULL == pStage) { + g_pD3D11Ctx->Unmap(pSurface, 0); + } else { + g_pD3D11Ctx->Unmap(pStage, 0); + // copy data only in case of user wants to write to stored surface + if (memId->rw & WILL_WRITE) + g_pD3D11Ctx->CopySubresourceRegion(pSurface, 0, 0, 0, 0, pStage, 0, NULL); + } + + if (ptr) { + ptr->Pitch=0; + ptr->U=ptr->V=ptr->Y=0; + ptr->A=ptr->R=ptr->G=ptr->B=0; + } + + return MFX_ERR_NONE; +} + +mfxStatus simple_gethdl(mfxHDL pthis, mfxMemId mid, mfxHDL* handle) +{ + pthis; // To suppress warning for this unused parameter + + if (NULL == handle) + return MFX_ERR_INVALID_HANDLE; + + mfxHDLPair* pPair = (mfxHDLPair*)handle; + CustomMemId* memId = (CustomMemId*)mid; + + pPair->first = memId->memId; // surface texture + pPair->second = 0; + + return MFX_ERR_NONE; +} + + +mfxStatus _simple_free(mfxFrameAllocResponse* response) +{ + if (response->mids) { + for (mfxU32 i = 0; i < response->NumFrameActual; i++) { + if (response->mids[i]) { + CustomMemId* mid = (CustomMemId*)response->mids[i]; + ID3D11Texture2D* pSurface = (ID3D11Texture2D*)mid->memId; + ID3D11Texture2D* pStage = (ID3D11Texture2D*)mid->memIdStage; + + if (pSurface) + pSurface->Release(); + if (pStage) + pStage->Release(); + + free(mid); + } + } + free(response->mids); + response->mids = NULL; + } + + return MFX_ERR_NONE; +} + +mfxStatus simple_free(mfxHDL pthis, mfxFrameAllocResponse* response) +{ + if (NULL == response) + return MFX_ERR_NULL_PTR; + + if (allocResponses.find(response->mids) == allocResponses.end()) { + // Decode free response handling + if (--allocDecodeRefCount[pthis] == 0) { + _simple_free(response); + allocDecodeResponses.erase(pthis); + allocDecodeRefCount.erase(pthis); + } + } else { + // Encode and VPP free response handling + allocResponses.erase(response->mids); + _simple_free(response); + } + + return MFX_ERR_NONE; +} diff --git a/plugins/obs-qsv11/common_directx11.h b/plugins/obs-qsv11/common_directx11.h new file mode 100644 index 000000000..3aa6075b3 --- /dev/null +++ b/plugins/obs-qsv11/common_directx11.h @@ -0,0 +1,39 @@ +/***************************************************************************** + +INTEL CORPORATION PROPRIETARY INFORMATION +This software is supplied under the terms of a license agreement or +nondisclosure agreement with Intel Corporation and may not be copied +or disclosed except in accordance with the terms of that agreement. +Copyright(c) 2005-2014 Intel Corporation. All Rights Reserved. + +*****************************************************************************/ + +#pragma once + +#include "common_utils.h" + +#include +#include +#include +#include + +#define DEVICE_MGR_TYPE MFX_HANDLE_D3D11_DEVICE + +// ================================================================= +// DirectX functionality required to manage D3D surfaces +// + +// Create DirectX 11 device context +// - Required when using D3D surfaces. +// - D3D Device created and handed to Intel Media SDK +// - Intel graphics device adapter will be determined automatically (does not have to be primary), +// but with the following caveats: +// - Device must be active (but monitor does NOT have to be attached) +// - Device must be enabled in BIOS. Required for the case when used together with a discrete graphics card +// - For switchable graphics solutions (mobile) make sure that Intel device is the active device +mfxStatus CreateHWDevice(mfxSession session, mfxHDL* deviceHandle, HWND hWnd, bool bCreateSharedHandles); +void CleanupHWDevice(); +void SetHWDeviceContext(CComPtr devCtx); +CComPtr GetHWDeviceContext(); +void ClearYUVSurfaceD3D(mfxMemId memId); +void ClearRGBSurfaceD3D(mfxMemId memId); \ No newline at end of file diff --git a/plugins/obs-qsv11/common_utils.cpp b/plugins/obs-qsv11/common_utils.cpp new file mode 100644 index 000000000..15ab60d2c --- /dev/null +++ b/plugins/obs-qsv11/common_utils.cpp @@ -0,0 +1,306 @@ +/***************************************************************************** + +INTEL CORPORATION PROPRIETARY INFORMATION +This software is supplied under the terms of a license agreement or +nondisclosure agreement with Intel Corporation and may not be copied +or disclosed except in accordance with the terms of that agreement. +Copyright(c) 2005-2014 Intel Corporation. All Rights Reserved. + +*****************************************************************************/ + +#include "common_utils.h" + +// ================================================================= +// Utility functions, not directly tied to Intel Media SDK functionality +// + + +void PrintErrString(int err,const char* filestr,int line) +{ + switch (err) { + case 0: + printf("\n No error.\n"); + break; + case -1: + printf("\n Unknown error: %s %d\n",filestr,line); + break; + case -2: + printf("\n Null pointer. Check filename/path + permissions? %s %d\n",filestr,line); + break; + case -3: + printf("\n Unsupported feature/library load error. %s %d\n",filestr,line); + break; + case -4: + printf("\n Could not allocate memory. %s %d\n",filestr,line); + break; + case -5: + printf("\n Insufficient IO buffers. %s %d\n",filestr,line); + break; + case -6: + printf("\n Invalid handle. %s %d\n",filestr,line); + break; + case -7: + printf("\n Memory lock failure. %s %d\n",filestr,line); + break; + case -8: + printf("\n Function called before initialization. %s %d\n",filestr,line); + break; + case -9: + printf("\n Specified object not found. %s %d\n",filestr,line); + break; + case -10: + printf("\n More input data expected. %s %d\n",filestr,line); + break; + case -11: + printf("\n More output surfaces expected. %s %d\n",filestr,line); + break; + case -12: + printf("\n Operation aborted. %s %d\n",filestr,line); + break; + case -13: + printf("\n HW device lost. %s %d\n",filestr,line); + break; + case -14: + printf("\n Incompatible video parameters. %s %d\n",filestr,line); + break; + case -15: + printf("\n Invalid video parameters. %s %d\n",filestr,line); + break; + case -16: + printf("\n Undefined behavior. %s %d\n",filestr,line); + break; + case -17: + printf("\n Device operation failure. %s %d\n",filestr,line); + break; + case -18: + printf("\n More bitstream data expected. %s %d\n",filestr,line); + break; + case -19: + printf("\n Incompatible audio parameters. %s %d\n",filestr,line); + break; + case -20: + printf("\n Invalid audio parameters. %s %d\n",filestr,line); + break; + default: + printf("\nError code %d,\t%s\t%d\n\n", err, filestr, line); + } +} + +mfxStatus ReadPlaneData(mfxU16 w, mfxU16 h, mfxU8* buf, mfxU8* ptr, + mfxU16 pitch, mfxU16 offset, FILE* fSource) +{ + mfxU32 nBytesRead; + for (mfxU16 i = 0; i < h; i++) { + nBytesRead = (mfxU32) fread(buf, 1, w, fSource); + if (w != nBytesRead) + return MFX_ERR_MORE_DATA; + for (mfxU16 j = 0; j < w; j++) + ptr[i * pitch + j * 2 + offset] = buf[j]; + } + return MFX_ERR_NONE; +} + +mfxStatus LoadRawFrame(mfxFrameSurface1* pSurface, FILE* fSource) +{ + if (!fSource) { + // Simulate instantaneous access to 1000 "empty" frames. + static int frameCount = 0; + if (1000 == frameCount++) + return MFX_ERR_MORE_DATA; + else + return MFX_ERR_NONE; + } + + mfxStatus sts = MFX_ERR_NONE; + mfxU32 nBytesRead; + mfxU16 w, h, i, pitch; + mfxU8* ptr; + mfxFrameInfo* pInfo = &pSurface->Info; + mfxFrameData* pData = &pSurface->Data; + + if (pInfo->CropH > 0 && pInfo->CropW > 0) { + w = pInfo->CropW; + h = pInfo->CropH; + } else { + w = pInfo->Width; + h = pInfo->Height; + } + + pitch = pData->Pitch; + ptr = pData->Y + pInfo->CropX + pInfo->CropY * pData->Pitch; + + // read luminance plane + for (i = 0; i < h; i++) { + nBytesRead = (mfxU32) fread(ptr + i * pitch, 1, w, fSource); + if (w != nBytesRead) + return MFX_ERR_MORE_DATA; + } + + mfxU8 buf[2048]; // maximum supported chroma width for nv12 + w /= 2; + h /= 2; + ptr = pData->UV + pInfo->CropX + (pInfo->CropY / 2) * pitch; + if (w > 2048) + return MFX_ERR_UNSUPPORTED; + + // load U + sts = ReadPlaneData(w, h, buf, ptr, pitch, 0, fSource); + if (MFX_ERR_NONE != sts) + return sts; + // load V + ReadPlaneData(w, h, buf, ptr, pitch, 1, fSource); + if (MFX_ERR_NONE != sts) + return sts; + + return MFX_ERR_NONE; +} + +mfxStatus LoadRawRGBFrame(mfxFrameSurface1* pSurface, FILE* fSource) +{ + if (!fSource) { + // Simulate instantaneous access to 1000 "empty" frames. + static int frameCount = 0; + if (1000 == frameCount++) + return MFX_ERR_MORE_DATA; + else + return MFX_ERR_NONE; + } + + size_t nBytesRead; + mfxU16 w, h; + mfxFrameInfo* pInfo = &pSurface->Info; + + if (pInfo->CropH > 0 && pInfo->CropW > 0) { + w = pInfo->CropW; + h = pInfo->CropH; + } else { + w = pInfo->Width; + h = pInfo->Height; + } + + for (mfxU16 i = 0; i < h; i++) { + nBytesRead = fread(pSurface->Data.B + i * pSurface->Data.Pitch, + 1, w * 4, fSource); + if ((size_t)(w * 4) != nBytesRead) + return MFX_ERR_MORE_DATA; + } + + return MFX_ERR_NONE; +} + +mfxStatus WriteBitStreamFrame(mfxBitstream* pMfxBitstream, FILE* fSink) +{ + mfxU32 nBytesWritten = + (mfxU32) fwrite(pMfxBitstream->Data + pMfxBitstream->DataOffset, 1, + pMfxBitstream->DataLength, fSink); + if (nBytesWritten != pMfxBitstream->DataLength) + return MFX_ERR_UNDEFINED_BEHAVIOR; + + pMfxBitstream->DataLength = 0; + + return MFX_ERR_NONE; +} + +mfxStatus ReadBitStreamData(mfxBitstream* pBS, FILE* fSource) +{ + memmove(pBS->Data, pBS->Data + pBS->DataOffset, pBS->DataLength); + pBS->DataOffset = 0; + + mfxU32 nBytesRead = (mfxU32) fread(pBS->Data + pBS->DataLength, 1, + pBS->MaxLength - pBS->DataLength, + fSource); + + if (0 == nBytesRead) + return MFX_ERR_MORE_DATA; + + pBS->DataLength += nBytesRead; + + return MFX_ERR_NONE; +} + +mfxStatus WriteSection(mfxU8* plane, mfxU16 factor, mfxU16 chunksize, + mfxFrameInfo* pInfo, mfxFrameData* pData, mfxU32 i, + mfxU32 j, FILE* fSink) +{ + if (chunksize != + fwrite(plane + + (pInfo->CropY * pData->Pitch / factor + pInfo->CropX) + + i * pData->Pitch + j, 1, chunksize, fSink)) + return MFX_ERR_UNDEFINED_BEHAVIOR; + return MFX_ERR_NONE; +} + +mfxStatus WriteRawFrame(mfxFrameSurface1* pSurface, FILE* fSink) +{ + mfxFrameInfo* pInfo = &pSurface->Info; + mfxFrameData* pData = &pSurface->Data; + mfxU32 i, j, h, w; + mfxStatus sts = MFX_ERR_NONE; + + for (i = 0; i < pInfo->CropH; i++) + sts = + WriteSection(pData->Y, 1, pInfo->CropW, pInfo, pData, i, 0, + fSink); + + h = pInfo->CropH / 2; + w = pInfo->CropW; + for (i = 0; i < h; i++) + for (j = 0; j < w; j += 2) + sts = + WriteSection(pData->UV, 2, 1, pInfo, pData, i, j, + fSink); + for (i = 0; i < h; i++) + for (j = 1; j < w; j += 2) + sts = + WriteSection(pData->UV, 2, 1, pInfo, pData, i, j, + fSink); + + return sts; +} + +int GetFreeTaskIndex(Task* pTaskPool, mfxU16 nPoolSize) +{ + if (pTaskPool) + for (int i = 0; i < nPoolSize; i++) + if (!pTaskPool[i].syncp) + return i; + return MFX_ERR_NOT_FOUND; +} + +void ClearYUVSurfaceSysMem(mfxFrameSurface1* pSfc, mfxU16 width, mfxU16 height) +{ + // In case simulating direct access to frames we initialize the allocated surfaces with default pattern + memset(pSfc->Data.Y, 100, width * height); // Y plane + memset(pSfc->Data.U, 50, (width * height)/2); // UV plane +} + + +// Get free raw frame surface +int GetFreeSurfaceIndex(mfxFrameSurface1** pSurfacesPool, mfxU16 nPoolSize) +{ + if (pSurfacesPool) + for (mfxU16 i = 0; i < nPoolSize; i++) + if (0 == pSurfacesPool[i]->Data.Locked) + return i; + return MFX_ERR_NOT_FOUND; +} + +char mfxFrameTypeString(mfxU16 FrameType) +{ + mfxU8 FrameTmp = FrameType & 0xF; + char FrameTypeOut; + switch (FrameTmp) { + case MFX_FRAMETYPE_I: + FrameTypeOut = 'I'; + break; + case MFX_FRAMETYPE_P: + FrameTypeOut = 'P'; + break; + case MFX_FRAMETYPE_B: + FrameTypeOut = 'B'; + break; + default: + FrameTypeOut = '*'; + } + return FrameTypeOut; +} diff --git a/plugins/obs-qsv11/common_utils.h b/plugins/obs-qsv11/common_utils.h new file mode 100644 index 000000000..4cb5c5751 --- /dev/null +++ b/plugins/obs-qsv11/common_utils.h @@ -0,0 +1,109 @@ +/***************************************************************************** + +INTEL CORPORATION PROPRIETARY INFORMATION +This software is supplied under the terms of a license agreement or +nondisclosure agreement with Intel Corporation and may not be copied +or disclosed except in accordance with the terms of that agreement. +Copyright(c) 2005-2014 Intel Corporation. All Rights Reserved. + +*****************************************************************************/ + +#pragma once + +#include + +#include "mfxvideo++.h" + +// ================================================================= +// OS-specific definitions of types, macro, etc... +// The following should be defined: +// - mfxTime +// - MSDK_FOPEN +// - MSDK_SLEEP +#if defined(_WIN32) || defined(_WIN64) +#include "bits/windows_defs.h" +#elif defined(__linux__) +#include "bits/linux_defs.h" +#endif + +// ================================================================= +// Helper macro definitions... +#define MSDK_PRINT_RET_MSG(ERR) {PrintErrString(ERR, __FILE__, __LINE__);} +#define MSDK_CHECK_RESULT(P, X, ERR) {if ((X) > (P)) {MSDK_PRINT_RET_MSG(ERR); return ERR;}} +#define MSDK_CHECK_POINTER(P, ERR) {if (!(P)) {MSDK_PRINT_RET_MSG(ERR); return ERR;}} +#define MSDK_CHECK_ERROR(P, X, ERR) {if ((X) == (P)) {MSDK_PRINT_RET_MSG(ERR); return ERR;}} +#define MSDK_IGNORE_MFX_STS(P, X) {if ((X) == (P)) {P = MFX_ERR_NONE;}} +#define MSDK_BREAK_ON_ERROR(P) {if (MFX_ERR_NONE != (P)) break;} +#define MSDK_SAFE_DELETE_ARRAY(P) {if (P) {delete[] P; P = NULL;}} +#define MSDK_ALIGN32(X) (((mfxU32)((X)+31)) & (~ (mfxU32)31)) +#define MSDK_ALIGN16(value) (((value + 15) >> 4) << 4) +#define MSDK_SAFE_RELEASE(X) {if (X) { X->Release(); X = NULL; }} +#define MSDK_MAX(A, B) (((A) > (B)) ? (A) : (B)) + +// Usage of the following two macros are only required for certain Windows DirectX11 use cases +#define WILL_READ 0x1000 +#define WILL_WRITE 0x2000 + +// ================================================================= +// Intel Media SDK memory allocator entrypoints.... +// Implementation of this functions is OS/Memory type specific. +mfxStatus simple_alloc(mfxHDL pthis, mfxFrameAllocRequest* request, mfxFrameAllocResponse* response); +mfxStatus simple_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData* ptr); +mfxStatus simple_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData* ptr); +mfxStatus simple_gethdl(mfxHDL pthis, mfxMemId mid, mfxHDL* handle); +mfxStatus simple_free(mfxHDL pthis, mfxFrameAllocResponse* response); + + + +// ================================================================= +// Utility functions, not directly tied to Media SDK functionality +// + +void PrintErrString(int err,const char* filestr,int line); + +// LoadRawFrame: Reads raw frame from YUV file (YV12) into NV12 surface +// - YV12 is a more common format for for YUV files than NV12 (therefore the conversion during read and write) +// - For the simulation case (fSource = NULL), the surface is filled with default image data +// LoadRawRGBFrame: Reads raw RGB32 frames from file into RGB32 surface +// - For the simulation case (fSource = NULL), the surface is filled with default image data + +mfxStatus LoadRawFrame(mfxFrameSurface1* pSurface, FILE* fSource); +mfxStatus LoadRawRGBFrame(mfxFrameSurface1* pSurface, FILE* fSource); + +// Write raw YUV (NV12) surface to YUV (YV12) file +mfxStatus WriteRawFrame(mfxFrameSurface1* pSurface, FILE* fSink); + +// Write bit stream data for frame to file +mfxStatus WriteBitStreamFrame(mfxBitstream* pMfxBitstream, FILE* fSink); +// Read bit stream data from file. Stream is read as large chunks (= many frames) +mfxStatus ReadBitStreamData(mfxBitstream* pBS, FILE* fSource); + +void ClearYUVSurfaceSysMem(mfxFrameSurface1* pSfc, mfxU16 width, mfxU16 height); +void ClearYUVSurfaceVMem(mfxMemId memId); +void ClearRGBSurfaceVMem(mfxMemId memId); + +// Get free raw frame surface +int GetFreeSurfaceIndex(mfxFrameSurface1** pSurfacesPool, mfxU16 nPoolSize); + +// For use with asynchronous task management +typedef struct { + mfxBitstream mfxBS; + mfxSyncPoint syncp; +} Task; + +// Get free task +int GetFreeTaskIndex(Task* pTaskPool, mfxU16 nPoolSize); + +// Initialize Intel Media SDK Session, device/display and memory manager +mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mfxFrameAllocator* pmfxAllocator, bool bCreateSharedHandles = false); + +// Release resources (device/display) +void Release(); + +// Convert frame type to string +char mfxFrameTypeString(mfxU16 FrameType); + +void mfxGetTime(mfxTime* timestamp); + +//void mfxInitTime(); might need this for Windows +double TimeDiffMsec(mfxTime tfinish, mfxTime tstart); diff --git a/plugins/obs-qsv11/common_utils_windows.cpp b/plugins/obs-qsv11/common_utils_windows.cpp new file mode 100644 index 000000000..2bb9f869e --- /dev/null +++ b/plugins/obs-qsv11/common_utils_windows.cpp @@ -0,0 +1,104 @@ +/***************************************************************************** + +INTEL CORPORATION PROPRIETARY INFORMATION +This software is supplied under the terms of a license agreement or +nondisclosure agreement with Intel Corporation and may not be copied +or disclosed except in accordance with the terms of that agreement. +Copyright(c) 2005-2014 Intel Corporation. All Rights Reserved. + +*****************************************************************************/ + +#include "common_utils.h" + +// ATTENTION: If D3D surfaces are used, DX9_D3D or DX11_D3D must be set in project settings or hardcoded here + +#ifdef DX9_D3D +#include "common_directx.h" +#elif DX11_D3D +#include "common_directx11.h" +#endif + +/* ======================================================= + * Windows implementation of OS-specific utility functions + */ + +mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, MFXVideoSession* pSession, mfxFrameAllocator* pmfxAllocator, bool bCreateSharedHandles) +{ + bCreateSharedHandles; // (Hugh) Currently unused + pmfxAllocator; // (Hugh) Currently unused + + mfxStatus sts = MFX_ERR_NONE; + + // If mfxFrameAllocator is provided it means we need to setup DirectX device and memory allocator + if (pmfxAllocator) { + // Initialize Intel Media SDK Session + sts = pSession->Init(impl, &ver); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + + // Create DirectX device context + mfxHDL deviceHandle; + sts = CreateHWDevice(*pSession, &deviceHandle, NULL, bCreateSharedHandles); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + + // Provide device manager to Media SDK + sts = pSession->SetHandle(DEVICE_MGR_TYPE, deviceHandle); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + + pmfxAllocator->pthis = *pSession; // We use Media SDK session ID as the allocation identifier + pmfxAllocator->Alloc = simple_alloc; + pmfxAllocator->Free = simple_free; + pmfxAllocator->Lock = simple_lock; + pmfxAllocator->Unlock = simple_unlock; + pmfxAllocator->GetHDL = simple_gethdl; + + // Since we are using video memory we must provide Media SDK with an external allocator + sts = pSession->SetFrameAllocator(pmfxAllocator); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + } + else + { + // Initialize Intel Media SDK Session + sts = pSession->Init(impl, &ver); + MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); + } + return sts; +} + +void Release() +{ +#if defined(DX9_D3D) || defined(DX11_D3D) + CleanupHWDevice(); +#endif +} + +void mfxGetTime(mfxTime* timestamp) +{ + QueryPerformanceCounter(timestamp); +} + +double TimeDiffMsec(mfxTime tfinish, mfxTime tstart) +{ + static LARGE_INTEGER tFreq = { 0 }; + + if (!tFreq.QuadPart) QueryPerformanceFrequency(&tFreq); + + double freq = (double)tFreq.QuadPart; + return 1000.0 * ((double)tfinish.QuadPart - (double)tstart.QuadPart) / freq; +} + +/* (Hugh) Functions currently unused */ +#if 0 +void ClearYUVSurfaceVMem(mfxMemId memId) +{ +#if defined(DX9_D3D) || defined(DX11_D3D) + ClearYUVSurfaceD3D(memId); +#endif +} + +void ClearRGBSurfaceVMem(mfxMemId memId) +{ +#if defined(DX9_D3D) || defined(DX11_D3D) + ClearRGBSurfaceD3D(memId); +#endif +} +#endif diff --git a/plugins/obs-qsv11/data/locale/en-US.ini b/plugins/obs-qsv11/data/locale/en-US.ini new file mode 100644 index 000000000..84b5e07c6 --- /dev/null +++ b/plugins/obs-qsv11/data/locale/en-US.ini @@ -0,0 +1,11 @@ +TargetUsage="Target Usage" +Bitrate="Bitrate" +MaxBitrate="Max Bitrate" +RateControl="Rate Control" +KeyframeIntervalSec="Keyframe Interval (seconds, 0=auto)" +Profile="Profile" +AsyncDepth="Async Depth" +Accuracy="Accuracy" +Convergence="Convergence" +ICQQuality="ICQ Quality" +LookAheadDepth="Lookahead Depth" diff --git a/plugins/obs-qsv11/libmfx/include/mfx_critical_section.h b/plugins/obs-qsv11/libmfx/include/mfx_critical_section.h new file mode 100644 index 000000000..ee3abd292 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/mfx_critical_section.h @@ -0,0 +1,76 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2012-2013 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_critical_section.h + +\* ****************************************************************************** */ + +#if !defined(__MFX_CRITICAL_SECTION_H) +#define __MFX_CRITICAL_SECTION_H + +#include + +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 // __MFX_CRITICAL_SECTION_H diff --git a/plugins/obs-qsv11/libmfx/include/mfx_dispatcher.h b/plugins/obs-qsv11/libmfx/include/mfx_dispatcher.h new file mode 100644 index 000000000..9555c52ed --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/mfx_dispatcher.h @@ -0,0 +1,213 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2012-2015 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_dispatcher.h + +\* ****************************************************************************** */ + +#if !defined(__MFX_DISPATCHER_H) +#define __MFX_DISPATCHER_H + +#include +#include +#include +#include +#include "mfx_dispatcher_defs.h" +#include "mfx_load_plugin.h" +#include "mfxenc.h" +#include "mfxpak.h" + + +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 +}; + +// +// 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, + eMFXJoinSession, + eMFXDisjoinSession, + eMFXCloneSession, + eMFXSetPriority, + eMFXGetPriority, + eMFXInitEx, +#include "mfx_exposed_functions_list.h" + eVideoFuncTotal +}; + +enum eAudioFunc +{ + eFakeAudioEnum = eMFXGetPriority, +#include "mfxaudio_exposed_functions_list.h" + eAudioFuncTotal +}; + +// 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 = 2 +}; + +// declare a dispatcher's handle +struct MFX_DISP_HANDLE +{ + // Default constructor + MFX_DISP_HANDLE(const mfxVersion requiredVersion); + // Destructor + ~MFX_DISP_HANDLE(void); + + // Load the library's module + mfxStatus LoadSelectedDLL(const msdk_disp_char *pPath, eMfxImplType implType, mfxIMPL impl, mfxIMPL implInterface, mfxInitParam &par); + // 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. + + // Library's implementation type (hardware or software) + eMfxImplType implType; + // Current library's implementation (exact implementation) + mfxIMPL impl; + // 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; + // A real handle passed to a called function + mfxSession session; + // 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 + msdk_disp_char subkeyName[MFX_MAX_REGISTRY_KEY_NAME]; + // Storage ID for windows version + int storageID; + + // Library's module handle + mfxModuleHandle hModule; + + MFX::MFXPluginStorage pluginHive; + MFX::MFXPluginFactory pluginFactory; + + // function call table + mfxFunctionPointer callTable[eVideoFuncTotal]; + mfxFunctionPointer callAudioTable[eAudioFuncTotal]; + +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 &); + +}; + +// declare comparison operator +inline +bool operator == (const mfxVersion &one, const mfxVersion &two) +{ + return (one.Version == two.Version); + +} // bool operator == (const mfxVersion &one, const mfxVersion &two) + +inline +bool operator < (const mfxVersion &one, const mfxVersion &two) +{ + return (one.Major == two.Major) && (one.Minor < two.Minor); + +} // bool operator < (const mfxVersion &one, const mfxVersion &two) + +inline +bool operator <= (const mfxVersion &one, const mfxVersion &two) +{ + return (one == two) || (one < two); +} // bool operator <= (const mfxVersion &one, const mfxVersion &two) + + +// +// 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 APIAudioFunc[eAudioFuncTotal]; +#endif // __MFX_DISPATCHER_H diff --git a/plugins/obs-qsv11/libmfx/include/mfx_dispatcher_defs.h b/plugins/obs-qsv11/libmfx/include/mfx_dispatcher_defs.h new file mode 100644 index 000000000..b9484033e --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/mfx_dispatcher_defs.h @@ -0,0 +1,85 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2013-2015 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_dispatcher_defs.h + +\* ****************************************************************************** */ + +#pragma once +#include "mfxdefs.h" +#include + +#if defined(MFX_DISPATCHER_LOG) +#include +#include +#endif + +#if defined(_WIN32) || defined(_WIN64) +typedef wchar_t msdk_disp_char; +#define MSDK2WIDE(x) x + +#if _MSC_VER >= 1400 + #define msdk_disp_char_cpy_s(to, to_size, from) wcscpy_s(to,to_size, from) +#else + #define msdk_disp_char_cpy_s(to, to_size, from) wcscpy(to, from) +#endif + +#else +typedef char msdk_disp_char; +//#define msdk_disp_char_cpy_s(to, to_size, from) strcpy(to, from) + +inline void msdk_disp_char_cpy_s(char * to, size_t to_size, const char * from) +{ + size_t source_len = strlen(from); + size_t num_chars = (to_size - 1) < source_len ? (to_size - 1) : source_len; + strncpy(to, from, num_chars); + to[num_chars] = 0; +} + +#if defined(MFX_DISPATCHER_LOG) +#define MSDK2WIDE(x) getWideString(x).c_str() + +inline std::wstring getWideString(const char * string) +{ + size_t len = strlen(string); + return std::wstring(string, string + len); +} +#else + #define MSDK2WIDE(x) x +#endif + +#endif + +#ifdef __GNUC__ +#define sscanf_s sscanf +#define swscanf_s swscanf +#endif + + +// declare library module's handle +typedef void * mfxModuleHandle; + +typedef void (MFX_CDECL * mfxFunctionPointer)(void); diff --git a/plugins/obs-qsv11/libmfx/include/mfx_dispatcher_log.h b/plugins/obs-qsv11/libmfx/include/mfx_dispatcher_log.h new file mode 100644 index 000000000..7225c88a8 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/mfx_dispatcher_log.h @@ -0,0 +1,306 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2012-2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_dispatcher_log.h + +\* ****************************************************************************** */ + +#if !defined(__MFX_DISPATCHER_LOG_H) +#define __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 + +#if defined(_WIN32) || defined(_WIN64) +// 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" + +#endif // #if defined(_WIN32) || defined(_WIN64) + +#include +#include + +//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 defined(_WIN32) || defined(_WIN64) +#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 +#else +#define DISPATCHER_LOG(lvl, opcode, str) +#define DISPATCHER_LOG_OPERATION(operation) +#endif + +#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 +#include +#include +#include + +template +class DSSingleTone +{ +public: + template + 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::auto_ptr instance; + if (NULL != obj) + { + instance.reset(obj); + } + return instance.get(); + } +}; + +class DispatchLog + : public DSSingleTone +{ + friend class DSSingleTone; + std::listm_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, ...); + DispatchLogBlockHelper (int level) + : m_level(level) + { + } + ~DispatchLogBlockHelper(); +}; + +//----utility sinks----- +#if defined(_WIN32) || defined(_WIN64) +#if defined(DISPATCHER_LOG_REGISTER_EVENT_PROVIDER) +class ETWHandlerFactory + : public DSSingleTone +{ + friend class DSSingleTone; + typedef std::map _storage_type; + _storage_type m_storage; + +public: + ~ETWHandlerFactory(); + IMsgHandler *GetSink(const wchar_t* sguid = DISPATCHER_LOG_EVENT_GUID); + +protected: + ETWHandlerFactory(){} +}; +#endif +#endif // #if defined(_WIN32) || defined(_WIN64) + +#if defined(DISPATCHER_LOG_REGISTER_FILE_WRITER) +class FileSink + : public DSSingleTone + , public IMsgHandler +{ + friend class DSSingleTone; +public: + virtual void Write(int level, int opcode, const char * msg, va_list argptr); + ~FileSink() + { + if (NULL != m_hdl) + fclose(m_hdl); + } +private: + FILE * m_hdl; + FileSink(const std::string & log_file) + { +#if defined(_WIN32) || defined(_WIN64) + fopen_s(&m_hdl, log_file.c_str(), "a"); +#else + m_hdl = fopen(log_file.c_str(), "a"); +#endif + } + +}; +#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 // !defined(__MFX_DISPATCHER_LOG_H) diff --git a/plugins/obs-qsv11/libmfx/include/mfx_dxva2_device.h b/plugins/obs-qsv11/libmfx/include/mfx_dxva2_device.h new file mode 100644 index 000000000..cd5e219ad --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/mfx_dxva2_device.h @@ -0,0 +1,210 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2012-2013 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_dxva2_device.h + +\* ****************************************************************************** */ + +#if !defined(__MFX_DXVA2_DEVICE_H) +#define __MFX_DXVA2_DEVICE_H + +#if defined(_WIN32) || defined(_WIN64) +#include +#endif // #if defined(_WIN32) || defined(_WIN64) + +#include + +#ifdef DXVA2DEVICE_LOG +#include +#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 +{ + +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); + +#if defined(_WIN32) || defined(_WIN64) + // Handle to the DLL library + HMODULE m_hModule; +#endif // #if defined(_WIN32) || defined(_WIN64) + + // 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 &); +}; + +#if defined(_WIN32) || defined(_WIN64) +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; + +}; + +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); + +protected: + + // Pointer to the DXGI1 factory + void *m_pDXGIFactory1; + // Pointer to the current DXGI1 adapter + void *m_pDXGIAdapter1; + +}; +#endif // #if defined(_WIN32) || defined(_WIN64) + +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; + + // Provide the number of available adapters + mfxU32 GetAdapterCount(void) const; + + void Close(void); + +protected: + + // Get vendor & device IDs by alternative way (D3D9 in Remote Desktop sessions) + void UseAlternativeWay(const D3D9Device *pD3D9Device); + + // Number of adapters available + mfxU32 m_numAdapters; + + // Vendor ID + mfxU32 m_vendorID; + // Device ID + mfxU32 m_deviceID; + //x.x.x.x + mfxU64 m_driverVersion; + +private: + // unimplemented by intent to make this class non-copyable + DXVA2Device(const DXVA2Device &); + void operator=(const DXVA2Device &); +}; + +} // namespace MFX + +#endif // __MFX_DXVA2_DEVICE_H diff --git a/plugins/obs-qsv11/libmfx/include/mfx_exposed_functions_list.h b/plugins/obs-qsv11/libmfx/include/mfx_exposed_functions_list.h new file mode 100644 index 000000000..50cce3a9a --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/mfx_exposed_functions_list.h @@ -0,0 +1,142 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2012-2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_exposed_functions_list.h + +\* ****************************************************************************** */ + +// +// WARNING: +// this file doesn't contain an include guard by intension. +// 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. +// + + + +// 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_SetBufferAllocator, (mfxSession session, mfxBufferAllocator *allocator), (session, allocator)) +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_GetHandle, (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, MFXVideoUSER_Register, (mfxSession session, mfxU32 type, const mfxPlugin *par), (session, type, par)) +FUNCTION(mfxStatus, MFXVideoUSER_Unregister, (mfxSession session, mfxU32 type), (session, type)) +FUNCTION(mfxStatus, MFXVideoUSER_ProcessFrameAsync, (mfxSession session, const mfxHDL *in, mfxU32 in_num, const mfxHDL *out, mfxU32 out_num, mfxSyncPoint *syncp), (session, in, in_num, out, out_num, syncp)) + +#undef API_VERSION + +// +// API version 1.10 functions +// + +#define API_VERSION {{10, 1}} + +FUNCTION(mfxStatus, MFXVideoENC_Query,(mfxSession session, mfxVideoParam *in, mfxVideoParam *out), (session,in,out)) +FUNCTION(mfxStatus, MFXVideoENC_QueryIOSurf,(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request), (session,par,request)) +FUNCTION(mfxStatus, MFXVideoENC_Init,(mfxSession session, mfxVideoParam *par), (session,par)) +FUNCTION(mfxStatus, MFXVideoENC_Reset,(mfxSession session, mfxVideoParam *par), (session,par)) +FUNCTION(mfxStatus, MFXVideoENC_Close,(mfxSession session),(session)) +FUNCTION(mfxStatus, MFXVideoENC_ProcessFrameAsync,(mfxSession session, mfxENCInput *in, mfxENCOutput *out, mfxSyncPoint *syncp),(session,in,out,syncp)) + +FUNCTION(mfxStatus, MFXVideoVPP_RunFrameVPPAsyncEx, (mfxSession session, mfxFrameSurface1 *in, mfxFrameSurface1 *work, mfxFrameSurface1 **out, mfxSyncPoint *syncp), (session, in, work, out, syncp)) + +#undef API_VERSION + +#define API_VERSION {{13, 1}} + +FUNCTION(mfxStatus, MFXVideoPAK_Query, (mfxSession session, mfxVideoParam *in, mfxVideoParam *out), (session, in, out)) +FUNCTION(mfxStatus, MFXVideoPAK_QueryIOSurf, (mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request), (session, par, request)) +FUNCTION(mfxStatus, MFXVideoPAK_Init, (mfxSession session, mfxVideoParam *par), (session, par)) +FUNCTION(mfxStatus, MFXVideoPAK_Reset, (mfxSession session, mfxVideoParam *par), (session, par)) +FUNCTION(mfxStatus, MFXVideoPAK_Close, (mfxSession session), (session)) +FUNCTION(mfxStatus, MFXVideoPAK_ProcessFrameAsync, (mfxSession session, mfxPAKInput *in, mfxPAKOutput *out, mfxSyncPoint *syncp), (session, in, out, syncp)) + +#undef API_VERSION + +#define API_VERSION {{14, 1}} + +// FUNCTION(mfxStatus, MFXInitEx, (mfxInitParam par, mfxSession session), (par, session)) +FUNCTION(mfxStatus, MFXDoWork, (mfxSession session), (session)) + +#undef API_VERSION \ No newline at end of file diff --git a/plugins/obs-qsv11/libmfx/include/mfx_library_iterator.h b/plugins/obs-qsv11/libmfx/include/mfx_library_iterator.h new file mode 100644 index 000000000..857881dba --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/mfx_library_iterator.h @@ -0,0 +1,161 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2012-2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_library_iterator.h + +\* ****************************************************************************** */ + +#if !defined(__MFX_LIBRARY_ITERATOR_H) +#define __MFX_LIBRARY_ITERATOR_H + + +#include +#include "mfx_win_reg_key.h" +#include "mfx_dispatcher.h" + +#if !defined(_WIN32) && !defined(_WIN64) +struct mfx_disp_adapters +{ + mfxU32 vendor_id; + mfxU32 device_id; +}; + +#ifndef __APPLE__ +#define MFX_SO_BASE_NAME_LEN 15 // sizeof("libmfxhw32-p.so") = 15 +#else + +#define MFX_SO_BASE_NAME_LEN 16 // sizeof("libmfxhw64.dylib") = 16 +#endif + +#define MFX_MIN_REAL_LIBNAME MFX_SO_BASE_NAME_LEN + 4 // sizeof("libmfxhw32-p.so.0.0") >= 19 +#define MFX_MAX_REAL_LIBNAME MFX_MIN_REAL_LIBNAME + 8 // sizeof("libmfxhw32-p.so..") <= 27, max(sizeof())=sizeof(0xFFFF) = sizeof(65535) = 5 + +struct mfx_libs +{ + char name[MFX_MAX_REAL_LIBNAME+1]; + mfxVersion version; +}; +#endif + +namespace MFX +{ + +// declare desired storage ID +#if defined(_WIN32) || defined(_WIN64) +enum +{ + MFX_UNKNOWN_KEY = -1, + MFX_CURRENT_USER_KEY = 0, + MFX_LOCAL_MACHINE_KEY = 1, + MFX_APP_FOLDER = 2, + + MFX_STORAGE_ID_FIRST = MFX_CURRENT_USER_KEY, + MFX_STORAGE_ID_LAST = MFX_LOCAL_MACHINE_KEY +}; +#else +enum +{ + MFX_UNKNOWN_KEY = -1, + MFX_STORAGE_ID_OPT = 0, // storage is: /opt/intel + MFX_APP_FOLDER = 1, + + MFX_STORAGE_ID_FIRST = MFX_STORAGE_ID_OPT, + MFX_STORAGE_ID_LAST = MFX_STORAGE_ID_OPT +}; +#endif + +// 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 +mfxStatus SelectImplementationType(const mfxU32 adapterNum, mfxIMPL *pImplInterface, mfxU32 *pVendorID, mfxU32 *pDeviceID); + +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(msdk_disp_char *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(msdk_disp_char *subKeyName, size_t length) const; + + int GetStorageID() const { return m_StorageID; } +protected: + + // Release the iterator + void Release(void); + + // Initialize the registry iterator + mfxStatus InitRegistry(eMfxImplType implType, mfxIMPL implInterface, const mfxU32 adapterNum, int storageID); + // Initialize the app folder iterator + mfxStatus InitFolder(eMfxImplType implType, mfxIMPL implInterface, const mfxU32 adapterNum, const msdk_disp_char * path); + + + 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(_WIN32) || defined(_WIN64) + WinRegKey m_baseRegKey; // (WinRegKey) main registry key + + mfxU32 m_lastLibIndex; // (mfxU32) index of previously returned library + mfxU32 m_lastLibMerit; // (mfxU32) merit of previously returned library +#else + int m_lastLibIndex; // (mfxU32) index of previously returned library + + mfxU32 m_adapters_num; + struct mfx_disp_adapters* m_adapters; + int m_selected_adapter; + mfxU32 m_libs_num; + struct mfx_libs* m_libs; +#endif // #if defined(_WIN32) || defined(_WIN64) + + msdk_disp_char m_path[260]; + +private: + // unimplemented by intent to make this class non-copyable + MFXLibraryIterator(const MFXLibraryIterator &); + void operator=(const MFXLibraryIterator &); +}; + +} // namespace MFX + +#endif // __MFX_LIBRARY_ITERATOR_H diff --git a/plugins/obs-qsv11/libmfx/include/mfx_load_dll.h b/plugins/obs-qsv11/libmfx/include/mfx_load_dll.h new file mode 100644 index 000000000..4a4cff57d --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/mfx_load_dll.h @@ -0,0 +1,59 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2012-2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_load_dll.h + +\* ****************************************************************************** */ + +#if !defined(__MFX_LOAD_DLL_H) +#define __MFX_LOAD_DLL_H + +#include "mfx_dispatcher.h" + +namespace MFX +{ + + + // + // declare DLL loading routines + // + + mfxStatus mfx_get_rt_dll_name(msdk_disp_char *pPath, size_t pathSize); + mfxStatus mfx_get_default_dll_name(msdk_disp_char *pPath, size_t pathSize, eMfxImplType implType); + mfxStatus mfx_get_default_plugin_name(msdk_disp_char *pPath, size_t pathSize, eMfxImplType implType); + + mfxStatus mfx_get_default_audio_dll_name(msdk_disp_char *pPath, size_t pathSize, eMfxImplType implType); + + + mfxModuleHandle mfx_dll_load(const msdk_disp_char *file_name); + //increments reference counter + mfxModuleHandle mfx_get_dll_handle(const msdk_disp_char *file_name); + mfxFunctionPointer mfx_dll_get_addr(mfxModuleHandle handle, const char *func_name); + bool mfx_dll_free(mfxModuleHandle handle); + +} // namespace MFX + +#endif // __MFX_LOAD_DLL_H diff --git a/plugins/obs-qsv11/libmfx/include/mfx_load_plugin.h b/plugins/obs-qsv11/libmfx/include/mfx_load_plugin.h new file mode 100644 index 000000000..d487ff419 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/mfx_load_plugin.h @@ -0,0 +1,93 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2013-2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_load_plugin.h + +\* ****************************************************************************** */ + +#pragma once +#include "mfxplugin.h" +#include "mfx_dispatcher_defs.h" +#include "mfx_plugin_hive.h" + +namespace MFX +{ + typedef mfxStatus (MFX_CDECL *CreatePluginPtr_t)(mfxPluginUID uid, mfxPlugin* plugin); + + class PluginModule + { + mfxModuleHandle mHmodule; + CreatePluginPtr_t mCreatePluginPtr; + msdk_disp_char mPath[MAX_PLUGIN_PATH]; + + public: + PluginModule(); + PluginModule(const msdk_disp_char * path); + PluginModule(const PluginModule & that) ; + PluginModule & operator = (const PluginModule & that); + bool Create(mfxPluginUID guid, mfxPlugin&); + ~PluginModule(void); + + private: + void Tidy(); + }; + + class MFXPluginFactory { + struct FactoryRecord { + mfxPluginParam plgParams; + PluginModule module; + mfxPlugin plugin; + FactoryRecord () {} + FactoryRecord(const mfxPluginParam &plgParams, + PluginModule &module, + mfxPlugin plugin) + : plgParams(plgParams) + , module(module) + , plugin(plugin) { + } + }; + MFXVector mPlugins; + mfxU32 nPlugins; + mfxSession mSession; + public: + MFXPluginFactory(mfxSession session); + void Close(); + mfxStatus Create(const PluginDescriptionRecord &); + bool Destroy(const mfxPluginUID &); + + ~MFXPluginFactory(); + protected: + void DestroyPlugin( FactoryRecord & ); + static bool RunVerification( const mfxPlugin & plg, const PluginDescriptionRecord &dsc, mfxPluginParam &pluginParams ); + static bool VerifyEncoder( const mfxVideoCodecPlugin &videoCodec ); + static bool VerifyAudioEncoder( const mfxAudioCodecPlugin &audioCodec ); + static bool VerifyEnc( const mfxVideoCodecPlugin &videoEnc ); + static bool VerifyVpp( const mfxVideoCodecPlugin &videoCodec ); + static bool VerifyDecoder( const mfxVideoCodecPlugin &videoCodec ); + static bool VerifyAudioDecoder( const mfxAudioCodecPlugin &audioCodec ); + static bool VerifyCodecCommon( const mfxVideoCodecPlugin & Video ); + }; +} diff --git a/plugins/obs-qsv11/libmfx/include/mfx_plugin_hive.h b/plugins/obs-qsv11/libmfx/include/mfx_plugin_hive.h new file mode 100644 index 000000000..91bfa8ed2 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/mfx_plugin_hive.h @@ -0,0 +1,132 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2013-2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_plugin_hive.h + +\* ****************************************************************************** */ + +#pragma once + +#include "mfx_dispatcher_defs.h" +#include "mfxplugin.h" +#include "mfx_win_reg_key.h" +#include "mfx_vector.h" +#include +#include +#include + +struct MFX_DISP_HANDLE; + +namespace MFX { + + enum + { + MAX_PLUGIN_PATH = 4096 + }; + + enum + { + MAX_PLUGIN_NAME = 4096 + }; + + inline bool operator == (const mfxPluginUID &lhs, const mfxPluginUID & rhs) + { + return !memcmp(lhs.Data, rhs.Data, sizeof(mfxPluginUID)); + } + + inline bool operator != (const mfxPluginUID &lhs, const mfxPluginUID & rhs) + { + return !(lhs == rhs); + } +#ifdef _WIN32 + //warning C4351: new behavior: elements of array 'MFX::PluginDescriptionRecord::sName' will be default initialized + #pragma warning (disable: 4351) +#endif + class PluginDescriptionRecord : public mfxPluginParam + { + public: + msdk_disp_char sPath[MAX_PLUGIN_PATH]; + char sName[MAX_PLUGIN_NAME]; + //used for FS plugins that has poor description + bool onlyVersionRegistered; + bool Default; + PluginDescriptionRecord() + : mfxPluginParam() + , sPath() + , sName() + , onlyVersionRegistered() + , Default() + { + } + }; + + typedef MFXVector MFXPluginStorage; + + class MFXPluginStorageBase : public MFXPluginStorage + { + protected: + mfxVersion mCurrentAPIVersion; + protected: + MFXPluginStorageBase(mfxVersion currentAPIVersion) + : mCurrentAPIVersion(currentAPIVersion) + { + } + void ConvertAPIVersion( mfxU32 APIVersion, PluginDescriptionRecord &descriptionRecord) const + { + descriptionRecord.APIVersion.Minor = static_cast (APIVersion & 0x0ff); + descriptionRecord.APIVersion.Major = static_cast (APIVersion >> 8); + } + }; + + //populated from registry + class MFXPluginsInHive : public MFXPluginStorageBase + { + public: + MFXPluginsInHive(int mfxStorageID, const msdk_disp_char *msdkLibSubKey, mfxVersion currentAPIVersion); + }; + + //plugins are loaded from FS close to executable + class MFXPluginsInFS : public MFXPluginStorageBase + { + bool mIsVersionParsed; + bool mIsAPIVersionParsed; + public: + MFXPluginsInFS(mfxVersion currentAPIVersion); + private: + bool ParseFile(FILE * f, PluginDescriptionRecord & des); + bool ParseKVPair( msdk_disp_char *key, msdk_disp_char * value, PluginDescriptionRecord & des); + }; + + + //plugins are loaded from FS close to Runtime library + class MFXDefaultPlugins : public MFXPluginStorageBase + { + public: + MFXDefaultPlugins(mfxVersion currentAPIVersion, MFX_DISP_HANDLE * hdl, int implType); + private: + }; + +} diff --git a/plugins/obs-qsv11/libmfx/include/mfx_vector.h b/plugins/obs-qsv11/libmfx/include/mfx_vector.h new file mode 100644 index 000000000..65af85919 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/mfx_vector.h @@ -0,0 +1,220 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2013-2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_vector.h + +\* ****************************************************************************** */ + +#pragma once +#include "mfxstructures.h" +#include + +namespace MFX +{ + template + class iterator_tmpl + { + template 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 & that )const + { + return mIndex == that.mIndex; + } + bool operator !=(const iterator_tmpl & that )const + { + return mIndex != that.mIndex; + } + mfxU32 operator - (const iterator_tmpl &that) const + { + return mIndex - that.mIndex; + } + iterator_tmpl & operator ++() + { + mIndex++; + return * this; + } + iterator_tmpl & operator ++(int) + { + mIndex++; + return * this; + } + T & operator *() + { + return mRecords[mIndex]; + } + T * operator ->() + { + return mRecords + mIndex; + } + }; + + class MFXVectorRangeError : public std::exception + { + }; + + template + 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 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) + { + 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 +#include "mfxplugin.h" +#include "mfx_dispatcher_log.h" + +namespace MFX { + +template struct RegKey{}; +template<> struct RegKey{enum {type = REG_DWORD};}; +template<> struct RegKey{enum {type = REG_DWORD};}; +template<> struct RegKey{enum {type = REG_BINARY};}; +template<> struct RegKey{enum {type = REG_DWORD};}; +template<> struct RegKey{enum {type = REG_SZ};}; +template<> struct RegKey{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::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 +inline bool QueryKey(WinRegKey & key, const wchar_t *pValueName, T &data ) { + DWORD size = sizeof(data); + return key.Query(pValueName, RegKey::type, (LPBYTE) &data, &size); +} + +template<> +inline bool QueryKey(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(_WIN32) || defined(_WIN64) + +#endif // __MFX_WIN_REG_KEY_H diff --git a/plugins/obs-qsv11/libmfx/include/mfxaudio_exposed_functions_list.h b/plugins/obs-qsv11/libmfx/include/mfxaudio_exposed_functions_list.h new file mode 100644 index 000000000..aa1240842 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/mfxaudio_exposed_functions_list.h @@ -0,0 +1,81 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2013-2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfxaudio_exposed_function_list.h + +\* ****************************************************************************** */ + +// +// WARNING: +// this file doesn't contain an include guard by intension. +// 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. +// + +// +// API version 1.8 functions +// + +// Minor value should precedes the major value +#define API_VERSION {{8, 1}} + +// CORE interface functions +FUNCTION(mfxStatus, MFXAudioCORE_SyncOperation, (mfxSession session, mfxSyncPoint syncp, mfxU32 wait), (session, syncp, wait)) + +// ENCODE interface functions +FUNCTION(mfxStatus, MFXAudioENCODE_Query, (mfxSession session, mfxAudioParam *in, mfxAudioParam *out), (session, in, out)) +FUNCTION(mfxStatus, MFXAudioENCODE_QueryIOSize, (mfxSession session, mfxAudioParam *par, mfxAudioAllocRequest *request), (session, par, request)) +FUNCTION(mfxStatus, MFXAudioENCODE_Init, (mfxSession session, mfxAudioParam *par), (session, par)) +FUNCTION(mfxStatus, MFXAudioENCODE_Reset, (mfxSession session, mfxAudioParam *par), (session, par)) +FUNCTION(mfxStatus, MFXAudioENCODE_Close, (mfxSession session), (session)) +FUNCTION(mfxStatus, MFXAudioENCODE_GetAudioParam, (mfxSession session, mfxAudioParam *par), (session, par)) +FUNCTION(mfxStatus, MFXAudioENCODE_EncodeFrameAsync, (mfxSession session, mfxAudioFrame *frame, mfxBitstream *buffer_out, mfxSyncPoint *syncp), (session, frame, buffer_out, syncp)) + +// DECODE interface functions +FUNCTION(mfxStatus, MFXAudioDECODE_Query, (mfxSession session, mfxAudioParam *in, mfxAudioParam *out), (session, in, out)) +FUNCTION(mfxStatus, MFXAudioDECODE_DecodeHeader, (mfxSession session, mfxBitstream *bs, mfxAudioParam *par), (session, bs, par)) +FUNCTION(mfxStatus, MFXAudioDECODE_Init, (mfxSession session, mfxAudioParam *par), (session, par)) +FUNCTION(mfxStatus, MFXAudioDECODE_Reset, (mfxSession session, mfxAudioParam *par), (session, par)) +FUNCTION(mfxStatus, MFXAudioDECODE_Close, (mfxSession session), (session)) +FUNCTION(mfxStatus, MFXAudioDECODE_QueryIOSize, (mfxSession session, mfxAudioParam *par, mfxAudioAllocRequest *request), (session, par, request)) +FUNCTION(mfxStatus, MFXAudioDECODE_GetAudioParam, (mfxSession session, mfxAudioParam *par), (session, par)) +FUNCTION(mfxStatus, MFXAudioDECODE_DecodeFrameAsync, (mfxSession session, mfxBitstream *bs, mfxAudioFrame *frame_out, mfxSyncPoint *syncp), (session, bs, frame_out, syncp)) + +#undef API_VERSION + +// +// API version 1.9 functions +// + +#define API_VERSION {{9, 1}} + +FUNCTION(mfxStatus, MFXAudioUSER_Register, (mfxSession session, mfxU32 type, const mfxPlugin *par), (session, type, par)) +FUNCTION(mfxStatus, MFXAudioUSER_Unregister, (mfxSession session, mfxU32 type), (session, type)) +FUNCTION(mfxStatus, MFXAudioUSER_ProcessFrameAsync, (mfxSession session, const mfxHDL *in, mfxU32 in_num, const mfxHDL *out, mfxU32 out_num, mfxSyncPoint *syncp), (session, in, in_num, out, out_num, syncp)) + + +#undef API_VERSION diff --git a/plugins/obs-qsv11/libmfx/include/msdk/include/mfxastructures.h b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxastructures.h new file mode 100644 index 000000000..6157aee1d --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxastructures.h @@ -0,0 +1,172 @@ +/******************************************************************************* + +Copyright (C) 2013 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfxastructures.h + +*******************************************************************************/ +#ifndef __MFXASTRUCTURES_H__ +#define __MFXASTRUCTURES_H__ +#include "mfxcommon.h" + +#if !defined (__GNUC__) +#pragma warning(disable: 4201) +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* CodecId */ +enum { + MFX_CODEC_AAC =MFX_MAKEFOURCC('A','A','C',' '), + MFX_CODEC_MP3 =MFX_MAKEFOURCC('M','P','3',' ') +}; + +enum { + /* AAC Profiles & Levels */ + MFX_PROFILE_AAC_LC =2, + MFX_PROFILE_AAC_LTP =4, + MFX_PROFILE_AAC_MAIN =1, + MFX_PROFILE_AAC_SSR =3, + MFX_PROFILE_AAC_HE =5, + MFX_PROFILE_AAC_ALS =0x20, + MFX_PROFILE_AAC_BSAC =22, + MFX_PROFILE_AAC_PS =29, + + /*MPEG AUDIO*/ + MFX_AUDIO_MPEG1_LAYER1 =0x00000110, + MFX_AUDIO_MPEG1_LAYER2 =0x00000120, + MFX_AUDIO_MPEG1_LAYER3 =0x00000140, + MFX_AUDIO_MPEG2_LAYER1 =0x00000210, + MFX_AUDIO_MPEG2_LAYER2 =0x00000220, + MFX_AUDIO_MPEG2_LAYER3 =0x00000240 +}; + +/*AAC HE decoder down sampling*/ +enum { + MFX_AUDIO_AAC_HE_DWNSMPL_OFF=0, + MFX_AUDIO_AAC_HE_DWNSMPL_ON= 1 +}; + +/* AAC decoder support of PS */ +enum { + MFX_AUDIO_AAC_PS_DISABLE= 0, + MFX_AUDIO_AAC_PS_PARSER= 1, + MFX_AUDIO_AAC_PS_ENABLE_BL= 111, + MFX_AUDIO_AAC_PS_ENABLE_UR= 411 +}; + +/*AAC decoder SBR support*/ +enum { + MFX_AUDIO_AAC_SBR_DISABLE = 0, + MFX_AUDIO_AAC_SBR_ENABLE= 1, + MFX_AUDIO_AAC_SBR_UNDEF= 2 +}; + +/*AAC header type*/ +enum{ + MFX_AUDIO_AAC_ADTS= 1, + MFX_AUDIO_AAC_ADIF= 2, + MFX_AUDIO_AAC_RAW= 3, +}; + +/*AAC encoder stereo mode*/ +enum +{ + MFX_AUDIO_AAC_MONO= 0, + MFX_AUDIO_AAC_LR_STEREO= 1, + MFX_AUDIO_AAC_MS_STEREO= 2, + MFX_AUDIO_AAC_JOINT_STEREO= 3 +}; + +typedef struct { + mfxU32 CodecId; + mfxU16 CodecProfile; + mfxU16 CodecLevel; + + mfxU32 Bitrate; + mfxU32 SampleFrequency; + mfxU16 NumChannel; + mfxU16 BitPerSample; + + mfxU16 reserved1[22]; + + union { + struct { /* AAC Decoding Options */ + mfxU16 FlagPSSupportLev; + mfxU16 Layer; + mfxU16 AACHeaderDataSize; + mfxU8 AACHeaderData[64]; + }; + struct { /* AAC Encoding Options */ + mfxU16 OutputFormat; + mfxU16 StereoMode; + mfxU16 reserved2[61]; + }; + }; +} mfxAudioInfoMFX; + +typedef struct { + mfxU16 AsyncDepth; + mfxU16 Protected; + mfxU16 reserved[14]; + + mfxAudioInfoMFX mfx; + mfxExtBuffer** ExtParam; + mfxU16 NumExtParam; +} mfxAudioParam; + +typedef struct { + mfxU32 SuggestedInputSize; + mfxU32 SuggestedOutputSize; + mfxU32 reserved[6]; +} mfxAudioAllocRequest; + +typedef struct { + mfxU64 TimeStamp; /* 1/90KHz */ + mfxU16 Locked; + mfxU16 NumChannels; + mfxU32 SampleFrequency; + mfxU16 BitPerSample; + mfxU16 reserved1[7]; + + mfxU8* Data; + mfxU32 reserved2; + mfxU32 DataLength; + mfxU32 MaxLength; + + mfxU32 NumExtParam; + mfxExtBuffer **ExtParam; +} mfxAudioFrame; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + + diff --git a/plugins/obs-qsv11/libmfx/include/msdk/include/mfxaudio++.h b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxaudio++.h new file mode 100644 index 000000000..52760a896 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxaudio++.h @@ -0,0 +1,113 @@ +/******************************************************************************* + +Copyright (C) 2013 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +File Name: mfxaudio++.h + + +*******************************************************************************/ +#ifndef __MFXAUDIOPLUSPLUS_H +#define __MFXAUDIOPLUSPLUS_H + +#include "mfxaudio.h" + +class MFXAudioSession +{ +public: + MFXAudioSession(void) { m_session = (mfxSession) 0; } + virtual ~MFXAudioSession(void) { Close(); } + + virtual mfxStatus Init(mfxIMPL impl, mfxVersion *ver) { return MFXInit(impl, ver, &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 SyncOperation(mfxSyncPoint syncp, mfxU32 wait) { return MFXAudioCORE_SyncOperation(m_session, syncp, wait); } + + virtual operator mfxSession (void) { return m_session; } + +protected: + + mfxSession m_session; // (mfxSession) handle to the owning session +}; + + +class MFXAudioDECODE +{ +public: + + MFXAudioDECODE(mfxSession session) { m_session = session; } + virtual ~MFXAudioDECODE(void) { Close(); } + + virtual mfxStatus Query(mfxAudioParam *in, mfxAudioParam *out) { return MFXAudioDECODE_Query(m_session, in, out); } + virtual mfxStatus DecodeHeader(mfxBitstream *bs, mfxAudioParam *par) { return MFXAudioDECODE_DecodeHeader(m_session, bs, par); } + virtual mfxStatus QueryIOSize(mfxAudioParam *par, mfxAudioAllocRequest *request) { return MFXAudioDECODE_QueryIOSize(m_session, par, request); } + virtual mfxStatus Init(mfxAudioParam *par) { return MFXAudioDECODE_Init(m_session, par); } + virtual mfxStatus Reset(mfxAudioParam *par) { return MFXAudioDECODE_Reset(m_session, par); } + virtual mfxStatus Close(void) { return MFXAudioDECODE_Close(m_session); } + virtual mfxStatus GetAudioParam(mfxAudioParam *par) { return MFXAudioDECODE_GetAudioParam(m_session, par); } + virtual mfxStatus DecodeFrameAsync(mfxBitstream *bs, mfxAudioFrame *frame, mfxSyncPoint *syncp) { return MFXAudioDECODE_DecodeFrameAsync(m_session, bs, frame, syncp); } + + +protected: + + mfxSession m_session; // (mfxSession) handle to the owning session +}; + + +class MFXAudioENCODE +{ +public: + + MFXAudioENCODE(mfxSession session) { m_session = session; } + virtual ~MFXAudioENCODE(void) { Close(); } + + virtual mfxStatus Query(mfxAudioParam *in, mfxAudioParam *out) { return MFXAudioENCODE_Query(m_session, in, out); } + virtual mfxStatus QueryIOSize(mfxAudioParam *par, mfxAudioAllocRequest *request) { return MFXAudioENCODE_QueryIOSize(m_session, par, request); } + virtual mfxStatus Init(mfxAudioParam *par) { return MFXAudioENCODE_Init(m_session, par); } + virtual mfxStatus Reset(mfxAudioParam *par) { return MFXAudioENCODE_Reset(m_session, par); } + virtual mfxStatus Close(void) { return MFXAudioENCODE_Close(m_session); } + virtual mfxStatus GetAudioParam(mfxAudioParam *par) { return MFXAudioENCODE_GetAudioParam(m_session, par); } + virtual mfxStatus EncodeFrameAsync(mfxAudioFrame *frame, mfxBitstream *buffer_out, mfxSyncPoint *syncp) { return MFXAudioENCODE_EncodeFrameAsync(m_session, frame, buffer_out, syncp); } + +protected: + + mfxSession m_session; // (mfxSession) handle to the owning session +}; + +#endif \ No newline at end of file diff --git a/plugins/obs-qsv11/libmfx/include/msdk/include/mfxaudio.h b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxaudio.h new file mode 100644 index 000000000..985da94a5 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxaudio.h @@ -0,0 +1,70 @@ +/******************************************************************************* + +Copyright (C) 2013 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfxaudio.h + +*******************************************************************************/ + +#ifndef __MFXAUDIO_H__ +#define __MFXAUDIO_H__ +#include "mfxsession.h" +#include "mfxastructures.h" + +#define MFX_AUDIO_VERSION_MAJOR 1 +#define MFX_AUDIO_VERSION_MINOR 15 + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* AudioCORE */ +mfxStatus MFX_CDECL MFXAudioCORE_SyncOperation(mfxSession session, mfxSyncPoint syncp, mfxU32 wait); + +/* AudioENCODE */ +mfxStatus MFX_CDECL MFXAudioENCODE_Query(mfxSession session, mfxAudioParam *in, mfxAudioParam *out); +mfxStatus MFX_CDECL MFXAudioENCODE_QueryIOSize(mfxSession session, mfxAudioParam *par, mfxAudioAllocRequest *request); +mfxStatus MFX_CDECL MFXAudioENCODE_Init(mfxSession session, mfxAudioParam *par); +mfxStatus MFX_CDECL MFXAudioENCODE_Reset(mfxSession session, mfxAudioParam *par); +mfxStatus MFX_CDECL MFXAudioENCODE_Close(mfxSession session); +mfxStatus MFX_CDECL MFXAudioENCODE_GetAudioParam(mfxSession session, mfxAudioParam *par); +mfxStatus MFX_CDECL MFXAudioENCODE_EncodeFrameAsync(mfxSession session, mfxAudioFrame *frame, mfxBitstream *bs, mfxSyncPoint *syncp); + +/* AudioDECODE */ +mfxStatus MFX_CDECL MFXAudioDECODE_Query(mfxSession session, mfxAudioParam *in, mfxAudioParam *out); +mfxStatus MFX_CDECL MFXAudioDECODE_DecodeHeader(mfxSession session, mfxBitstream *bs, mfxAudioParam* par); +mfxStatus MFX_CDECL MFXAudioDECODE_Init(mfxSession session, mfxAudioParam *par); +mfxStatus MFX_CDECL MFXAudioDECODE_Reset(mfxSession session, mfxAudioParam *par); +mfxStatus MFX_CDECL MFXAudioDECODE_Close(mfxSession session); +mfxStatus MFX_CDECL MFXAudioDECODE_QueryIOSize(mfxSession session, mfxAudioParam *par, mfxAudioAllocRequest *request); +mfxStatus MFX_CDECL MFXAudioDECODE_GetAudioParam(mfxSession session, mfxAudioParam *par); +mfxStatus MFX_CDECL MFXAudioDECODE_DecodeFrameAsync(mfxSession session, mfxBitstream *bs, mfxAudioFrame *frame, mfxSyncPoint *syncp); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/plugins/obs-qsv11/libmfx/include/msdk/include/mfxcommon.h b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxcommon.h new file mode 100644 index 000000000..a9c6e4a71 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxcommon.h @@ -0,0 +1,159 @@ +/******************************************************************************* + +Copyright (C) 2013-2015 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfxcommon.h + +*******************************************************************************/ +#ifndef __MFXCOMMON_H__ +#define __MFXCOMMON_H__ +#include "mfxdefs.h" + +#if !defined (__GNUC__) +#pragma warning(disable: 4201) +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#define MFX_MAKEFOURCC(A,B,C,D) ((((int)A))+(((int)B)<<8)+(((int)C)<<16)+(((int)D)<<24)) + +/* Extended Configuration Header Structure */ +typedef struct { + mfxU32 BufferId; + mfxU32 BufferSz; +} mfxExtBuffer; + +/* Library initialization and deinitialization */ +typedef mfxI32 mfxIMPL; +#define MFX_IMPL_BASETYPE(x) (0x00ff & (x)) + +enum { + MFX_IMPL_AUTO = 0x0000, /* Auto Selection/In or Not Supported/Out */ + MFX_IMPL_SOFTWARE = 0x0001, /* Pure Software Implementation */ + MFX_IMPL_HARDWARE = 0x0002, /* Hardware Accelerated Implementation (default device) */ + MFX_IMPL_AUTO_ANY = 0x0003, /* Auto selection of any hardware/software implementation */ + MFX_IMPL_HARDWARE_ANY = 0x0004, /* Auto selection of any hardware implementation */ + MFX_IMPL_HARDWARE2 = 0x0005, /* Hardware accelerated implementation (2nd device) */ + MFX_IMPL_HARDWARE3 = 0x0006, /* Hardware accelerated implementation (3rd device) */ + MFX_IMPL_HARDWARE4 = 0x0007, /* Hardware accelerated implementation (4th device) */ + MFX_IMPL_RUNTIME = 0x0008, + + MFX_IMPL_VIA_ANY = 0x0100, + MFX_IMPL_VIA_D3D9 = 0x0200, + MFX_IMPL_VIA_D3D11 = 0x0300, + MFX_IMPL_VIA_VAAPI = 0x0400, + + MFX_IMPL_AUDIO = 0x8000, + + MFX_IMPL_UNSUPPORTED = 0x0000 /* One of the MFXQueryIMPL returns */ +}; + +/* Version Info */ +typedef union { + struct { + mfxU16 Minor; + mfxU16 Major; + }; + mfxU32 Version; +} mfxVersion; + +/* session priority */ +typedef enum +{ + MFX_PRIORITY_LOW = 0, + MFX_PRIORITY_NORMAL = 1, + MFX_PRIORITY_HIGH = 2 + +} mfxPriority; + +typedef struct _mfxEncryptedData mfxEncryptedData; +typedef struct { + union { + struct { + mfxEncryptedData* EncryptedData; + mfxExtBuffer **ExtParam; + mfxU16 NumExtParam; + }; + mfxU32 reserved[6]; + }; + mfxI64 DecodeTimeStamp; + mfxU64 TimeStamp; + mfxU8* Data; + mfxU32 DataOffset; + mfxU32 DataLength; + mfxU32 MaxLength; + + mfxU16 PicStruct; + mfxU16 FrameType; + mfxU16 DataFlag; + mfxU16 reserved2; +} mfxBitstream; + +typedef struct _mfxSyncPoint *mfxSyncPoint; + +/* GPUCopy */ +enum { + MFX_GPUCOPY_DEFAULT = 0, + MFX_GPUCOPY_ON = 1, + MFX_GPUCOPY_OFF = 2 +}; + +typedef struct { + mfxIMPL Implementation; + mfxVersion Version; + mfxU16 ExternalThreads; + union { + struct { + mfxExtBuffer **ExtParam; + mfxU16 NumExtParam; + }; + mfxU16 reserved2[5]; + }; + mfxU16 GPUCopy; + mfxU16 reserved[21]; +} mfxInitParam; + +enum { + MFX_EXTBUFF_THREADS_PARAM = MFX_MAKEFOURCC('T','H','D','P') +}; + +typedef struct { + mfxExtBuffer Header; + + mfxU16 NumThread; + mfxI32 SchedulingType; + mfxI32 Priority; + mfxU16 reserved[55]; +} mfxExtThreadsParam; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/plugins/obs-qsv11/libmfx/include/msdk/include/mfxdefs.h b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxdefs.h new file mode 100644 index 000000000..3091275ae --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxdefs.h @@ -0,0 +1,153 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2007-2015 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfxdefs.h + +\* ****************************************************************************** */ +#ifndef __MFXDEFS_H__ +#define __MFXDEFS_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + +#if (defined( _WIN32 ) || defined ( _WIN64 )) && !defined (__GNUC__) + #define __INT64 __int64 + #define __UINT64 unsigned __int64 +#else + #define __INT64 long long + #define __UINT64 unsigned long long +#endif + +#ifdef _WIN32 + #define MFX_CDECL __cdecl + #define MFX_STDCALL __stdcall +#else + #define MFX_CDECL + #define MFX_STDCALL +#endif /* _WIN32 */ + +#define MFX_INFINITE 0xFFFFFFFF + +typedef unsigned char mfxU8; +typedef char mfxI8; +typedef short mfxI16; +typedef unsigned short mfxU16; +typedef unsigned int mfxU32; +typedef int mfxI32; +#if defined( _WIN32 ) || defined ( _WIN64 ) +typedef unsigned long mfxUL32; +typedef long mfxL32; +#else +typedef unsigned int mfxUL32; +typedef int mfxL32; +#endif +typedef float mfxF32; +typedef double mfxF64; +typedef __UINT64 mfxU64; +typedef __INT64 mfxI64; +typedef void* mfxHDL; +typedef mfxHDL mfxMemId; +typedef void* mfxThreadTask; +typedef char mfxChar; + +typedef struct { + mfxI16 x; + mfxI16 y; +} mfxI16Pair; + +typedef struct { + mfxHDL first; + mfxHDL second; +} mfxHDLPair; + + +/*********************************************************************************\ +Error message +\*********************************************************************************/ +typedef enum +{ + /* no error */ + MFX_ERR_NONE = 0, /* no error */ + + /* reserved for unexpected errors */ + MFX_ERR_UNKNOWN = -1, /* unknown error. */ + + /* error codes <0 */ + MFX_ERR_NULL_PTR = -2, /* null pointer */ + MFX_ERR_UNSUPPORTED = -3, /* undeveloped feature */ + MFX_ERR_MEMORY_ALLOC = -4, /* failed to allocate memory */ + MFX_ERR_NOT_ENOUGH_BUFFER = -5, /* insufficient buffer at input/output */ + MFX_ERR_INVALID_HANDLE = -6, /* invalid handle */ + MFX_ERR_LOCK_MEMORY = -7, /* failed to lock the memory block */ + MFX_ERR_NOT_INITIALIZED = -8, /* member function called before initialization */ + MFX_ERR_NOT_FOUND = -9, /* the specified object is not found */ + MFX_ERR_MORE_DATA = -10, /* expect more data at input */ + MFX_ERR_MORE_SURFACE = -11, /* expect more surface at output */ + MFX_ERR_ABORTED = -12, /* operation aborted */ + MFX_ERR_DEVICE_LOST = -13, /* lose the HW acceleration device */ + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM = -14, /* incompatible video parameters */ + MFX_ERR_INVALID_VIDEO_PARAM = -15, /* invalid video parameters */ + MFX_ERR_UNDEFINED_BEHAVIOR = -16, /* undefined behavior */ + MFX_ERR_DEVICE_FAILED = -17, /* device operation failure */ + MFX_ERR_MORE_BITSTREAM = -18, /* expect more bitstream buffers at output */ + MFX_ERR_INCOMPATIBLE_AUDIO_PARAM = -19, /* incompatible audio parameters */ + MFX_ERR_INVALID_AUDIO_PARAM = -20, /* invalid audio parameters */ + + /* warnings >0 */ + MFX_WRN_IN_EXECUTION = 1, /* the previous asynchronous operation is in execution */ + MFX_WRN_DEVICE_BUSY = 2, /* the HW acceleration device is busy */ + MFX_WRN_VIDEO_PARAM_CHANGED = 3, /* the video parameters are changed during decoding */ + MFX_WRN_PARTIAL_ACCELERATION = 4, /* SW is used */ + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM = 5, /* incompatible video parameters */ + MFX_WRN_VALUE_NOT_CHANGED = 6, /* the value is saturated based on its valid range */ + MFX_WRN_OUT_OF_RANGE = 7, /* the value is out of valid range */ + MFX_WRN_FILTER_SKIPPED = 10, /* one of requested filters has been skipped */ + MFX_WRN_INCOMPATIBLE_AUDIO_PARAM = 11, /* incompatible audio parameters */ + + /* threading statuses */ + MFX_TASK_DONE = MFX_ERR_NONE, /* task has been completed */ + MFX_TASK_WORKING = 8, /* there is some more work to do */ + MFX_TASK_BUSY = 9 /* task is waiting for resources */ + +} mfxStatus; + + +// Application +#if defined(MFX_DISPATCHER_EXPOSED_PREFIX) + +#include "mfxdispatcherprefixedfunctions.h" + +#endif // MFX_DISPATCHER_EXPOSED_PREFIX + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __MFXDEFS_H__ */ diff --git a/plugins/obs-qsv11/libmfx/include/msdk/include/mfxenc.h b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxenc.h new file mode 100644 index 000000000..f4ff9c6f1 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxenc.h @@ -0,0 +1,80 @@ +/******************************************************************************* *\ + +Copyright (C) 2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfxenc.h + +*******************************************************************************/ +#ifndef __MFXENC_H__ +#define __MFXENC_H__ +#include "mfxdefs.h" +#include "mfxvstructures.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +typedef struct _mfxENCInput mfxENCInput; +struct _mfxENCInput{ + mfxU32 reserved[32]; + + mfxFrameSurface1 *InSurface; + + mfxU16 NumFrameL0; + mfxFrameSurface1 **L0Surface; + mfxU16 NumFrameL1; + mfxFrameSurface1 **L1Surface; + + mfxU16 NumExtParam; + mfxExtBuffer **ExtParam; +} ; +typedef struct _mfxENCOutput mfxENCOutput; +struct _mfxENCOutput{ + mfxU32 reserved[32]; + + mfxFrameSurface1 *OutSurface; + + mfxU16 NumExtParam; + mfxExtBuffer **ExtParam; +} ; + + +mfxStatus MFX_CDECL MFXVideoENC_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out); +mfxStatus MFX_CDECL MFXVideoENC_QueryIOSurf(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request); +mfxStatus MFX_CDECL MFXVideoENC_Init(mfxSession session, mfxVideoParam *par); +mfxStatus MFX_CDECL MFXVideoENC_Reset(mfxSession session, mfxVideoParam *par); +mfxStatus MFX_CDECL MFXVideoENC_Close(mfxSession session); + +mfxStatus MFX_CDECL MFXVideoENC_ProcessFrameAsync(mfxSession session, mfxENCInput *in, mfxENCOutput *out, mfxSyncPoint *syncp); + + +#ifdef __cplusplus +} // extern "C" +#endif /* __cplusplus */ + + +#endif + diff --git a/plugins/obs-qsv11/libmfx/include/msdk/include/mfxjpeg.h b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxjpeg.h new file mode 100644 index 000000000..396604717 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxjpeg.h @@ -0,0 +1,107 @@ +/******************************************************************************* *\ + +Copyright (C) 2010-2013 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfxjpeg.h + +*******************************************************************************/ +#ifndef __MFX_JPEG_H__ +#define __MFX_JPEG_H__ + +#include "mfxdefs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* CodecId */ +enum { + MFX_CODEC_JPEG = MFX_MAKEFOURCC('J','P','E','G') +}; + +/* CodecProfile, CodecLevel */ +enum +{ + MFX_PROFILE_JPEG_BASELINE = 1 +}; + +enum +{ + MFX_ROTATION_0 = 0, + MFX_ROTATION_90 = 1, + MFX_ROTATION_180 = 2, + MFX_ROTATION_270 = 3 +}; + +enum { + MFX_EXTBUFF_JPEG_QT = MFX_MAKEFOURCC('J','P','G','Q'), + MFX_EXTBUFF_JPEG_HUFFMAN = MFX_MAKEFOURCC('J','P','G','H') +}; + +enum { + MFX_JPEG_COLORFORMAT_UNKNOWN = 0, + MFX_JPEG_COLORFORMAT_YCbCr = 1, + MFX_JPEG_COLORFORMAT_RGB = 2 +}; + +enum { + MFX_SCANTYPE_UNKNOWN = 0, + MFX_SCANTYPE_INTERLEAVED = 1, + MFX_SCANTYPE_NONINTERLEAVED = 2 +}; + +typedef struct { + mfxExtBuffer Header; + + mfxU16 reserved[7]; + mfxU16 NumTable; + + mfxU16 Qm[4][64]; +} mfxExtJPEGQuantTables; + +typedef struct { + mfxExtBuffer Header; + + mfxU16 reserved[2]; + mfxU16 NumDCTable; + mfxU16 NumACTable; + + struct { + mfxU8 Bits[16]; + mfxU8 Values[12]; + } DCTables[4]; + + struct { + mfxU8 Bits[16]; + mfxU8 Values[162]; + } ACTables[4]; +} mfxExtJPEGHuffmanTables; + +#ifdef __cplusplus +} // extern "C" +#endif /* __cplusplus */ + +#endif // __MFX_JPEG_H__ diff --git a/plugins/obs-qsv11/libmfx/include/msdk/include/mfxmvc.h b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxmvc.h new file mode 100644 index 000000000..e9ebe8590 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxmvc.h @@ -0,0 +1,109 @@ +/******************************************************************************* *\ + +Copyright (C) 2010-2013 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfxmvc.h + +*******************************************************************************/ +#ifndef __MFXMVC_H__ +#define __MFXMVC_H__ + +#include "mfxdefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* CodecProfile, CodecLevel */ +enum { + /* MVC profiles */ + MFX_PROFILE_AVC_MULTIVIEW_HIGH =118, + MFX_PROFILE_AVC_STEREO_HIGH =128 +}; + +/* Extended Buffer Ids */ +enum { + MFX_EXTBUFF_MVC_SEQ_DESC = MFX_MAKEFOURCC('M','V','C','D'), + MFX_EXTBUFF_MVC_TARGET_VIEWS = MFX_MAKEFOURCC('M','V','C','T') +}; + +typedef struct { + mfxU16 ViewId; + + mfxU16 NumAnchorRefsL0; + mfxU16 NumAnchorRefsL1; + mfxU16 AnchorRefL0[16]; + mfxU16 AnchorRefL1[16]; + + mfxU16 NumNonAnchorRefsL0; + mfxU16 NumNonAnchorRefsL1; + mfxU16 NonAnchorRefL0[16]; + mfxU16 NonAnchorRefL1[16]; +} mfxMVCViewDependency; + +typedef struct { + mfxU16 TemporalId; + mfxU16 LevelIdc; + + mfxU16 NumViews; + mfxU16 NumTargetViews; + mfxU16 *TargetViewId; +} mfxMVCOperationPoint; + +typedef struct { + mfxExtBuffer Header; + + mfxU32 NumView; + mfxU32 NumViewAlloc; + mfxMVCViewDependency *View; + + mfxU32 NumViewId; + mfxU32 NumViewIdAlloc; + mfxU16 *ViewId; + + mfxU32 NumOP; + mfxU32 NumOPAlloc; + mfxMVCOperationPoint *OP; + + mfxU16 NumRefsTotal; + mfxU32 Reserved[16]; + +} mfxExtMVCSeqDesc; + +typedef struct { + mfxExtBuffer Header; + + mfxU16 TemporalId; + mfxU32 NumView; + mfxU16 ViewId[1024]; +} mfxExtMVCTargetViews ; + + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif + diff --git a/plugins/obs-qsv11/libmfx/include/msdk/include/mfxpak.h b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxpak.h new file mode 100644 index 000000000..b124901ac --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxpak.h @@ -0,0 +1,78 @@ +/******************************************************************************* *\ + +Copyright (C) 2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfxpak.h + +*******************************************************************************/ +#ifndef __MFXPAK_H__ +#define __MFXPAK_H__ +#include "mfxdefs.h" +#include "mfxvstructures.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +typedef struct { + mfxU32 reserved[32]; + + mfxFrameSurface1 *InSurface; + + mfxU16 NumFrameL0; + mfxFrameSurface1 **L0Surface; + mfxU16 NumFrameL1; + mfxFrameSurface1 **L1Surface; + + mfxU16 NumExtParam; + mfxExtBuffer **ExtParam; +} mfxPAKInput; + +typedef struct { + mfxBitstream *Bs; + + mfxFrameSurface1 *OutSurface; + + mfxU16 NumExtParam; + mfxExtBuffer **ExtParam; +} mfxPAKOutput; + +typedef struct _mfxSession *mfxSession; +mfxStatus MFX_CDECL MFXVideoPAK_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out); +mfxStatus MFX_CDECL MFXVideoPAK_QueryIOSurf(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request); +mfxStatus MFX_CDECL MFXVideoPAK_Init(mfxSession session, mfxVideoParam *par); +mfxStatus MFX_CDECL MFXVideoPAK_Reset(mfxSession session, mfxVideoParam *par); +mfxStatus MFX_CDECL MFXVideoPAK_Close(mfxSession session); + +mfxStatus MFX_CDECL MFXVideoPAK_ProcessFrameAsync(mfxSession session, mfxPAKInput *in, mfxPAKOutput *out, mfxSyncPoint *syncp); + + +#ifdef __cplusplus +} // extern "C" +#endif /* __cplusplus */ + + +#endif diff --git a/plugins/obs-qsv11/libmfx/include/msdk/include/mfxplugin++.h b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxplugin++.h new file mode 100644 index 000000000..47212ddc1 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxplugin++.h @@ -0,0 +1,719 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2007-2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +File Name: mfxplugin++.h + +\* ****************************************************************************** */ + +#ifndef __MFXPLUGINPLUSPLUS_H +#define __MFXPLUGINPLUSPLUS_H + +#include "mfxplugin.h" + +// base class for MFXVideoUSER/MFXAudioUSER API + +class MFXBaseUSER { +public: + explicit MFXBaseUSER(mfxSession session = NULL) + : m_session(session){} + + virtual ~MFXBaseUSER() {}; + + virtual mfxStatus Register(mfxU32 type, const mfxPlugin *par) = 0; + virtual mfxStatus Unregister(mfxU32 type) = 0; + virtual mfxStatus ProcessFrameAsync(const mfxHDL *in, mfxU32 in_num, const mfxHDL *out, mfxU32 out_num, mfxSyncPoint *syncp) = 0; + +protected: + mfxSession m_session; +}; + +//c++ wrapper over only 3 exposed functions from MFXVideoUSER module +class MFXVideoUSER: public MFXBaseUSER { +public: + explicit MFXVideoUSER(mfxSession session = NULL) + : MFXBaseUSER(session){} + + virtual mfxStatus Register(mfxU32 type, const mfxPlugin *par) { + return MFXVideoUSER_Register(m_session, type, par); + } + virtual mfxStatus Unregister(mfxU32 type) { + return MFXVideoUSER_Unregister(m_session, type); + } + virtual mfxStatus ProcessFrameAsync(const mfxHDL *in, mfxU32 in_num, const mfxHDL *out, mfxU32 out_num, mfxSyncPoint *syncp) { + return MFXVideoUSER_ProcessFrameAsync(m_session, in, in_num, out, out_num, syncp); + } +}; + +//c++ wrapper over only 3 exposed functions from MFXAudioUSER module +class MFXAudioUSER: public MFXBaseUSER { +public: + explicit MFXAudioUSER(mfxSession session = NULL) + : MFXBaseUSER(session){} + + virtual mfxStatus Register(mfxU32 type, const mfxPlugin *par) { + return MFXAudioUSER_Register(m_session, type, par); + } + virtual mfxStatus Unregister(mfxU32 type) { + return MFXAudioUSER_Unregister(m_session, type); + } + virtual mfxStatus ProcessFrameAsync(const mfxHDL *in, mfxU32 in_num, const mfxHDL *out, mfxU32 out_num, mfxSyncPoint *syncp) { + return MFXAudioUSER_ProcessFrameAsync(m_session, in, in_num, out, out_num, syncp); + } +}; + + +//initialize mfxPlugin struct +class MFXPluginParam { + mfxPluginParam m_param; + +public: + MFXPluginParam(mfxU32 CodecId, mfxU32 Type, mfxPluginUID uid, mfxThreadPolicy ThreadPolicy = MFX_THREADPOLICY_SERIAL, mfxU32 MaxThreadNum = 1) + : m_param() { + m_param.PluginUID = uid; + m_param.Type = Type; + m_param.CodecId = CodecId; + m_param.MaxThreadNum = MaxThreadNum; + m_param.ThreadPolicy = ThreadPolicy; + } + operator const mfxPluginParam& () const { + return m_param; + } + operator mfxPluginParam& () { + return m_param; + } +}; + +//common interface part for every plugin: decoder/encoder and generic +struct MFXPlugin +{ + virtual ~MFXPlugin() {}; + //init function always required for any transform or codec plugins, for codec plugins it maps to callback from MediaSDK + //for generic plugin application should call it + //MediaSDK mfxPlugin API mapping + virtual mfxStatus PluginInit(mfxCoreInterface *core) = 0; + //release CoreInterface, and destroy plugin state, not destroy plugin instance + virtual mfxStatus PluginClose() = 0; + virtual mfxStatus GetPluginParam(mfxPluginParam *par) = 0; + virtual mfxStatus Execute(mfxThreadTask task, mfxU32 uid_p, mfxU32 uid_a) = 0; + virtual mfxStatus FreeResources(mfxThreadTask task, mfxStatus sts) = 0; + //destroy plugin due to shared module distribution model plugin wont support virtual destructor + virtual void Release() = 0; + //release resources associated with current instance of plugin, but do not release CoreInterface related resource set in pluginInit + virtual mfxStatus Close() = 0; + //communication protocol between particular version of plugin and application + virtual mfxStatus SetAuxParams(void* auxParam, int auxParamSize) = 0; +}; + +//common extension interface that codec plugins should expose additionally to MFXPlugin +struct MFXCodecPlugin : MFXPlugin +{ + virtual mfxStatus Init(mfxVideoParam *par) = 0; + virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest *in, mfxFrameAllocRequest *out) = 0; + virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) =0; + virtual mfxStatus Reset(mfxVideoParam *par) = 0; + virtual mfxStatus GetVideoParam(mfxVideoParam *par) = 0; +}; + +//common extension interface that audio codec plugins should expose additionally to MFXPlugin +struct MFXAudioCodecPlugin : MFXPlugin +{ + virtual mfxStatus Init(mfxAudioParam *par) = 0; + virtual mfxStatus Query(mfxAudioParam *in, mfxAudioParam *out) =0; + virtual mfxStatus QueryIOSize(mfxAudioParam *par, mfxAudioAllocRequest *request) = 0; + virtual mfxStatus Reset(mfxAudioParam *par) = 0; + virtual mfxStatus GetAudioParam(mfxAudioParam *par) = 0; +}; + +//general purpose transform plugin interface, not a codec plugin +struct MFXGenericPlugin : MFXPlugin +{ + virtual mfxStatus Init(mfxVideoParam *par) = 0; + virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest *in, mfxFrameAllocRequest *out) = 0; + virtual mfxStatus Submit(const mfxHDL *in, mfxU32 in_num, const mfxHDL *out, mfxU32 out_num, mfxThreadTask *task) = 0; +}; + +//decoder plugins may only support this interface +struct MFXDecoderPlugin : MFXCodecPlugin +{ + virtual mfxStatus DecodeHeader(mfxBitstream *bs, mfxVideoParam *par) = 0; + virtual mfxStatus GetPayload(mfxU64 *ts, mfxPayload *payload) = 0; + virtual mfxStatus DecodeFrameSubmit(mfxBitstream *bs, mfxFrameSurface1 *surface_work, mfxFrameSurface1 **surface_out, mfxThreadTask *task) = 0; +}; + +//audio decoder plugins may only support this interface +struct MFXAudioDecoderPlugin : MFXAudioCodecPlugin +{ + virtual mfxStatus DecodeHeader(mfxBitstream *bs, mfxAudioParam *par) = 0; +// virtual mfxStatus GetPayload(mfxU64 *ts, mfxPayload *payload) = 0; + virtual mfxStatus DecodeFrameSubmit(mfxBitstream *in, mfxAudioFrame *out, mfxThreadTask *task) = 0; +}; + +//encoder plugins may only support this interface +struct MFXEncoderPlugin : MFXCodecPlugin +{ + virtual mfxStatus EncodeFrameSubmit(mfxEncodeCtrl *ctrl, mfxFrameSurface1 *surface, mfxBitstream *bs, mfxThreadTask *task) = 0; +}; + +//audio encoder plugins may only support this interface +struct MFXAudioEncoderPlugin : MFXAudioCodecPlugin +{ + virtual mfxStatus EncodeFrameSubmit(mfxAudioFrame *aFrame, mfxBitstream *out, mfxThreadTask *task) = 0; +}; + +//vpp plugins may only support this interface +struct MFXVPPPlugin : MFXCodecPlugin +{ + virtual mfxStatus VPPFrameSubmit(mfxFrameSurface1 *surface_in, mfxFrameSurface1 *surface_out, mfxExtVppAuxData *aux, mfxThreadTask *task) = 0; + virtual mfxStatus VPPFrameSubmitEx(mfxFrameSurface1 *in, mfxFrameSurface1 *surface_work, mfxFrameSurface1 **surface_out, mfxThreadTask *task) = 0; +}; + +struct MFXEncPlugin : MFXCodecPlugin +{ + virtual mfxStatus EncFrameSubmit(mfxENCInput *in, mfxENCOutput *out, mfxThreadTask *task) = 0; +}; + + + + +class MFXCoreInterface +{ +protected: + mfxCoreInterface m_core; +public: + + MFXCoreInterface() + : m_core() { + } + MFXCoreInterface(const mfxCoreInterface & pCore) + : m_core(pCore) { + } + + MFXCoreInterface(const MFXCoreInterface & that) + : m_core(that.m_core) { + } + MFXCoreInterface &operator = (const MFXCoreInterface & that) + { + m_core = that.m_core; + return *this; + } + bool IsCoreSet() { + return m_core.pthis != 0; + } + mfxStatus GetCoreParam(mfxCoreParam *par) { + if (!IsCoreSet()) { + return MFX_ERR_NULL_PTR; + } + return m_core.GetCoreParam(m_core.pthis, par); + } + mfxStatus GetHandle (mfxHandleType type, mfxHDL *handle) { + if (!IsCoreSet()) { + return MFX_ERR_NULL_PTR; + } + return m_core.GetHandle(m_core.pthis, type, handle); + } + mfxStatus IncreaseReference (mfxFrameData *fd) { + if (!IsCoreSet()) { + return MFX_ERR_NULL_PTR; + } + return m_core.IncreaseReference(m_core.pthis, fd); + } + mfxStatus DecreaseReference (mfxFrameData *fd) { + if (!IsCoreSet()) { + return MFX_ERR_NULL_PTR; + } + return m_core.DecreaseReference(m_core.pthis, fd); + } + mfxStatus CopyFrame (mfxFrameSurface1 *dst, mfxFrameSurface1 *src) { + if (!IsCoreSet()) { + return MFX_ERR_NULL_PTR; + } + return m_core.CopyFrame(m_core.pthis, dst, src); + } + mfxStatus CopyBuffer(mfxU8 *dst, mfxU32 size, mfxFrameSurface1 *src) { + if (!IsCoreSet()) { + return MFX_ERR_NULL_PTR; + } + return m_core.CopyBuffer(m_core.pthis, dst, size, src); + } + mfxStatus MapOpaqueSurface(mfxU32 num, mfxU32 type, mfxFrameSurface1 **op_surf) { + if (!IsCoreSet()) { + return MFX_ERR_NULL_PTR; + } + return m_core.MapOpaqueSurface(m_core.pthis, num, type, op_surf); + } + mfxStatus UnmapOpaqueSurface(mfxU32 num, mfxU32 type, mfxFrameSurface1 **op_surf) { + if (!IsCoreSet()) { + return MFX_ERR_NULL_PTR; + } + return m_core.UnmapOpaqueSurface(m_core.pthis, num, type, op_surf); + } + mfxStatus GetRealSurface(mfxFrameSurface1 *op_surf, mfxFrameSurface1 **surf) { + if (!IsCoreSet()) { + return MFX_ERR_NULL_PTR; + } + return m_core.GetRealSurface(m_core.pthis, op_surf, surf); + } + mfxStatus GetOpaqueSurface(mfxFrameSurface1 *surf, mfxFrameSurface1 **op_surf) { + if (!IsCoreSet()) { + return MFX_ERR_NULL_PTR; + } + return m_core.GetOpaqueSurface(m_core.pthis, surf, op_surf); + } + mfxStatus CreateAccelerationDevice(mfxHandleType type, mfxHDL *handle) { + if (!IsCoreSet()) { + return MFX_ERR_NULL_PTR; + } + return m_core.CreateAccelerationDevice(m_core.pthis, type, handle); + } + mfxFrameAllocator & FrameAllocator() { + return m_core.FrameAllocator; + } + +} ; + +/* Class adapter between "C" structure mfxPlugin and C++ interface MFXPlugin */ + +namespace detail +{ + template + class MFXPluginAdapterBase + { + protected: + mfxPlugin m_mfxAPI; + public: + MFXPluginAdapterBase( T *plugin, mfxVideoCodecPlugin *pCodec = NULL) + { + SetupCallbacks(plugin, pCodec); + } + + MFXPluginAdapterBase( T *plugin, mfxAudioCodecPlugin *pCodec) + { + SetupCallbacks(plugin, pCodec); + } + + operator mfxPlugin () const { + return m_mfxAPI; + } + void SetupCallbacks(T *plugin) { + m_mfxAPI.pthis = plugin; + m_mfxAPI.PluginInit = _PluginInit; + m_mfxAPI.PluginClose = _PluginClose; + m_mfxAPI.GetPluginParam = _GetPluginParam; + m_mfxAPI.Submit = 0; + m_mfxAPI.Execute = _Execute; + m_mfxAPI.FreeResources = _FreeResources; + } + + void SetupCallbacks( T *plugin, mfxVideoCodecPlugin *pCodec) { + SetupCallbacks(plugin); + m_mfxAPI.Video = pCodec; + } + + void SetupCallbacks( T *plugin, mfxAudioCodecPlugin *pCodec) { + SetupCallbacks(plugin); + m_mfxAPI.Audio = pCodec; + } + private: + + static mfxStatus _PluginInit(mfxHDL pthis, mfxCoreInterface *core) { + return reinterpret_cast(pthis)->PluginInit(core); + } + static mfxStatus _PluginClose(mfxHDL pthis) { + return reinterpret_cast(pthis)->PluginClose(); + } + static mfxStatus _GetPluginParam(mfxHDL pthis, mfxPluginParam *par) { + return reinterpret_cast(pthis)->GetPluginParam(par); + } + static mfxStatus _Execute(mfxHDL pthis, mfxThreadTask task, mfxU32 thread_id, mfxU32 call_count) { + return reinterpret_cast(pthis)->Execute(task, thread_id, call_count); + } + static mfxStatus _FreeResources(mfxHDL pthis, mfxThreadTask task, mfxStatus sts) { + return reinterpret_cast(pthis)->FreeResources(task, sts); + } + }; + + template + class MFXCodecPluginAdapterBase : public MFXPluginAdapterBase + { + protected: + //stub to feed mediasdk plugin API + mfxVideoCodecPlugin m_codecPlg; + public: + MFXCodecPluginAdapterBase(T * pCodecPlg) + : MFXPluginAdapterBase(pCodecPlg, &m_codecPlg) + , m_codecPlg() + { + m_codecPlg.Query = _Query; + m_codecPlg.QueryIOSurf = _QueryIOSurf ; + m_codecPlg.Init = _Init; + m_codecPlg.Reset = _Reset; + m_codecPlg.Close = _Close; + m_codecPlg.GetVideoParam = _GetVideoParam; + } + MFXCodecPluginAdapterBase(const MFXCodecPluginAdapterBase & that) + : MFXPluginAdapterBase(reinterpret_cast(that.m_mfxAPI.pthis), &m_codecPlg) + , m_codecPlg() { + SetupCallbacks(); + } + MFXCodecPluginAdapterBase& operator = (const MFXCodecPluginAdapterBase & that) { + MFXPluginAdapterBase :: SetupCallbacks(reinterpret_cast(that.m_mfxAPI.pthis), &m_codecPlg); + SetupCallbacks(); + return *this; + } + + private: + void SetupCallbacks() { + m_codecPlg.Query = _Query; + m_codecPlg.QueryIOSurf = _QueryIOSurf ; + m_codecPlg.Init = _Init; + m_codecPlg.Reset = _Reset; + m_codecPlg.Close = _Close; + m_codecPlg.GetVideoParam = _GetVideoParam; + } + static mfxStatus _Query(mfxHDL pthis, mfxVideoParam *in, mfxVideoParam *out) { + return reinterpret_cast(pthis)->Query(in, out); + } + static mfxStatus _QueryIOSurf(mfxHDL pthis, mfxVideoParam *par, mfxFrameAllocRequest *in, mfxFrameAllocRequest *out){ + return reinterpret_cast(pthis)->QueryIOSurf(par, in, out); + } + static mfxStatus _Init(mfxHDL pthis, mfxVideoParam *par){ + return reinterpret_cast(pthis)->Init(par); + } + static mfxStatus _Reset(mfxHDL pthis, mfxVideoParam *par){ + return reinterpret_cast(pthis)->Reset(par); + } + static mfxStatus _Close(mfxHDL pthis) { + return reinterpret_cast(pthis)->Close(); + } + static mfxStatus _GetVideoParam(mfxHDL pthis, mfxVideoParam *par) { + return reinterpret_cast(pthis)->GetVideoParam(par); + } + }; + + template + class MFXAudioCodecPluginAdapterBase : public MFXPluginAdapterBase + { + protected: + //stub to feed mediasdk plugin API + mfxAudioCodecPlugin m_codecPlg; + public: + MFXAudioCodecPluginAdapterBase(T * pCodecPlg) + : MFXPluginAdapterBase(pCodecPlg, &m_codecPlg) + , m_codecPlg() + { + m_codecPlg.Query = _Query; + m_codecPlg.QueryIOSize = _QueryIOSize ; + m_codecPlg.Init = _Init; + m_codecPlg.Reset = _Reset; + m_codecPlg.Close = _Close; + m_codecPlg.GetAudioParam = _GetAudioParam; + } + MFXAudioCodecPluginAdapterBase(const MFXCodecPluginAdapterBase & that) + : MFXPluginAdapterBase(reinterpret_cast(that.m_mfxAPI.pthis), &m_codecPlg) + , m_codecPlg() { + SetupCallbacks(); + } + MFXAudioCodecPluginAdapterBase& operator = (const MFXAudioCodecPluginAdapterBase & that) { + MFXPluginAdapterBase :: SetupCallbacks(reinterpret_cast(that.m_mfxAPI.pthis), &m_codecPlg); + SetupCallbacks(); + return *this; + } + + private: + void SetupCallbacks() { + m_codecPlg.Query = _Query; + m_codecPlg.QueryIOSize = _QueryIOSize; + m_codecPlg.Init = _Init; + m_codecPlg.Reset = _Reset; + m_codecPlg.Close = _Close; + m_codecPlg.GetAudioParam = _GetAudioParam; + } + static mfxStatus _Query(mfxHDL pthis, mfxAudioParam *in, mfxAudioParam *out) { + return reinterpret_cast(pthis)->Query(in, out); + } + static mfxStatus _QueryIOSize(mfxHDL pthis, mfxAudioParam *par, mfxAudioAllocRequest *request){ + return reinterpret_cast(pthis)->QueryIOSize(par, request); + } + static mfxStatus _Init(mfxHDL pthis, mfxAudioParam *par){ + return reinterpret_cast(pthis)->Init(par); + } + static mfxStatus _Reset(mfxHDL pthis, mfxAudioParam *par){ + return reinterpret_cast(pthis)->Reset(par); + } + static mfxStatus _Close(mfxHDL pthis) { + return reinterpret_cast(pthis)->Close(); + } + static mfxStatus _GetAudioParam(mfxHDL pthis, mfxAudioParam *par) { + return reinterpret_cast(pthis)->GetAudioParam(par); + } + }; + + template + struct MFXPluginAdapterInternal{}; + template<> + class MFXPluginAdapterInternal : public MFXPluginAdapterBase + { + public: + MFXPluginAdapterInternal(MFXGenericPlugin *pPlugin) + : MFXPluginAdapterBase(pPlugin) + { + m_mfxAPI.Submit = _Submit; + } + MFXPluginAdapterInternal(const MFXPluginAdapterInternal & that ) + : MFXPluginAdapterBase(that) { + m_mfxAPI.Submit = that._Submit; + } + MFXPluginAdapterInternal& operator = (const MFXPluginAdapterInternal & that) { + MFXPluginAdapterBase::operator=(that); + m_mfxAPI.Submit = that._Submit; + return *this; + } + + private: + static mfxStatus _Submit(mfxHDL pthis, const mfxHDL *in, mfxU32 in_num, const mfxHDL *out, mfxU32 out_num, mfxThreadTask *task) { + return reinterpret_cast(pthis)->Submit(in, in_num, out, out_num, task); + } + }; + + template<> + class MFXPluginAdapterInternal : public MFXCodecPluginAdapterBase + { + public: + MFXPluginAdapterInternal(MFXDecoderPlugin *pPlugin) + : MFXCodecPluginAdapterBase(pPlugin) + { + SetupCallbacks(); + } + + MFXPluginAdapterInternal(const MFXPluginAdapterInternal & that) + : MFXCodecPluginAdapterBase(that) { + SetupCallbacks(); + } + + MFXPluginAdapterInternal& operator = (const MFXPluginAdapterInternal & that) { + MFXCodecPluginAdapterBase::operator=(that); + SetupCallbacks(); + return *this; + } + + private: + void SetupCallbacks() { + m_codecPlg.DecodeHeader = _DecodeHeader; + m_codecPlg.GetPayload = _GetPayload; + m_codecPlg.DecodeFrameSubmit = _DecodeFrameSubmit; + } + static mfxStatus _DecodeHeader(mfxHDL pthis, mfxBitstream *bs, mfxVideoParam *par) { + return reinterpret_cast(pthis)->DecodeHeader(bs, par); + } + static mfxStatus _GetPayload(mfxHDL pthis, mfxU64 *ts, mfxPayload *payload) { + return reinterpret_cast(pthis)->GetPayload(ts, payload); + } + static mfxStatus _DecodeFrameSubmit(mfxHDL pthis, mfxBitstream *bs, mfxFrameSurface1 *surface_work, mfxFrameSurface1 **surface_out, mfxThreadTask *task) { + return reinterpret_cast(pthis)->DecodeFrameSubmit(bs, surface_work, surface_out, task); + } + }; + + template<> + class MFXPluginAdapterInternal : public MFXAudioCodecPluginAdapterBase + { + public: + MFXPluginAdapterInternal(MFXAudioDecoderPlugin *pPlugin) + : MFXAudioCodecPluginAdapterBase(pPlugin) + { + SetupCallbacks(); + } + + MFXPluginAdapterInternal(const MFXPluginAdapterInternal & that) + : MFXAudioCodecPluginAdapterBase(that) { + SetupCallbacks(); + } + + MFXPluginAdapterInternal& operator = (const MFXPluginAdapterInternal & that) { + MFXAudioCodecPluginAdapterBase::operator=(that); + SetupCallbacks(); + return *this; + } + + private: + void SetupCallbacks() { + m_codecPlg.DecodeHeader = _DecodeHeader; +// m_codecPlg.GetPayload = _GetPayload; + m_codecPlg.DecodeFrameSubmit = _DecodeFrameSubmit; + } + static mfxStatus _DecodeHeader(mfxHDL pthis, mfxBitstream *bs, mfxAudioParam *par) { + return reinterpret_cast(pthis)->DecodeHeader(bs, par); + } +// static mfxStatus _GetPayload(mfxHDL pthis, mfxU64 *ts, mfxPayload *payload) { + // return reinterpret_cast(pthis)->GetPayload(ts, payload); + // } + static mfxStatus _DecodeFrameSubmit(mfxHDL pthis, mfxBitstream *in, mfxAudioFrame *out, mfxThreadTask *task) { + return reinterpret_cast(pthis)->DecodeFrameSubmit(in, out, task); + } + }; + + template<> + class MFXPluginAdapterInternal : public MFXCodecPluginAdapterBase + { + public: + MFXPluginAdapterInternal(MFXEncoderPlugin *pPlugin) + : MFXCodecPluginAdapterBase(pPlugin) + { + m_codecPlg.EncodeFrameSubmit = _EncodeFrameSubmit; + } + MFXPluginAdapterInternal(const MFXPluginAdapterInternal & that) + : MFXCodecPluginAdapterBase(that) { + m_codecPlg.EncodeFrameSubmit = _EncodeFrameSubmit; + } + + MFXPluginAdapterInternal& operator = (const MFXPluginAdapterInternal & that) { + MFXCodecPluginAdapterBase::operator = (that); + m_codecPlg.EncodeFrameSubmit = _EncodeFrameSubmit; + return *this; + } + + private: + static mfxStatus _EncodeFrameSubmit(mfxHDL pthis, mfxEncodeCtrl *ctrl, mfxFrameSurface1 *surface, mfxBitstream *bs, mfxThreadTask *task) { + return reinterpret_cast(pthis)->EncodeFrameSubmit(ctrl, surface, bs, task); + } + }; + + template<> + class MFXPluginAdapterInternal : public MFXAudioCodecPluginAdapterBase + { + public: + MFXPluginAdapterInternal(MFXAudioEncoderPlugin *pPlugin) + : MFXAudioCodecPluginAdapterBase(pPlugin) + { + SetupCallbacks(); + } + + MFXPluginAdapterInternal(const MFXPluginAdapterInternal & that) + : MFXAudioCodecPluginAdapterBase(that) { + SetupCallbacks(); + } + + MFXPluginAdapterInternal& operator = (const MFXPluginAdapterInternal & that) { + MFXAudioCodecPluginAdapterBase::operator=(that); + SetupCallbacks(); + return *this; + } + + private: + void SetupCallbacks() { + m_codecPlg.EncodeFrameSubmit = _EncodeFrameSubmit; + } + static mfxStatus _EncodeFrameSubmit(mfxHDL pthis, mfxAudioFrame *aFrame, mfxBitstream *out, mfxThreadTask *task) { + return reinterpret_cast(pthis)->EncodeFrameSubmit(aFrame, out, task); + } + }; + + template<> + class MFXPluginAdapterInternal : public MFXCodecPluginAdapterBase + { + public: + MFXPluginAdapterInternal(MFXEncPlugin *pPlugin) + : MFXCodecPluginAdapterBase(pPlugin) + { + m_codecPlg.ENCFrameSubmit = _ENCFrameSubmit; + } + MFXPluginAdapterInternal(const MFXPluginAdapterInternal & that) + : MFXCodecPluginAdapterBase(that) { + m_codecPlg.ENCFrameSubmit = _ENCFrameSubmit; + } + + MFXPluginAdapterInternal& operator = (const MFXPluginAdapterInternal & that) { + MFXCodecPluginAdapterBase::operator = (that); + m_codecPlg.ENCFrameSubmit = _ENCFrameSubmit; + return *this; + } + + private: + static mfxStatus _ENCFrameSubmit(mfxHDL pthis,mfxENCInput *in, mfxENCOutput *out, mfxThreadTask *task) { + return reinterpret_cast(pthis)->EncFrameSubmit(in, out, task); + } + }; + + + template<> + class MFXPluginAdapterInternal : public MFXCodecPluginAdapterBase + { + public: + MFXPluginAdapterInternal(MFXVPPPlugin *pPlugin) + : MFXCodecPluginAdapterBase(pPlugin) + { + SetupCallbacks(); + } + MFXPluginAdapterInternal(const MFXPluginAdapterInternal & that) + : MFXCodecPluginAdapterBase(that) { + SetupCallbacks(); + } + + MFXPluginAdapterInternal& operator = (const MFXPluginAdapterInternal & that) { + MFXCodecPluginAdapterBase::operator = (that); + SetupCallbacks(); + return *this; + } + + private: + void SetupCallbacks() { + m_codecPlg.VPPFrameSubmit = _VPPFrameSubmit; + m_codecPlg.VPPFrameSubmitEx = _VPPFrameSubmitEx; + } + static mfxStatus _VPPFrameSubmit(mfxHDL pthis, mfxFrameSurface1 *surface_in, mfxFrameSurface1 *surface_out, mfxExtVppAuxData *aux, mfxThreadTask *task) { + return reinterpret_cast(pthis)->VPPFrameSubmit(surface_in, surface_out, aux, task); + } + static mfxStatus _VPPFrameSubmitEx(mfxHDL pthis, mfxFrameSurface1 *surface_in, mfxFrameSurface1 *surface_work, mfxFrameSurface1 **surface_out, mfxThreadTask *task) { + return reinterpret_cast(pthis)->VPPFrameSubmitEx(surface_in, surface_work, surface_out, task); + } + }; +} + +/* adapter for particular plugin type*/ +template +class MFXPluginAdapter +{ +public: + detail::MFXPluginAdapterInternal m_Adapter; + + operator mfxPlugin () const { + return m_Adapter.operator mfxPlugin(); + } + + MFXPluginAdapter(T* pPlugin = NULL) + : m_Adapter(pPlugin) + { + } +}; + +template +inline MFXPluginAdapter make_mfx_plugin_adapter(T* pPlugin) { + + MFXPluginAdapter adapt(pPlugin); + return adapt; +} + +#endif // __MFXPLUGINPLUSPLUS_H diff --git a/plugins/obs-qsv11/libmfx/include/msdk/include/mfxplugin.h b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxplugin.h new file mode 100644 index 000000000..3d34d1346 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxplugin.h @@ -0,0 +1,206 @@ +/******************************************************************************* *\ + +Copyright (C) 2007-2015 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfxplugin.h + +*******************************************************************************/ +#ifndef __MFXPLUGIN_H__ +#define __MFXPLUGIN_H__ +#include "mfxvideo.h" +#include "mfxaudio.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +typedef struct { + mfxU8 Data[16]; +} mfxPluginUID; + +static const mfxPluginUID MFX_PLUGINID_HEVCD_SW = {{0x15, 0xdd, 0x93, 0x68, 0x25, 0xad, 0x47, 0x5e, 0xa3, 0x4e, 0x35, 0xf3, 0xf5, 0x42, 0x17, 0xa6}}; +static const mfxPluginUID MFX_PLUGINID_HEVCD_HW = {{0x33, 0xa6, 0x1c, 0x0b, 0x4c, 0x27, 0x45, 0x4c, 0xa8, 0xd8, 0x5d, 0xde, 0x75, 0x7c, 0x6f, 0x8e}}; +static const mfxPluginUID MFX_PLUGINID_HEVCE_SW = {{0x2f, 0xca, 0x99, 0x74, 0x9f, 0xdb, 0x49, 0xae, 0xb1, 0x21, 0xa5, 0xb6, 0x3e, 0xf5, 0x68, 0xf7}}; +static const mfxPluginUID MFX_PLUGINID_HEVCE_GACC = {{0xe5, 0x40, 0x0a, 0x06, 0xc7, 0x4d, 0x41, 0xf5, 0xb1, 0x2d, 0x43, 0x0b, 0xba, 0xa2, 0x3d, 0x0b}}; +static const mfxPluginUID MFX_PLUGINID_HEVCE_HW = {{0x6f, 0xad, 0xc7, 0x91, 0xa0, 0xc2, 0xeb, 0x47, 0x9a, 0xb6, 0xdc, 0xd5, 0xea, 0x9d, 0xa3, 0x47}}; +static const mfxPluginUID MFX_PLUGINID_VP8D_HW = {{0xf6, 0x22, 0x39, 0x4d, 0x8d, 0x87, 0x45, 0x2f, 0x87, 0x8c, 0x51, 0xf2, 0xfc, 0x9b, 0x41, 0x31}}; +static const mfxPluginUID MFX_PLUGINID_VP8E_HW = {{0xbf, 0xfc, 0x51, 0x8c, 0xde, 0x13, 0x4d, 0xf9, 0x8a, 0x96, 0xf4, 0xcf, 0x81, 0x6c, 0x0f, 0xac}}; +static const mfxPluginUID MFX_PLUGINID_VP9E_HW = {{0xce, 0x44, 0xef, 0x6f, 0x1a, 0x6d, 0x22, 0x46, 0xb4, 0x12, 0xbb, 0x38, 0xd6, 0xe4, 0x51, 0x82}}; +static const mfxPluginUID MFX_PLUGINID_VP9D_HW = {{0xa9, 0x22, 0x39, 0x4d, 0x8d, 0x87, 0x45, 0x2f, 0x87, 0x8c, 0x51, 0xf2, 0xfc, 0x9b, 0x41, 0x31}}; +static const mfxPluginUID MFX_PLUGINID_CAMERA_HW = {{0x54, 0x54, 0x26, 0x16, 0x24, 0x33, 0x41, 0xe6, 0x93, 0xae, 0x89, 0x99, 0x42, 0xce, 0x73, 0x55}}; +static const mfxPluginUID MFX_PLUGINID_CAPTURE_HW = {{0x22, 0xd6, 0x2c, 0x07, 0xe6, 0x72, 0x40, 0x8f, 0xbb, 0x4c, 0xc2, 0x0e, 0xd7, 0xa0, 0x53, 0xe4}}; +static const mfxPluginUID MFX_PLUGINID_ITELECINE_HW = {{0xe7, 0x44, 0x75, 0x3a, 0xcd, 0x74, 0x40, 0x2e, 0x89, 0xa2, 0xee, 0x06, 0x35, 0x49, 0x61, 0x79}}; +static const mfxPluginUID MFX_PLUGINID_H264LA_HW = {{0x58, 0x8f, 0x11, 0x85, 0xd4, 0x7b, 0x42, 0x96, 0x8d, 0xea, 0x37, 0x7b, 0xb5, 0xd0, 0xdc, 0xb4}}; +static const mfxPluginUID MFX_PLUGINID_AACD = {{0xe9, 0x34, 0x67, 0x25, 0xac, 0x2f, 0x4c, 0x93, 0xaa, 0x58, 0x5c, 0x11, 0xc7, 0x08, 0x7c, 0xf4}}; +static const mfxPluginUID MFX_PLUGINID_AACE = {{0xb2, 0xa2, 0xa0, 0x5a, 0x4e, 0xac, 0x46, 0xbf, 0xa9, 0xde, 0x7e, 0x80, 0xc9, 0x8d, 0x2e, 0x18}}; +static const mfxPluginUID MFX_PLUGINID_HEVCE_FEI_HW = {{0x87, 0xe0, 0xe8, 0x02, 0x07, 0x37, 0x52, 0x40, 0x85, 0x25, 0x15, 0xcf, 0x4a, 0x5e, 0xdd, 0xe6}}; + + +typedef enum { + MFX_PLUGINTYPE_VIDEO_GENERAL = 0, + MFX_PLUGINTYPE_VIDEO_DECODE = 1, + MFX_PLUGINTYPE_VIDEO_ENCODE = 2, + MFX_PLUGINTYPE_VIDEO_VPP = 3, + MFX_PLUGINTYPE_VIDEO_ENC = 4, + MFX_PLUGINTYPE_AUDIO_DECODE = 5, + MFX_PLUGINTYPE_AUDIO_ENCODE = 6 +} mfxPluginType; + +typedef enum { + MFX_THREADPOLICY_SERIAL = 0, + MFX_THREADPOLICY_PARALLEL = 1 +} mfxThreadPolicy; + +typedef struct mfxPluginParam { + mfxU32 reserved[6]; + mfxU16 reserved1; + mfxU16 PluginVersion; + mfxVersion APIVersion; + mfxPluginUID PluginUID; + mfxU32 Type; + mfxU32 CodecId; + mfxThreadPolicy ThreadPolicy; + mfxU32 MaxThreadNum; +} mfxPluginParam; + +typedef struct mfxCoreParam{ + mfxU32 reserved[13]; + mfxIMPL Impl; + mfxVersion Version; + mfxU32 NumWorkingThread; +} mfxCoreParam; + +typedef struct mfxCoreInterface { + mfxHDL pthis; + + mfxHDL reserved1[2]; + mfxFrameAllocator FrameAllocator; + mfxBufferAllocator reserved3; + + mfxStatus (MFX_CDECL *GetCoreParam)(mfxHDL pthis, mfxCoreParam *par); + mfxStatus (MFX_CDECL *GetHandle) (mfxHDL pthis, mfxHandleType type, mfxHDL *handle); + mfxStatus (MFX_CDECL *IncreaseReference) (mfxHDL pthis, mfxFrameData *fd); + mfxStatus (MFX_CDECL *DecreaseReference) (mfxHDL pthis, mfxFrameData *fd); + mfxStatus (MFX_CDECL *CopyFrame) (mfxHDL pthis, mfxFrameSurface1 *dst, mfxFrameSurface1 *src); + mfxStatus (MFX_CDECL *CopyBuffer)(mfxHDL pthis, mfxU8 *dst, mfxU32 size, mfxFrameSurface1 *src); + + mfxStatus (MFX_CDECL *MapOpaqueSurface)(mfxHDL pthis, mfxU32 num, mfxU32 type, mfxFrameSurface1 **op_surf); + mfxStatus (MFX_CDECL *UnmapOpaqueSurface)(mfxHDL pthis, mfxU32 num, mfxU32 type, mfxFrameSurface1 **op_surf); + + mfxStatus (MFX_CDECL *GetRealSurface)(mfxHDL pthis, mfxFrameSurface1 *op_surf, mfxFrameSurface1 **surf); + mfxStatus (MFX_CDECL *GetOpaqueSurface)(mfxHDL pthis, mfxFrameSurface1 *surf, mfxFrameSurface1 **op_surf); + + mfxStatus (MFX_CDECL *CreateAccelerationDevice)(mfxHDL pthis, mfxHandleType type, mfxHDL *handle); + + mfxHDL reserved4[3]; +} mfxCoreInterface; + +/* video codec plugin extension*/ +typedef struct _mfxENCInput mfxENCInput; +typedef struct _mfxENCOutput mfxENCOutput; +typedef struct mfxVideoCodecPlugin{ + mfxStatus (MFX_CDECL *Query)(mfxHDL pthis, mfxVideoParam *in, mfxVideoParam *out); + mfxStatus (MFX_CDECL *QueryIOSurf)(mfxHDL pthis, mfxVideoParam *par, mfxFrameAllocRequest *in, mfxFrameAllocRequest *out); + mfxStatus (MFX_CDECL *Init)(mfxHDL pthis, mfxVideoParam *par); + mfxStatus (MFX_CDECL *Reset)(mfxHDL pthis, mfxVideoParam *par); + mfxStatus (MFX_CDECL *Close)(mfxHDL pthis); + mfxStatus (MFX_CDECL *GetVideoParam)(mfxHDL pthis, mfxVideoParam *par); + + mfxStatus (MFX_CDECL *EncodeFrameSubmit)(mfxHDL pthis, mfxEncodeCtrl *ctrl, mfxFrameSurface1 *surface, mfxBitstream *bs, mfxThreadTask *task); + + mfxStatus (MFX_CDECL *DecodeHeader)(mfxHDL pthis, mfxBitstream *bs, mfxVideoParam *par); + mfxStatus (MFX_CDECL *GetPayload)(mfxHDL pthis, mfxU64 *ts, mfxPayload *payload); + mfxStatus (MFX_CDECL *DecodeFrameSubmit)(mfxHDL pthis, mfxBitstream *bs, mfxFrameSurface1 *surface_work, mfxFrameSurface1 **surface_out, mfxThreadTask *task); + + mfxStatus (MFX_CDECL *VPPFrameSubmit)(mfxHDL pthis, mfxFrameSurface1 *in, mfxFrameSurface1 *out, mfxExtVppAuxData *aux, mfxThreadTask *task); + mfxStatus (MFX_CDECL *VPPFrameSubmitEx)(mfxHDL pthis, mfxFrameSurface1 *in, mfxFrameSurface1 *surface_work, mfxFrameSurface1 **surface_out, mfxThreadTask *task); + + mfxStatus (MFX_CDECL *ENCFrameSubmit)(mfxHDL pthis, mfxENCInput *in, mfxENCOutput *out, mfxThreadTask *task); + + mfxHDL reserved1[3]; + mfxU32 reserved2[8]; +} mfxVideoCodecPlugin; + +typedef struct mfxAudioCodecPlugin{ + mfxStatus (MFX_CDECL *Query)(mfxHDL pthis, mfxAudioParam *in, mfxAudioParam *out); + mfxStatus (MFX_CDECL *QueryIOSize)(mfxHDL pthis, mfxAudioParam *par, mfxAudioAllocRequest *request); + mfxStatus (MFX_CDECL *Init)(mfxHDL pthis, mfxAudioParam *par); + mfxStatus (MFX_CDECL *Reset)(mfxHDL pthis, mfxAudioParam *par); + mfxStatus (MFX_CDECL *Close)(mfxHDL pthis); + mfxStatus (MFX_CDECL *GetAudioParam)(mfxHDL pthis, mfxAudioParam *par); + + mfxStatus (MFX_CDECL *EncodeFrameSubmit)(mfxHDL pthis, mfxAudioFrame *aFrame, mfxBitstream *out, mfxThreadTask *task); + + mfxStatus (MFX_CDECL *DecodeHeader)(mfxHDL pthis, mfxBitstream *bs, mfxAudioParam *par); +// mfxStatus (MFX_CDECL *GetPayload)(mfxHDL pthis, mfxU64 *ts, mfxPayload *payload); + mfxStatus (MFX_CDECL *DecodeFrameSubmit)(mfxHDL pthis, mfxBitstream *in, mfxAudioFrame *out, mfxThreadTask *task); + + mfxHDL reserved1[6]; + mfxU32 reserved2[8]; +} mfxAudioCodecPlugin; + +typedef struct mfxPlugin{ + mfxHDL pthis; + + mfxStatus (MFX_CDECL *PluginInit) (mfxHDL pthis, mfxCoreInterface *core); + mfxStatus (MFX_CDECL *PluginClose) (mfxHDL pthis); + + mfxStatus (MFX_CDECL *GetPluginParam)(mfxHDL pthis, mfxPluginParam *par); + + mfxStatus (MFX_CDECL *Submit)(mfxHDL pthis, const mfxHDL *in, mfxU32 in_num, const mfxHDL *out, mfxU32 out_num, mfxThreadTask *task); + mfxStatus (MFX_CDECL *Execute)(mfxHDL pthis, mfxThreadTask task, mfxU32 uid_p, mfxU32 uid_a); + mfxStatus (MFX_CDECL *FreeResources)(mfxHDL pthis, mfxThreadTask task, mfxStatus sts); + + union { + mfxVideoCodecPlugin *Video; + mfxAudioCodecPlugin *Audio; + }; + + mfxHDL reserved[8]; +} mfxPlugin; + + + +mfxStatus MFX_CDECL MFXVideoUSER_Register(mfxSession session, mfxU32 type, const mfxPlugin *par); +mfxStatus MFX_CDECL MFXVideoUSER_Unregister(mfxSession session, mfxU32 type); +mfxStatus MFX_CDECL MFXVideoUSER_ProcessFrameAsync(mfxSession session, const mfxHDL *in, mfxU32 in_num, const mfxHDL *out, mfxU32 out_num, mfxSyncPoint *syncp); + +mfxStatus MFX_CDECL MFXVideoUSER_Load(mfxSession session, const mfxPluginUID *uid, mfxU32 version); +mfxStatus MFX_CDECL MFXVideoUSER_LoadByPath(mfxSession session, const mfxPluginUID *uid, mfxU32 version, const mfxChar *path, mfxU32 len); +mfxStatus MFX_CDECL MFXVideoUSER_UnLoad(mfxSession session, const mfxPluginUID *uid); + +mfxStatus MFX_CDECL MFXAudioUSER_Register(mfxSession session, mfxU32 type, const mfxPlugin *par); +mfxStatus MFX_CDECL MFXAudioUSER_Unregister(mfxSession session, mfxU32 type); +mfxStatus MFX_CDECL MFXAudioUSER_ProcessFrameAsync(mfxSession session, const mfxHDL *in, mfxU32 in_num, const mfxHDL *out, mfxU32 out_num, mfxSyncPoint *syncp); + +mfxStatus MFX_CDECL MFXAudioUSER_Load(mfxSession session, const mfxPluginUID *uid, mfxU32 version); +mfxStatus MFX_CDECL MFXAudioUSER_UnLoad(mfxSession session, const mfxPluginUID *uid); + +#ifdef __cplusplus +} // extern "C" +#endif /* __cplusplus */ + +#endif /* __MFXPLUGIN_H__ */ diff --git a/plugins/obs-qsv11/libmfx/include/msdk/include/mfxsession.h b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxsession.h new file mode 100644 index 000000000..e93c99340 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxsession.h @@ -0,0 +1,60 @@ +/******************************************************************************* + +Copyright (C) 2013 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfxsession.h + +*******************************************************************************/ +#ifndef __MFXSESSION_H__ +#define __MFXSESSION_H__ +#include "mfxcommon.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* Global Functions */ +typedef struct _mfxSession *mfxSession; +mfxStatus MFX_CDECL MFXInit(mfxIMPL impl, mfxVersion *ver, mfxSession *session); +mfxStatus MFX_CDECL MFXInitEx(mfxInitParam par, mfxSession *session); +mfxStatus MFX_CDECL MFXClose(mfxSession session); + +mfxStatus MFX_CDECL MFXQueryIMPL(mfxSession session, mfxIMPL *impl); +mfxStatus MFX_CDECL MFXQueryVersion(mfxSession session, mfxVersion *version); + +mfxStatus MFX_CDECL MFXJoinSession(mfxSession session, mfxSession child); +mfxStatus MFX_CDECL MFXDisjoinSession(mfxSession session); +mfxStatus MFX_CDECL MFXCloneSession(mfxSession session, mfxSession *clone); +mfxStatus MFX_CDECL MFXSetPriority(mfxSession session, mfxPriority priority); +mfxStatus MFX_CDECL MFXGetPriority(mfxSession session, mfxPriority *priority); +mfxStatus MFX_CDECL MFXDoWork(mfxSession session); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/plugins/obs-qsv11/libmfx/include/msdk/include/mfxstructures.h b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxstructures.h new file mode 100644 index 000000000..041157d57 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxstructures.h @@ -0,0 +1,1379 @@ +/******************************************************************************* *\ + +Copyright (C) 2007-2015 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfxstructures.h + +*******************************************************************************/ +#ifndef __MFXSTRUCTURES_H__ +#define __MFXSTRUCTURES_H__ +#include "mfxcommon.h" + +#if !defined (__GNUC__) +#pragma warning(disable: 4201) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Frame ID for SVC and MVC */ +typedef struct { + mfxU16 TemporalId; + mfxU16 PriorityId; + union { + struct { + mfxU16 DependencyId; + mfxU16 QualityId; + }; + struct { + mfxU16 ViewId; + }; + }; +} mfxFrameId; + +#pragma pack(push, 4) +/* Frame Info */ +typedef struct { + mfxU32 reserved[4]; + mfxU16 reserved4; + mfxU16 BitDepthLuma; + mfxU16 BitDepthChroma; + mfxU16 Shift; + + mfxFrameId FrameId; + + mfxU32 FourCC; + union { + struct { /* Frame parameters */ + mfxU16 Width; + mfxU16 Height; + + mfxU16 CropX; + mfxU16 CropY; + mfxU16 CropW; + mfxU16 CropH; + }; + struct { /* Buffer parameters (for plain formats like P8) */ + mfxU64 BufferSize; + mfxU32 reserved5; + }; + }; + + mfxU32 FrameRateExtN; + mfxU32 FrameRateExtD; + mfxU16 reserved3; + + mfxU16 AspectRatioW; + mfxU16 AspectRatioH; + + mfxU16 PicStruct; + mfxU16 ChromaFormat; + mfxU16 reserved2; +} mfxFrameInfo; +#pragma pack(pop) + +/* FourCC */ +enum { + MFX_FOURCC_NV12 = MFX_MAKEFOURCC('N','V','1','2'), /* Native Format */ + MFX_FOURCC_YV12 = MFX_MAKEFOURCC('Y','V','1','2'), + MFX_FOURCC_NV16 = MFX_MAKEFOURCC('N','V','1','6'), + MFX_FOURCC_YUY2 = MFX_MAKEFOURCC('Y','U','Y','2'), + MFX_FOURCC_RGB3 = MFX_MAKEFOURCC('R','G','B','3'), /* deprecated */ + MFX_FOURCC_RGB4 = MFX_MAKEFOURCC('R','G','B','4'), /* ARGB in that order, A channel is 8 MSBs */ + MFX_FOURCC_P8 = 41, /* D3DFMT_P8 */ + MFX_FOURCC_P8_TEXTURE = MFX_MAKEFOURCC('P','8','M','B'), + MFX_FOURCC_P010 = MFX_MAKEFOURCC('P','0','1','0'), + MFX_FOURCC_P210 = MFX_MAKEFOURCC('P','2','1','0'), + MFX_FOURCC_BGR4 = MFX_MAKEFOURCC('B','G','R','4'), /* ABGR in that order, A channel is 8 MSBs */ + MFX_FOURCC_A2RGB10 = MFX_MAKEFOURCC('R','G','1','0'), /* ARGB in that order, A channel is two MSBs */ + MFX_FOURCC_ARGB16 = MFX_MAKEFOURCC('R','G','1','6'), /* ARGB in that order, 64 bits, A channel is 16 MSBs */ + MFX_FOURCC_ABGR16 = MFX_MAKEFOURCC('B','G','1','6'), /* ABGR in that order, 64 bits, A channel is 16 MSBs */ + MFX_FOURCC_R16 = MFX_MAKEFOURCC('R','1','6','U'), + MFX_FOURCC_AYUV = MFX_MAKEFOURCC('A','Y','U','V'), /* YUV 4:4:4, AYUV in that order, A channel is 8 MSBs */ + MFX_FOURCC_AYUV_RGB4 = MFX_MAKEFOURCC('A','V','U','Y'), /* ARGB in that order, A channel is 8 MSBs stored in AYUV surface*/ + MFX_FOURCC_UYVY = MFX_MAKEFOURCC('U','Y','V','Y') +}; + +/* PicStruct */ +enum { + MFX_PICSTRUCT_UNKNOWN =0x00, + MFX_PICSTRUCT_PROGRESSIVE =0x01, + MFX_PICSTRUCT_FIELD_TFF =0x02, + MFX_PICSTRUCT_FIELD_BFF =0x04, + + MFX_PICSTRUCT_FIELD_REPEATED=0x10, /* first field repeated, pic_struct=5 or 6 in H.264 */ + MFX_PICSTRUCT_FRAME_DOUBLING=0x20, /* pic_struct=7 in H.264 */ + MFX_PICSTRUCT_FRAME_TRIPLING=0x40 /* pic_struct=8 in H.264 */ +}; + +/* ColorFormat */ +enum { + MFX_CHROMAFORMAT_MONOCHROME =0, + MFX_CHROMAFORMAT_YUV420 =1, + MFX_CHROMAFORMAT_YUV422 =2, + MFX_CHROMAFORMAT_YUV444 =3, + MFX_CHROMAFORMAT_YUV400 = MFX_CHROMAFORMAT_MONOCHROME, + MFX_CHROMAFORMAT_YUV411 = 4, + MFX_CHROMAFORMAT_YUV422H = MFX_CHROMAFORMAT_YUV422, + MFX_CHROMAFORMAT_YUV422V = 5 +}; + +enum { + MFX_TIMESTAMP_UNKNOWN = -1 +}; + +enum { + MFX_FRAMEORDER_UNKNOWN = -1 +}; + +/* DataFlag in mfxFrameData */ +enum { + MFX_FRAMEDATA_ORIGINAL_TIMESTAMP = 0x0001 +}; + +/* Corrupted in mfxFrameData */ +enum { + MFX_CORRUPTION_MINOR = 0x0001, + MFX_CORRUPTION_MAJOR = 0x0002, + MFX_CORRUPTION_ABSENT_TOP_FIELD = 0x0004, + MFX_CORRUPTION_ABSENT_BOTTOM_FIELD = 0x0008, + MFX_CORRUPTION_REFERENCE_FRAME = 0x0010, + MFX_CORRUPTION_REFERENCE_LIST = 0x0020 +}; + +/* Frame Data Info */ +typedef struct { + union { + mfxExtBuffer **ExtParam; + mfxU64 reserved2; + }; + mfxU16 NumExtParam; + + mfxU16 reserved[10]; + mfxU16 PitchHigh; + + mfxU64 TimeStamp; + mfxU32 FrameOrder; + mfxU16 Locked; + union{ + mfxU16 Pitch; + mfxU16 PitchLow; + }; + + /* color planes */ + union { + mfxU8 *Y; + mfxU16 *Y16; + mfxU8 *R; + }; + union { + mfxU8 *UV; /* for UV merged formats */ + mfxU8 *VU; /* for VU merged formats */ + mfxU8 *CbCr; /* for CbCr merged formats */ + mfxU8 *CrCb; /* for CrCb merged formats */ + mfxU8 *Cb; + mfxU8 *U; + mfxU16 *U16; + mfxU8 *G; + }; + union { + mfxU8 *Cr; + mfxU8 *V; + mfxU16 *V16; + mfxU8 *B; + }; + mfxU8 *A; + mfxMemId MemId; + + /* Additional Flags */ + mfxU16 Corrupted; + mfxU16 DataFlag; +} mfxFrameData; + +/* Frame Surface */ +typedef struct { + mfxU32 reserved[4]; + mfxFrameInfo Info; + mfxFrameData Data; +} mfxFrameSurface1; + +enum { + MFX_TIMESTAMPCALC_UNKNOWN = 0, + MFX_TIMESTAMPCALC_TELECINE = 1, +}; + +/* Transcoding Info */ +typedef struct { + mfxU32 reserved[7]; + + mfxU16 LowPower; + mfxU16 BRCParamMultiplier; + + mfxFrameInfo FrameInfo; + mfxU32 CodecId; + mfxU16 CodecProfile; + mfxU16 CodecLevel; + mfxU16 NumThread; + + union { + struct { /* MPEG-2/H.264 Encoding Options */ + mfxU16 TargetUsage; + + mfxU16 GopPicSize; + mfxU16 GopRefDist; + mfxU16 GopOptFlag; + mfxU16 IdrInterval; + + mfxU16 RateControlMethod; + union { + mfxU16 InitialDelayInKB; + mfxU16 QPI; + mfxU16 Accuracy; + }; + mfxU16 BufferSizeInKB; + union { + mfxU16 TargetKbps; + mfxU16 QPP; + mfxU16 ICQQuality; + }; + union { + mfxU16 MaxKbps; + mfxU16 QPB; + mfxU16 Convergence; + }; + + mfxU16 NumSlice; + mfxU16 NumRefFrame; + mfxU16 EncodedOrder; + }; + struct { /* H.264, MPEG-2 and VC-1 Decoding Options */ + mfxU16 DecodedOrder; + mfxU16 ExtendedPicStruct; + mfxU16 TimeStampCalc; + mfxU16 SliceGroupsPresent; + mfxU16 MaxDecFrameBuffering; + mfxU16 reserved2[8]; + }; + struct { /* JPEG Decoding Options */ + mfxU16 JPEGChromaFormat; + mfxU16 Rotation; + mfxU16 JPEGColorFormat; + mfxU16 InterleavedDec; + mfxU16 reserved3[9]; + }; + struct { /* JPEG Encoding Options */ + mfxU16 Interleaved; + mfxU16 Quality; + mfxU16 RestartInterval; + mfxU16 reserved5[10]; + }; + }; +} mfxInfoMFX; + +typedef struct { + mfxU32 reserved[8]; + mfxFrameInfo In; + mfxFrameInfo Out; +} mfxInfoVPP; + +typedef struct { + mfxU32 AllocId; + mfxU32 reserved[2]; + mfxU16 reserved3; + mfxU16 AsyncDepth; + + union { + mfxInfoMFX mfx; + mfxInfoVPP vpp; + }; + mfxU16 Protected; + mfxU16 IOPattern; + mfxExtBuffer** ExtParam; + mfxU16 NumExtParam; + mfxU16 reserved2; +} mfxVideoParam; + +/* IOPattern */ +enum { + MFX_IOPATTERN_IN_VIDEO_MEMORY = 0x01, + MFX_IOPATTERN_IN_SYSTEM_MEMORY = 0x02, + MFX_IOPATTERN_IN_OPAQUE_MEMORY = 0x04, + MFX_IOPATTERN_OUT_VIDEO_MEMORY = 0x10, + MFX_IOPATTERN_OUT_SYSTEM_MEMORY = 0x20, + MFX_IOPATTERN_OUT_OPAQUE_MEMORY = 0x40 +}; + +/* CodecId */ +enum { + MFX_CODEC_AVC =MFX_MAKEFOURCC('A','V','C',' '), + MFX_CODEC_HEVC =MFX_MAKEFOURCC('H','E','V','C'), + MFX_CODEC_MPEG2 =MFX_MAKEFOURCC('M','P','G','2'), + MFX_CODEC_VC1 =MFX_MAKEFOURCC('V','C','1',' '), + MFX_CODEC_CAPTURE =MFX_MAKEFOURCC('C','A','P','T') +}; + +/* CodecProfile, CodecLevel */ +enum { + MFX_PROFILE_UNKNOWN =0, + MFX_LEVEL_UNKNOWN =0, + + /* AVC Profiles & Levels */ + MFX_PROFILE_AVC_CONSTRAINT_SET0 = (0x100 << 0), + MFX_PROFILE_AVC_CONSTRAINT_SET1 = (0x100 << 1), + MFX_PROFILE_AVC_CONSTRAINT_SET2 = (0x100 << 2), + MFX_PROFILE_AVC_CONSTRAINT_SET3 = (0x100 << 3), + MFX_PROFILE_AVC_CONSTRAINT_SET4 = (0x100 << 4), + MFX_PROFILE_AVC_CONSTRAINT_SET5 = (0x100 << 5), + + MFX_PROFILE_AVC_BASELINE =66, + MFX_PROFILE_AVC_MAIN =77, + MFX_PROFILE_AVC_EXTENDED =88, + MFX_PROFILE_AVC_HIGH =100, + MFX_PROFILE_AVC_HIGH_422 =122, + MFX_PROFILE_AVC_CONSTRAINED_BASELINE =MFX_PROFILE_AVC_BASELINE + MFX_PROFILE_AVC_CONSTRAINT_SET1, + MFX_PROFILE_AVC_CONSTRAINED_HIGH =MFX_PROFILE_AVC_HIGH + MFX_PROFILE_AVC_CONSTRAINT_SET4 + + MFX_PROFILE_AVC_CONSTRAINT_SET5, + MFX_PROFILE_AVC_PROGRESSIVE_HIGH =MFX_PROFILE_AVC_HIGH + MFX_PROFILE_AVC_CONSTRAINT_SET4, + + MFX_LEVEL_AVC_1 =10, + MFX_LEVEL_AVC_1b =9, + MFX_LEVEL_AVC_11 =11, + MFX_LEVEL_AVC_12 =12, + MFX_LEVEL_AVC_13 =13, + MFX_LEVEL_AVC_2 =20, + MFX_LEVEL_AVC_21 =21, + MFX_LEVEL_AVC_22 =22, + MFX_LEVEL_AVC_3 =30, + MFX_LEVEL_AVC_31 =31, + MFX_LEVEL_AVC_32 =32, + MFX_LEVEL_AVC_4 =40, + MFX_LEVEL_AVC_41 =41, + MFX_LEVEL_AVC_42 =42, + MFX_LEVEL_AVC_5 =50, + MFX_LEVEL_AVC_51 =51, + MFX_LEVEL_AVC_52 =52, + + /* MPEG-2 Profiles & Levels */ + MFX_PROFILE_MPEG2_SIMPLE =0x50, + MFX_PROFILE_MPEG2_MAIN =0x40, + MFX_PROFILE_MPEG2_HIGH =0x10, + + MFX_LEVEL_MPEG2_LOW =0xA, + MFX_LEVEL_MPEG2_MAIN =0x8, + MFX_LEVEL_MPEG2_HIGH =0x4, + MFX_LEVEL_MPEG2_HIGH1440 =0x6, + + /* VC1 Profiles & Levels */ + MFX_PROFILE_VC1_SIMPLE =(0+1), + MFX_PROFILE_VC1_MAIN =(4+1), + MFX_PROFILE_VC1_ADVANCED =(12+1), + + /* VC1 levels for simple & main profiles */ + MFX_LEVEL_VC1_LOW =(0+1), + MFX_LEVEL_VC1_MEDIAN =(2+1), + MFX_LEVEL_VC1_HIGH =(4+1), + + /* VC1 levels for the advanced profile */ + MFX_LEVEL_VC1_0 =(0x00+1), + MFX_LEVEL_VC1_1 =(0x01+1), + MFX_LEVEL_VC1_2 =(0x02+1), + MFX_LEVEL_VC1_3 =(0x03+1), + MFX_LEVEL_VC1_4 =(0x04+1), + + /* HEVC Profiles & Levels & Tiers */ + MFX_PROFILE_HEVC_MAIN =1, + MFX_PROFILE_HEVC_MAIN10 =2, + MFX_PROFILE_HEVC_MAINSP =3, + MFX_PROFILE_HEVC_REXT =4, + + MFX_LEVEL_HEVC_1 = 10, + MFX_LEVEL_HEVC_2 = 20, + MFX_LEVEL_HEVC_21 = 21, + MFX_LEVEL_HEVC_3 = 30, + MFX_LEVEL_HEVC_31 = 31, + MFX_LEVEL_HEVC_4 = 40, + MFX_LEVEL_HEVC_41 = 41, + MFX_LEVEL_HEVC_5 = 50, + MFX_LEVEL_HEVC_51 = 51, + MFX_LEVEL_HEVC_52 = 52, + MFX_LEVEL_HEVC_6 = 60, + MFX_LEVEL_HEVC_61 = 61, + MFX_LEVEL_HEVC_62 = 62, + + MFX_TIER_HEVC_MAIN = 0, + MFX_TIER_HEVC_HIGH = 0x100, +}; + +/* GopOptFlag */ +enum { + MFX_GOP_CLOSED =1, + MFX_GOP_STRICT =2 +}; + +/* TargetUsages: from 1 to 7 inclusive */ +enum { + MFX_TARGETUSAGE_1 =1, + MFX_TARGETUSAGE_2 =2, + MFX_TARGETUSAGE_3 =3, + MFX_TARGETUSAGE_4 =4, + MFX_TARGETUSAGE_5 =5, + MFX_TARGETUSAGE_6 =6, + MFX_TARGETUSAGE_7 =7, + + MFX_TARGETUSAGE_UNKNOWN =0, + MFX_TARGETUSAGE_BEST_QUALITY =MFX_TARGETUSAGE_1, + MFX_TARGETUSAGE_BALANCED =MFX_TARGETUSAGE_4, + MFX_TARGETUSAGE_BEST_SPEED =MFX_TARGETUSAGE_7 +}; + +/* RateControlMethod */ +enum { + MFX_RATECONTROL_CBR =1, + MFX_RATECONTROL_VBR =2, + MFX_RATECONTROL_CQP =3, + MFX_RATECONTROL_AVBR =4, + MFX_RATECONTROL_RESERVED1 =5, + MFX_RATECONTROL_RESERVED2 =6, + MFX_RATECONTROL_RESERVED3 =100, + MFX_RATECONTROL_RESERVED4 =7, + MFX_RATECONTROL_LA =8, + MFX_RATECONTROL_ICQ =9, + MFX_RATECONTROL_VCM =10, + MFX_RATECONTROL_LA_ICQ =11, + MFX_RATECONTROL_LA_EXT =12, + MFX_RATECONTROL_LA_HRD =13, + MFX_RATECONTROL_QVBR =14 +}; + +/* Trellis control*/ +enum { + MFX_TRELLIS_UNKNOWN =0, + MFX_TRELLIS_OFF =0x01, + MFX_TRELLIS_I =0x02, + MFX_TRELLIS_P =0x04, + MFX_TRELLIS_B =0x08 +}; + +typedef struct { + mfxExtBuffer Header; + + mfxU16 reserved1; + mfxU16 RateDistortionOpt; /* tri-state option */ + mfxU16 MECostType; + mfxU16 MESearchType; + mfxI16Pair MVSearchWindow; + mfxU16 EndOfSequence; /* tri-state option */ + mfxU16 FramePicture; /* tri-state option */ + + mfxU16 CAVLC; /* tri-state option */ + mfxU16 reserved2[2]; + mfxU16 RecoveryPointSEI; /* tri-state option */ + mfxU16 ViewOutput; /* tri-state option */ + mfxU16 NalHrdConformance; /* tri-state option */ + mfxU16 SingleSeiNalUnit; /* tri-state option */ + mfxU16 VuiVclHrdParameters; /* tri-state option */ + + mfxU16 RefPicListReordering; /* tri-state option */ + mfxU16 ResetRefList; /* tri-state option */ + mfxU16 RefPicMarkRep; /* tri-state option */ + mfxU16 FieldOutput; /* tri-state option */ + + mfxU16 IntraPredBlockSize; + mfxU16 InterPredBlockSize; + mfxU16 MVPrecision; + mfxU16 MaxDecFrameBuffering; + + mfxU16 AUDelimiter; /* tri-state option */ + mfxU16 EndOfStream; /* tri-state option */ + mfxU16 PicTimingSEI; /* tri-state option */ + mfxU16 VuiNalHrdParameters; /* tri-state option */ +} mfxExtCodingOption; + +enum { + MFX_B_REF_UNKNOWN = 0, + MFX_B_REF_OFF = 1, + MFX_B_REF_PYRAMID = 2 +}; + +enum { + MFX_LOOKAHEAD_DS_UNKNOWN = 0, + MFX_LOOKAHEAD_DS_OFF = 1, + MFX_LOOKAHEAD_DS_2x = 2, + MFX_LOOKAHEAD_DS_4x = 3 +}; + +enum { + MFX_BPSEI_DEFAULT = 0x00, + MFX_BPSEI_IFRAME = 0x01 +}; + +enum { + MFX_SKIPFRAME_NO_SKIP = 0, + MFX_SKIPFRAME_INSERT_DUMMY = 1, + MFX_SKIPFRAME_INSERT_NOTHING = 2, + MFX_SKIPFRAME_BRC_ONLY = 3, +}; + +typedef struct { + mfxExtBuffer Header; + + mfxU16 IntRefType; + mfxU16 IntRefCycleSize; + mfxI16 IntRefQPDelta; + + mfxU32 MaxFrameSize; + mfxU32 MaxSliceSize; + + mfxU16 BitrateLimit; /* tri-state option */ + mfxU16 MBBRC; /* tri-state option */ + mfxU16 ExtBRC; /* tri-state option */ + mfxU16 LookAheadDepth; + mfxU16 Trellis; + mfxU16 RepeatPPS; /* tri-state option */ + mfxU16 BRefType; + mfxU16 AdaptiveI; /* tri-state option */ + mfxU16 AdaptiveB; /* tri-state option */ + mfxU16 LookAheadDS; + mfxU16 NumMbPerSlice; + mfxU16 SkipFrame; + mfxU8 MinQPI; /* 1..51, 0 = default */ + mfxU8 MaxQPI; /* 1..51, 0 = default */ + mfxU8 MinQPP; /* 1..51, 0 = default */ + mfxU8 MaxQPP; /* 1..51, 0 = default */ + mfxU8 MinQPB; /* 1..51, 0 = default */ + mfxU8 MaxQPB; /* 1..51, 0 = default */ + mfxU16 FixedFrameRate; /* tri-state option */ + mfxU16 DisableDeblockingIdc; + mfxU16 DisableVUI; + mfxU16 BufferingPeriodSEI; + mfxU16 EnableMAD; /* tri-state option */ + mfxU16 UseRawRef; /* tri-state option */ +} mfxExtCodingOption2; + +/* WeightedPred */ +enum { + MFX_WEIGHTED_PRED_UNKNOWN = 0, + MFX_WEIGHTED_PRED_DEFAULT = 1, + MFX_WEIGHTED_PRED_EXPLICIT = 2, + MFX_WEIGHTED_PRED_IMPLICIT = 3 +}; + +/* ScenarioInfo */ +enum { + MFX_SCENARIO_UNKNOWN = 0, + MFX_SCENARIO_DISPLAY_REMOTING = 1, + MFX_SCENARIO_VIDEO_CONFERENCE = 2, + MFX_SCENARIO_ARCHIVE = 3, + MFX_SCENARIO_LIVE_STREAMING = 4, + MFX_SCENARIO_CAMERA_CAPTURE = 5 +}; + +/* ContentInfo */ +enum { + MFX_CONTENT_UNKNOWN = 0, + MFX_CONTENT_FULL_SCREEN_VIDEO = 1, + MFX_CONTENT_NON_VIDEO_SCREEN = 2 +}; + +/* PRefType */ +enum { + MFX_P_REF_DEFAULT = 0, + MFX_P_REF_SIMPLE = 1, + MFX_P_REF_PYRAMID = 2 +}; + +typedef struct { + mfxExtBuffer Header; + + mfxU16 NumSliceI; + mfxU16 NumSliceP; + mfxU16 NumSliceB; + + mfxU16 WinBRCMaxAvgKbps; + mfxU16 WinBRCSize; + + mfxU16 QVBRQuality; + mfxU16 EnableMBQP; + mfxU16 IntRefCycleDist; + mfxU16 DirectBiasAdjustment; /* tri-state option */ + mfxU16 GlobalMotionBiasAdjustment; /* tri-state option */ + mfxU16 MVCostScalingFactor; + mfxU16 MBDisableSkipMap; /* tri-state option */ + + mfxU16 WeightedPred; + mfxU16 WeightedBiPred; + + mfxU16 AspectRatioInfoPresent; /* tri-state option */ + mfxU16 OverscanInfoPresent; /* tri-state option */ + mfxU16 OverscanAppropriate; /* tri-state option */ + mfxU16 TimingInfoPresent; /* tri-state option */ + mfxU16 BitstreamRestriction; /* tri-state option */ + mfxU16 reserved1[4]; + + mfxU16 ScenarioInfo; + mfxU16 ContentInfo; + + mfxU16 PRefType; + mfxU16 FadeDetection; /* tri-state option */ + mfxU16 reserved[225]; +} mfxExtCodingOption3; + +/* IntraPredBlockSize/InterPredBlockSize */ +enum { + MFX_BLOCKSIZE_UNKNOWN = 0, + MFX_BLOCKSIZE_MIN_16X16 = 1, /* 16x16 */ + MFX_BLOCKSIZE_MIN_8X8 = 2, /* 16x16, 8x8 */ + MFX_BLOCKSIZE_MIN_4X4 = 3 /* 16x16, 8x8, 4x4 */ +}; + +/* MVPrecision */ +enum { + MFX_MVPRECISION_UNKNOWN = 0, + MFX_MVPRECISION_INTEGER = (1 << 0), + MFX_MVPRECISION_HALFPEL = (1 << 1), + MFX_MVPRECISION_QUARTERPEL = (1 << 2) +}; + +enum { + MFX_CODINGOPTION_UNKNOWN =0, + MFX_CODINGOPTION_ON =0x10, + MFX_CODINGOPTION_OFF =0x20, + MFX_CODINGOPTION_ADAPTIVE =0x30 +}; + +/* Data Flag for mfxBitstream*/ +enum { + MFX_BITSTREAM_COMPLETE_FRAME = 0x0001, /* the bitstream contains a complete frame or field pair of data */ + MFX_BITSTREAM_EOS = 0x0002 +}; + +/* Extended Buffer Ids */ +enum { + MFX_EXTBUFF_CODING_OPTION = MFX_MAKEFOURCC('C','D','O','P'), + MFX_EXTBUFF_CODING_OPTION_SPSPPS = MFX_MAKEFOURCC('C','O','S','P'), + MFX_EXTBUFF_VPP_DONOTUSE = MFX_MAKEFOURCC('N','U','S','E'), + MFX_EXTBUFF_VPP_AUXDATA = MFX_MAKEFOURCC('A','U','X','D'), + MFX_EXTBUFF_VPP_DENOISE = MFX_MAKEFOURCC('D','N','I','S'), + MFX_EXTBUFF_VPP_SCENE_ANALYSIS = MFX_MAKEFOURCC('S','C','L','Y'), + MFX_EXTBUFF_VPP_SCENE_CHANGE = MFX_EXTBUFF_VPP_SCENE_ANALYSIS, + MFX_EXTBUFF_VPP_PROCAMP = MFX_MAKEFOURCC('P','A','M','P'), + MFX_EXTBUFF_VPP_DETAIL = MFX_MAKEFOURCC('D','E','T',' '), + MFX_EXTBUFF_VIDEO_SIGNAL_INFO = MFX_MAKEFOURCC('V','S','I','N'), + MFX_EXTBUFF_VPP_DOUSE = MFX_MAKEFOURCC('D','U','S','E'), + MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION = MFX_MAKEFOURCC('O','P','Q','S'), + MFX_EXTBUFF_AVC_REFLIST_CTRL = MFX_MAKEFOURCC('R','L','S','T'), + MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION = MFX_MAKEFOURCC('F','R','C',' '), + MFX_EXTBUFF_PICTURE_TIMING_SEI = MFX_MAKEFOURCC('P','T','S','E'), + MFX_EXTBUFF_AVC_TEMPORAL_LAYERS = MFX_MAKEFOURCC('A','T','M','L'), + MFX_EXTBUFF_CODING_OPTION2 = MFX_MAKEFOURCC('C','D','O','2'), + MFX_EXTBUFF_VPP_IMAGE_STABILIZATION = MFX_MAKEFOURCC('I','S','T','B'), + MFX_EXTBUFF_VPP_PICSTRUCT_DETECTION = MFX_MAKEFOURCC('I','D','E','T'), + MFX_EXTBUFF_ENCODER_CAPABILITY = MFX_MAKEFOURCC('E','N','C','P'), + MFX_EXTBUFF_ENCODER_RESET_OPTION = MFX_MAKEFOURCC('E','N','R','O'), + MFX_EXTBUFF_ENCODED_FRAME_INFO = MFX_MAKEFOURCC('E','N','F','I'), + MFX_EXTBUFF_VPP_COMPOSITE = MFX_MAKEFOURCC('V','C','M','P'), + MFX_EXTBUFF_VPP_VIDEO_SIGNAL_INFO = MFX_MAKEFOURCC('V','V','S','I'), + MFX_EXTBUFF_ENCODER_ROI = MFX_MAKEFOURCC('E','R','O','I'), + MFX_EXTBUFF_VPP_DEINTERLACING = MFX_MAKEFOURCC('V','P','D','I'), + MFX_EXTBUFF_AVC_REFLISTS = MFX_MAKEFOURCC('R','L','T','S'), + MFX_EXTBUFF_VPP_FIELD_PROCESSING = MFX_MAKEFOURCC('F','P','R','O'), + MFX_EXTBUFF_CODING_OPTION3 = MFX_MAKEFOURCC('C','D','O','3'), + MFX_EXTBUFF_CHROMA_LOC_INFO = MFX_MAKEFOURCC('C','L','I','N'), + MFX_EXTBUFF_MBQP = MFX_MAKEFOURCC('M','B','Q','P'), + MFX_EXTBUFF_HEVC_TILES = MFX_MAKEFOURCC('2','6','5','T'), + MFX_EXTBUFF_MB_DISABLE_SKIP_MAP = MFX_MAKEFOURCC('M','D','S','M'), + MFX_EXTBUFF_HEVC_PARAM = MFX_MAKEFOURCC('2','6','5','P'), + MFX_EXTBUFF_DECODED_FRAME_INFO = MFX_MAKEFOURCC('D','E','F','I'), + MFX_EXTBUFF_TIME_CODE = MFX_MAKEFOURCC('T','M','C','D'), + MFX_EXTBUFF_HEVC_REGION = MFX_MAKEFOURCC('2','6','5','R'), + MFX_EXTBUFF_PRED_WEIGHT_TABLE = MFX_MAKEFOURCC('E','P','W','T'), + MFX_EXTBUFF_DIRTY_RECTANGLES = MFX_MAKEFOURCC('D','R','O','I'), + MFX_EXTBUFF_MOVING_RECTANGLES = MFX_MAKEFOURCC('M','R','O','I'), + MFX_EXTBUFF_CODING_OPTION_VPS = MFX_MAKEFOURCC('C','O','V','P'), + MFX_EXTBUFF_VPP_ROTATION = MFX_MAKEFOURCC('R','O','T',' ') +}; + +/* VPP Conf: Do not use certain algorithms */ +typedef struct { + mfxExtBuffer Header; + mfxU32 NumAlg; + mfxU32* AlgList; +} mfxExtVPPDoNotUse; + +typedef struct { + mfxExtBuffer Header; + mfxU16 DenoiseFactor; +} mfxExtVPPDenoise; + +typedef struct { + mfxExtBuffer Header; + mfxU16 DetailFactor; +} mfxExtVPPDetail; + +typedef struct { + mfxExtBuffer Header; + mfxF64 Brightness; + mfxF64 Contrast; + mfxF64 Hue; + mfxF64 Saturation; +} mfxExtVPPProcAmp; + +/* statistics collected for decode, encode and vpp */ +typedef struct { + mfxU32 reserved[16]; + mfxU32 NumFrame; + mfxU64 NumBit; + mfxU32 NumCachedFrame; +} mfxEncodeStat; + +typedef struct { + mfxU32 reserved[16]; + mfxU32 NumFrame; + mfxU32 NumSkippedFrame; + mfxU32 NumError; + mfxU32 NumCachedFrame; +} mfxDecodeStat; + +typedef struct { + mfxU32 reserved[16]; + mfxU32 NumFrame; + mfxU32 NumCachedFrame; +} mfxVPPStat; + +typedef struct { + mfxExtBuffer Header; + + union{ + struct{ + mfxU32 SpatialComplexity; + mfxU32 TemporalComplexity; + }; + struct{ + mfxU16 PicStruct; + mfxU16 reserved[3]; + }; + }; + mfxU16 SceneChangeRate; + mfxU16 RepeatedFrame; +} mfxExtVppAuxData; + +typedef struct { + mfxU32 reserved[4]; + mfxU8 *Data; /* buffer pointer */ + mfxU32 NumBit; /* number of bits */ + mfxU16 Type; /* SEI message type in H.264 or user data start_code in MPEG-2 */ + mfxU16 BufSize; /* payload buffer size in bytes */ +} mfxPayload; + +typedef struct { + mfxExtBuffer Header; + mfxU32 reserved[5]; + mfxU16 SkipFrame; + + mfxU16 QP; /* per frame QP */ + + mfxU16 FrameType; + mfxU16 NumExtParam; + mfxU16 NumPayload; /* MPEG-2 user data or H.264 SEI message(s) */ + mfxU16 reserved2; + + mfxExtBuffer **ExtParam; + mfxPayload **Payload; /* for field pair, first field uses even payloads and second field uses odd payloads */ +} mfxEncodeCtrl; + +/* Buffer Memory Types */ +enum { + /* Buffer types */ + MFX_MEMTYPE_PERSISTENT_MEMORY =0x0002 +}; + +/* Frame Memory Types */ +#define MFX_MEMTYPE_BASE(x) (0xf0ff & (x)) + +enum { + MFX_MEMTYPE_DXVA2_DECODER_TARGET =0x0010, + MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET =0x0020, + MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET = MFX_MEMTYPE_DXVA2_DECODER_TARGET, + MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET = MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET, + MFX_MEMTYPE_SYSTEM_MEMORY =0x0040, + MFX_MEMTYPE_RESERVED1 =0x0080, + + MFX_MEMTYPE_FROM_ENCODE = 0x0100, + MFX_MEMTYPE_FROM_DECODE = 0x0200, + MFX_MEMTYPE_FROM_VPPIN = 0x0400, + MFX_MEMTYPE_FROM_VPPOUT = 0x0800, + + MFX_MEMTYPE_INTERNAL_FRAME = 0x0001, + MFX_MEMTYPE_EXTERNAL_FRAME = 0x0002, + MFX_MEMTYPE_OPAQUE_FRAME = 0x0004, + MFX_MEMTYPE_EXPORT_FRAME = 0x0008, + + MFX_MEMTYPE_RESERVED2 = 0x1000 +}; + +typedef struct { + union { + mfxU32 AllocId; + mfxU32 reserved[1]; + }; + mfxU32 reserved3[3]; + mfxFrameInfo Info; + mfxU16 Type; /* decoder or processor render targets */ + mfxU16 NumFrameMin; + mfxU16 NumFrameSuggested; + mfxU16 reserved2; +} mfxFrameAllocRequest; + +typedef struct { + mfxU32 AllocId; + mfxU32 reserved[3]; + mfxMemId *mids; /* the array allocated by application */ + mfxU16 NumFrameActual; + mfxU16 reserved2; +} mfxFrameAllocResponse; + +/* FrameType */ +enum { + MFX_FRAMETYPE_UNKNOWN =0x0000, + + MFX_FRAMETYPE_I =0x0001, + MFX_FRAMETYPE_P =0x0002, + MFX_FRAMETYPE_B =0x0004, + MFX_FRAMETYPE_S =0x0008, + + MFX_FRAMETYPE_REF =0x0040, + MFX_FRAMETYPE_IDR =0x0080, + + MFX_FRAMETYPE_xI =0x0100, + MFX_FRAMETYPE_xP =0x0200, + MFX_FRAMETYPE_xB =0x0400, + MFX_FRAMETYPE_xS =0x0800, + + MFX_FRAMETYPE_xREF =0x4000, + MFX_FRAMETYPE_xIDR =0x8000 +}; + +typedef enum { + MFX_HANDLE_DIRECT3D_DEVICE_MANAGER9 =1, /* IDirect3DDeviceManager9 */ + MFX_HANDLE_D3D9_DEVICE_MANAGER = MFX_HANDLE_DIRECT3D_DEVICE_MANAGER9, + MFX_HANDLE_RESERVED1 = 2, + MFX_HANDLE_D3D11_DEVICE = 3, + MFX_HANDLE_VA_DISPLAY = 4, + MFX_HANDLE_RESERVED3 = 5 +} mfxHandleType; + +typedef enum { + MFX_SKIPMODE_NOSKIP=0, + MFX_SKIPMODE_MORE=1, + MFX_SKIPMODE_LESS=2 +} mfxSkipMode; + +typedef struct { + mfxExtBuffer Header; + mfxU8 *SPSBuffer; + mfxU8 *PPSBuffer; + mfxU16 SPSBufSize; + mfxU16 PPSBufSize; + mfxU16 SPSId; + mfxU16 PPSId; +} mfxExtCodingOptionSPSPPS; + +typedef struct { + mfxExtBuffer Header; + + union { + mfxU8 *VPSBuffer; + mfxU64 reserved1; + }; + mfxU16 VPSBufSize; + mfxU16 VPSId; + + mfxU16 reserved[6]; +} mfxExtCodingOptionVPS; + +typedef struct { + mfxExtBuffer Header; + mfxU16 VideoFormat; + mfxU16 VideoFullRange; + mfxU16 ColourDescriptionPresent; + mfxU16 ColourPrimaries; + mfxU16 TransferCharacteristics; + mfxU16 MatrixCoefficients; +} mfxExtVideoSignalInfo; + +typedef struct { + mfxExtBuffer Header; + mfxU32 NumAlg; + mfxU32 *AlgList; +} mfxExtVPPDoUse; + +typedef struct { + mfxExtBuffer Header; + mfxU32 reserved1[2]; + struct { + mfxFrameSurface1 **Surfaces; + mfxU32 reserved2[5]; + mfxU16 Type; + mfxU16 NumSurface; + } In, Out; +} mfxExtOpaqueSurfaceAlloc; + +typedef struct { + mfxExtBuffer Header; + mfxU16 NumRefIdxL0Active; + mfxU16 NumRefIdxL1Active; + + struct { + mfxU32 FrameOrder; + mfxU16 PicStruct; + mfxU16 ViewId; + mfxU16 LongTermIdx; + mfxU16 reserved[3]; + } PreferredRefList[32], RejectedRefList[16], LongTermRefList[16]; + + mfxU16 ApplyLongTermIdx; + mfxU16 reserved[15]; +} mfxExtAVCRefListCtrl; + +enum { + MFX_FRCALGM_PRESERVE_TIMESTAMP = 0x0001, + MFX_FRCALGM_DISTRIBUTED_TIMESTAMP = 0x0002, + MFX_FRCALGM_FRAME_INTERPOLATION = 0x0004 +}; + +typedef struct { + mfxExtBuffer Header; + mfxU16 Algorithm; + mfxU16 reserved; + mfxU32 reserved2[15]; +} mfxExtVPPFrameRateConversion; + +enum { + MFX_IMAGESTAB_MODE_UPSCALE = 0x0001, + MFX_IMAGESTAB_MODE_BOXING = 0x0002 +}; + +typedef struct { + mfxExtBuffer Header; + mfxU16 Mode; + mfxU16 reserved[11]; +} mfxExtVPPImageStab; + +typedef struct { + mfxExtBuffer Header; + mfxU32 reserved[14]; + + struct { + mfxU16 ClockTimestampFlag; + mfxU16 CtType; + mfxU16 NuitFieldBasedFlag; + mfxU16 CountingType; + mfxU16 FullTimestampFlag; + mfxU16 DiscontinuityFlag; + mfxU16 CntDroppedFlag; + mfxU16 NFrames; + mfxU16 SecondsFlag; + mfxU16 MinutesFlag; + mfxU16 HoursFlag; + mfxU16 SecondsValue; + mfxU16 MinutesValue; + mfxU16 HoursValue; + mfxU32 TimeOffset; + } TimeStamp[3]; +} mfxExtPictureTimingSEI; + +typedef struct { + mfxExtBuffer Header; + mfxU32 reserved1[4]; + mfxU16 reserved2; + mfxU16 BaseLayerPID; + + struct { + mfxU16 Scale; + mfxU16 reserved[3]; + }Layer[8]; +} mfxExtAvcTemporalLayers; + +typedef struct { + mfxExtBuffer Header; + + mfxU32 MBPerSec; + mfxU16 reserved[58]; +} mfxExtEncoderCapability; + +typedef struct { + mfxExtBuffer Header; + + mfxU16 StartNewSequence; + mfxU16 reserved[11]; +} mfxExtEncoderResetOption; + +/*LongTermIdx*/ +enum { + MFX_LONGTERM_IDX_NO_IDX = 0xFFFF +}; + +typedef struct { + mfxExtBuffer Header; + + mfxU32 FrameOrder; + mfxU16 PicStruct; + mfxU16 LongTermIdx; + mfxU32 MAD; + mfxU16 BRCPanicMode; + mfxU16 QP; + mfxU32 SecondFieldOffset; + mfxU16 reserved[2]; + + struct { + mfxU32 FrameOrder; + mfxU16 PicStruct; + mfxU16 LongTermIdx; + mfxU16 reserved[4]; + } UsedRefListL0[32], UsedRefListL1[32]; +} mfxExtAVCEncodedFrameInfo; + +typedef struct mfxVPPCompInputStream { + mfxU32 DstX; + mfxU32 DstY; + mfxU32 DstW; + mfxU32 DstH; + + mfxU16 LumaKeyEnable; + mfxU16 LumaKeyMin; + mfxU16 LumaKeyMax; + + mfxU16 GlobalAlphaEnable; + mfxU16 GlobalAlpha; + + mfxU16 PixelAlphaEnable; + + mfxU16 reserved2[18]; +} mfxVPPCompInputStream; + +typedef struct { + mfxExtBuffer Header; + + /* background color*/ + union { + mfxU16 Y; + mfxU16 R; + }; + union { + mfxU16 U; + mfxU16 G; + }; + union { + mfxU16 V; + mfxU16 B; + }; + + mfxU16 reserved1[24]; + + mfxU16 NumInputStream; + mfxVPPCompInputStream *InputStream; +} mfxExtVPPComposite; + +/* TransferMatrix */ +enum { + MFX_TRANSFERMATRIX_UNKNOWN = 0, + MFX_TRANSFERMATRIX_BT709 = 1, + MFX_TRANSFERMATRIX_BT601 = 2 +}; + +/* NominalRange */ +enum { + MFX_NOMINALRANGE_UNKNOWN = 0, + MFX_NOMINALRANGE_0_255 = 1, + MFX_NOMINALRANGE_16_235 = 2 +}; + +typedef struct { + mfxExtBuffer Header; + mfxU16 reserved1[4]; + + struct { + mfxU16 TransferMatrix; + mfxU16 NominalRange; + mfxU16 reserved2[6]; + } In, Out; +} mfxExtVPPVideoSignalInfo; + +typedef struct { + mfxExtBuffer Header; + + mfxU16 NumROI; + mfxU16 reserved1[11]; + + struct { + mfxU32 Left; + mfxU32 Top; + mfxU32 Right; + mfxU32 Bottom; + + mfxI16 Priority; + mfxU16 reserved2[7]; + } ROI[256]; +} mfxExtEncoderROI; + +/*Deinterlacing Mode*/ +enum { + MFX_DEINTERLACING_BOB = 1, + MFX_DEINTERLACING_ADVANCED = 2, + MFX_DEINTERLACING_AUTO_DOUBLE = 3, + MFX_DEINTERLACING_AUTO_SINGLE = 4, + MFX_DEINTERLACING_FULL_FR_OUT = 5, + MFX_DEINTERLACING_HALF_FR_OUT = 6, + MFX_DEINTERLACING_24FPS_OUT = 7, + MFX_DEINTERLACING_FIXED_TELECINE_PATTERN = 8, + MFX_DEINTERLACING_30FPS_OUT = 9, + MFX_DEINTERLACING_DETECT_INTERLACE = 10, + MFX_DEINTERLACING_ADVANCED_NOREF = 11 +}; + +/*TelecinePattern*/ +enum { + MFX_TELECINE_PATTERN_32 = 0, + MFX_TELECINE_PATTERN_2332 = 1, + MFX_TELECINE_PATTERN_FRAME_REPEAT = 2, + MFX_TELECINE_PATTERN_41 = 3, + MFX_TELECINE_POSITION_PROVIDED = 4 +}; + +typedef struct { + mfxExtBuffer Header; + mfxU16 Mode; + mfxU16 TelecinePattern; + mfxU16 TelecineLocation; + mfxU16 reserved[9]; +} mfxExtVPPDeinterlacing; + +typedef struct { + mfxExtBuffer Header; + mfxU16 NumRefIdxL0Active; + mfxU16 NumRefIdxL1Active; + mfxU16 reserved[2]; + + struct mfxRefPic{ + mfxU32 FrameOrder; + mfxU16 PicStruct; + mfxU16 reserved[5]; + } RefPicList0[32], RefPicList1[32]; + +}mfxExtAVCRefLists; + +enum { + MFX_VPP_COPY_FRAME =0x01, + MFX_VPP_COPY_FIELD =0x02, + MFX_VPP_SWAP_FIELDS =0x03 +}; + +/*PicType*/ +enum { + MFX_PICTYPE_UNKNOWN =0x00, + MFX_PICTYPE_FRAME =0x01, + MFX_PICTYPE_TOPFIELD =0x02, + MFX_PICTYPE_BOTTOMFIELD =0x04 +}; + +typedef struct { + mfxExtBuffer Header; + + mfxU16 Mode; + mfxU16 InField; + mfxU16 OutField; + mfxU16 reserved[25]; +} mfxExtVPPFieldProcessing; + +typedef struct { + mfxExtBuffer Header; + + mfxU16 ChromaLocInfoPresentFlag; + mfxU16 ChromaSampleLocTypeTopField; + mfxU16 ChromaSampleLocTypeBottomField; + mfxU16 reserved[9]; +} mfxExtChromaLocInfo; + +typedef struct { + mfxExtBuffer Header; + + mfxU32 reserved[11]; + mfxU32 NumQPAlloc; + union { + mfxU8 *QP; + mfxU64 reserved2; + }; +} mfxExtMBQP; + +typedef struct { + mfxExtBuffer Header; + + mfxU16 NumTileRows; + mfxU16 NumTileColumns; + mfxU16 reserved[74]; +}mfxExtHEVCTiles; + +typedef struct { + mfxExtBuffer Header; + + mfxU32 reserved[11]; + mfxU32 MapSize; + union { + mfxU8 *Map; + mfxU64 reserved2; + }; +} mfxExtMBDisableSkipMap; + +/*GeneralConstraintFlags*/ +enum { + /* REXT Profile constraint flags*/ + MFX_HEVC_CONSTR_REXT_MAX_12BIT = (1 << 0), + MFX_HEVC_CONSTR_REXT_MAX_10BIT = (1 << 1), + MFX_HEVC_CONSTR_REXT_MAX_8BIT = (1 << 2), + MFX_HEVC_CONSTR_REXT_MAX_422CHROMA = (1 << 3), + MFX_HEVC_CONSTR_REXT_MAX_420CHROMA = (1 << 4), + MFX_HEVC_CONSTR_REXT_MAX_MONOCHROME = (1 << 5), + MFX_HEVC_CONSTR_REXT_INTRA = (1 << 6), + MFX_HEVC_CONSTR_REXT_ONE_PICTURE_ONLY = (1 << 7), + MFX_HEVC_CONSTR_REXT_LOWER_BIT_RATE = (1 << 8) +}; + +#pragma pack(push, 4) +typedef struct { + mfxExtBuffer Header; + + mfxU16 PicWidthInLumaSamples; + mfxU16 PicHeightInLumaSamples; + mfxU64 GeneralConstraintFlags; + mfxU16 reserved[118]; +} mfxExtHEVCParam; +#pragma pack(pop) + +typedef struct { + mfxExtBuffer Header; + + mfxU16 FrameType; + mfxU16 reserved[59]; +} mfxExtDecodedFrameInfo; + +typedef struct { + mfxExtBuffer Header; + + mfxU16 DropFrameFlag; + mfxU16 TimeCodeHours; + mfxU16 TimeCodeMinutes; + mfxU16 TimeCodeSeconds; + mfxU16 TimeCodePictures; + mfxU16 reserved[7]; +} mfxExtTimeCode; + +/*RegionType*/ +enum { + MFX_HEVC_REGION_SLICE = 0 +}; + +/*RegionEncoding*/ +enum { + MFX_HEVC_REGION_ENCODING_ON = 0, + MFX_HEVC_REGION_ENCODING_OFF = 1 +}; + +typedef struct { + mfxExtBuffer Header; + + mfxU32 RegionId; + mfxU16 RegionType; + mfxU16 RegionEncoding; + mfxU16 reserved[24]; +} mfxExtHEVCRegion; + +typedef struct { + mfxExtBuffer Header; + + mfxU16 LumaLog2WeightDenom; // 0..7 + mfxU16 ChromaLog2WeightDenom; // 0..7 + mfxU16 LumaWeightFlag[2][32]; // [list] 0,1 + mfxU16 ChromaWeightFlag[2][32]; // [list] 0,1 + mfxI16 Weights[2][32][3][2]; // [list][list entry][Y, Cb, Cr][weight, offset] + mfxU16 reserved[58]; +} mfxExtPredWeightTable; + +typedef struct { + mfxExtBuffer Header; + + mfxU16 NumRect; + mfxU16 reserved1[11]; + + struct { + mfxU32 Left; + mfxU32 Top; + mfxU32 Right; + mfxU32 Bottom; + + mfxU16 reserved2[8]; + } Rect[256]; +} mfxExtDirtyRect; + +typedef struct { + mfxExtBuffer Header; + + mfxU16 NumRect; + mfxU16 reserved1[11]; + + struct { + mfxU32 DestLeft; + mfxU32 DestTop; + mfxU32 DestRight; + mfxU32 DestBottom; + + mfxU32 SourceLeft; + mfxU32 SourceTop; + mfxU16 reserved2[4]; + } Rect[256]; +} mfxExtMoveRect; + +/* Angle */ +enum { + MFX_ANGLE_0 = 0, + MFX_ANGLE_90 = 90, + MFX_ANGLE_180 = 180, + MFX_ANGLE_270 = 270 +}; + +typedef struct { + mfxExtBuffer Header; + + mfxU16 Angle; + mfxU16 reserved[11]; +} mfxExtVPPRotation; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif + diff --git a/plugins/obs-qsv11/libmfx/include/msdk/include/mfxvideo++.h b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxvideo++.h new file mode 100644 index 000000000..971456a71 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxvideo++.h @@ -0,0 +1,197 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2007-2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +File Name: mfxvideo++.h + +\* ****************************************************************************** */ + +#ifndef __MFXVIDEOPLUSPLUS_H +#define __MFXVIDEOPLUSPLUS_H + +#include "mfxvideo.h" +#include "mfxenc.h" +#include "mfxpak.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 SetBufferAllocator(mfxBufferAllocator *allocator) { return MFXVideoCORE_SetBufferAllocator(m_session, allocator); } + 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 SyncOperation(mfxSyncPoint syncp, mfxU32 wait) { return MFXVideoCORE_SyncOperation(m_session, syncp, wait); } + + virtual mfxStatus DoWork() { return MFXDoWork(m_session); } + + 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: + + 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 +}; + +class MFXVideoDECODE +{ +public: + + 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 +}; + +class MFXVideoVPP +{ +public: + + 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); } + virtual mfxStatus RunFrameVPPAsyncEx(mfxFrameSurface1 *in, mfxFrameSurface1 *work, mfxFrameSurface1 **out, mfxSyncPoint *syncp) {return MFXVideoVPP_RunFrameVPPAsyncEx(m_session, in, work, out, syncp); } + +protected: + + mfxSession m_session; // (mfxSession) handle to the owning session +}; + +class MFXVideoENC +{ +public: + + MFXVideoENC(mfxSession session) { m_session = session; } + virtual ~MFXVideoENC(void) { Close(); } + + virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) { return MFXVideoENC_Query(m_session, in, out); } + virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest *request) { return MFXVideoENC_QueryIOSurf(m_session, par, request); } + virtual mfxStatus Init(mfxVideoParam *par) { return MFXVideoENC_Init(m_session, par); } + virtual mfxStatus Reset(mfxVideoParam *par) { return MFXVideoENC_Reset(m_session, par); } + virtual mfxStatus Close(void) { return MFXVideoENC_Close(m_session); } + + virtual mfxStatus ProcessFrameAsync(mfxENCInput *in, mfxENCOutput *out, mfxSyncPoint *syncp) { return MFXVideoENC_ProcessFrameAsync(m_session, in, out, syncp); } + +protected: + + mfxSession m_session; // (mfxSession) handle to the owning session +}; + +class MFXVideoPAK +{ +public: + + MFXVideoPAK(mfxSession session) { m_session = session; } + virtual ~MFXVideoPAK(void) { Close(); } + + virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) { return MFXVideoPAK_Query(m_session, in, out); } + virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest *request) { return MFXVideoPAK_QueryIOSurf(m_session, par, request); } + virtual mfxStatus Init(mfxVideoParam *par) { return MFXVideoPAK_Init(m_session, par); } + virtual mfxStatus Reset(mfxVideoParam *par) { return MFXVideoPAK_Reset(m_session, par); } + virtual mfxStatus Close(void) { return MFXVideoPAK_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 ProcessFrameAsync(mfxPAKInput *in, mfxPAKOutput *out, mfxSyncPoint *syncp) { return MFXVideoPAK_ProcessFrameAsync(m_session, in, out, syncp); } + +protected: + + mfxSession m_session; // (mfxSession) handle to the owning session +}; + +#endif // __MFXVIDEOPLUSPLUS_H diff --git a/plugins/obs-qsv11/libmfx/include/msdk/include/mfxvideo.h b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxvideo.h new file mode 100644 index 000000000..7042c1719 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxvideo.h @@ -0,0 +1,112 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2007-2015 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfxvideo.h + +\* ****************************************************************************** */ +#ifndef __MFXVIDEO_H__ +#define __MFXVIDEO_H__ +#include "mfxsession.h" +#include "mfxvstructures.h" + +#define MFX_VERSION_MAJOR 1 +#define MFX_VERSION_MINOR 17 + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* MFXVideoCORE */ +typedef struct { + mfxU32 reserved[4]; + mfxHDL pthis; + mfxStatus (MFX_CDECL *Alloc) (mfxHDL pthis, mfxU32 nbytes, mfxU16 type, mfxMemId *mid); + mfxStatus (MFX_CDECL *Lock) (mfxHDL pthis, mfxMemId mid, mfxU8 **ptr); + mfxStatus (MFX_CDECL *Unlock) (mfxHDL pthis, mfxMemId mid); + mfxStatus (MFX_CDECL *Free) (mfxHDL pthis, mfxMemId mid); +} mfxBufferAllocator; + +typedef struct { + mfxU32 reserved[4]; + mfxHDL pthis; + + mfxStatus (MFX_CDECL *Alloc) (mfxHDL pthis, mfxFrameAllocRequest *request, mfxFrameAllocResponse *response); + mfxStatus (MFX_CDECL *Lock) (mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr); + mfxStatus (MFX_CDECL *Unlock) (mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr); + mfxStatus (MFX_CDECL *GetHDL) (mfxHDL pthis, mfxMemId mid, mfxHDL *handle); + mfxStatus (MFX_CDECL *Free) (mfxHDL pthis, mfxFrameAllocResponse *response); +} mfxFrameAllocator; + +/* VideoCORE */ +mfxStatus MFX_CDECL MFXVideoCORE_SetBufferAllocator(mfxSession session, mfxBufferAllocator *allocator); +mfxStatus MFX_CDECL MFXVideoCORE_SetFrameAllocator(mfxSession session, mfxFrameAllocator *allocator); +mfxStatus MFX_CDECL MFXVideoCORE_SetHandle(mfxSession session, mfxHandleType type, mfxHDL hdl); +mfxStatus MFX_CDECL MFXVideoCORE_GetHandle(mfxSession session, mfxHandleType type, mfxHDL *hdl); +mfxStatus MFX_CDECL MFXVideoCORE_SyncOperation(mfxSession session, mfxSyncPoint syncp, mfxU32 wait); + +/* VideoENCODE */ +mfxStatus MFX_CDECL MFXVideoENCODE_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out); +mfxStatus MFX_CDECL MFXVideoENCODE_QueryIOSurf(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request); +mfxStatus MFX_CDECL MFXVideoENCODE_Init(mfxSession session, mfxVideoParam *par); +mfxStatus MFX_CDECL MFXVideoENCODE_Reset(mfxSession session, mfxVideoParam *par); +mfxStatus MFX_CDECL MFXVideoENCODE_Close(mfxSession session); + +mfxStatus MFX_CDECL MFXVideoENCODE_GetVideoParam(mfxSession session, mfxVideoParam *par); +mfxStatus MFX_CDECL MFXVideoENCODE_GetEncodeStat(mfxSession session, mfxEncodeStat *stat); +mfxStatus MFX_CDECL MFXVideoENCODE_EncodeFrameAsync(mfxSession session, mfxEncodeCtrl *ctrl, mfxFrameSurface1 *surface, mfxBitstream *bs, mfxSyncPoint *syncp); + +/* VideoDECODE */ +mfxStatus MFX_CDECL MFXVideoDECODE_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out); +mfxStatus MFX_CDECL MFXVideoDECODE_DecodeHeader(mfxSession session, mfxBitstream *bs, mfxVideoParam *par); +mfxStatus MFX_CDECL MFXVideoDECODE_QueryIOSurf(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request); +mfxStatus MFX_CDECL MFXVideoDECODE_Init(mfxSession session, mfxVideoParam *par); +mfxStatus MFX_CDECL MFXVideoDECODE_Reset(mfxSession session, mfxVideoParam *par); +mfxStatus MFX_CDECL MFXVideoDECODE_Close(mfxSession session); + +mfxStatus MFX_CDECL MFXVideoDECODE_GetVideoParam(mfxSession session, mfxVideoParam *par); +mfxStatus MFX_CDECL MFXVideoDECODE_GetDecodeStat(mfxSession session, mfxDecodeStat *stat); +mfxStatus MFX_CDECL MFXVideoDECODE_SetSkipMode(mfxSession session, mfxSkipMode mode); +mfxStatus MFX_CDECL MFXVideoDECODE_GetPayload(mfxSession session, mfxU64 *ts, mfxPayload *payload); +mfxStatus MFX_CDECL MFXVideoDECODE_DecodeFrameAsync(mfxSession session, mfxBitstream *bs, mfxFrameSurface1 *surface_work, mfxFrameSurface1 **surface_out, mfxSyncPoint *syncp); + +/* VideoVPP */ +mfxStatus MFX_CDECL MFXVideoVPP_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out); +mfxStatus MFX_CDECL MFXVideoVPP_QueryIOSurf(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest request[2]); +mfxStatus MFX_CDECL MFXVideoVPP_Init(mfxSession session, mfxVideoParam *par); +mfxStatus MFX_CDECL MFXVideoVPP_Reset(mfxSession session, mfxVideoParam *par); +mfxStatus MFX_CDECL MFXVideoVPP_Close(mfxSession session); + +mfxStatus MFX_CDECL MFXVideoVPP_GetVideoParam(mfxSession session, mfxVideoParam *par); +mfxStatus MFX_CDECL MFXVideoVPP_GetVPPStat(mfxSession session, mfxVPPStat *stat); +mfxStatus MFX_CDECL MFXVideoVPP_RunFrameVPPAsync(mfxSession session, mfxFrameSurface1 *in, mfxFrameSurface1 *out, mfxExtVppAuxData *aux, mfxSyncPoint *syncp); +mfxStatus MFX_CDECL MFXVideoVPP_RunFrameVPPAsyncEx(mfxSession session, mfxFrameSurface1 *in, mfxFrameSurface1 *surface_work, mfxFrameSurface1 **surface_out, mfxSyncPoint *syncp); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/plugins/obs-qsv11/libmfx/include/msdk/include/mfxvstructures.h b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxvstructures.h new file mode 100644 index 000000000..eae07a485 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/include/msdk/include/mfxvstructures.h @@ -0,0 +1,32 @@ +/******************************************************************************* + +Copyright (C) 2013 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfxvstructures.h + +*******************************************************************************/ +#include "mfxstructures.h" + + diff --git a/plugins/obs-qsv11/libmfx/src/main.cpp b/plugins/obs-qsv11/libmfx/src/main.cpp new file mode 100644 index 000000000..9097830f4 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/src/main.cpp @@ -0,0 +1,937 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2012-2015 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: main.cpp + +\* ****************************************************************************** */ + +#include "mfx_dispatcher.h" +#include "mfx_load_dll.h" +#include "mfx_dispatcher_log.h" +#include "mfx_library_iterator.h" +#include "mfx_critical_section.h" + +#include /* for memset on Linux */ +#include +#include /* for qsort on Linux */ +#include "mfx_load_plugin.h" +#include "mfx_plugin_hive.h" + +// module-local definitions +namespace +{ + + const + struct + { + // instance implementation type + eMfxImplType implType; + // real implementation + mfxIMPL impl; + // adapter numbers + mfxU32 adapterID; + + } implTypes[] = + { + // MFX_IMPL_AUTO case + {MFX_LIB_HARDWARE, MFX_IMPL_HARDWARE, 0}, + {MFX_LIB_SOFTWARE, MFX_IMPL_SOFTWARE, 0}, + + // MFX_IMPL_ANY case + {MFX_LIB_HARDWARE, MFX_IMPL_HARDWARE, 0}, + {MFX_LIB_HARDWARE, MFX_IMPL_HARDWARE2, 1}, + {MFX_LIB_HARDWARE, MFX_IMPL_HARDWARE3, 2}, + {MFX_LIB_HARDWARE, MFX_IMPL_HARDWARE4, 3}, + {MFX_LIB_SOFTWARE, MFX_IMPL_SOFTWARE, 0}, + {MFX_LIB_SOFTWARE, MFX_IMPL_SOFTWARE | MFX_IMPL_AUDIO, 0} + }; + + const + struct + { + // start index in implTypes table for specified implementation + mfxU32 minIndex; + // last index in implTypes table for specified implementation + mfxU32 maxIndex; + + } implTypesRange[] = + { + {0, 1}, // MFX_IMPL_AUTO + {1, 1}, // MFX_IMPL_SOFTWARE + {0, 0}, // MFX_IMPL_HARDWARE + {2, 6}, // MFX_IMPL_AUTO_ANY + {2, 5}, // MFX_IMPL_HARDWARE_ANY + {3, 3}, // MFX_IMPL_HARDWARE2 + {4, 4}, // MFX_IMPL_HARDWARE3 + {5, 5}, // MFX_IMPL_HARDWARE4 + {2, 6}, // MFX_IMPL_RUNTIME, same as MFX_IMPL_HARDWARE_ANY + {7, 7} // MFX_IMPL_AUDIO + }; + + MFX::mfxCriticalSection dispGuard = 0; + +} // namespace + +using namespace MFX; +// +// Implement DLL exposed functions. MFXInit and MFXClose have to do +// slightly more than other. They require to be implemented explicitly. +// All other functions are implemented implicitly. +// + +typedef MFXVector HandleVector; +typedef MFXVector StatusVector; + +struct VectorHandleGuard +{ + VectorHandleGuard(HandleVector& aVector): m_vector(aVector) {} + ~VectorHandleGuard() + { + HandleVector::iterator it = m_vector.begin(), + et = m_vector.end(); + for ( ; it != et; ++it) + { + delete *it; + } + } + + HandleVector& m_vector; +private: + void operator=(const VectorHandleGuard&); +}; + + +int HandleSort (const void * plhs, const void * prhs) +{ + const MFX_DISP_HANDLE * lhs = *(const MFX_DISP_HANDLE **)plhs; + const MFX_DISP_HANDLE * rhs = *(const MFX_DISP_HANDLE **)prhs; + + if (lhs->actualApiVersion < rhs->actualApiVersion) + { + return -1; + } + if (rhs->actualApiVersion < lhs->actualApiVersion) + { + return 1; + } + + // if versions are equal prefer library with HW + if (lhs->loadStatus == MFX_WRN_PARTIAL_ACCELERATION && rhs->loadStatus == MFX_ERR_NONE) + { + return 1; + } + if (lhs->loadStatus == MFX_ERR_NONE && rhs->loadStatus == MFX_WRN_PARTIAL_ACCELERATION) + { + return -1; + } + + return 0; +} + +mfxStatus MFXInit(mfxIMPL impl, mfxVersion *pVer, mfxSession *session) +{ + mfxInitParam par = {}; + + par.Implementation = impl; + if (pVer) + { + par.Version = *pVer; + } + else + { + par.Version.Major = DEFAULT_API_VERSION_MAJOR; + par.Version.Minor = DEFAULT_API_VERSION_MINOR; + } + par.ExternalThreads = 0; + + return MFXInitEx(par, session); +} + +mfxStatus MFXInitEx(mfxInitParam par, mfxSession *session) +{ + MFX::MFXAutomaticCriticalSection guard(&dispGuard); + + DISPATCHER_LOG_BLOCK( ("MFXInitEx (impl=%s, pVer=%d.%d, ExternalThreads=%d session=0x%p\n" + , DispatcherLog_GetMFXImplString(par.Implementation).c_str() + , par.Version.Major + , par.Version.Minor + , par.ExternalThreads + , session)); + + mfxStatus mfxRes; + HandleVector allocatedHandle; + VectorHandleGuard handleGuard(allocatedHandle); + + MFX_DISP_HANDLE *pHandle; + msdk_disp_char dllName[MFX_MAX_DLL_PATH]; + MFX::MFXLibraryIterator libIterator; + // there iterators are used only if the caller specified implicit type like AUTO + mfxU32 curImplIdx, maxImplIdx; + // particular implementation value + mfxIMPL curImpl; + // implementation method masked from the input parameter + // special case for audio library + const mfxIMPL implMethod = (par.Implementation & MFX_IMPL_AUDIO) ? (sizeof(implTypesRange) / sizeof(implTypesRange[0]) - 1) : (par.Implementation & (MFX_IMPL_VIA_ANY - 1)); + + // implementation interface masked from the input parameter + mfxIMPL implInterface = par.Implementation & -MFX_IMPL_VIA_ANY; + mfxIMPL implInterfaceOrig = implInterface; + mfxVersion requiredVersion = {{MFX_VERSION_MINOR, MFX_VERSION_MAJOR}}; + + // check error(s) + if (NULL == session) + { + return MFX_ERR_NULL_PTR; + } + if (((MFX_IMPL_AUTO > implMethod) || (MFX_IMPL_RUNTIME < implMethod)) && !(par.Implementation & MFX_IMPL_AUDIO)) + { + return MFX_ERR_UNSUPPORTED; + } + + // set the minimal required version + requiredVersion = par.Version; + + try + { + // reset the session value + *session = 0; + + // allocate the dispatching handle and call-table + pHandle = new MFX_DISP_HANDLE(requiredVersion); + } + catch(...) + { + return MFX_ERR_MEMORY_ALLOC; + } + + DISPATCHER_LOG_INFO((("Required API version is %u.%u\n"), requiredVersion.Major, requiredVersion.Minor)); + + // Load HW library or RT from system location + curImplIdx = implTypesRange[implMethod].minIndex; + maxImplIdx = implTypesRange[implMethod].maxIndex; + mfxU32 hwImplIdx = 0; + do + { + int currentStorage = MFX::MFX_STORAGE_ID_FIRST; + implInterface = implInterfaceOrig; + do + { + // initialize the library iterator + mfxRes = libIterator.Init(implTypes[curImplIdx].implType, + implInterface, + implTypes[curImplIdx].adapterID, + currentStorage); + + // look through the list of installed SDK version, + // looking for a suitable library with higher merit value. + if (MFX_ERR_NONE == mfxRes) + { + + if ( + MFX_LIB_HARDWARE == implTypes[curImplIdx].implType + && (!implInterface + || MFX_IMPL_VIA_ANY == implInterface)) + { + implInterface = libIterator.GetImplementationType(); + } + + do + { + eMfxImplType implType; + + // select a desired DLL + mfxRes = libIterator.SelectDLLVersion(dllName, + sizeof(dllName) / sizeof(dllName[0]), + &implType, + pHandle->apiVersion); + if (MFX_ERR_NONE != mfxRes) + { + break; + } + DISPATCHER_LOG_INFO((("loading library %S\n"), MSDK2WIDE(dllName))); + if (MFX_LIB_HARDWARE == implTypes[curImplIdx].implType) + hwImplIdx = curImplIdx; + // try to load the selected DLL + curImpl = implTypes[curImplIdx].impl; + mfxRes = pHandle->LoadSelectedDLL(dllName, implType, curImpl, implInterface, par); + // unload the failed DLL + if (MFX_ERR_NONE != mfxRes) + { + pHandle->Close(); + } + else + { + libIterator.GetSubKeyName(pHandle->subkeyName, sizeof(pHandle->subkeyName)/sizeof(pHandle->subkeyName[0])) ; + pHandle->storageID = libIterator.GetStorageID(); + allocatedHandle.push_back(pHandle); + pHandle = new MFX_DISP_HANDLE(requiredVersion); + } + + } while (MFX_ERR_NONE != mfxRes); + } + + // select another registry key + currentStorage += 1; + + } while ((MFX_ERR_NONE != mfxRes) && (MFX::MFX_STORAGE_ID_LAST >= currentStorage)); + + } while ((MFX_ERR_NONE != mfxRes) && (++curImplIdx <= maxImplIdx)); + + + curImplIdx = implTypesRange[implMethod].minIndex; + maxImplIdx = implTypesRange[implMethod].maxIndex; + + // Load RT from app folder (libmfxsw64 with API >= 1.10) + do + { + implInterface = implInterfaceOrig; + // initialize the library iterator + mfxRes = libIterator.Init(implTypes[curImplIdx].implType, + implInterface, + implTypes[curImplIdx].adapterID, + MFX::MFX_APP_FOLDER); + + if (MFX_ERR_NONE == mfxRes) + { + + if ( + MFX_LIB_HARDWARE == implTypes[curImplIdx].implType + && (!implInterface + || MFX_IMPL_VIA_ANY == implInterface)) + { + implInterface = libIterator.GetImplementationType(); + } + + do + { + eMfxImplType implType; + + // select a desired DLL + mfxRes = libIterator.SelectDLLVersion(dllName, + sizeof(dllName) / sizeof(dllName[0]), + &implType, + pHandle->apiVersion); + if (MFX_ERR_NONE != mfxRes) + { + break; + } + DISPATCHER_LOG_INFO((("loading library %S\n"), MSDK2WIDE(dllName))); + + // try to load the selected DLL + curImpl = implTypes[curImplIdx].impl; + mfxRes = pHandle->LoadSelectedDLL(dllName, implType, curImpl, implInterface, par); + // unload the failed DLL + if (MFX_ERR_NONE != mfxRes) + { + pHandle->Close(); + } + else + { + if (pHandle->actualApiVersion.Major == 1 && pHandle->actualApiVersion.Minor <= 9) + { + // this is not RT, skip it + mfxRes = MFX_ERR_ABORTED; + break; + } + pHandle->storageID = MFX::MFX_UNKNOWN_KEY; + allocatedHandle.push_back(pHandle); + pHandle = new MFX_DISP_HANDLE(requiredVersion); + } + + } while (MFX_ERR_NONE != mfxRes); + } + } while ((MFX_ERR_NONE != mfxRes) && (++curImplIdx <= maxImplIdx)); + + // Load HW and SW libraries using legacy default DLL search mechanism + // set current library index again + curImplIdx = implTypesRange[implMethod].minIndex; + do + { + mfxU32 backupIdx = curImplIdx; + if (MFX_LIB_HARDWARE == implTypes[curImplIdx].implType) + { + curImplIdx = hwImplIdx; + } + implInterface = implInterfaceOrig; + + if (par.Implementation & MFX_IMPL_AUDIO) + { + mfxRes = MFX::mfx_get_default_audio_dll_name(dllName, + sizeof(dllName) / sizeof(dllName[0]), + implTypes[curImplIdx].implType); + } + else + { + mfxRes = MFX::mfx_get_default_dll_name(dllName, + sizeof(dllName) / sizeof(dllName[0]), + implTypes[curImplIdx].implType); + } + + if (MFX_ERR_NONE == mfxRes) + { + DISPATCHER_LOG_INFO((("loading default library %S\n"), MSDK2WIDE(dllName))) + + // try to load the selected DLL using default DLL search mechanism + if (MFX_LIB_HARDWARE == implTypes[curImplIdx].implType) + { + if (!implInterface) + { + implInterface = MFX_IMPL_VIA_ANY; + } + mfxRes = MFX::SelectImplementationType(implTypes[curImplIdx].adapterID, &implInterface, NULL, NULL); + } + if (MFX_ERR_NONE == mfxRes) + { + // try to load the selected DLL using default DLL search mechanism + mfxRes = pHandle->LoadSelectedDLL(dllName, + implTypes[curImplIdx].implType, + implTypes[curImplIdx].impl, + implInterface, + par); + } + // unload the failed DLL + if ((MFX_ERR_NONE != mfxRes) && + (MFX_WRN_PARTIAL_ACCELERATION != mfxRes)) + { + pHandle->Close(); + } + else + { + pHandle->storageID = MFX::MFX_UNKNOWN_KEY; + allocatedHandle.push_back(pHandle); + pHandle = new MFX_DISP_HANDLE(requiredVersion); + } + } + curImplIdx = backupIdx; + } + while ((MFX_ERR_NONE > mfxRes) && (++curImplIdx <= maxImplIdx)); + delete pHandle; + + if (allocatedHandle.size() == 0) + return MFX_ERR_UNSUPPORTED; + + bool NeedSort = false; + HandleVector::iterator first = allocatedHandle.begin(), + it = allocatedHandle.begin(), + et = allocatedHandle.end(); + for (it++; it != et; ++it) + if (HandleSort(&(*first), &(*it)) != 0) + NeedSort = true; + + // select dll with version with lowest version number still greater or equal to requested + if (NeedSort) + qsort(&(*allocatedHandle.begin()), allocatedHandle.size(), sizeof(MFX_DISP_HANDLE*), &HandleSort); + + HandleVector::iterator candidate = allocatedHandle.begin(); + // check the final result of loading + try + { + pHandle = *candidate; + //pulling up current mediasdk version, that required to match plugin version + mfxVersion apiVerActual; + mfxStatus stsQueryVersion; + stsQueryVersion = MFXQueryVersion((mfxSession)pHandle, &apiVerActual); + if (MFX_ERR_NONE != stsQueryVersion) + { + DISPATCHER_LOG_ERROR((("MFXQueryVersion returned: %d, cannot load plugins\n"), mfxRes)) + } + else + { + MFX::MFXPluginStorage & hive = pHandle->pluginHive; + + HandleVector::iterator it = allocatedHandle.begin(), + et = allocatedHandle.end(); + for (; it != et; ++it) + { + // Registering default plugins set + MFX::MFXDefaultPlugins defaultPugins(apiVerActual, *it, (*it)->implType); + hive.insert(hive.end(), defaultPugins.begin(), defaultPugins.end()); + + if ((*it)->storageID != MFX::MFX_UNKNOWN_KEY) + { + // Scan HW plugins in subkeys of registry library + MFX::MFXPluginsInHive plgsInHive((*it)->storageID, (*it)->subkeyName, apiVerActual); + hive.insert(hive.end(), plgsInHive.begin(), plgsInHive.end()); + } + } + + //setting up plugins records + for(int i = MFX::MFX_STORAGE_ID_FIRST; i <= MFX::MFX_STORAGE_ID_LAST; i++) + { + MFX::MFXPluginsInHive plgsInHive(i, NULL, apiVerActual); + hive.insert(hive.end(), plgsInHive.begin(), plgsInHive.end()); + } + + MFX::MFXPluginsInFS plgsInFS(apiVerActual); + hive.insert(hive.end(), plgsInFS.begin(), plgsInFS.end()); + } + } + catch(...) + { + DISPATCHER_LOG_ERROR((("unknown exception while loading plugins\n"))) + } + + // everything is OK. Save pointers to the output variable + *candidate = 0; // keep this one safe from guard destructor + *((MFX_DISP_HANDLE **) session) = pHandle; + + return pHandle->loadStatus; + +} // mfxStatus MFXInit(mfxIMPL impl, mfxVersion *ver, mfxSession *session) + +mfxStatus MFXClose(mfxSession session) +{ + MFX::MFXAutomaticCriticalSection guard(&dispGuard); + + mfxStatus mfxRes = MFX_ERR_INVALID_HANDLE; + MFX_DISP_HANDLE *pHandle = (MFX_DISP_HANDLE *) session; + + // check error(s) + if (pHandle) + { + try + { + // unload the DLL library + mfxRes = pHandle->Close(); + + // it is possible, that there is an active child session. + // can't unload library in that case. + if (MFX_ERR_UNDEFINED_BEHAVIOR != mfxRes) + { + // release the handle + delete pHandle; + } + } + catch(...) + { + mfxRes = MFX_ERR_INVALID_HANDLE; + } + } + + return mfxRes; + +} // mfxStatus MFXClose(mfxSession session) + +mfxStatus MFXJoinSession(mfxSession session, mfxSession child_session) +{ + mfxStatus mfxRes = MFX_ERR_INVALID_HANDLE; + MFX_DISP_HANDLE *pHandle = (MFX_DISP_HANDLE *) session; + MFX_DISP_HANDLE *pChildHandle = (MFX_DISP_HANDLE *) child_session; + + // get the function's address and make a call + if ((pHandle) && (pChildHandle) && (pHandle->apiVersion == pChildHandle->apiVersion)) + { + /* check whether it is audio session or video */ + int tableIndex = eMFXJoinSession; + mfxFunctionPointer pFunc; + if (pHandle->impl & MFX_IMPL_AUDIO) + { + pFunc = pHandle->callAudioTable[tableIndex]; + } + else + { + pFunc = pHandle->callTable[tableIndex]; + } + + if (pFunc) + { + // pass down the call + mfxRes = (*(mfxStatus (MFX_CDECL *) (mfxSession, mfxSession)) pFunc) (pHandle->session, + pChildHandle->session); + } + } + + return mfxRes; + +} // mfxStatus MFXJoinSession(mfxSession session, mfxSession child_session) + +mfxStatus MFXCloneSession(mfxSession session, mfxSession *clone) +{ + mfxStatus mfxRes = MFX_ERR_INVALID_HANDLE; + MFX_DISP_HANDLE *pHandle = (MFX_DISP_HANDLE *) session; + mfxVersion apiVersion; + mfxIMPL impl; + + // check error(s) + if (pHandle) + { + // initialize the clone session + apiVersion = pHandle->apiVersion; + impl = pHandle->impl | pHandle->implInterface; + mfxRes = MFXInit(impl, &apiVersion, clone); + if (MFX_ERR_NONE != mfxRes) + { + return mfxRes; + } + + // join the sessions + mfxRes = MFXJoinSession(session, *clone); + if (MFX_ERR_NONE != mfxRes) + { + MFXClose(*clone); + *clone = NULL; + return mfxRes; + } + } + + return mfxRes; + +} // mfxStatus MFXCloneSession(mfxSession session, mfxSession *clone) + + +mfxStatus MFXVideoUSER_Load(mfxSession session, const mfxPluginUID *uid, mfxU32 version) +{ + mfxStatus sts = MFX_ERR_NONE; + bool ErrFlag = false; + MFX_DISP_HANDLE &pHandle = *(MFX_DISP_HANDLE *) session; + if (!&pHandle) + { + DISPATCHER_LOG_ERROR((("MFXVideoUSER_Load: session=NULL\n"))); + return MFX_ERR_NULL_PTR; + } + if (!uid) + { + DISPATCHER_LOG_ERROR((("MFXVideoUSER_Load: uid=NULL\n"))); + return MFX_ERR_NULL_PTR; + } + DISPATCHER_LOG_INFO((("MFXVideoUSER_Load: uid="MFXGUIDTYPE()" version=%d\n") + , MFXGUIDTOHEX(uid) + , version)) + size_t pluginsChecked = 0; + + for (MFX::MFXPluginStorage::iterator i = pHandle.pluginHive.begin();i != pHandle.pluginHive.end(); i++, pluginsChecked++) + { + if (i->PluginUID != *uid) + { + continue; + } + //check rest in records + if (i->PluginVersion < version) + { + DISPATCHER_LOG_INFO((("MFXVideoUSER_Load: registered \"Plugin Version\" for GUID="MFXGUIDTYPE()" is %d, that is smaller that requested\n") + , MFXGUIDTOHEX(uid) + , i->PluginVersion)) + continue; + } + try + { + sts = pHandle.pluginFactory.Create(*i); + if( MFX_ERR_NONE != sts) + { + ErrFlag = (ErrFlag || (sts == MFX_ERR_UNDEFINED_BEHAVIOR)); + continue; + } + return MFX_ERR_NONE; + } + catch(...) + { + continue; + } + } + + // Specified UID was not found among individually registed plugins, now try load it from default sets if any + for (MFX::MFXPluginStorage::iterator i = pHandle.pluginHive.begin();i != pHandle.pluginHive.end(); i++, pluginsChecked++) + { + if (!i->Default) + continue; + + i->PluginUID = *uid; + i->PluginVersion = (mfxU16)version; + try + { + sts = pHandle.pluginFactory.Create(*i); + if( MFX_ERR_NONE != sts) + { + ErrFlag = (ErrFlag || (sts == MFX_ERR_UNDEFINED_BEHAVIOR)); + continue; + } + return MFX_ERR_NONE; + } + catch(...) + { + continue; + } + } + + DISPATCHER_LOG_ERROR((("MFXVideoUSER_Load: cannot find registered plugin with requested UID, total plugins available=%d\n"), pHandle.pluginHive.size())); + if (ErrFlag) + return MFX_ERR_UNDEFINED_BEHAVIOR; + else + return MFX_ERR_NOT_FOUND; +} + + +mfxStatus MFXVideoUSER_LoadByPath(mfxSession session, const mfxPluginUID *uid, mfxU32 version, const mfxChar *path, mfxU32 len) +{ + MFX_DISP_HANDLE &pHandle = *(MFX_DISP_HANDLE *) session; + if (!&pHandle) + { + DISPATCHER_LOG_ERROR((("MFXVideoUSER_LoadByPath: session=NULL\n"))); + return MFX_ERR_NULL_PTR; + } + if (!uid) + { + DISPATCHER_LOG_ERROR((("MFXVideoUSER_LoadByPath: uid=NULL\n"))); + return MFX_ERR_NULL_PTR; + } + + DISPATCHER_LOG_INFO((("MFXVideoUSER_LoadByPath: %S uid="MFXGUIDTYPE()" version=%d\n") + , MSDK2WIDE(path) + , MFXGUIDTOHEX(uid) + , version)) + + PluginDescriptionRecord record; + record.sName[0] = 0; + +#ifdef _WIN32 + msdk_disp_char wPath[MAX_PLUGIN_PATH]; + int res = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, path, len, wPath, MAX_PLUGIN_PATH); + if (!res) + { + DISPATCHER_LOG_ERROR((("MFXVideoUSER_LoadByPath: cant convert UTF-8 path to UTF-16\n"))); + return MFX_ERR_NOT_FOUND; + } + msdk_disp_char_cpy_s(record.sPath, res < MAX_PLUGIN_PATH ? res : MAX_PLUGIN_PATH, wPath); +#else // Linux/Android + msdk_disp_char_cpy_s(record.sPath, len < MAX_PLUGIN_PATH ? len : MAX_PLUGIN_PATH, path); +#endif + + record.PluginUID = *uid; + record.PluginVersion = (mfxU16)version; + record.Default = true; + + try + { + return pHandle.pluginFactory.Create(record); + } + catch(...) + { + return MFX_ERR_NOT_FOUND; + } +} + + +mfxStatus MFXVideoUSER_UnLoad(mfxSession session, const mfxPluginUID *uid) +{ + MFX_DISP_HANDLE &rHandle = *(MFX_DISP_HANDLE *) session; + if (!&rHandle) + { + DISPATCHER_LOG_ERROR((("MFXVideoUSER_UnLoad: session=NULL\n"))); + return MFX_ERR_NULL_PTR; + } + if (!uid) + { + DISPATCHER_LOG_ERROR((("MFXVideoUSER_Load: uid=NULL\n"))); + return MFX_ERR_NULL_PTR; + } + + bool bDestroyed = rHandle.pluginFactory.Destroy(*uid); + if (bDestroyed) + { + DISPATCHER_LOG_INFO((("MFXVideoUSER_UnLoad : plugin with GUID="MFXGUIDTYPE()" unloaded\n"), MFXGUIDTOHEX(uid))); + } else + { + DISPATCHER_LOG_ERROR((("MFXVideoUSER_UnLoad : plugin with GUID="MFXGUIDTYPE()" not found\n"), MFXGUIDTOHEX(uid))); + } + + return bDestroyed ? MFX_ERR_NONE : MFX_ERR_NOT_FOUND; +} + +mfxStatus MFXAudioUSER_Load(mfxSession session, const mfxPluginUID *uid, mfxU32 version) +{ + MFX_DISP_HANDLE &pHandle = *(MFX_DISP_HANDLE *) session; + if (!&pHandle) + { + DISPATCHER_LOG_ERROR((("MFXAudioUSER_Load: session=NULL\n"))); + return MFX_ERR_NULL_PTR; + } + if (!uid) + { + DISPATCHER_LOG_ERROR((("MFXAudioUSER_Load: uid=NULL\n"))); + return MFX_ERR_NULL_PTR; + } + DISPATCHER_LOG_INFO((("MFXAudioUSER_Load: uid="MFXGUIDTYPE()" version=%d\n") + , MFXGUIDTOHEX(uid) + , version)) + size_t pluginsChecked = 0; + PluginDescriptionRecord defaultPluginRecord; + for (MFX::MFXPluginStorage::iterator i = pHandle.pluginHive.begin();i != pHandle.pluginHive.end(); i++, pluginsChecked++) + { + if (i->PluginUID != *uid) + { + if (i->Default) // PluginUID == 0 for default set + { + defaultPluginRecord = *i; + } + continue; + } + //check rest in records + if (i->PluginVersion < version) + { + DISPATCHER_LOG_INFO((("MFXAudioUSER_Load: registered \"Plugin Version\" for GUID="MFXGUIDTYPE()" is %d, that is smaller that requested\n") + , MFXGUIDTOHEX(uid) + , i->PluginVersion)) + continue; + } + try { + return pHandle.pluginFactory.Create(*i); + } + catch(...) { + return MFX_ERR_UNKNOWN; + } + } + + // Specified UID was not found among individually registed plugins, now try load it from default set if any + if (defaultPluginRecord.Default) + { + defaultPluginRecord.PluginUID = *uid; + defaultPluginRecord.onlyVersionRegistered = true; + defaultPluginRecord.PluginVersion = (mfxU16)version; + try { + return pHandle.pluginFactory.Create(defaultPluginRecord); + } + catch(...) { + return MFX_ERR_UNKNOWN; + } + } + + DISPATCHER_LOG_ERROR((("MFXAudioUSER_Load: cannot find registered plugin with requested UID, total plugins available=%d\n"), pHandle.pluginHive.size())); + return MFX_ERR_NOT_FOUND; +} + +mfxStatus MFXAudioUSER_UnLoad(mfxSession session, const mfxPluginUID *uid) +{ + MFX_DISP_HANDLE &rHandle = *(MFX_DISP_HANDLE *) session; + if (!&rHandle) + { + DISPATCHER_LOG_ERROR((("MFXAudioUSER_UnLoad: session=NULL\n"))); + return MFX_ERR_NULL_PTR; + } + if (!uid) + { + DISPATCHER_LOG_ERROR((("MFXAudioUSER_Load: uid=NULL\n"))); + return MFX_ERR_NULL_PTR; + } + + bool bDestroyed = rHandle.pluginFactory.Destroy(*uid); + if (bDestroyed) + { + DISPATCHER_LOG_INFO((("MFXAudioUSER_UnLoad : plugin with GUID="MFXGUIDTYPE()" unloaded\n"), MFXGUIDTOHEX(uid))); + } else + { + DISPATCHER_LOG_ERROR((("MFXAudioUSER_UnLoad : plugin with GUID="MFXGUIDTYPE()" not found\n"), MFXGUIDTOHEX(uid))); + } + + return bDestroyed ? MFX_ERR_NONE : MFX_ERR_NOT_FOUND; +} + +// +// implement all other calling functions. +// They just call a procedure of DLL library from the table. +// + +// define for common functions (from mfxsession.h) +#undef FUNCTION +#define FUNCTION(return_value, func_name, formal_param_list, actual_param_list) \ + return_value func_name formal_param_list \ +{ \ + mfxStatus mfxRes = MFX_ERR_INVALID_HANDLE; \ + MFX_DISP_HANDLE *pHandle = (MFX_DISP_HANDLE *) session; \ + /* get the function's address and make a call */ \ + if (pHandle) \ +{ \ + /* check whether it is audio session or video */ \ + int tableIndex = e##func_name; \ + mfxFunctionPointer pFunc; \ + if (pHandle->impl & MFX_IMPL_AUDIO) \ +{ \ + pFunc = pHandle->callAudioTable[tableIndex]; \ +} \ + else \ +{ \ + pFunc = pHandle->callTable[tableIndex]; \ +} \ + if (pFunc) \ +{ \ + /* get the real session pointer */ \ + session = pHandle->session; \ + /* pass down the call */ \ + mfxRes = (*(mfxStatus (MFX_CDECL *) formal_param_list) pFunc) actual_param_list; \ +} \ +} \ + return mfxRes; \ +} + +FUNCTION(mfxStatus, MFXQueryIMPL, (mfxSession session, mfxIMPL *impl), (session, impl)) +FUNCTION(mfxStatus, MFXQueryVersion, (mfxSession session, mfxVersion *version), (session, version)) +FUNCTION(mfxStatus, MFXDisjoinSession, (mfxSession session), (session)) +FUNCTION(mfxStatus, MFXSetPriority, (mfxSession session, mfxPriority priority), (session, priority)) +FUNCTION(mfxStatus, MFXGetPriority, (mfxSession session, mfxPriority *priority), (session, priority)) + +#undef FUNCTION +#define FUNCTION(return_value, func_name, formal_param_list, actual_param_list) \ + return_value func_name formal_param_list \ +{ \ + mfxStatus mfxRes = MFX_ERR_INVALID_HANDLE; \ + MFX_DISP_HANDLE *pHandle = (MFX_DISP_HANDLE *) session; \ + /* get the function's address and make a call */ \ + if (pHandle) \ +{ \ + mfxFunctionPointer pFunc = pHandle->callTable[e##func_name]; \ + if (pFunc) \ +{ \ + /* get the real session pointer */ \ + session = pHandle->session; \ + /* pass down the call */ \ + mfxRes = (*(mfxStatus (MFX_CDECL *) formal_param_list) pFunc) actual_param_list; \ +} \ +} \ + return mfxRes; \ +} + +#include "mfx_exposed_functions_list.h" +#undef FUNCTION +#define FUNCTION(return_value, func_name, formal_param_list, actual_param_list) \ + return_value func_name formal_param_list \ +{ \ + mfxStatus mfxRes = MFX_ERR_INVALID_HANDLE; \ + MFX_DISP_HANDLE *pHandle = (MFX_DISP_HANDLE *) session; \ + /* get the function's address and make a call */ \ + if (pHandle) \ +{ \ + mfxFunctionPointer pFunc = pHandle->callAudioTable[e##func_name]; \ + if (pFunc) \ +{ \ + /* get the real session pointer */ \ + session = pHandle->session; \ + /* pass down the call */ \ + mfxRes = (*(mfxStatus (MFX_CDECL *) formal_param_list) pFunc) actual_param_list; \ +} \ +} \ + return mfxRes; \ +} + +#include "mfxaudio_exposed_functions_list.h" diff --git a/plugins/obs-qsv11/libmfx/src/mfx_critical_section.cpp b/plugins/obs-qsv11/libmfx/src/mfx_critical_section.cpp new file mode 100644 index 000000000..1e088212d --- /dev/null +++ b/plugins/obs-qsv11/libmfx/src/mfx_critical_section.cpp @@ -0,0 +1,88 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2012-2013 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_critical_section.cpp + +\* ****************************************************************************** */ + +#include "mfx_critical_section.h" + +#if defined(_WIN32) || defined(_WIN64) + +#include +// 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 + +#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 + +#endif // #if defined(_WIN32) || defined(_WIN64) diff --git a/plugins/obs-qsv11/libmfx/src/mfx_dispatcher.cpp b/plugins/obs-qsv11/libmfx/src/mfx_dispatcher.cpp new file mode 100644 index 000000000..0b42d025e --- /dev/null +++ b/plugins/obs-qsv11/libmfx/src/mfx_dispatcher.cpp @@ -0,0 +1,349 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2012-2015 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_dispatcher.cpp + +\* ****************************************************************************** */ + +#include "mfx_dispatcher.h" +#include "mfx_dispatcher_log.h" +#include "mfx_load_dll.h" + +#include +#if defined(_WIN32) || defined(_WIN64) + #include + #pragma warning(disable:4355) +#else + +#include +#include + +#endif // defined(_WIN32) || defined(_WIN64) + +MFX_DISP_HANDLE::MFX_DISP_HANDLE(const mfxVersion requiredVersion) : + apiVersion(requiredVersion), + pluginFactory((mfxSession)this) +{ + 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; + session = (mfxSession) 0; + + hModule = (mfxModuleHandle) 0; + + memset(callTable, 0, sizeof(callTable)); + memset(callAudioTable, 0, sizeof(callAudioTable)); + +} // 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(); + + // the library wasn't unloaded + 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; + session = (mfxSession) 0; + + hModule = (mfxModuleHandle) 0; + + memset(callTable, 0, sizeof(callTable)); + memset(callAudioTable, 0, sizeof(callAudioTable)); + } + + return mfxRes; + +} // mfxStatus MFX_DISP_HANDLE::Close(void) + +mfxStatus MFX_DISP_HANDLE::LoadSelectedDLL(const msdk_disp_char *pPath, eMfxImplType implType, + mfxIMPL impl, mfxIMPL implInterface, mfxInitParam &par) +{ + mfxStatus mfxRes = MFX_ERR_NONE; + + // check error(s) + if ((MFX_LIB_SOFTWARE != implType) && + (MFX_LIB_HARDWARE != implType)) + { + DISPATCHER_LOG_ERROR((("implType == %s, should be either MFX_LIB_SOFTWARE ot MFX_LIB_HARDWARE\n"), DispatcherLog_GetMFXImplString(implType).c_str())); + loadStatus = MFX_ERR_ABORTED; + return loadStatus; + } + // only exact types of implementation is allowed + if (!(impl & MFX_IMPL_AUDIO) && + (MFX_IMPL_SOFTWARE != impl) && + (MFX_IMPL_HARDWARE != impl) && + (MFX_IMPL_HARDWARE2 != impl) && + (MFX_IMPL_HARDWARE3 != impl) && + (MFX_IMPL_HARDWARE4 != impl)) + { + DISPATCHER_LOG_ERROR((("invalid implementation impl == %s\n"), DispatcherLog_GetMFXImplString(impl).c_str())); + loadStatus = MFX_ERR_ABORTED; + return loadStatus; + } + // only mfxExtThreadsParam is allowed + if (par.NumExtParam) + { + if ((par.NumExtParam > 1) || !par.ExtParam) + { + loadStatus = MFX_ERR_ABORTED; + return loadStatus; + } + if ((par.ExtParam[0]->BufferId != MFX_EXTBUFF_THREADS_PARAM) || + (par.ExtParam[0]->BufferSz != sizeof(mfxExtThreadsParam))) + { + loadStatus = MFX_ERR_ABORTED; + return loadStatus; + } + } + + // close the handle before initialization + Close(); + + // save the library's type + this->implType = implType; + this->impl = impl; + this->implInterface = implInterface; + + { + DISPATCHER_LOG_BLOCK(("invoking LoadLibrary(%S)\n", MSDK2WIDE(pPath))); + // load the DLL into the memory + hModule = MFX::mfx_dll_load(pPath); + + if (hModule) + { + int i; + + DISPATCHER_LOG_OPERATION({ + msdk_disp_char modulePath[1024]; + GetModuleFileNameW((HMODULE)hModule, modulePath, sizeof(modulePath)/sizeof(modulePath[0])); + DISPATCHER_LOG_INFO((("loaded module %S\n"), MSDK2WIDE(modulePath))) + }); + + if (impl & MFX_IMPL_AUDIO) + { + // load audio functions: pointers to exposed functions + for (i = 0; i < eAudioFuncTotal; i += 1) + { + // construct correct name of the function - remove "_a" postfix + + mfxFunctionPointer pProc = (mfxFunctionPointer) MFX::mfx_dll_get_addr(hModule, APIAudioFunc[i].pName); + #ifdef ANDROID + // on Android very first call to dlsym may fail + if (!pProc) pProc = (mfxFunctionPointer) MFX::mfx_dll_get_addr(hModule, APIAudioFunc[i].pName); + #endif + if (pProc) + { + // function exists in the library, + // save the pointer. + callAudioTable[i] = pProc; + } + else + { + // The library doesn't contain the function + DISPATCHER_LOG_WRN((("Can't find API function \"%s\"\n"), APIAudioFunc[i].pName)); + if (apiVersion.Version >= APIAudioFunc[i].apiVersion.Version) + { + DISPATCHER_LOG_ERROR((("\"%s\" is required for API %u.%u\n"), APIAudioFunc[i].pName, apiVersion.Major, apiVersion.Minor)); + mfxRes = MFX_ERR_UNSUPPORTED; + break; + } + } + } + } + else + { + // 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); + #ifdef ANDROID + // on Android very first call to dlsym may fail + if (!pProc) pProc = (mfxFunctionPointer) MFX::mfx_dll_get_addr(hModule, APIFunc[i].pName); + #endif + 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; + } + } + } + } + } + else + { +#if defined(_WIN32) || defined(_WIN64) + DISPATCHER_LOG_WRN((("can't find DLL: GetLastErr()=0x%x\n"), GetLastError())) +#else + DISPATCHER_LOG_WRN((("can't find DLL: dlerror() = \"%s\"\n"), dlerror())); +#endif + mfxRes = MFX_ERR_UNSUPPORTED; + } + } + + // initialize the loaded DLL + if (MFX_ERR_NONE == mfxRes) + { + mfxVersion version(apiVersion); + + /* check whether it is audio session or video */ + mfxFunctionPointer *actualTable = (impl & MFX_IMPL_AUDIO) ? callAudioTable : callTable; + + // Call old-style MFXInit init for older libraries and audio library + bool callOldInit = (impl & MFX_IMPL_AUDIO) || !actualTable[eMFXInitEx]; // if true call eMFXInit, if false - eMFXInitEx + int tableIndex = (callOldInit) ? eMFXInit : eMFXInitEx; + + mfxFunctionPointer pFunc = actualTable[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, skiped 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 succesfully\n")) + } + } + } + + loadStatus = mfxRes; + return mfxRes; + +} // mfxStatus MFX_DISP_HANDLE::LoadSelectedDLL(const msdk_disp_char *pPath, eMfxImplType implType, mfxIMPL impl) + +mfxStatus MFX_DISP_HANDLE::UnLoadSelectedDLL(void) +{ + mfxStatus mfxRes = MFX_ERR_NONE; + + //unregistered plugins if any + pluginFactory.Close(); + + // close the loaded DLL + if (session) + { + /* check whether it is audio session or video */ + int tableIndex = eMFXClose; + mfxFunctionPointer pFunc; + if (impl & MFX_IMPL_AUDIO) + { + pFunc = callAudioTable[tableIndex]; + } + else + { + 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) \ No newline at end of file diff --git a/plugins/obs-qsv11/libmfx/src/mfx_dispatcher_log.cpp b/plugins/obs-qsv11/libmfx/src/mfx_dispatcher_log.cpp new file mode 100644 index 000000000..d355b1ad9 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/src/mfx_dispatcher_log.cpp @@ -0,0 +1,449 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2012-2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_dispatcher_log.h + +\* ****************************************************************************** */ + +#if defined(MFX_DISPATCHER_LOG) + +#include "mfx_dispatcher_log.h" +#include "mfxstructures.h" +#if defined(_WIN32) || defined(_WIN64) +#include +#if defined(DISPATCHER_LOG_REGISTER_EVENT_PROVIDER) +#include +#include +#endif +#endif // #if defined(_WIN32) || defined(_WIN64) +#include +#include +#include +#include + +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 :: 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: improve this , add opcode handling + printf("%s %s", CODE_TO_STRING(level, LevelStrings), msg_formated); + } + break; + } + + case DL_SINK_IMsgHandler: + { + std::list::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: + 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: 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: + 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 SinkRegistrator +{ +}; + +#if defined(DISPATCHER_LOG_REGISTER_EVENT_PROVIDER) +template <> +class SinkRegistrator +{ +public: + 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 +{ +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 g_registrator1; +#endif + + +#ifdef DISPATCHER_LOG_REGISTER_FILE_WRITER + static SinkRegistrator g_registrator2; +#endif + + +#endif//(MFX_DISPATCHER_LOG) \ No newline at end of file diff --git a/plugins/obs-qsv11/libmfx/src/mfx_dxva2_device.cpp b/plugins/obs-qsv11/libmfx/src/mfx_dxva2_device.cpp new file mode 100644 index 000000000..9ba86cbf5 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/src/mfx_dxva2_device.cpp @@ -0,0 +1,558 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2012-2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_dxva2_device.cpp + +\* ****************************************************************************** */ + +#if defined(_WIN32) || defined(_WIN64) + +#define INITGUID +#include +#include + +#include "mfx_dxva2_device.h" + + +using namespace MFX; + + +DXDevice::DXDevice(void) +{ + m_hModule = (HMODULE) 0; + + m_numAdapters = 0; + + m_vendorID = 0; + m_deviceID = 0; + m_driverVersion = 0; + m_luid = 0; + +} // 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 = 0; + +} // void DXDevice::Close(void) + +void DXDevice::LoadDLLModule(const wchar_t *pModuleName) +{ + DWORD prevErrorMode = 0; + + // unload the module if it is required + UnloadDLLModule(); + + // set the silent error mode +#if (_WIN32_WINNT >= 0x0600) && !(__GNUC__) + SetThreadErrorMode(SEM_FAILCRITICALERRORS, &prevErrorMode); +#else + prevErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); +#endif + // load specified library + m_hModule = LoadLibraryExW(pModuleName, NULL, 0); + + // set the previous error mode +#if (_WIN32_WINNT >= 0x0600) && !(__GNUC__) + SetThreadErrorMode(prevErrorMode, NULL); +#else + SetErrorMode(prevErrorMode); +#endif + +} // void LoadDLLModule(const wchar_t *pModuleName) + +void DXDevice::UnloadDLLModule(void) +{ + if (m_hModule) + { + FreeLibrary(m_hModule); + m_hModule = (HMODULE) 0; + } + +} // void DXDevice::UnloaDLLdModule(void) + + +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 + *((LUID *) &m_luid) = 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) + +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(); + + // load up the library if it is not loaded + if (NULL == m_hModule) + { + LoadDLLModule(L"dxgi.dll"); + } + + if (m_hModule) + { + DXGICreateFactoryFunc pFunc; + IDXGIFactory1 *pFactory; + IDXGIAdapter1 *pAdapter; + DXGI_ADAPTER_DESC1 desc; + mfxU32 curAdapter, maxAdapters; + HRESULT hRes; + + // 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; + + // 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; + *((LUID *) &m_luid) = desc.AdapterLuid; + } + + return true; + +} // bool DXGI1Device::Init(const mfxU32 adapterNum) + +DXVA2Device::DXVA2Device(void) +{ + m_numAdapters = 0; + + m_vendorID = 0; + m_deviceID = 0; + +} // DXVA2Device::DXVA2Device(void) + +DXVA2Device::~DXVA2Device(void) +{ + Close(); + +} // DXVA2Device::~DXVA2Device(void) + +void DXVA2Device::Close(void) +{ + m_numAdapters = 0; + + m_vendorID = 0; + m_deviceID = 0; + +} // void DXVA2Device::Close(void) + +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(); + } + + // ... say goodbye + return true; +} // bool InitD3D9(const mfxU32 adapterNum) + +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(); + + // ... say goodbye + return true; + +} // bool DXVA2Device::InitDXGI1(const mfxU32 adapterNum) + +void DXVA2Device::UseAlternativeWay(const D3D9Device *pD3D9Device) +{ + mfxU64 d3d9LUID = pD3D9Device->GetLUID(); + + // work only with valid LUIDs + if (0 == 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(); + 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) + +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 +#endif diff --git a/plugins/obs-qsv11/libmfx/src/mfx_function_table.cpp b/plugins/obs-qsv11/libmfx/src/mfx_function_table.cpp new file mode 100644 index 000000000..8da6a510e --- /dev/null +++ b/plugins/obs-qsv11/libmfx/src/mfx_function_table.cpp @@ -0,0 +1,143 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2012-2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_function_table.cpp + +\* ****************************************************************************** */ + +#include "mfx_dispatcher.h" + +// +// implement a table with functions names +// + +#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}}}, + + {"MFXJoinSession", {{1, 1}}}, + {"MFXDisjoinSession", {{1, 1}}}, + {"MFXCloneSession", {{1, 1}}}, + {"MFXSetPriority", {{1, 1}}}, + {"MFXGetPriority", {{1, 1}}}, + + {"MFXInitEx", {{1, 14}}}, + +#include "mfx_exposed_functions_list.h" +}; + +const +FUNCTION_DESCRIPTION APIAudioFunc[eAudioFuncTotal] = +{ + {"MFXInit", {{8, 1}}}, + {"MFXClose", {{8, 1}}}, + {"MFXQueryIMPL", {{8, 1}}}, + {"MFXQueryVersion", {{8, 1}}}, + + {"MFXJoinSession", {{8, 1}}}, + {"MFXDisjoinSession", {{8, 1}}}, + {"MFXCloneSession", {{8, 1}}}, + {"MFXSetPriority", {{8, 1}}}, + {"MFXGetPriority", {{8, 1}}}, + +#include "mfxaudio_exposed_functions_list.h" +}; + +// 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 + impl = impl; + ver = ver; + session = session; + + return MFX_ERR_UNKNOWN; + +} // mfxStatus pseudoMFXInit(mfxIMPL impl, mfxVersion *ver, mfxSession *session) + +mfxStatus pseudoMFXClose(mfxSession session) +{ + // touch unreferenced parameters + session = session; + + return MFX_ERR_UNKNOWN; + +} // mfxStatus pseudoMFXClose(mfxSession session) + +mfxStatus pseudoMFXJoinSession(mfxSession session, mfxSession child_session) +{ + // touch unreferenced parameters + session = session; + child_session = child_session; + + return MFX_ERR_UNKNOWN; + +} // mfxStatus pseudoMFXJoinSession(mfxSession session, mfxSession child_session) + +mfxStatus pseudoMFXCloneSession(mfxSession session, mfxSession *clone) +{ + // touch unreferenced parameters + session = session; + clone = 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 "mfx_exposed_functions_list.h" + +} // namespace diff --git a/plugins/obs-qsv11/libmfx/src/mfx_library_iterator.cpp b/plugins/obs-qsv11/libmfx/src/mfx_library_iterator.cpp new file mode 100644 index 000000000..cdbb125ce --- /dev/null +++ b/plugins/obs-qsv11/libmfx/src/mfx_library_iterator.cpp @@ -0,0 +1,475 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2012-2015 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_library_iterator.cpp + +\* ****************************************************************************** */ + +#if defined(_WIN32) || defined(_WIN64) + +#include "mfx_library_iterator.h" + +#include "mfx_dispatcher.h" +#include "mfx_dispatcher_log.h" + +#include "mfx_dxva2_device.h" +#include "mfx_load_dll.h" + +#include +#include + +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) +{ + if (NULL == pImplInterface) + { + return MFX_ERR_NULL_PTR; + } + + DXVA2Device dxvaDevice; + if (MFX_IMPL_VIA_D3D9 == *pImplInterface) + { + // 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 == *pImplInterface) + { + // 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 == *pImplInterface) + { + // 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(); + } + + return MFX_ERR_NONE; +} + +MFXLibraryIterator::MFXLibraryIterator(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_bIsSubKeyValid = 0; + m_StorageID = 0; + + m_SubKeyName[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) + +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; + + if (storageID == MFX_CURRENT_USER_KEY || storageID == MFX_LOCAL_MACHINE_KEY) + { + return InitRegistry(implType, implInterface, adapterNum, storageID); + } + else if (storageID == MFX_APP_FOLDER) + { + msdk_disp_char path[_MAX_PATH] = {}; + + ::GetModuleFileNameW(0, path, _MAX_PATH); + msdk_disp_char * dirSeparator = wcsrchr(path, L'\\'); + if (dirSeparator < (path + _MAX_PATH)) + { + *++dirSeparator = 0; + } + + return InitFolder(implType, implInterface, adapterNum, path); + } + + return MFX_ERR_UNSUPPORTED; +} // mfxStatus MFXLibraryIterator::Init(eMfxImplType implType, const mfxU32 adapterNum, int storageID) + +mfxStatus MFXLibraryIterator::InitRegistry(eMfxImplType implType, mfxIMPL implInterface, const mfxU32 adapterNum, int storageID) +{ + HKEY rootHKey; + bool bRes; + + // open required registry key + rootHKey = (MFX_LOCAL_MACHINE_KEY == storageID) ? (HKEY_LOCAL_MACHINE) : (HKEY_CURRENT_USER); + 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; + } + + // set the required library's implementation type + m_implType = implType; + m_implInterface = implInterface != 0 + ? implInterface + : MFX_IMPL_VIA_ANY; + + //deviceID and vendorID are not actual for SW library loading + if (m_implType != MFX_LIB_SOFTWARE) + { + mfxStatus mfxRes = MFX::SelectImplementationType(adapterNum, &m_implInterface, &m_vendorID, &m_deviceID); + if (MFX_ERR_NONE != mfxRes) + { + return mfxRes; + } + } + + DISPATCHER_LOG_INFO((("Inspecting %s\\%S\n"), + (MFX_LOCAL_MACHINE_KEY == storageID) ? ("HKEY_LOCAL_MACHINE") : ("HKEY_CURRENT_USER"), + rootDispPath)) + + return MFX_ERR_NONE; +} // mfxStatus MFXLibraryIterator::InitRegistry(eMfxImplType implType, mfxIMPL implInterface, const mfxU32 adapterNum, int storageID) + +mfxStatus MFXLibraryIterator::InitFolder(eMfxImplType implType, mfxIMPL implInterface, const mfxU32 adapterNum, const msdk_disp_char * path) +{ + const int maxPathLen = sizeof(m_path)/sizeof(m_path[0]); + m_path[0] = 0; + msdk_disp_char_cpy_s(m_path, maxPathLen, path); + size_t pathLen = wcslen(m_path); + + // we looking for runtime in application folder, it should be named libmfxsw64 or libmfxsw32 + mfx_get_default_dll_name(m_path + pathLen, maxPathLen - pathLen, MFX_LIB_SOFTWARE); + + // set the required library's implementation type + m_implType = implType; + m_implInterface = implInterface != 0 + ? implInterface + : MFX_IMPL_VIA_ANY; + + //deviceID and vendorID are not actual for SW library loading + if (m_implType != MFX_LIB_SOFTWARE) + { + mfxStatus mfxRes = MFX::SelectImplementationType(adapterNum, &m_implInterface, &m_vendorID, &m_deviceID); + if (MFX_ERR_NONE != mfxRes) + { + return mfxRes; + } + } + return MFX_ERR_NONE; +} // mfxStatus MFXLibraryIterator::InitFolder(eMfxImplType implType, mfxIMPL implInterface, const mfxU32 adapterNum, const msdk_disp_char * path) + +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; + + m_lastLibIndex = 1; + msdk_disp_char_cpy_s(pPath, pathSize, m_path); + *pImplType = MFX_LIB_SOFTWARE; + return MFX_ERR_NONE; + } + + 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]; + 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)); + + msdk_disp_char_cpy_s(libPath, sizeof(libPath) / sizeof(libPath[0]), tmpPath); + msdk_disp_char_cpy_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; + } + + msdk_disp_char_cpy_s(pPath, pathSize, libPath); + + m_lastLibIndex = libIndex; + m_lastLibMerit = libMerit; + m_bIsSubKeyValid = true; + + 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(msdk_disp_char *subKeyName, size_t length) const +{ + msdk_disp_char_cpy_s(subKeyName, length, m_SubKeyName); + return m_bIsSubKeyValid; +} +} // namespace MFX +#endif // #if defined(_WIN32) || defined(_WIN64) + diff --git a/plugins/obs-qsv11/libmfx/src/mfx_load_dll.cpp b/plugins/obs-qsv11/libmfx/src/mfx_load_dll.cpp new file mode 100644 index 000000000..bfb77e2dd --- /dev/null +++ b/plugins/obs-qsv11/libmfx/src/mfx_load_dll.cpp @@ -0,0 +1,241 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2012-2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_load_dll.cpp + +\* ****************************************************************************** */ + +#if defined(_WIN32) || defined(_WIN64) + +#include "mfx_dispatcher.h" +#include "mfx_load_dll.h" + +#include +#include +#include + +#if !defined(_DEBUG) + +#if defined(_WIN64) +const +wchar_t * const defaultDLLName[2] = {L"libmfxhw64.dll", + L"libmfxsw64.dll"}; +const +wchar_t * const defaultAudioDLLName[2] = {L"libmfxaudiosw64.dll", + L"libmfxaudiosw64.dll"}; + +const +wchar_t * const defaultPluginDLLName[2] = {L"mfxplugin64_hw.dll", + L"mfxplugin64_sw.dll"}; + +#elif defined(_WIN32) +const +wchar_t * const defaultDLLName[2] = {L"libmfxhw32.dll", + L"libmfxsw32.dll"}; + +const +wchar_t * const defaultAudioDLLName[2] = {L"libmfxaudiosw32.dll", + L"libmfxaudiosw32.dll"}; + +const +wchar_t * const defaultPluginDLLName[2] = {L"mfxplugin32_hw.dll", + L"mfxplugin32_sw.dll"}; + +#endif // (defined(_WIN64)) + +#else // defined(_DEBUG) + +#if defined(_WIN64) +const +wchar_t * const defaultDLLName[2] = {L"libmfxhw64_d.dll", + L"libmfxsw64_d.dll"}; +const +wchar_t * const defaultAudioDLLName[2] = {L"libmfxaudiosw64_d.dll", + L"libmfxaudiosw64_d.dll"}; + +const +wchar_t * const defaultPluginDLLName[2] = {L"mfxplugin64_hw_d.dll", + L"mfxplugin64_sw_d.dll"}; + +#elif defined(WIN32) +const +wchar_t * const defaultDLLName[2] = {L"libmfxhw32_d.dll", + L"libmfxsw32_d.dll"}; + + +const +wchar_t * const defaultAudioDLLName[2] = {L"libmfxaudiosw32_d.dll", + L"libmfxaudiosw32_d.dll"}; + +const +wchar_t * const defaultPluginDLLName[2] = {L"mfxplugin32_hw_d.dll", + L"mfxplugin32_sw_d.dll"}; + +#endif // (defined(_WIN64)) + +#endif // !defined(_DEBUG) + +namespace MFX +{ + + +mfxStatus mfx_get_default_dll_name(msdk_disp_char *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_plugin_name(msdk_disp_char *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(msdk_disp_char *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 msdk_disp_char *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) && !(__GNUC__) + SetThreadErrorMode(SEM_FAILCRITICALERRORS, &prevErrorMode); +#else + prevErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); +#endif + // load the library's module + hModule = LoadLibraryExW(pFileName,NULL,0); + // set the previous error mode +#if (_WIN32_WINNT >= 0x0600) && !(__GNUC__) + SetThreadErrorMode(prevErrorMode, NULL); +#else + SetErrorMode(prevErrorMode); +#endif + + 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) + +mfxModuleHandle mfx_get_dll_handle(const msdk_disp_char *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) && !(__GNUC__) + 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) && !(__GNUC__) + SetThreadErrorMode(prevErrorMode, NULL); +#else + SetErrorMode(prevErrorMode); +#endif + return hModule; +} + + +} // namespace MFX + +#endif // #if defined(_WIN32) || defined(_WIN64) diff --git a/plugins/obs-qsv11/libmfx/src/mfx_load_plugin.cpp b/plugins/obs-qsv11/libmfx/src/mfx_load_plugin.cpp new file mode 100644 index 000000000..394804074 --- /dev/null +++ b/plugins/obs-qsv11/libmfx/src/mfx_load_plugin.cpp @@ -0,0 +1,458 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2013-2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_load_plugin.h + +\* ****************************************************************************** */ + +#include "mfx_load_plugin.h" +#include "mfx_load_dll.h" +#include "mfx_dispatcher_log.h" + +#define TRACE_PLUGIN_ERROR(str, ...) DISPATCHER_LOG_ERROR((("[PLUGIN]: "str), __VA_ARGS__)) +#define TRACE_PLUGIN_INFO(str, ...) DISPATCHER_LOG_INFO((("[PLUGIN]: "str), __VA_ARGS__)) + +#define CREATE_PLUGIN_FNC "CreatePlugin" + +MFX::PluginModule::PluginModule() + : mHmodule() + , mCreatePluginPtr() + , mPath() +{ +} + +MFX::PluginModule::PluginModule(const PluginModule & that) + : mHmodule(mfx_dll_load(that.mPath)) + , mCreatePluginPtr(that.mCreatePluginPtr) +{ + msdk_disp_char_cpy_s(mPath, sizeof(mPath) / sizeof(*mPath), that.mPath); +} + +MFX::PluginModule & MFX::PluginModule::operator = (const MFX::PluginModule & that) +{ + if (this != &that) + { + Tidy(); + mHmodule = mfx_dll_load(that.mPath); + mCreatePluginPtr = that.mCreatePluginPtr; + msdk_disp_char_cpy_s(mPath, sizeof(mPath) / sizeof(*mPath), that.mPath); + } + return *this; +} + +MFX::PluginModule::PluginModule(const msdk_disp_char * path) + : mCreatePluginPtr() +{ + mHmodule = mfx_dll_load(path); + if (NULL == mHmodule) { + TRACE_PLUGIN_ERROR("Cannot load module: %S\n", MSDK2WIDE(path)); + return ; + } + TRACE_PLUGIN_INFO("Plugin loaded at: %S\n", MSDK2WIDE(path)); + + mCreatePluginPtr = (CreatePluginPtr_t)mfx_dll_get_addr(mHmodule, CREATE_PLUGIN_FNC); + if (NULL == mCreatePluginPtr) { + TRACE_PLUGIN_ERROR("Cannot get procedure address: %s\n", CREATE_PLUGIN_FNC); + return ; + } + + msdk_disp_char_cpy_s(mPath, sizeof(mPath) / sizeof(*mPath), path); +} + +bool MFX::PluginModule::Create( mfxPluginUID uid, mfxPlugin& plg) +{ + bool result = false; + if (mCreatePluginPtr) + { + mfxStatus mfxResult = mCreatePluginPtr(uid, &plg); + result = (MFX_ERR_NONE == mfxResult); + if (!result) { + TRACE_PLUGIN_ERROR("\"%S::%s\" returned %d\n", MSDK2WIDE(mPath), CREATE_PLUGIN_FNC, mfxResult); + } else { + TRACE_PLUGIN_INFO("\"%S::%s\" SUCCEED\n", MSDK2WIDE(mPath), CREATE_PLUGIN_FNC); + } + } + return result; +} + +void MFX::PluginModule::Tidy() +{ + mfx_dll_free(mHmodule); + mCreatePluginPtr = NULL; + mHmodule = NULL; +} + +MFX::PluginModule::~PluginModule(void) +{ + Tidy(); +} + +bool MFX::MFXPluginFactory::RunVerification( const mfxPlugin & plg, const PluginDescriptionRecord &dsc, mfxPluginParam &pluginParams) +{ + if (plg.PluginInit == 0) + { + TRACE_PLUGIN_ERROR("plg->PluginInit = 0\n", 0); + return false; + } + if (plg.PluginClose == 0) + { + TRACE_PLUGIN_ERROR("plg->PluginClose = 0\n", 0); + return false; + } + if (plg.GetPluginParam == 0) + { + TRACE_PLUGIN_ERROR("plg->GetPluginParam = 0\n", 0); + return false; + } + + if (plg.Execute == 0) + { + TRACE_PLUGIN_ERROR("plg->Execute = 0\n", 0); + return false; + } + if (plg.FreeResources == 0) + { + TRACE_PLUGIN_ERROR("plg->FreeResources = 0\n", 0); + return false; + } + + mfxStatus sts = plg.GetPluginParam(plg.pthis, &pluginParams); + if (sts != MFX_ERR_NONE) + { + TRACE_PLUGIN_ERROR("plg->GetPluginParam() returned %d\n", sts); + return false; + } + + if (dsc.Default) + { + // for default plugins there is no description, dsc.APIVersion, dsc.PluginVersion and dsc.PluginUID were set by dispatcher + // dsc.PluginVersion == requested plugin version (parameter of MFXVideoUSER_Load); dsc.APIVersion == loaded library API + if (dsc.PluginVersion > pluginParams.PluginVersion) + { + TRACE_PLUGIN_ERROR("plg->GetPluginParam() returned PluginVersion=%d, but it is smaller than requested : %d\n", pluginParams.PluginVersion, dsc.PluginVersion); + return false; + } + } + else + { + if (!dsc.onlyVersionRegistered && pluginParams.CodecId != dsc.CodecId) + { + TRACE_PLUGIN_ERROR("plg->GetPluginParam() returned CodecId="MFXFOURCCTYPE()", but registration has CodecId="MFXFOURCCTYPE()"\n" + , MFXU32TOFOURCC(pluginParams.CodecId), MFXU32TOFOURCC(dsc.CodecId)); + return false; + } + + if (!dsc.onlyVersionRegistered && pluginParams.Type != dsc.Type) + { + TRACE_PLUGIN_ERROR("plg->GetPluginParam() returned Type=%d, but registration has Type=%d\n", pluginParams.Type, dsc.Type); + return false; + } + + if (pluginParams.PluginUID != dsc.PluginUID) + { + TRACE_PLUGIN_ERROR("plg->GetPluginParam() returned UID="MFXGUIDTYPE()", but registration has UID="MFXGUIDTYPE()"\n" + , MFXGUIDTOHEX(&pluginParams.PluginUID), MFXGUIDTOHEX(&dsc.PluginUID)); + return false; + } + + if (pluginParams.PluginVersion != dsc.PluginVersion) + { + TRACE_PLUGIN_ERROR("plg->GetPluginParam() returned PluginVersion=%d, but registration has PlgVer=%d\n", pluginParams.PluginVersion, dsc.PluginVersion); + return false; + } + + if (pluginParams.APIVersion.Version != dsc.APIVersion.Version) + { + TRACE_PLUGIN_ERROR("plg->GetPluginParam() returned APIVersion=%d.%d, but registration has APIVer=%d.%d\n" + , pluginParams.APIVersion.Major, pluginParams.APIVersion.Minor + , dsc.APIVersion.Major, dsc.APIVersion.Minor); + return false; + } + } + + switch(pluginParams.Type) + { + case MFX_PLUGINTYPE_VIDEO_DECODE: + case MFX_PLUGINTYPE_VIDEO_ENCODE: + case MFX_PLUGINTYPE_VIDEO_VPP: + { + TRACE_PLUGIN_INFO("plugin type= %d\n", pluginParams.Type); + if (plg.Video == 0) + { + TRACE_PLUGIN_ERROR("plg->Video = 0\n", 0); + return false; + } + + if (!VerifyCodecCommon(*plg.Video)) + return false; + break; + } + } + + switch(pluginParams.Type) + { + case MFX_PLUGINTYPE_VIDEO_DECODE: + return VerifyDecoder(*plg.Video); + case MFX_PLUGINTYPE_AUDIO_DECODE: + return VerifyAudioDecoder(*plg.Audio); + case MFX_PLUGINTYPE_VIDEO_ENCODE: + return VerifyEncoder(*plg.Video); + case MFX_PLUGINTYPE_AUDIO_ENCODE: + return VerifyAudioEncoder(*plg.Audio); + case MFX_PLUGINTYPE_VIDEO_VPP: + return VerifyVpp(*plg.Video); + case MFX_PLUGINTYPE_VIDEO_ENC: + return VerifyEnc(*plg.Video); + default: + { + TRACE_PLUGIN_ERROR("unsupported plugin type: %d\n", pluginParams.Type); + return false; + } + } +} + +bool MFX::MFXPluginFactory::VerifyVpp( const mfxVideoCodecPlugin &vpp ) +{ + if (vpp.VPPFrameSubmit == 0) + { + TRACE_PLUGIN_ERROR("plg->Video->VPPFrameSubmit = 0\n", 0); + return false; + } + + return true; + +} + +bool MFX::MFXPluginFactory::VerifyEncoder( const mfxVideoCodecPlugin &encoder ) +{ + if (encoder.EncodeFrameSubmit == 0) + { + TRACE_PLUGIN_ERROR("plg->Video->EncodeFrameSubmit = 0\n", 0); + return false; + } + + return true; +} + +bool MFX::MFXPluginFactory::VerifyAudioEncoder( const mfxAudioCodecPlugin &encoder ) +{ + if (encoder.EncodeFrameSubmit == 0) + { + TRACE_PLUGIN_ERROR("plg->Audio->EncodeFrameSubmit = 0\n", 0); + return false; + } + + return true; +} + +bool MFX::MFXPluginFactory::VerifyEnc( const mfxVideoCodecPlugin &videoEnc ) +{ + if (videoEnc.ENCFrameSubmit == 0) + { + TRACE_PLUGIN_ERROR("plg->Video->EncodeFrameSubmit = 0\n", 0); + return false; + } + + return true; +} + +bool MFX::MFXPluginFactory::VerifyDecoder( const mfxVideoCodecPlugin &decoder ) +{ + if (decoder.DecodeHeader == 0) + { + TRACE_PLUGIN_ERROR("plg->Video->DecodeHeader = 0\n", 0); + return false; + } + if (decoder.GetPayload == 0) + { + TRACE_PLUGIN_ERROR("plg->Video->GetPayload = 0\n", 0); + return false; + } + if (decoder.DecodeFrameSubmit == 0) + { + TRACE_PLUGIN_ERROR("plg->Video->DecodeFrameSubmit = 0\n", 0); + return false; + } + + return true; +} + +bool MFX::MFXPluginFactory::VerifyAudioDecoder( const mfxAudioCodecPlugin &decoder ) +{ + if (decoder.DecodeHeader == 0) + { + TRACE_PLUGIN_ERROR("plg->Audio->DecodeHeader = 0\n", 0); + return false; + } +// if (decoder.GetPayload == 0) + { + // TRACE_PLUGIN_ERROR("plg->Audio->GetPayload = 0\n", 0); + // return false; + } + if (decoder.DecodeFrameSubmit == 0) + { + TRACE_PLUGIN_ERROR("plg->Audio->DecodeFrameSubmit = 0\n", 0); + return false; + } + + return true; +} + +bool MFX::MFXPluginFactory::VerifyCodecCommon( const mfxVideoCodecPlugin & videoCodec ) +{ + if (videoCodec.Query == 0) + { + TRACE_PLUGIN_ERROR("plg->Video->Query = 0\n", 0); + return false; + } + //todo: remove + if (videoCodec.Query == 0) + { + TRACE_PLUGIN_ERROR("plg->Video->Query = 0\n", 0); + return false; + } + if (videoCodec.QueryIOSurf == 0) + { + TRACE_PLUGIN_ERROR("plg->Video->QueryIOSurf = 0\n", 0); + return false; + } + if (videoCodec.Init == 0) + { + TRACE_PLUGIN_ERROR("plg->Video->Init = 0\n", 0); + return false; + } + if (videoCodec.Reset == 0) + { + TRACE_PLUGIN_ERROR("plg->Video->Reset = 0\n", 0); + return false; + } + if (videoCodec.Close == 0) + { + TRACE_PLUGIN_ERROR("plg->Video->Close = 0\n", 0); + return false; + } + if (videoCodec.GetVideoParam == 0) + { + TRACE_PLUGIN_ERROR("plg->Video->GetVideoParam = 0\n", 0); + return false; + } + + return true; +} + +mfxStatus MFX::MFXPluginFactory::Create(const PluginDescriptionRecord & rec) +{ + PluginModule plgModule(rec.sPath); + mfxPlugin plg = {}; + mfxPluginParam plgParams; + + if (!plgModule.Create(rec.PluginUID, plg)) + { + return MFX_ERR_UNKNOWN; + } + + if (!RunVerification(plg, rec, plgParams)) + { + //will do not call plugin close since it is not safe to do that until structure is corrected + return MFX_ERR_UNKNOWN; + } + + + if (rec.Type == MFX_PLUGINTYPE_AUDIO_DECODE || + rec.Type == MFX_PLUGINTYPE_AUDIO_ENCODE) + { + mfxStatus sts = MFXAudioUSER_Register(mSession, plgParams.Type, &plg); + if (MFX_ERR_NONE != sts) + { + TRACE_PLUGIN_ERROR(" MFXAudioUSER_Register returned %d\n", sts); + return sts; + } + } + else + { + mfxStatus sts = MFXVideoUSER_Register(mSession, plgParams.Type, &plg); + if (MFX_ERR_NONE != sts) + { + TRACE_PLUGIN_ERROR(" MFXVideoUSER_Register returned %d\n", sts); + return sts; + } + } + + mPlugins.push_back(FactoryRecord(plgParams, plgModule, plg)); + + return MFX_ERR_NONE; +} + +MFX::MFXPluginFactory::~MFXPluginFactory() +{ + Close(); +} + +MFX::MFXPluginFactory::MFXPluginFactory( mfxSession session ) +{ + mSession = session; +} + +bool MFX::MFXPluginFactory::Destroy( const mfxPluginUID & uidToDestroy) +{ + for (MFXVector::iterator i = mPlugins.begin(); i!= mPlugins.end(); i++) + { + if (i->plgParams.PluginUID == uidToDestroy) + { + DestroyPlugin(*i); + //dll unload should happen here + //todo: check that dll_free fail is traced + mPlugins.erase(i); + return true; + } + } + return false; +} + +void MFX::MFXPluginFactory::Close() +{ + for (MFXVector::iterator i = mPlugins.begin(); i!= mPlugins.end(); i++) + { + DestroyPlugin(*i); + } + mPlugins.clear(); +} + +void MFX::MFXPluginFactory::DestroyPlugin( FactoryRecord & record) +{ + mfxStatus sts; + if (record.plgParams.Type == MFX_PLUGINTYPE_AUDIO_DECODE || + record.plgParams.Type == MFX_PLUGINTYPE_AUDIO_ENCODE) + { + sts = MFXAudioUSER_Unregister(mSession, record.plgParams.Type); + TRACE_PLUGIN_INFO(" MFXAudioUSER_Unregister for Type=%d, returned %d\n", record.plgParams.Type, sts); + } + else + { + sts = MFXVideoUSER_Unregister(mSession, record.plgParams.Type); + TRACE_PLUGIN_INFO(" MFXVideoUSER_Unregister for Type=%d, returned %d\n", record.plgParams.Type, sts); + } +} \ No newline at end of file diff --git a/plugins/obs-qsv11/libmfx/src/mfx_plugin_hive.cpp b/plugins/obs-qsv11/libmfx/src/mfx_plugin_hive.cpp new file mode 100644 index 000000000..02eb8f87c --- /dev/null +++ b/plugins/obs-qsv11/libmfx/src/mfx_plugin_hive.cpp @@ -0,0 +1,500 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2013-2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_plugin_hive.cpp + +\* ****************************************************************************** */ + +#if defined(_WIN32) || defined(_WIN64) + +#include "mfx_plugin_hive.h" +#include "mfx_library_iterator.h" +#include "mfx_dispatcher.h" +#include "mfx_dispatcher_log.h" +#include "mfx_load_dll.h" + +#define TRACE_HIVE_ERROR(str, ...) DISPATCHER_LOG_ERROR((("[HIVE]: "str), __VA_ARGS__)) +#define TRACE_HIVE_INFO(str, ...) DISPATCHER_LOG_INFO((("[HIVE]: "str), __VA_ARGS__)) +#define TRACE_HIVE_WRN(str, ...) DISPATCHER_LOG_WRN((("[HIVE]: "str), __VA_ARGS__)) + +namespace +{ + const wchar_t rootPluginPath[] = L"Software\\Intel\\MediaSDK\\Plugin"; + const wchar_t rootDispatchPath[] = L"Software\\Intel\\MediaSDK\\Dispatch"; + const wchar_t pluginSubkey[] = L"Plugin"; + const wchar_t TypeKeyName[] = L"Type"; + const wchar_t CodecIDKeyName[] = L"CodecID"; + const wchar_t GUIDKeyName[] = L"GUID"; + const wchar_t PathKeyName[] = L"Path"; + const wchar_t DefaultKeyName[] = L"Default"; + const wchar_t PlgVerKeyName[] = L"PluginVersion"; + const wchar_t APIVerKeyName[] = L"APIVersion"; +} + +namespace +{ +#ifdef _WIN64 + const wchar_t pluginFileName[] = L"FileName64"; +#else + const wchar_t pluginFileName[] = L"FileName32"; +#endif // _WIN64 + + //do not allow store plugin in different hierarchy + const wchar_t pluginFileNameRestrictedCharacters[] = L"\\/"; + const wchar_t pluginCfgFileName[] = L"plugin.cfg"; + const wchar_t pluginSearchPattern[] = L"????????????????????????????????"; + const mfxU32 pluginCfgFileNameLen = 10; + const mfxU32 pluginDirNameLen = 32; + const mfxU32 defaultPluginNameLen = 25; + const mfxU32 charsPermfxU8 = 2; + const mfxU32 slashLen = 1; + enum + { + MAX_PLUGIN_FILE_LINE = 4096 + }; + + #define alignStr() "%-14S" +} + +MFX::MFXPluginsInHive::MFXPluginsInHive(int mfxStorageID, const msdk_disp_char *msdkLibSubKey, mfxVersion currentAPIVersion) + : MFXPluginStorageBase(currentAPIVersion) +{ + HKEY rootHKey; + bool bRes; + WinRegKey regKey; + + if (MFX_LOCAL_MACHINE_KEY != mfxStorageID && MFX_CURRENT_USER_KEY != mfxStorageID) + return; + + // open required registry key + rootHKey = (MFX_LOCAL_MACHINE_KEY == mfxStorageID) ? (HKEY_LOCAL_MACHINE) : (HKEY_CURRENT_USER); + if (msdkLibSubKey) { + //dispatch/subkey/plugin + bRes = regKey.Open(rootHKey, rootDispatchPath, KEY_READ); + if (bRes) + { + bRes = regKey.Open(regKey, msdkLibSubKey, KEY_READ); + } + if (bRes) + { + bRes = regKey.Open(regKey, pluginSubkey, KEY_READ); + } + } + else + { + bRes = regKey.Open(rootHKey, rootPluginPath, KEY_READ); + } + + if (false == bRes) { + return; + } + DWORD index = 0; + if (!regKey.QueryInfo(&index)) { + return; + } + try + { + resize(index); + } + catch (...) { + TRACE_HIVE_ERROR("new PluginDescriptionRecord[%d] threw an exception: \n", index); + return; + } + + for(index = 0; ; index++) + { + wchar_t subKeyName[MFX_MAX_REGISTRY_KEY_NAME]; + DWORD subKeyNameSize = sizeof(subKeyName) / sizeof(subKeyName[0]); + WinRegKey subKey; + + // query next value name + bool enumRes = regKey.EnumKey(index, subKeyName, &subKeyNameSize); + if (!enumRes) { + break; + } + + // open the sub key + bRes = subKey.Open(regKey, subKeyName, KEY_READ); + if (!bRes) { + continue; + } + + if (msdkLibSubKey) + { + TRACE_HIVE_INFO("Found Plugin: %s\\%S\\%S\\%S\\%S\n", (MFX_LOCAL_MACHINE_KEY == mfxStorageID) ? ("HKEY_LOCAL_MACHINE") : ("HKEY_CURRENT_USER"), + rootDispatchPath, msdkLibSubKey, pluginSubkey, subKeyName); + } + else + { + TRACE_HIVE_INFO("Found Plugin: %s\\%S\\%S\n", (MFX_LOCAL_MACHINE_KEY == mfxStorageID) ? ("HKEY_LOCAL_MACHINE") : ("HKEY_CURRENT_USER"), + rootPluginPath, subKeyName); + } + + PluginDescriptionRecord descriptionRecord; + + if (!QueryKey(subKey, TypeKeyName, descriptionRecord.Type)) + { + continue; + } + TRACE_HIVE_INFO(alignStr()" : %d\n", TypeKeyName, descriptionRecord.Type); + + if (QueryKey(subKey, CodecIDKeyName, descriptionRecord.CodecId)) + { + TRACE_HIVE_INFO(alignStr()" : "MFXFOURCCTYPE()" \n", CodecIDKeyName, MFXU32TOFOURCC(descriptionRecord.CodecId)); + } + else + { + TRACE_HIVE_INFO(alignStr()" : \n", CodecIDKeyName, "NOT REGISTERED"); + } + + if (!QueryKey(subKey, GUIDKeyName, descriptionRecord.PluginUID)) + { + continue; + } + TRACE_HIVE_INFO(alignStr()" : "MFXGUIDTYPE()"\n", GUIDKeyName, MFXGUIDTOHEX(&descriptionRecord.PluginUID)); + + mfxU32 nSize = sizeof(descriptionRecord.sPath)/sizeof(*descriptionRecord.sPath); + if (!subKey.Query(PathKeyName, descriptionRecord.sPath, nSize)) + { + TRACE_HIVE_WRN("no value for : %S\n", PathKeyName); + continue; + } + TRACE_HIVE_INFO(alignStr()" : %S\n", PathKeyName, descriptionRecord.sPath); + + if (!QueryKey(subKey, DefaultKeyName, descriptionRecord.Default)) + { + continue; + } + TRACE_HIVE_INFO(alignStr()" : %s\n", DefaultKeyName, descriptionRecord.Default ? "true" : "false"); + + mfxU32 version; + if (!QueryKey(subKey, PlgVerKeyName, version)) + { + continue; + } + descriptionRecord.PluginVersion = static_cast(version); + if (0 == version) + { + TRACE_HIVE_ERROR(alignStr()" : %d, which is invalid\n", PlgVerKeyName, descriptionRecord.PluginVersion); + continue; + } + else + { + TRACE_HIVE_INFO(alignStr()" : %d\n", PlgVerKeyName, descriptionRecord.PluginVersion); + } + + mfxU32 APIVersion; + if (!QueryKey(subKey, APIVerKeyName, APIVersion)) + { + continue; + } + ConvertAPIVersion(APIVersion, descriptionRecord); + TRACE_HIVE_INFO(alignStr()" : %d.%d \n", APIVerKeyName, descriptionRecord.APIVersion.Major, descriptionRecord.APIVersion.Minor); + + try + { + operator[](index) = descriptionRecord; + } + catch (...) { + TRACE_HIVE_ERROR("operator[](%d) = descriptionRecord; - threw exception \n", index); + } + } +} + +MFX::MFXPluginsInFS::MFXPluginsInFS( mfxVersion currentAPIVersion ) + : MFXPluginStorageBase(currentAPIVersion) + , mIsVersionParsed() + , mIsAPIVersionParsed() +{ + WIN32_FIND_DATAW find_data; + msdk_disp_char currentModuleName[MAX_PLUGIN_PATH]; + + GetModuleFileNameW(NULL, currentModuleName, MAX_PLUGIN_PATH); + if (GetLastError() != 0) + { + TRACE_HIVE_ERROR("GetModuleFileName() reported an error: %d\n", GetLastError()); + return; + } + msdk_disp_char *lastSlashPos = wcsrchr(currentModuleName, L'\\'); + if (!lastSlashPos) { + lastSlashPos = currentModuleName; + } + mfxU32 executableDirLen = (mfxU32)(lastSlashPos - currentModuleName) + slashLen; + if (executableDirLen + pluginDirNameLen + pluginCfgFileNameLen >= MAX_PLUGIN_PATH) + { + TRACE_HIVE_ERROR("MAX_PLUGIN_PATH which is %d, not enough to locate plugin path\n", MAX_PLUGIN_PATH); + return; + } + msdk_disp_char_cpy_s(lastSlashPos + slashLen + , MAX_PLUGIN_PATH - executableDirLen, pluginSearchPattern); + + HANDLE fileFirst = FindFirstFileW(currentModuleName, &find_data); + if (INVALID_HANDLE_VALUE == fileFirst) + { + TRACE_HIVE_ERROR("FindFirstFileW() unable to locate any plugins folders\n", 0); + return; + } + do + { + if (!(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + continue; + } + if (pluginDirNameLen != wcslen(find_data.cFileName)) + { + continue; + } + //converting dirname into guid + PluginDescriptionRecord descriptionRecord; + descriptionRecord.APIVersion = currentAPIVersion; + descriptionRecord.onlyVersionRegistered = true; + + mfxU32 i = 0; + for(i = 0; i != pluginDirNameLen / charsPermfxU8; i++) + { + mfxU32 hexNum = 0; + if (1 != swscanf_s(find_data.cFileName + charsPermfxU8 * i, L"%2x", &hexNum)) + { + // it is ok to have non-plugin subdirs with length 32 + //TRACE_HIVE_INFO("folder name \"%S\" is not a valid GUID string\n", find_data.cFileName); + break; + } + if (hexNum == 0 && find_data.cFileName + charsPermfxU8 * i != wcsstr(find_data.cFileName + 2*i, L"00")) + { + // it is ok to have non-plugin subdirs with length 32 + //TRACE_HIVE_INFO("folder name \"%S\" is not a valid GUID string\n", find_data.cFileName); + break; + } + descriptionRecord.PluginUID.Data[i] = (mfxU8)hexNum; + } + if (i != pluginDirNameLen / charsPermfxU8) { + continue; + } + + msdk_disp_char_cpy_s(currentModuleName + executableDirLen + , MAX_PLUGIN_PATH - executableDirLen, find_data.cFileName); + + msdk_disp_char_cpy_s(currentModuleName + executableDirLen + pluginDirNameLen + , MAX_PLUGIN_PATH - executableDirLen - pluginDirNameLen, L"\\"); + + //this is path to plugin directory + msdk_disp_char_cpy_s(descriptionRecord.sPath + , sizeof(descriptionRecord.sPath) / sizeof(*descriptionRecord.sPath), currentModuleName); + + msdk_disp_char_cpy_s(currentModuleName + executableDirLen + pluginDirNameLen + slashLen + , MAX_PLUGIN_PATH - executableDirLen - pluginDirNameLen - slashLen, pluginCfgFileName); + + FILE *pluginCfgFile = 0; + _wfopen_s(&pluginCfgFile, currentModuleName, L"r"); + if (!pluginCfgFile) + { + TRACE_HIVE_INFO("in directory \"%S\" no mandatory \"%S\"\n" + , find_data.cFileName, pluginCfgFileName); + continue; + } + + if (ParseFile(pluginCfgFile, descriptionRecord)) + { + try + { + push_back(descriptionRecord); + } + catch (...) { + TRACE_HIVE_ERROR("mRecords.push_back(descriptionRecord); - threw exception \n", 0); + } + } + + fclose(pluginCfgFile); + }while (FindNextFileW(fileFirst, &find_data)); + FindClose(fileFirst); +} + +bool MFX::MFXPluginsInFS::ParseFile(FILE * f, PluginDescriptionRecord & descriptionRecord) +{ + msdk_disp_char line[MAX_PLUGIN_FILE_LINE]; + + while(NULL != fgetws(line, sizeof(line) / sizeof(*line), f)) + { + msdk_disp_char *delimiter = wcschr(line, L'='); + if (0 == delimiter) + { + TRACE_HIVE_INFO("plugin.cfg contains line \"%S\" which is not in K=V format, skipping \n", line); + continue; + } + *delimiter = 0; + if (!ParseKVPair(line, delimiter + 1, descriptionRecord)) + { + return false; + } + } + + if (!mIsVersionParsed) + { + TRACE_HIVE_ERROR("%S : Mandatory key %S not found\n", pluginCfgFileName, PlgVerKeyName); + return false; + } + + if (!mIsAPIVersionParsed) + { + TRACE_HIVE_ERROR("%S : Mandatory key %S not found\n", pluginCfgFileName, APIVerKeyName); + return false; + } + + if (!wcslen(descriptionRecord.sPath)) + { + TRACE_HIVE_ERROR("%S : Mandatory key %S not found\n", pluginCfgFileName, pluginFileName); + return false; + } + + return true; +} + +bool MFX::MFXPluginsInFS::ParseKVPair( msdk_disp_char * key, msdk_disp_char* value, PluginDescriptionRecord & descriptionRecord) +{ + if (0 != wcsstr(key, PlgVerKeyName)) + { + mfxU32 version ; + if (0 == swscanf_s(value, L"%d", &version)) + { + return false; + } + descriptionRecord.PluginVersion = (mfxU16)version; + + if (0 == descriptionRecord.PluginVersion) + { + TRACE_HIVE_ERROR("%S: %S = %d, which is invalid\n", pluginCfgFileName, PlgVerKeyName, descriptionRecord.PluginVersion); + return false; + } + + TRACE_HIVE_INFO("%S: %S = %d \n", pluginCfgFileName, PlgVerKeyName, descriptionRecord.PluginVersion); + mIsVersionParsed = true; + return true; + } + + if (0 != wcsstr(key, APIVerKeyName)) + { + mfxU32 APIversion; + if (0 == swscanf_s(value, L"%d", &APIversion)) + { + return false; + } + + ConvertAPIVersion(APIversion, descriptionRecord); + TRACE_HIVE_INFO("%S: %S = %d.%d \n", pluginCfgFileName, APIVerKeyName, descriptionRecord.APIVersion.Major, descriptionRecord.APIVersion.Minor); + + mIsAPIVersionParsed = true; + return true; + } + + + if (0!=wcsstr(key, pluginFileName)) + { + msdk_disp_char *startQuoteMark = wcschr(value, L'\"'); + if (!startQuoteMark) + { + TRACE_HIVE_ERROR("plugin filename not in quotes : %S\n", value); + return false; + } + msdk_disp_char *endQuoteMark = wcschr(startQuoteMark + 1, L'\"'); + + if (!endQuoteMark) + { + TRACE_HIVE_ERROR("plugin filename not in quotes : %S\n", value); + return false; + } + *endQuoteMark = 0; + + mfxU32 currentPathLen = (mfxU32)wcslen(descriptionRecord.sPath); + if (currentPathLen + wcslen(startQuoteMark + 1) > sizeof(descriptionRecord.sPath) / sizeof(*descriptionRecord.sPath)) + { + TRACE_HIVE_ERROR("buffer of MAX_PLUGIN_PATH characters which is %d, not enough lo store plugin path: %S%S\n" + , MAX_PLUGIN_PATH, descriptionRecord.sPath, startQuoteMark + 1); + return false; + } + + size_t restrictedCharIdx = wcscspn(startQuoteMark + 1, pluginFileNameRestrictedCharacters); + if (restrictedCharIdx != wcslen(startQuoteMark + 1)) + { + TRACE_HIVE_ERROR("plugin filename :%S, contains one of restricted characters: %S\n", startQuoteMark + 1, pluginFileNameRestrictedCharacters); + return false; + } + + msdk_disp_char_cpy_s(descriptionRecord.sPath + currentPathLen + , sizeof(descriptionRecord.sPath) / sizeof(*descriptionRecord.sPath) - currentPathLen, startQuoteMark + 1); + + TRACE_HIVE_INFO("%S: %S = \"%S\" \n", pluginCfgFileName, pluginFileName, startQuoteMark + 1); + + return true; + } + + + return true; +} + +MFX::MFXDefaultPlugins::MFXDefaultPlugins(mfxVersion currentAPIVersion, MFX_DISP_HANDLE * hdl, int implType) + : MFXPluginStorageBase(currentAPIVersion) +{ + msdk_disp_char libModuleName[MAX_PLUGIN_PATH]; + + GetModuleFileNameW((HMODULE)hdl->hModule, libModuleName, MAX_PLUGIN_PATH); + if (GetLastError() != 0) + { + TRACE_HIVE_ERROR("GetModuleFileName() reported an error: %d\n", GetLastError()); + return; + } + msdk_disp_char *lastSlashPos = wcsrchr(libModuleName, L'\\'); + if (!lastSlashPos) { + lastSlashPos = libModuleName; + } + mfxU32 executableDirLen = (mfxU32)(lastSlashPos - libModuleName) + slashLen; + if (executableDirLen + defaultPluginNameLen >= MAX_PLUGIN_PATH) + { + TRACE_HIVE_ERROR("MAX_PLUGIN_PATH which is %d, not enough to locate default plugin path\n", MAX_PLUGIN_PATH); + return; + } + + mfx_get_default_plugin_name(lastSlashPos + slashLen, MAX_PLUGIN_PATH - executableDirLen, (eMfxImplType)implType); + + if (-1 != GetFileAttributesW(libModuleName)) + { + // add single default plugin description + PluginDescriptionRecord descriptionRecord; + descriptionRecord.APIVersion = currentAPIVersion; + descriptionRecord.Default = true; + + msdk_disp_char_cpy_s(descriptionRecord.sPath + , sizeof(descriptionRecord.sPath) / sizeof(*descriptionRecord.sPath), libModuleName); + + push_back(descriptionRecord); + } + else + { + TRACE_HIVE_INFO("GetFileAttributesW() unable to locate default plugin dll named %S\n", libModuleName); + } +} + + +#endif diff --git a/plugins/obs-qsv11/libmfx/src/mfx_win_reg_key.cpp b/plugins/obs-qsv11/libmfx/src/mfx_win_reg_key.cpp new file mode 100644 index 000000000..fb8c1190f --- /dev/null +++ b/plugins/obs-qsv11/libmfx/src/mfx_win_reg_key.cpp @@ -0,0 +1,228 @@ +/* ****************************************************************************** *\ + +Copyright (C) 2012-2014 Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +- Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +- Neither the name of Intel Corporation nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +File Name: mfx_win_reg_key.cpp + +\* ****************************************************************************** */ + +#if defined(_WIN32) || defined(_WIN64) + +#include "mfx_win_reg_key.h" +#include "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); + + // 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(_WIN32) || defined(_WIN64) diff --git a/plugins/obs-qsv11/obs-qsv11-plugin-main.c b/plugins/obs-qsv11/obs-qsv11-plugin-main.c new file mode 100644 index 000000000..b7abbd0bd --- /dev/null +++ b/plugins/obs-qsv11/obs-qsv11-plugin-main.c @@ -0,0 +1,86 @@ +/* + +This file is provided under a dual BSD/GPLv2 license. When using or +redistributing this file, you may do so under either license. + +GPL LICENSE SUMMARY + +Copyright(c) Oct. 2015 Intel Corporation. + +This program is free software; you can redistribute it and/or modify +it under the terms of version 2 of the GNU General Public License as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +Contact Information: + +Seung-Woo Kim, seung-woo.kim@intel.com +705 5th Ave S #500, Seattle, WA 98104 + +BSD LICENSE + +Copyright(c) Intel Corporation. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the +distribution. + +* Neither the name of Intel Corporation nor the names of its +contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include "mfxsession.h" + +OBS_DECLARE_MODULE() +OBS_MODULE_USE_DEFAULT_LOCALE("obs-qsv11", "en-US") + +extern struct obs_encoder_info obs_qsv_encoder; + +bool obs_module_load(void) +{ + mfxIMPL impl = MFX_IMPL_HARDWARE_ANY | MFX_IMPL_VIA_D3D11; + mfxVersion ver = {{0 , 1}}; + mfxSession session; + mfxStatus sts; + + sts = MFXInit(impl, &ver, &session); + + if (sts == MFX_ERR_NONE) { + obs_register_encoder(&obs_qsv_encoder); + MFXClose(session); + } else { + impl = MFX_IMPL_HARDWARE_ANY | MFX_IMPL_VIA_D3D9; + sts = MFXInit(impl, &ver, &session); + if (sts == MFX_ERR_NONE) { + obs_register_encoder(&obs_qsv_encoder); + MFXClose(session); + } + } + + return true; +} diff --git a/plugins/obs-qsv11/obs-qsv11.c b/plugins/obs-qsv11/obs-qsv11.c new file mode 100644 index 000000000..deca4c273 --- /dev/null +++ b/plugins/obs-qsv11/obs-qsv11.c @@ -0,0 +1,687 @@ +/* + +This file is provided under a dual BSD/GPLv2 license. When using or +redistributing this file, you may do so under either license. + +GPL LICENSE SUMMARY + +Copyright(c) Oct. 2015 Intel Corporation. + +This program is free software; you can redistribute it and/or modify +it under the terms of version 2 of the GNU General Public License as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +Contact Information: + +Seung-Woo Kim, seung-woo.kim@intel.com +705 5th Ave S #500, Seattle, WA 98104 + +BSD LICENSE + +Copyright(c) Intel Corporation. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the +distribution. + +* Neither the name of Intel Corporation nor the names of its +contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include + +#ifndef _STDINT_H_INCLUDED +#define _STDINT_H_INCLUDED +#endif + +#include "QSV_Encoder.h" +#include + +#define do_log(level, format, ...) \ + blog(level, "[qsv encoder: '%s'] " format, \ + obs_encoder_get_name(obsqsv->encoder), ##__VA_ARGS__) + +#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__) +#define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__) +#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__) + +/* ------------------------------------------------------------------------- */ + +struct obs_qsv { + obs_encoder_t *encoder; + + qsv_param_t params; + qsv_t *context; + + DARRAY(uint8_t) packet_data; + + uint8_t *extra_data; + uint8_t *sei; + + size_t extra_data_size; + size_t sei_size; + + os_performance_token_t *performance_token; +}; + +/* ------------------------------------------------------------------------- */ + +static CRITICAL_SECTION g_QsvCs; +static unsigned short g_verMajor; +static unsigned short g_verMinor; +static int64_t g_pts2dtsShift; +static int64_t g_prevDts; +static bool g_bFirst; + +static const char *obs_qsv_getname(void *type_data) +{ + UNUSED_PARAMETER(type_data); + return "qsv11"; +} + +static void obs_qsv_stop(void *data); + +static void clear_data(struct obs_qsv *obsqsv) +{ + if (obsqsv->context) { + qsv_encoder_close(obsqsv->context); + // bfree(obsqsv->sei); + bfree(obsqsv->extra_data); + + obsqsv->context = NULL; + // obsqsv->sei = NULL; + obsqsv->extra_data = NULL; + } +} + +static void obs_qsv_destroy(void *data) +{ + struct obs_qsv *obsqsv = (struct obs_qsv *)data; + + if (obsqsv) { + os_end_high_performance(obsqsv->performance_token); + clear_data(obsqsv); + da_free(obsqsv->packet_data); + bfree(obsqsv); + } +} + +static void obs_qsv_defaults(obs_data_t *settings) +{ + obs_data_set_default_string(settings, "target_usage", "balanced"); + obs_data_set_default_int(settings, "bitrate", 2500); + obs_data_set_default_int(settings, "max_bitrate", 3000); + obs_data_set_default_string(settings, "profile", "main"); + obs_data_set_default_int(settings, "async_depth", 4); + obs_data_set_default_string(settings, "rate_control", "CBR"); + + obs_data_set_default_int(settings, "accuracy", 1000); + obs_data_set_default_int(settings, "convergence", 1); + obs_data_set_default_int(settings, "qpi", 23); + obs_data_set_default_int(settings, "qpp", 23); + obs_data_set_default_int(settings, "qpb", 23); + obs_data_set_default_int(settings, "icq_quality", 23); + obs_data_set_default_int(settings, "la_depth", 40); + + obs_data_set_default_int(settings, "keyint_sec", 3); +} + +static inline void add_strings(obs_property_t *list, const char *const *strings) +{ + while (*strings) { + obs_property_list_add_string(list, *strings, *strings); + strings++; + } +} + +#define TEXT_SPEED obs_module_text("TargetUsage") +#define TEXT_TARGET_BITRATE obs_module_text("Bitrate") +#define TEXT_MAX_BITRATE obs_module_text("MaxBitrate") +#define TEXT_PROFILE obs_module_text("Profile") +#define TEXT_ASYNC_DEPTH obs_module_text("AsyncDepth") +#define TEXT_RATE_CONTROL obs_module_text("RateControl") +#define TEXT_ACCURACY obs_module_text("Accuracy") +#define TEXT_CONVERGENCE obs_module_text("Convergence") +#define TEXT_ICQ_QUALITY obs_module_text("ICQQuality") +#define TEXT_LA_DEPTH obs_module_text("LookAheadDepth") +#define TEXT_KEYINT_SEC obs_module_text("KeyframeIntervalSec") + +static bool rate_control_modified(obs_properties_t *ppts, obs_property_t *p, + obs_data_t *settings) +{ + const char *rate_control = obs_data_get_string(settings, "rate_control"); + + bool bVisible = + astrcmpi(rate_control, "VCM") == 0 || + astrcmpi(rate_control, "VBR") == 0; + p = obs_properties_get(ppts, "max_bitrate"); + obs_property_set_visible(p, bVisible); + + bVisible = + astrcmpi(rate_control, "CQP") == 0 || + astrcmpi(rate_control, "LA_ICQ") == 0 || + astrcmpi(rate_control, "ICQ") == 0; + p = obs_properties_get(ppts, "bitrate"); + obs_property_set_visible(p, !bVisible); + + bVisible = astrcmpi(rate_control, "AVBR") == 0; + p = obs_properties_get(ppts, "accuracy"); + obs_property_set_visible(p, bVisible); + p = obs_properties_get(ppts, "convergence"); + obs_property_set_visible(p, bVisible); + + bVisible = astrcmpi(rate_control, "CQP") == 0; + p = obs_properties_get(ppts, "qpi"); + obs_property_set_visible(p, bVisible); + p = obs_properties_get(ppts, "qpb"); + obs_property_set_visible(p, bVisible); + p = obs_properties_get(ppts, "qpp"); + obs_property_set_visible(p, bVisible); + + bVisible = astrcmpi(rate_control, "ICQ") == 0 || + astrcmpi(rate_control, "LA_ICQ") == 0; + p = obs_properties_get(ppts, "icq_quality"); + obs_property_set_visible(p, bVisible); + + bVisible = astrcmpi(rate_control, "LA_ICQ") == 0 || + astrcmpi(rate_control, "LA") == 0; + p = obs_properties_get(ppts, "la_depth"); + obs_property_set_visible(p, bVisible); + + return true; +} + +static inline void add_rate_controls(obs_property_t *list, + const struct qsv_rate_control_info *rc) +{ + enum qsv_cpu_platform plat = qsv_get_cpu_platform(); + while (rc->name) { + if (!rc->haswell_or_greater || plat >= QSV_CPU_PLATFORM_HSW) + obs_property_list_add_string(list, rc->name, rc->name); + rc++; + } +} + +static obs_properties_t *obs_qsv_props(void *unused) +{ + UNUSED_PARAMETER(unused); + + obs_properties_t *props = obs_properties_create(); + obs_property_t *list; + + list = obs_properties_add_list(props, "target_usage", TEXT_SPEED, + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); + add_strings(list, qsv_usage_names); + + list = obs_properties_add_list(props, "profile", TEXT_PROFILE, + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); + add_strings(list, qsv_profile_names); + + obs_properties_add_int(props, "keyint_sec", TEXT_KEYINT_SEC, 1, 20, 1); + obs_properties_add_int(props, "async_depth", TEXT_ASYNC_DEPTH, 1, 7, 1); + + list = obs_properties_add_list(props, "rate_control", TEXT_RATE_CONTROL, + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); + add_rate_controls(list, qsv_ratecontrols); + obs_property_set_modified_callback(list, rate_control_modified); + + obs_properties_add_int(props, "bitrate", TEXT_TARGET_BITRATE, 50, + 10000000, 1); + obs_properties_add_int(props, "max_bitrate", TEXT_MAX_BITRATE, 50, + 10000000, 1); + obs_properties_add_int(props, "accuracy", TEXT_ACCURACY, 0, 10000, 1); + obs_properties_add_int(props, "convergence", TEXT_CONVERGENCE, 0, 10, 1); + obs_properties_add_int(props, "qpi", "QPI", 1, 51, 1); + obs_properties_add_int(props, "qpp", "QPP", 1, 51, 1); + obs_properties_add_int(props, "qpb", "QPB", 1, 51, 1); + obs_properties_add_int(props, "icq_quality", TEXT_ICQ_QUALITY, 1, 51, 1); + obs_properties_add_int(props, "la_depth", TEXT_LA_DEPTH, 10, 100, 1); + + return props; +} + +static void update_params(struct obs_qsv *obsqsv, obs_data_t *settings) +{ + video_t *video = obs_encoder_video(obsqsv->encoder); + const struct video_output_info *voi = video_output_get_info(video); + + const char *target_usage = obs_data_get_string(settings, "target_usage"); + const char *profile = obs_data_get_string(settings, "profile"); + const char *rate_control = obs_data_get_string(settings, "rate_control"); + int async_depth = (int)obs_data_get_int(settings, "async_depth"); + int target_bitrate = (int)obs_data_get_int(settings, "bitrate"); + int max_bitrate = (int)obs_data_get_int(settings, "max_bitrate"); + int accuracy = (int)obs_data_get_int(settings, "accuracy"); + int convergence = (int)obs_data_get_int(settings, "convergence"); + int qpi = (int)obs_data_get_int(settings, "qpi"); + int qpp = (int)obs_data_get_int(settings, "qpp"); + int qpb = (int)obs_data_get_int(settings, "qpb"); + int icq_quality = (int)obs_data_get_int(settings, "icq_quality"); + int la_depth = (int)obs_data_get_int(settings, "la_depth"); + int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec"); + bool cbr_override = obs_data_get_bool(settings, "cbr"); + int bFrames = 7; + + int width = (int)obs_encoder_get_width(obsqsv->encoder); + int height = (int)obs_encoder_get_height(obsqsv->encoder); + if (astrcmpi(target_usage, "quality") == 0) + obsqsv->params.nTargetUsage = MFX_TARGETUSAGE_BEST_QUALITY; + else if (astrcmpi(target_usage, "balanced") == 0) + obsqsv->params.nTargetUsage = MFX_TARGETUSAGE_BALANCED; + else if (astrcmpi(target_usage, "speed") == 0) + obsqsv->params.nTargetUsage = MFX_TARGETUSAGE_BEST_SPEED; + + if (astrcmpi(profile, "baseline") == 0) + obsqsv->params.nCodecProfile = MFX_PROFILE_AVC_BASELINE; + else if (astrcmpi(profile, "main") == 0) + obsqsv->params.nCodecProfile = MFX_PROFILE_AVC_MAIN; + else if (astrcmpi(profile, "high") == 0) + obsqsv->params.nCodecProfile = MFX_PROFILE_AVC_HIGH; + + /* internal convenience parameter, overrides rate control param */ + if (cbr_override) + rate_control = "CBR"; + + if (astrcmpi(rate_control, "CBR") == 0) + obsqsv->params.nRateControl = MFX_RATECONTROL_CBR; + else if (astrcmpi(rate_control, "VBR") == 0) + obsqsv->params.nRateControl = MFX_RATECONTROL_VBR; + else if (astrcmpi(rate_control, "VCM") == 0) + obsqsv->params.nRateControl = MFX_RATECONTROL_VCM; + else if (astrcmpi(rate_control, "CQP") == 0) + obsqsv->params.nRateControl = MFX_RATECONTROL_CQP; + else if (astrcmpi(rate_control, "AVBR") == 0) + obsqsv->params.nRateControl = MFX_RATECONTROL_AVBR; + else if (astrcmpi(rate_control, "ICQ") == 0) + obsqsv->params.nRateControl = MFX_RATECONTROL_ICQ; + else if (astrcmpi(rate_control, "LA_ICQ") == 0) + obsqsv->params.nRateControl = MFX_RATECONTROL_LA_ICQ; + else if (astrcmpi(rate_control, "LA") == 0) + obsqsv->params.nRateControl = MFX_RATECONTROL_LA; + + obsqsv->params.nAsyncDepth = (mfxU16)async_depth; + obsqsv->params.nAccuracy = (mfxU16)accuracy; + obsqsv->params.nConvergence = (mfxU16)convergence; + obsqsv->params.nQPI = (mfxU16)qpi; + obsqsv->params.nQPP = (mfxU16)qpp; + obsqsv->params.nQPB = (mfxU16)qpb; + obsqsv->params.nLADEPTH = (mfxU16)la_depth; + obsqsv->params.nTargetBitRate = (mfxU16)target_bitrate; + obsqsv->params.nMaxBitRate = (mfxU16)max_bitrate; + obsqsv->params.nWidth = (mfxU16)width; + obsqsv->params.nHeight = (mfxU16)height; + obsqsv->params.nFpsNum = (mfxU16)voi->fps_num; + obsqsv->params.nFpsDen = (mfxU16)voi->fps_den; + obsqsv->params.nbFrames = (mfxU16)bFrames; + obsqsv->params.nKeyIntSec = (mfxU16)keyint_sec; + obsqsv->params.nICQQuality = (mfxU16)icq_quality; + + info("settings:\n\trate_control: %s", rate_control); + + if (obsqsv->params.nRateControl != MFX_RATECONTROL_LA_ICQ && + obsqsv->params.nRateControl != MFX_RATECONTROL_ICQ && + obsqsv->params.nRateControl != MFX_RATECONTROL_CQP) + blog(LOG_INFO, + "\ttarget_bitrate: %d", + (int)obsqsv->params.nTargetBitRate); + + if (obsqsv->params.nRateControl == MFX_RATECONTROL_VBR || + obsqsv->params.nRateControl == MFX_RATECONTROL_VCM) + blog(LOG_INFO, + "\tmax_bitrate: %d", + (int)obsqsv->params.nMaxBitRate); + + if (obsqsv->params.nRateControl == MFX_RATECONTROL_LA_ICQ || + obsqsv->params.nRateControl == MFX_RATECONTROL_ICQ) + blog(LOG_INFO, + "\tICQ Quality: %d", + (int)obsqsv->params.nICQQuality); + + if (obsqsv->params.nRateControl == MFX_RATECONTROL_LA_ICQ || + obsqsv->params.nRateControl == MFX_RATECONTROL_LA) + blog(LOG_INFO, + "\tLookahead Depth:%d", + (int)obsqsv->params.nLADEPTH); + + if (obsqsv->params.nRateControl == MFX_RATECONTROL_CQP) + blog(LOG_INFO, + "\tqpi: %d\n" + "\tqpb: %d\n" + "\tqpp: %d", + qpi, qpb, qpp); + + blog(LOG_INFO, + "\tfps_num: %d\n" + "\tfps_den: %d\n" + "\twidth: %d\n" + "\theight: %d", + voi->fps_num, voi->fps_den, + width, height); + + info("debug info:"); +} + +static bool update_settings(struct obs_qsv *obsqsv, obs_data_t *settings) +{ + update_params(obsqsv, settings); + return true; +} + +static void load_headers(struct obs_qsv *obsqsv) +{ + DARRAY(uint8_t) header; + uint8_t sei = 0; + + // Not sure if SEI is needed. + // Just filling in empty meaningless SEI message. + // Seems to work fine. + // DARRAY(uint8_t) sei; + + da_init(header); + // da_init(sei); + + uint8_t *pSPS, *pPPS; + uint16_t nSPS, nPPS; + qsv_encoder_headers(obsqsv->context, &pSPS, &pPPS, &nSPS, &nPPS); + da_push_back_array(header, pSPS, nSPS); + da_push_back_array(header, pPPS, nPPS); + + obsqsv->extra_data = header.array; + obsqsv->extra_data_size = header.num; + obsqsv->sei = &sei; + obsqsv->sei_size = 1; +} + +static bool obs_qsv_update(void *data, obs_data_t *settings) +{ + struct obs_qsv *obsqsv = data; + bool success = update_settings(obsqsv, settings); + int ret; + + + if (success) { + EnterCriticalSection(&g_QsvCs); + + ret = qsv_encoder_reconfig(obsqsv->context, &obsqsv->params); + if (ret != 0) + warn("Failed to reconfigure: %d", ret); + + LeaveCriticalSection(&g_QsvCs); + + return ret == 0; + } + + return false; +} + +static void *obs_qsv_create(obs_data_t *settings, obs_encoder_t *encoder) +{ + InitializeCriticalSection(&g_QsvCs); + + struct obs_qsv *obsqsv = bzalloc(sizeof(struct obs_qsv)); + obsqsv->encoder = encoder; + + if (update_settings(obsqsv, settings)) { + obsqsv->context = qsv_encoder_open(&obsqsv->params); + + if (obsqsv->context == NULL) + warn("qsv failed to load"); + else + load_headers(obsqsv); + } else { + warn("bad settings specified"); + } + + qsv_encoder_version(&g_verMajor, &g_verMinor); + + blog(LOG_INFO, "\tmajor: %d\n" + "\tminor: %d", + g_verMajor, g_verMinor); + + // MSDK 1.6 or less doesn't have automatic DTS calculation + // including early SandyBridge. + // Need to add manual DTS from PTS. + if (g_verMajor == 1 && g_verMinor < 7) { + int64_t interval = obsqsv->params.nbFrames + 1; + int64_t GopPicSize = (int64_t)(obsqsv->params.nKeyIntSec * + obsqsv->params.nFpsNum / + (float)obsqsv->params.nFpsDen); + g_pts2dtsShift = GopPicSize - (GopPicSize / interval) * + interval; + + blog(LOG_INFO, "\tinterval: %d\n" + "\tGopPictSize: %d\n" + "\tg_pts2dtsShift: %d", + interval, GopPicSize, g_pts2dtsShift); + } + else + g_pts2dtsShift = -1; + + if (!obsqsv->context) { + bfree(obsqsv); + return NULL; + } + + obsqsv->performance_token = + os_request_high_performance("qsv encoding"); + + g_bFirst = true; + + return obsqsv; +} + +static bool obs_qsv_extra_data(void *data, uint8_t **extra_data, size_t *size) +{ + struct obs_qsv *obsqsv = data; + + if (!obsqsv->context) + return false; + + *extra_data = obsqsv->extra_data; + *size = obsqsv->extra_data_size; + return true; +} + +static bool obs_qsv_sei(void *data, uint8_t **sei,size_t *size) +{ + struct obs_qsv *obsqsv = data; + + if (!obsqsv->context) + return false; + + /* (Jim) Unused */ + UNUSED_PARAMETER(sei); + UNUSED_PARAMETER(size); + + *sei = obsqsv->sei; + *size = obsqsv->sei_size; + return true; +} + +static inline bool valid_format(enum video_format format) +{ + return format == VIDEO_FORMAT_NV12; +} + +static inline void cap_resolution(struct video_scale_info *info, + const struct video_output_info *vid_info) +{ + enum qsv_cpu_platform qsv_platform = qsv_get_cpu_platform(); + + info->height = vid_info->height; + info->width = vid_info->width; + + if (qsv_platform <= QSV_CPU_PLATFORM_IVB) { + if (vid_info->width > 1920) { + info->width = 1920; + } + + if (vid_info->height > 1200) { + info->height = 1200; + } + } +} + +static void obs_qsv_video_info(void *data, struct video_scale_info *info) +{ + struct obs_qsv *obsqsv = data; + video_t *video = obs_encoder_video(obsqsv->encoder); + const struct video_output_info *vid_info = video_output_get_info(video); + enum video_format pref_format; + + pref_format = obs_encoder_get_preferred_video_format(obsqsv->encoder); + + if (!valid_format(pref_format)) { + pref_format = valid_format(info->format) ? + info->format : VIDEO_FORMAT_NV12; + } + + info->format = pref_format; + cap_resolution(info, vid_info); +} + +static void parse_packet(struct obs_qsv *obsqsv, struct encoder_packet *packet, mfxBitstream *pBS, uint32_t fps_num, bool *received_packet) +{ + if (pBS == NULL || pBS->DataLength == 0) { + *received_packet = false; + return; + } + + da_resize(obsqsv->packet_data, 0); + da_push_back_array(obsqsv->packet_data, &pBS->Data[pBS->DataOffset], + pBS->DataLength); + + packet->data = obsqsv->packet_data.array; + packet->size = obsqsv->packet_data.num; + packet->type = OBS_ENCODER_VIDEO; + packet->pts = pBS->TimeStamp * fps_num / 90000; + packet->keyframe = (pBS->FrameType & + (MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF)); + + //bool iFrame = pBS->FrameType & MFX_FRAMETYPE_I; + //bool bFrame = pBS->FrameType & MFX_FRAMETYPE_B; + bool pFrame = pBS->FrameType & MFX_FRAMETYPE_P; + //int iType = iFrame ? 0 : (bFrame ? 1 : (pFrame ? 2 : -1)); + //int64_t interval = obsqsv->params.nbFrames + 1; + + // In case MSDK does't support automatic DecodeTimeStamp, do manual + // calculation + if (g_pts2dtsShift >= 0) + { + if (g_bFirst) { + packet->dts = packet->pts - 3 * obsqsv->params.nFpsDen; + } else if (pFrame) { + packet->dts = packet->pts - 10 * obsqsv->params.nFpsDen; + g_prevDts = packet->dts; + } else { + packet->dts = g_prevDts + obsqsv->params.nFpsDen; + g_prevDts = packet->dts; + } + } else { + packet->dts = pBS->DecodeTimeStamp * fps_num / 90000; + } + +#if 0 + info("parse packet:\n" + "\tFrameType: %d\n" + "\tpts: %d\n" + "\tdts: %d", + iType, packet->pts, packet->dts); +#endif + + *received_packet = true; + pBS->DataLength = 0; + + g_bFirst = false; +} + +static bool obs_qsv_encode(void *data, struct encoder_frame *frame, + struct encoder_packet *packet, bool *received_packet) +{ + struct obs_qsv *obsqsv = data; + + if (!frame || !packet || !received_packet) + return false; + + EnterCriticalSection(&g_QsvCs); + + + video_t *video = obs_encoder_video(obsqsv->encoder); + const struct video_output_info *voi = video_output_get_info(video); + + mfxBitstream *pBS = NULL; + + int ret; + + mfxU64 qsvPTS = frame->pts * 90000 / voi->fps_num; + + if (frame) + ret = qsv_encoder_encode( + obsqsv->context, + qsvPTS, + frame->data[0], frame->data[1], frame->linesize[0], + frame->linesize[1], + &pBS); + else + ret = qsv_encoder_encode( + obsqsv->context, + qsvPTS, + NULL, NULL, 0, 0, &pBS); + + if (ret < 0) { + warn("encode failed"); + return false; + } + + parse_packet(obsqsv, packet, pBS, voi->fps_num, received_packet); + + LeaveCriticalSection(&g_QsvCs); + + return true; +} + +struct obs_encoder_info obs_qsv_encoder = { + .id = "obs_qsv11", + .type = OBS_ENCODER_VIDEO, + .codec = "h264", + .get_name = obs_qsv_getname, + .create = obs_qsv_create, + .destroy = obs_qsv_destroy, + .encode = obs_qsv_encode, + .update = obs_qsv_update, + .get_properties = obs_qsv_props, + .get_defaults = obs_qsv_defaults, + .get_extra_data = obs_qsv_extra_data, + .get_sei_data = obs_qsv_sei, + .get_video_info = obs_qsv_video_info +};