From d0c86365d23503d7339d20e7ea0f27839594f9aa Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sat, 16 Oct 2021 01:15:06 +0900 Subject: [PATCH] mediafoundation: Use GetProcAddress() for OS version dependent symbols We are using some symbols which are not available on Windows 7, specifically D3D11 interop related ones Part-of: --- .../sys/mediafoundation/gstmfplatloader.c | 126 ++++++++++++++++++ .../sys/mediafoundation/gstmfplatloader.h | 44 ++++++ .../sys/mediafoundation/gstmftransform.cpp | 43 +----- .../sys/mediafoundation/gstmftransform.h | 2 - .../sys/mediafoundation/gstmfvideoenc.cpp | 7 +- .../sys/mediafoundation/meson.build | 1 + .../sys/mediafoundation/plugin.c | 6 +- 7 files changed, 181 insertions(+), 48 deletions(-) create mode 100644 subprojects/gst-plugins-bad/sys/mediafoundation/gstmfplatloader.c create mode 100644 subprojects/gst-plugins-bad/sys/mediafoundation/gstmfplatloader.h diff --git a/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfplatloader.c b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfplatloader.c new file mode 100644 index 0000000000..d07fc29d5b --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfplatloader.c @@ -0,0 +1,126 @@ +/* GStreamer + * Copyright (C) 2021 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstmfplatloader.h" +#include + +/* *INDENT-OFF* */ +G_BEGIN_DECLS + +GST_DEBUG_CATEGORY_EXTERN (gst_mf_debug); +#define GST_CAT_DEFAULT gst_mf_debug + +G_END_DECLS + +#define LOAD_SYMBOL(name,func) G_STMT_START { \ + if (!g_module_symbol (module, G_STRINGIFY (name), (gpointer *) &vtable->func)) { \ + GST_WARNING ("Failed to load '%s', %s", G_STRINGIFY (name), g_module_error()); \ + goto out; \ + } \ +} G_STMT_END; + +typedef struct _GstMFPlatVTable +{ + gboolean loaded; + + HRESULT (__stdcall * GstMFTEnum2) (GUID guidCategory, + UINT32 Flags, + const MFT_REGISTER_TYPE_INFO * pInputType, + const MFT_REGISTER_TYPE_INFO * pOutputType, + IMFAttributes * pAttributes, + IMFActivate *** pppMFTActivate, + UINT32 * pnumMFTActivate); + + HRESULT (__stdcall * GstMFCreateDXGIDeviceManager) (UINT * resetToken, + IMFDXGIDeviceManager ** ppDeviceManager); + + HRESULT (__stdcall * GstMFCreateVideoSampleAllocatorEx) (REFIID riid, + void** ppSampleAllocator); +} GstMFPlatVTable; +/* *INDENT-ON* */ + +static GstMFPlatVTable gst_mf_plat_vtable = { 0, }; + +static gboolean +load_library_once (void) +{ + static gsize load_once = 0; + if (g_once_init_enter (&load_once)) { + GModule *module; + GstMFPlatVTable *vtable = &gst_mf_plat_vtable; + + module = g_module_open ("mfplat.dll", G_MODULE_BIND_LAZY); + if (!module) + goto out; + + LOAD_SYMBOL (MFTEnum2, GstMFTEnum2); + LOAD_SYMBOL (MFCreateDXGIDeviceManager, GstMFCreateDXGIDeviceManager); + LOAD_SYMBOL (MFCreateVideoSampleAllocatorEx, + GstMFCreateVideoSampleAllocatorEx); + + vtable->loaded = TRUE; + + out: + g_once_init_leave (&load_once, 1); + } + + return gst_mf_plat_vtable.loaded; +} + +gboolean +gst_mf_plat_load_library (void) +{ + return load_library_once (); +} + +HRESULT __stdcall +GstMFTEnum2 (GUID guidCategory, UINT32 Flags, + const MFT_REGISTER_TYPE_INFO * pInputType, + const MFT_REGISTER_TYPE_INFO * pOutputType, + IMFAttributes * pAttributes, IMFActivate *** pppMFTActivate, + UINT32 * pnumMFTActivate) +{ + g_assert (gst_mf_plat_vtable.GstMFTEnum2 != NULL); + + return gst_mf_plat_vtable.GstMFTEnum2 (guidCategory, Flags, pInputType, + pOutputType, pAttributes, pppMFTActivate, pnumMFTActivate); +} + +HRESULT __stdcall +GstMFCreateDXGIDeviceManager (UINT * resetToken, + IMFDXGIDeviceManager ** ppDeviceManager) +{ + g_assert (gst_mf_plat_vtable.GstMFCreateDXGIDeviceManager != NULL); + + return gst_mf_plat_vtable.GstMFCreateDXGIDeviceManager (resetToken, + ppDeviceManager); +} + +HRESULT __stdcall +GstMFCreateVideoSampleAllocatorEx (REFIID riid, void **ppSampleAllocator) +{ + g_assert (gst_mf_plat_vtable.GstMFCreateVideoSampleAllocatorEx != NULL); + + return gst_mf_plat_vtable.GstMFCreateVideoSampleAllocatorEx (riid, + ppSampleAllocator); +} diff --git a/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfplatloader.h b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfplatloader.h new file mode 100644 index 0000000000..4c1b7dcb0a --- /dev/null +++ b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfplatloader.h @@ -0,0 +1,44 @@ +/* GStreamer + * Copyright (C) 2021 Seungha Yang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include +#include +#include + +G_BEGIN_DECLS + +gboolean gst_mf_plat_load_library (void); + +HRESULT __stdcall GstMFTEnum2 (GUID guidCategory, + UINT32 Flags, + const MFT_REGISTER_TYPE_INFO * pInputType, + const MFT_REGISTER_TYPE_INFO * pOutputType, + IMFAttributes * pAttributes, + IMFActivate *** pppMFTActivate, + UINT32 * pnumMFTActivate); + +HRESULT __stdcall GstMFCreateDXGIDeviceManager (UINT * resetToken, + IMFDXGIDeviceManager ** ppDeviceManager); + +HRESULT __stdcall GstMFCreateVideoSampleAllocatorEx (REFIID riid, + void** ppSampleAllocator); + +G_END_DECLS diff --git a/subprojects/gst-plugins-bad/sys/mediafoundation/gstmftransform.cpp b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmftransform.cpp index 4c3de1141b..b6839e8f8c 100644 --- a/subprojects/gst-plugins-bad/sys/mediafoundation/gstmftransform.cpp +++ b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmftransform.cpp @@ -25,9 +25,9 @@ #include "gstmfconfig.h" #include -#include #include "gstmftransform.h" #include "gstmfutils.h" +#include "gstmfplatloader.h" #include #include @@ -41,43 +41,6 @@ GST_DEBUG_CATEGORY_EXTERN (gst_mf_transform_debug); G_END_DECLS -static GModule *mf_plat_module = NULL; -typedef HRESULT (__stdcall *pMFTEnum2) (GUID guidCategory, - UINT32 Flags, - const MFT_REGISTER_TYPE_INFO * pInputType, - const MFT_REGISTER_TYPE_INFO * pOutputType, - IMFAttributes * pAttributes, - IMFActivate *** pppMFTActivate, - UINT32 * pnumMFTActivate); -static pMFTEnum2 GstMFTEnum2Func = NULL; - -gboolean -gst_mf_transform_load_library (void) -{ -#if GST_MF_HAVE_D3D11 - static gsize _init = 0; - if (g_once_init_enter (&_init)) { - mf_plat_module = g_module_open ("mfplat.dll", G_MODULE_BIND_LAZY); - - if (mf_plat_module) { - if (!g_module_symbol (mf_plat_module, "MFTEnum2", - (gpointer *) & GstMFTEnum2Func)) { - GST_WARNING ("Cannot load MFTEnum2 symbol"); - g_module_close (mf_plat_module); - mf_plat_module = NULL; - GstMFTEnum2Func = NULL; - } else { - GST_INFO ("MFTEnum2 symbol is available"); - } - } - - g_once_init_leave (&_init, 1); - } -#endif - - return ! !GstMFTEnum2Func; -} - typedef HRESULT (*GstMFTransformAsyncCallbackOnEvent) (MediaEventType event, GstObject * client); @@ -508,7 +471,7 @@ gst_mf_transform_thread_func (GstMFTransform * self) /* NOTE: MFTEnum2 is desktop only and requires Windows 10 */ #if GST_MF_HAVE_D3D11 - if (GstMFTEnum2Func && self->enum_params.adapter_luid && + if (gst_mf_plat_load_library () && self->enum_params.adapter_luid && (self->enum_params.enum_flags & MFT_ENUM_FLAG_HARDWARE) != 0) { ComPtr < IMFAttributes > attr; LUID luid; @@ -533,7 +496,7 @@ gst_mf_transform_thread_func (GstMFTransform * self) goto run_loop; } - hr = GstMFTEnum2Func (self->enum_params.category, + hr = GstMFTEnum2 (self->enum_params.category, self->enum_params.enum_flags, self->enum_params.input_typeinfo, self->enum_params.output_typeinfo, attr.Get (), &devices, &num_devices); } else diff --git a/subprojects/gst-plugins-bad/sys/mediafoundation/gstmftransform.h b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmftransform.h index 8e2402ed28..b053f4adc1 100644 --- a/subprojects/gst-plugins-bad/sys/mediafoundation/gstmftransform.h +++ b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmftransform.h @@ -69,8 +69,6 @@ typedef HRESULT (*GstMFTransformNewSampleCallback) (GstMFTransform * object, IMFSample * sample, gpointer user_data); -gboolean gst_mf_transform_load_library (void); - GstMFTransform * gst_mf_transform_new (GstMFTransformEnumParams * params); gboolean gst_mf_transform_open (GstMFTransform * object); diff --git a/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfvideoenc.cpp b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfvideoenc.cpp index 72dd1775f9..94cdef0326 100644 --- a/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfvideoenc.cpp +++ b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfvideoenc.cpp @@ -24,8 +24,9 @@ #include #include "gstmfvideoenc.h" -#include #include "gstmfvideobuffer.h" +#include "gstmfplatloader.h" +#include #include #include @@ -167,7 +168,7 @@ gst_mf_video_enc_open (GstVideoEncoder * enc) device = self->d3d11_device; - hr = MFCreateDXGIDeviceManager (&self->reset_token, &self->device_manager); + hr = GstMFCreateDXGIDeviceManager (&self->reset_token, &self->device_manager); if (!gst_mf_result (hr)) { GST_ERROR_OBJECT (self, "Couldn't create DXGI device manager"); gst_clear_object (&self->other_d3d11_device); @@ -477,7 +478,7 @@ gst_mf_video_enc_set_format (GstVideoEncoder * enc, GstVideoCodecState * state) GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) { GST_DEBUG_OBJECT (self, "found D3D11 memory feature"); - hr = MFCreateVideoSampleAllocatorEx (IID_PPV_ARGS (&allocator)); + hr = GstMFCreateVideoSampleAllocatorEx (IID_PPV_ARGS (&allocator)); if (!gst_mf_result (hr)) GST_WARNING_OBJECT (self, "IMFVideoSampleAllocatorEx interface is unavailable"); diff --git a/subprojects/gst-plugins-bad/sys/mediafoundation/meson.build b/subprojects/gst-plugins-bad/sys/mediafoundation/meson.build index b4722365d8..9c6c922678 100644 --- a/subprojects/gst-plugins-bad/sys/mediafoundation/meson.build +++ b/subprojects/gst-plugins-bad/sys/mediafoundation/meson.build @@ -13,6 +13,7 @@ mf_sources = [ 'gstmfaacenc.cpp', 'gstmfmp3enc.cpp', 'gstmfvideobuffer.cpp', + 'gstmfplatloader.c', ] mf_desktop_sources = [ diff --git a/subprojects/gst-plugins-bad/sys/mediafoundation/plugin.c b/subprojects/gst-plugins-bad/sys/mediafoundation/plugin.c index 7e6ad46a87..9d97da70cb 100644 --- a/subprojects/gst-plugins-bad/sys/mediafoundation/plugin.c +++ b/subprojects/gst-plugins-bad/sys/mediafoundation/plugin.c @@ -36,10 +36,10 @@ #include "gstmfvp9enc.h" #include "gstmfaacenc.h" #include "gstmfmp3enc.h" -#include "gstmftransform.h" #if GST_MF_HAVE_D3D11 #include +#include #endif GST_DEBUG_CATEGORY (gst_mf_debug); @@ -67,7 +67,7 @@ get_d3d11_devices (void) IMFVideoSampleAllocatorEx *allocator = NULL; /* Check whether we can use IMFVideoSampleAllocatorEx interface */ - hr = MFCreateVideoSampleAllocatorEx (&IID_IMFVideoSampleAllocatorEx, + hr = GstMFCreateVideoSampleAllocatorEx (&IID_IMFVideoSampleAllocatorEx, &allocator); if (!gst_mf_result (hr)) { GST_DEBUG ("IMFVideoSampleAllocatorEx interface is unavailable"); @@ -189,7 +189,7 @@ plugin_init (GstPlugin * plugin) * So, resulting MFT and D3D11 might not be compatible in case of multi-GPU * environment on UWP. */ #if GST_MF_HAVE_D3D11 - if (gst_mf_transform_load_library ()) + if (gst_mf_plat_load_library ()) device_list = get_d3d11_devices (); #endif