mediafoundation: Use GetProcAddress() for OS version dependent symbols
authorSeungha Yang <seungha@centricular.com>
Fri, 15 Oct 2021 16:15:06 +0000 (01:15 +0900)
committerSeungha Yang <seungha@centricular.com>
Sat, 16 Oct 2021 09:07:06 +0000 (18:07 +0900)
We are using some symbols which are not available on Windows 7,
specifically D3D11 interop related ones

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1167>

subprojects/gst-plugins-bad/sys/mediafoundation/gstmfplatloader.c [new file with mode: 0644]
subprojects/gst-plugins-bad/sys/mediafoundation/gstmfplatloader.h [new file with mode: 0644]
subprojects/gst-plugins-bad/sys/mediafoundation/gstmftransform.cpp
subprojects/gst-plugins-bad/sys/mediafoundation/gstmftransform.h
subprojects/gst-plugins-bad/sys/mediafoundation/gstmfvideoenc.cpp
subprojects/gst-plugins-bad/sys/mediafoundation/meson.build
subprojects/gst-plugins-bad/sys/mediafoundation/plugin.c

diff --git a/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfplatloader.c b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfplatloader.c
new file mode 100644 (file)
index 0000000..d07fc29
--- /dev/null
@@ -0,0 +1,126 @@
+/* GStreamer
+ * Copyright (C) 2021 Seungha Yang <seungha@centricular.com>
+ *
+ * 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 <gmodule.h>
+
+/* *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 (file)
index 0000000..4c1b7dc
--- /dev/null
@@ -0,0 +1,44 @@
+/* GStreamer
+ * Copyright (C) 2021 Seungha Yang <seungha@centricular.com>
+ *
+ * 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 <gst/gst.h>
+#include <windows.h>
+#include <mfapi.h>
+
+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
index 4c3de11..b6839e8 100644 (file)
@@ -25,9 +25,9 @@
 #include "gstmfconfig.h"
 
 #include <gst/gst.h>
-#include <gmodule.h>
 #include "gstmftransform.h"
 #include "gstmfutils.h"
+#include "gstmfplatloader.h"
 #include <string.h>
 #include <wrl.h>
 
@@ -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
index 8e2402e..b053f4a 100644 (file)
@@ -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);
index 72dd177..94cdef0 100644 (file)
@@ -24,8 +24,9 @@
 
 #include <gst/gst.h>
 #include "gstmfvideoenc.h"
-#include <wrl.h>
 #include "gstmfvideobuffer.h"
+#include "gstmfplatloader.h"
+#include <wrl.h>
 #include <string.h>
 #include <cmath>
 
@@ -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");
index b472236..9c6c922 100644 (file)
@@ -13,6 +13,7 @@ mf_sources = [
   'gstmfaacenc.cpp',
   'gstmfmp3enc.cpp',
   'gstmfvideobuffer.cpp',
+  'gstmfplatloader.c',
 ]
 
 mf_desktop_sources = [
index 7e6ad46..9d97da7 100644 (file)
 #include "gstmfvp9enc.h"
 #include "gstmfaacenc.h"
 #include "gstmfmp3enc.h"
-#include "gstmftransform.h"
 
 #if GST_MF_HAVE_D3D11
 #include <gst/d3d11/gstd3d11.h>
+#include <gstmfplatloader.h>
 #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