From 7a2448672c9f2ccfd8d00f798cac5219dbcf271c Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 29 Jun 2018 22:54:58 +0300 Subject: [PATCH] videoio(MSMF): avoid OpenCV load failure on Win7 machines OpenCV binaries are compiled on Win10 environment --- modules/videoio/src/cap_msmf.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/modules/videoio/src/cap_msmf.cpp b/modules/videoio/src/cap_msmf.cpp index 8e1a60a00b..338cf587c9 100644 --- a/modules/videoio/src/cap_msmf.cpp +++ b/modules/videoio/src/cap_msmf.cpp @@ -83,6 +83,21 @@ #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))) {