videoio(MSMF): avoid OpenCV load failure on Win7 machines
authorAlexander Alekhin <alexander.a.alekhin@gmail.com>
Fri, 29 Jun 2018 19:54:58 +0000 (22:54 +0300)
committerAlexander Alekhin <alexander.a.alekhin@gmail.com>
Fri, 29 Jun 2018 20:22:26 +0000 (20:22 +0000)
OpenCV binaries are compiled on Win10 environment

modules/videoio/src/cap_msmf.cpp

index 8e1a60a..338cf58 100644 (file)
 #pragma comment(lib, "Mfreadwrite")
 #ifdef HAVE_DXVA
 #pragma comment(lib, "d3d11")
+// MFCreateDXGIDeviceManager() is available since Win8 only.
+// To avoid OpenCV loading failure on Win7 use dynamic detection of this symbol.
+// Details: https://github.com/opencv/opencv/issues/11858
+typedef HRESULT (*FN_MFCreateDXGIDeviceManager)(UINT *resetToken, IMFDXGIDeviceManager **ppDeviceManager);
+static bool pMFCreateDXGIDeviceManager_initialized = false;
+static FN_MFCreateDXGIDeviceManager pMFCreateDXGIDeviceManager = NULL;
+static void init_MFCreateDXGIDeviceManager()
+{
+    HMODULE h = LoadLibraryA("mfplat.dll");
+    if (h)
+    {
+        pMFCreateDXGIDeviceManager = (FN_MFCreateDXGIDeviceManager)GetProcAddress(h, "MFCreateDXGIDeviceManager");
+    }
+    pMFCreateDXGIDeviceManager_initialized = true;
+}
 #endif
 #if (WINVER >= 0x0602) // Available since Win 8
 #pragma comment(lib, "MinCore_Downlevel")
@@ -768,6 +783,10 @@ bool CvCapture_MSMF::configureHW(bool enable)
 #ifdef HAVE_DXVA
     if ((enable && D3DMgr && D3DDev) || (!enable && !D3DMgr && !D3DDev))
         return true;
+    if (!pMFCreateDXGIDeviceManager_initialized)
+        init_MFCreateDXGIDeviceManager();
+    if (enable && !pMFCreateDXGIDeviceManager)
+        return false;
 
     bool reopen = isOpen;
     int prevcam = camid;
@@ -788,7 +807,7 @@ bool CvCapture_MSMF::configureHW(bool enable)
             {
                 D3DDevMT->SetMultithreadProtected(TRUE);
                 D3DDevMT.Release();
-                if (SUCCEEDED(MFCreateDXGIDeviceManager(&mgrRToken, &D3DMgr)))
+                if (SUCCEEDED(pMFCreateDXGIDeviceManager(&mgrRToken, &D3DMgr)))
                 {
                     if (SUCCEEDED(D3DMgr->ResetDevice(D3DDev.Get(), mgrRToken)))
                     {