Commit 7b099e0f authored by Alexander Alekhin's avatar Alexander Alekhin Committed by Alexander Alekhin

videoio: plugins support on Win32

parent 66d7956e
...@@ -52,7 +52,11 @@ ...@@ -52,7 +52,11 @@
#include <cstdio> #include <cstdio>
#if defined(__GNUC__) || defined(__clang__) // at least GCC 3.1+, clang 3.5+ #if defined(__GNUC__) || defined(__clang__) // at least GCC 3.1+, clang 3.5+
# define CV_FORMAT_PRINTF(string_idx, first_to_check) __attribute__ ((format (printf, string_idx, first_to_check))) # if defined(__MINGW_PRINTF_FORMAT) // https://sourceforge.net/p/mingw-w64/wiki2/gnu%20printf/.
# define CV_FORMAT_PRINTF(string_idx, first_to_check) __attribute__ ((format (__MINGW_PRINTF_FORMAT, string_idx, first_to_check)))
# else
# define CV_FORMAT_PRINTF(string_idx, first_to_check) __attribute__ ((format (printf, string_idx, first_to_check)))
# endif
#else #else
# define CV_FORMAT_PRINTF(A, B) # define CV_FORMAT_PRINTF(A, B)
#endif #endif
......
...@@ -872,9 +872,17 @@ Passed subdirectories are used in LIFO order. ...@@ -872,9 +872,17 @@ Passed subdirectories are used in LIFO order.
*/ */
CV_EXPORTS void addDataSearchSubDirectory(const cv::String& subdir); CV_EXPORTS void addDataSearchSubDirectory(const cv::String& subdir);
/** @brief Return location of OpenCV libraries or current executable /** @brief Retrieve location of OpenCV libraries or current executable
*/ */
CV_EXPORTS std::string getBinLocation(); CV_EXPORTS bool getBinLocation(std::string& dst);
#if defined(_WIN32)
/** @brief Retrieve location of OpenCV libraries or current executable
@note WIN32 only
*/
CV_EXPORTS bool getBinLocation(std::wstring& dst);
#endif
//! @} //! @}
......
...@@ -28,6 +28,7 @@ CV_EXPORTS cv::String join(const cv::String& base, const cv::String& path); ...@@ -28,6 +28,7 @@ CV_EXPORTS cv::String join(const cv::String& base, const cv::String& path);
/** Get parent directory */ /** Get parent directory */
CV_EXPORTS cv::String getParent(const cv::String &path); CV_EXPORTS cv::String getParent(const cv::String &path);
CV_EXPORTS std::wstring getParent(const std::wstring& path);
/** /**
* Generate a list of all files that match the globbing pattern. * Generate a list of all files that match the globbing pattern.
......
...@@ -144,11 +144,38 @@ static cv::String getModuleLocation(const void* addr) ...@@ -144,11 +144,38 @@ static cv::String getModuleLocation(const void* addr)
return cv::String(); return cv::String();
} }
std::string getBinLocation() bool getBinLocation(std::string& dst)
{ {
return getModuleLocation((void*)getModuleLocation); // use code addr, doesn't work with static linkage! dst = getModuleLocation((void*)getModuleLocation); // using code address, doesn't work with static linkage!
return !dst.empty();
} }
#ifdef _WIN32
bool getBinLocation(std::wstring& dst)
{
void* addr = (void*)getModuleLocation; // using code address, doesn't work with static linkage!
HMODULE m = 0;
#if _WIN32_WINNT >= 0x0501
::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
reinterpret_cast<LPCTSTR>(addr),
&m);
#endif
if (m)
{
wchar_t path[4096];
const size_t path_size = sizeof(path)/sizeof(*path);
size_t sz = GetModuleFileNameW(m, path, path_size);
if (sz > 0 && sz < path_size)
{
path[sz] = '\0';
dst.assign(path, sz);
return true;
}
}
return false;
}
#endif
cv::String findDataFile(const cv::String& relative_path, cv::String findDataFile(const cv::String& relative_path,
const char* configuration_parameter, const char* configuration_parameter,
const std::vector<String>* search_paths, const std::vector<String>* search_paths,
...@@ -292,8 +319,15 @@ cv::String findDataFile(const cv::String& relative_path, ...@@ -292,8 +319,15 @@ cv::String findDataFile(const cv::String& relative_path,
} }
} }
cv::String module_path = getBinLocation(); cv::String module_path;
CV_LOG_DEBUG(NULL, "Detected module path: '" << module_path << '\''); if (getBinLocation(module_path))
{
CV_LOG_DEBUG(NULL, "Detected module path: '" << module_path << '\'');
}
else
{
CV_LOG_INFO(NULL, "Can't detect module binaries location");
}
if (!has_tested_build_directory && if (!has_tested_build_directory &&
(isSubDirectory(build_dir, module_path) || isSubDirectory(utils::fs::canonical(build_dir), utils::fs::canonical(module_path))) (isSubDirectory(build_dir, module_path) || isSubDirectory(utils::fs::canonical(build_dir), utils::fs::canonical(module_path)))
......
...@@ -91,6 +91,14 @@ CV_EXPORTS cv::String getParent(const cv::String &path) ...@@ -91,6 +91,14 @@ CV_EXPORTS cv::String getParent(const cv::String &path)
return std::string(path, 0, loc); return std::string(path, 0, loc);
} }
CV_EXPORTS std::wstring getParent(const std::wstring& path)
{
std::wstring::size_type loc = path.find_last_of(L"/\\");
if (loc == std::wstring::npos)
return std::wstring();
return std::wstring(path, 0, loc);
}
#if OPENCV_HAVE_FILESYSTEM_SUPPORT #if OPENCV_HAVE_FILESYSTEM_SUPPORT
cv::String canonical(const cv::String& path) cv::String canonical(const cv::String& path)
......
...@@ -131,7 +131,9 @@ if(TARGET ocv.3rdparty.ximea) ...@@ -131,7 +131,9 @@ if(TARGET ocv.3rdparty.ximea)
endif() endif()
if(TARGET ocv.3rdparty.ffmpeg) if(TARGET ocv.3rdparty.ffmpeg)
if("ffmpeg" IN_LIST VIDEOIO_PLUGIN_LIST) if(HAVE_FFMPEG_WRAPPER)
list(APPEND tgts ocv.3rdparty.ffmpeg)
elseif("ffmpeg" IN_LIST VIDEOIO_PLUGIN_LIST)
ocv_create_builtin_videoio_plugin("opencv_videoio_ffmpeg" ocv.3rdparty.ffmpeg "cap_ffmpeg.cpp") ocv_create_builtin_videoio_plugin("opencv_videoio_ffmpeg" ocv.3rdparty.ffmpeg "cap_ffmpeg.cpp")
else() else()
list(APPEND videoio_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/cap_ffmpeg_impl.hpp) list(APPEND videoio_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/cap_ffmpeg_impl.hpp)
...@@ -202,7 +204,7 @@ ocv_target_link_libraries(${the_module} LINK_PRIVATE ${tgts}) ...@@ -202,7 +204,7 @@ ocv_target_link_libraries(${the_module} LINK_PRIVATE ${tgts})
# copy FFmpeg dll to the output folder # copy FFmpeg dll to the output folder
if(WIN32 AND HAVE_FFMPEG_WRAPPER) if(WIN32 AND HAVE_FFMPEG_WRAPPER)
if(MSVC64 OR MINGW64) if(MSVC64 OR MINGW64)
set(FFMPEG_SUFFIX _64) set(FFMPEG_SUFFIX "_64")
endif() endif()
set(ffmpeg_dir "${OpenCV_BINARY_DIR}/3rdparty/ffmpeg") set(ffmpeg_dir "${OpenCV_BINARY_DIR}/3rdparty/ffmpeg")
set(ffmpeg_bare_name "opencv_ffmpeg${FFMPEG_SUFFIX}.dll") set(ffmpeg_bare_name "opencv_ffmpeg${FFMPEG_SUFFIX}.dll")
......
...@@ -54,12 +54,10 @@ endif() ...@@ -54,12 +54,10 @@ endif()
#================================== #==================================
if(HAVE_FFMPEG) if(HAVE_FFMPEG_WRAPPER)
set(defs "HAVE_FFMPEG") ocv_add_external_target(ffmpeg "" "" "HAVE_FFMPEG_WRAPPER")
if(HAVE_FFMPEG_WRAPPER) elseif(HAVE_FFMPEG)
list(APPEND defs "HAVE_FFMPEG_WRAPPER") ocv_add_external_target(ffmpeg "${FFMPEG_INCLUDE_DIRS}" "${FFMPEG_LIBRARIES}" "HAVE_FFMPEG")
endif()
ocv_add_external_target(ffmpeg "${FFMPEG_INCLUDE_DIRS}" "${FFMPEG_LIBRARIES}" "${defs}")
endif() endif()
set(HAVE_FFMPEG ${HAVE_FFMPEG} PARENT_SCOPE) set(HAVE_FFMPEG ${HAVE_FFMPEG} PARENT_SCOPE)
...@@ -25,9 +25,22 @@ function(ocv_create_builtin_videoio_plugin name target) ...@@ -25,9 +25,22 @@ function(ocv_create_builtin_videoio_plugin name target)
ocv_target_include_directories(${name} PRIVATE "${OPENCV_MODULE_${mod}_LOCATION}/include") ocv_target_include_directories(${name} PRIVATE "${OPENCV_MODULE_${mod}_LOCATION}/include")
endforeach() endforeach()
if(WIN32)
set(OPENCV_PLUGIN_VERSION "${OPENCV_DLLVERSION}" CACHE STRING "")
if(CMAKE_CXX_SIZEOF_DATA_PTR EQUAL 8)
set(OPENCV_PLUGIN_ARCH "_64" CACHE STRING "")
else()
set(OPENCV_PLUGIN_ARCH "" CACHE STRING "")
endif()
else()
set(OPENCV_PLUGIN_VERSION "" CACHE STRING "")
set(OPENCV_PLUGIN_ARCH "" CACHE STRING "")
endif()
set_target_properties(${name} PROPERTIES set_target_properties(${name} PROPERTIES
CXX_STANDARD 11 CXX_STANDARD 11
CXX_VISIBILITY_PRESET hidden CXX_VISIBILITY_PRESET hidden
OUTPUT_NAME "${name}${OPENCV_PLUGIN_VERSION}${OPENCV_PLUGIN_ARCH}"
) )
if(WIN32) if(WIN32)
......
...@@ -28,7 +28,7 @@ function(ocv_create_videoio_plugin default_name target target_desc videoio_src_f ...@@ -28,7 +28,7 @@ function(ocv_create_videoio_plugin default_name target target_desc videoio_src_f
message(FATAL_ERROR "${target_desc} was not found!") message(FATAL_ERROR "${target_desc} was not found!")
endif() endif()
set(modules_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../..") get_filename_component(modules_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../.." ABSOLUTE)
set(videoio_ROOT "${modules_ROOT}/videoio") set(videoio_ROOT "${modules_ROOT}/videoio")
set(core_ROOT "${modules_ROOT}/core") set(core_ROOT "${modules_ROOT}/core")
set(imgproc_ROOT "${modules_ROOT}/imgproc") set(imgproc_ROOT "${modules_ROOT}/imgproc")
...@@ -45,22 +45,20 @@ function(ocv_create_videoio_plugin default_name target target_desc videoio_src_f ...@@ -45,22 +45,20 @@ function(ocv_create_videoio_plugin default_name target target_desc videoio_src_f
) )
target_compile_definitions(${OPENCV_PLUGIN_NAME} PRIVATE BUILD_PLUGIN) target_compile_definitions(${OPENCV_PLUGIN_NAME} PRIVATE BUILD_PLUGIN)
# Fixes for build
target_compile_definitions(${OPENCV_PLUGIN_NAME} PRIVATE __OPENCV_BUILD)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cvconfig.h" "#pragma once")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cv_cpu_config.h" "#pragma once")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/opencv2/opencv_modules.hpp" "#pragma once")
target_link_libraries(${OPENCV_PLUGIN_NAME} PRIVATE ${target}) target_link_libraries(${OPENCV_PLUGIN_NAME} PRIVATE ${target})
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES
CXX_STANDARD 11 CXX_STANDARD 11
CXX_VISIBILITY_PRESET hidden CXX_VISIBILITY_PRESET hidden
) )
if(DEFINED OPENCV_PLUGIN_MODULE_PREFIX)
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES PREFIX "${OPENCV_PLUGIN_MODULE_PREFIX}")
endif()
# Hack for Windows # Hack for Windows
if(WIN32) if(WIN32)
find_package(OpenCV REQUIRED core imgproc videoio) find_package(OpenCV REQUIRED core imgproc videoio)
target_link_libraries(${OPENCV_PLUGIN_NAME} ${OpenCV_LIBS}) target_link_libraries(${OPENCV_PLUGIN_NAME} PRIVATE ${OpenCV_LIBS})
endif() endif()
if(OPENCV_PLUGIN_DESTINATION) if(OPENCV_PLUGIN_DESTINATION)
...@@ -68,6 +66,8 @@ function(ocv_create_videoio_plugin default_name target target_desc videoio_src_f ...@@ -68,6 +66,8 @@ function(ocv_create_videoio_plugin default_name target target_desc videoio_src_f
message(STATUS "Output destination: ${OPENCV_PLUGIN_DESTINATION}") message(STATUS "Output destination: ${OPENCV_PLUGIN_DESTINATION}")
endif() endif()
install(TARGETS ${OPENCV_PLUGIN_NAME} LIBRARY DESTINATION . COMPONENT plugins)
message(STATUS "Library name: ${OPENCV_PLUGIN_NAME}") message(STATUS "Library name: ${OPENCV_PLUGIN_NAME}")
endfunction() endfunction()
...@@ -29,10 +29,43 @@ namespace cv { namespace impl { ...@@ -29,10 +29,43 @@ namespace cv { namespace impl {
#if defined(_WIN32) #if defined(_WIN32)
typedef HMODULE LibHandle_t; typedef HMODULE LibHandle_t;
#elif defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) typedef wchar_t FileSystemChar_t;
typedef std::wstring FileSystemPath_t;
static
FileSystemPath_t toFileSystemPath(const std::string& p)
{
FileSystemPath_t result;
result.resize(p.size());
for (size_t i = 0; i < p.size(); i++)
result[i] = (wchar_t)p[i];
return result;
}
static
std::string toPrintablePath(const FileSystemPath_t& p)
{
std::string result;
result.resize(p.size());
for (size_t i = 0; i < p.size(); i++)
{
wchar_t ch = p[i];
if ((int)ch >= ' ' && (int)ch < 128)
result[i] = (char)ch;
else
result[i] = '?';
}
return result;
}
#else // !_WIN32
typedef void* LibHandle_t; typedef void* LibHandle_t;
typedef char FileSystemChar_t;
typedef std::string FileSystemPath_t;
static inline FileSystemPath_t toFileSystemPath(const std::string& p) { return p; }
static inline std::string toPrintablePath(const FileSystemPath_t& p) { return p; }
#endif #endif
static Mutex& getInitializationMutex() static Mutex& getInitializationMutex()
{ {
static Mutex initializationMutex; static Mutex initializationMutex;
...@@ -50,12 +83,16 @@ void* getSymbol_(LibHandle_t h, const char* symbolName) ...@@ -50,12 +83,16 @@ void* getSymbol_(LibHandle_t h, const char* symbolName)
} }
static inline static inline
LibHandle_t libraryLoad_(const char* filename) LibHandle_t libraryLoad_(const FileSystemPath_t& filename)
{ {
#if defined(_WIN32) #if defined(_WIN32)
return LoadLibraryA(filename); # ifdef WINRT
return LoadPackagedLibrary(filename.c_str(), 0);
# else
return LoadLibraryW(filename.c_str());
#endif
#elif defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) #elif defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
return dlopen(filename, RTLD_LAZY); return dlopen(filename.c_str(), RTLD_LAZY);
#endif #endif
} }
...@@ -73,7 +110,7 @@ static inline ...@@ -73,7 +110,7 @@ static inline
std::string libraryPrefix() std::string libraryPrefix()
{ {
#if defined(_WIN32) #if defined(_WIN32)
return string(); return "";
#else #else
return "lib"; return "lib";
#endif #endif
...@@ -82,9 +119,13 @@ static inline ...@@ -82,9 +119,13 @@ static inline
std::string librarySuffix() std::string librarySuffix()
{ {
#if defined(_WIN32) #if defined(_WIN32)
return ".dll"; const char* suffix = ""
#elif defined(__APPLE__) CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION)
return ".dylib"; #if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__)
"_64"
#endif
".dll";
return suffix;
#else #else
return ".so"; return ".so";
#endif #endif
...@@ -96,10 +137,10 @@ class DynamicLib ...@@ -96,10 +137,10 @@ class DynamicLib
{ {
private: private:
LibHandle_t handle; LibHandle_t handle;
const std::string fname; const FileSystemPath_t fname;
public: public:
DynamicLib(const std::string &filename) DynamicLib(const FileSystemPath_t& filename)
: handle(0), fname(filename) : handle(0), fname(filename)
{ {
libraryLoad(filename); libraryLoad(filename);
...@@ -120,21 +161,21 @@ public: ...@@ -120,21 +161,21 @@ public:
} }
void * res = getSymbol_(handle, symbolName); void * res = getSymbol_(handle, symbolName);
if (!res) if (!res)
CV_LOG_ERROR(NULL, "No symbol '" << symbolName << "' in " << fname); CV_LOG_ERROR(NULL, "No symbol '" << symbolName << "' in " << toPrintablePath(fname));
return res; return res;
} }
const std::string& getName() const { return fname; } const std::string getName() const { return toPrintablePath(fname); }
private: private:
void libraryLoad(const std::string &filename) void libraryLoad(const FileSystemPath_t& filename)
{ {
handle = libraryLoad_(filename.c_str()); handle = libraryLoad_(filename);
CV_LOG_INFO(NULL, "load " << filename << " => " << (handle ? "OK" : "FAILED")); CV_LOG_INFO(NULL, "load " << toPrintablePath(filename) << " => " << (handle ? "OK" : "FAILED"));
} }
void libraryRelease() void libraryRelease()
{ {
CV_LOG_INFO(NULL, "unload "<< fname);
if (handle) if (handle)
{ {
CV_LOG_INFO(NULL, "unload "<< toPrintablePath(fname));
libraryRelease_(handle); libraryRelease_(handle);
handle = 0; handle = 0;
} }
...@@ -230,39 +271,79 @@ protected: ...@@ -230,39 +271,79 @@ protected:
}; };
static static
std::vector<string> getPluginCandidates(const std::string& baseName) std::vector<FileSystemPath_t> getPluginCandidates(const std::string& baseName)
{ {
using namespace cv::utils; using namespace cv::utils;
using namespace cv::utils::fs; using namespace cv::utils::fs;
const string baseName_l = toLowerCase(baseName);
const string baseName_u = toUpperCase(baseName);
const FileSystemPath_t baseName_l_fs = toFileSystemPath(baseName_l);
vector<FileSystemPath_t> paths;
const vector<string> paths_ = getConfigurationParameterPaths("OPENCV_VIDEOIO_PLUGIN_PATH", vector<string>());
if (paths_.size() != 0)
{
for (size_t i = 0; i < paths_.size(); i++)
{
paths.push_back(toFileSystemPath(paths_[i]));
}
}
else
{
FileSystemPath_t binaryLocation;
if (getBinLocation(binaryLocation))
{
binaryLocation = getParent(binaryLocation);
#ifndef CV_VIDEOIO_PLUGIN_SUBDIRECTORY #ifndef CV_VIDEOIO_PLUGIN_SUBDIRECTORY
#define CV_VIDEOIO_PLUGIN_SUBDIRECTORY_STR "" paths.push_back(binaryLocation);
#else #else
#define CV_VIDEOIO_PLUGIN_SUBDIRECTORY_STR CVAUX_STR(CV_VIDEOIO_PLUGIN_SUBDIRECTORY) paths.push_back(binaryLocation + toFileSystemPath("/") + toFileSystemPath(CV_VIDEOIO_PLUGIN_SUBDIRECTORY_STR));
#endif #endif
const vector<string> default_paths = { utils::fs::join(getParent(getBinLocation()), CV_VIDEOIO_PLUGIN_SUBDIRECTORY_STR) }; }
const vector<string> paths = getConfigurationParameterPaths("OPENCV_VIDEOIO_PLUGIN_PATH", default_paths); }
const string baseName_l = toLowerCase(baseName);
const string baseName_u = toUpperCase(baseName);
const string default_expr = libraryPrefix() + "opencv_videoio_" + baseName_l + "*" + librarySuffix(); const string default_expr = libraryPrefix() + "opencv_videoio_" + baseName_l + "*" + librarySuffix();
const string expr = getConfigurationParameterString((std::string("OPENCV_VIDEOIO_PLUGIN_") + baseName_u).c_str(), default_expr.c_str()); const string plugin_expr = getConfigurationParameterString((std::string("OPENCV_VIDEOIO_PLUGIN_") + baseName_u).c_str(), default_expr.c_str());
CV_LOG_INFO(NULL, "VideoIO pluigin (" << baseName << "): glob is '" << expr << "', " << paths.size() << " location(s)"); vector<FileSystemPath_t> results;
vector<string> results; #ifdef _WIN32
for(const string & path : paths) FileSystemPath_t moduleName = toFileSystemPath(libraryPrefix() + "opencv_videoio_" + baseName_l + librarySuffix());
#ifndef WINRT
if (baseName_u == "FFMPEG") // backward compatibility
{
const wchar_t* ffmpeg_env_path = _wgetenv(L"OPENCV_FFMPEG_DLL_DIR");
if (ffmpeg_env_path)
{
results.push_back(FileSystemPath_t(ffmpeg_env_path) + L"\\" + moduleName);
}
}
#endif
if (plugin_expr != default_expr)
{
moduleName = toFileSystemPath(plugin_expr);
results.push_back(moduleName);
}
for (const FileSystemPath_t& path : paths)
{
results.push_back(path + L"\\" + moduleName);
}
results.push_back(moduleName);
#else
CV_LOG_INFO(NULL, "VideoIO pluigin (" << baseName << "): glob is '" << plugin_expr << "', " << paths.size() << " location(s)");
for (const string & path : paths)
{ {
if (path.empty()) if (path.empty())
continue; continue;
vector<string> candidates; vector<string> candidates;
cv::glob(utils::fs::join(path, expr), candidates); cv::glob(utils::fs::join(path, plugin_expr), candidates);
CV_LOG_INFO(NULL, " - " << path << ": " << candidates.size()); CV_LOG_INFO(NULL, " - " << path << ": " << candidates.size());
copy(candidates.begin(), candidates.end(), back_inserter(results)); copy(candidates.begin(), candidates.end(), back_inserter(results));
} }
#endif
CV_LOG_INFO(NULL, "Found " << results.size() << " plugin(s) for " << baseName); CV_LOG_INFO(NULL, "Found " << results.size() << " plugin(s) for " << baseName);
return results; return results;
} }
void PluginBackendFactory::loadPlugin() void PluginBackendFactory::loadPlugin()
{ {
for(const std::string & plugin : getPluginCandidates(baseName_)) for (const FileSystemPath_t& plugin : getPluginCandidates(baseName_))
{ {
Ptr<DynamicLib> lib = makePtr<DynamicLib>(plugin); Ptr<DynamicLib> lib = makePtr<DynamicLib>(plugin);
if (!lib->isLoaded()) if (!lib->isLoaded())
...@@ -287,7 +368,7 @@ void PluginBackendFactory::loadPlugin() ...@@ -287,7 +368,7 @@ void PluginBackendFactory::loadPlugin()
} }
catch (...) catch (...)
{ {
CV_LOG_INFO(NULL, "Video I/O: exception during plugin initialization: " << plugin << ". SKIP"); CV_LOG_WARNING(NULL, "Video I/O: exception during plugin initialization: " << toPrintablePath(plugin) << ". SKIP");
} }
} }
} }
......
...@@ -41,11 +41,12 @@ ...@@ -41,11 +41,12 @@
#include "precomp.hpp" #include "precomp.hpp"
#if defined(HAVE_FFMPEG) #if !defined(HAVE_FFMPEG)
#error "Build configuration error"
#endif
#include <string> #include <string>
#if !defined(HAVE_FFMPEG_WRAPPER)
#include "cap_ffmpeg_impl.hpp" #include "cap_ffmpeg_impl.hpp"
#define icvCreateFileCapture_FFMPEG_p cvCreateFileCapture_FFMPEG #define icvCreateFileCapture_FFMPEG_p cvCreateFileCapture_FFMPEG
...@@ -58,152 +59,6 @@ ...@@ -58,152 +59,6 @@
#define icvReleaseVideoWriter_FFMPEG_p cvReleaseVideoWriter_FFMPEG #define icvReleaseVideoWriter_FFMPEG_p cvReleaseVideoWriter_FFMPEG
#define icvWriteFrame_FFMPEG_p cvWriteFrame_FFMPEG #define icvWriteFrame_FFMPEG_p cvWriteFrame_FFMPEG
#else
#include "cap_ffmpeg_api.hpp"
namespace cv { namespace {
static CvCreateFileCapture_Plugin icvCreateFileCapture_FFMPEG_p = 0;
static CvReleaseCapture_Plugin icvReleaseCapture_FFMPEG_p = 0;
static CvGrabFrame_Plugin icvGrabFrame_FFMPEG_p = 0;
static CvRetrieveFrame_Plugin icvRetrieveFrame_FFMPEG_p = 0;
static CvSetCaptureProperty_Plugin icvSetCaptureProperty_FFMPEG_p = 0;
static CvGetCaptureProperty_Plugin icvGetCaptureProperty_FFMPEG_p = 0;
static CvCreateVideoWriter_Plugin icvCreateVideoWriter_FFMPEG_p = 0;
static CvReleaseVideoWriter_Plugin icvReleaseVideoWriter_FFMPEG_p = 0;
static CvWriteFrame_Plugin icvWriteFrame_FFMPEG_p = 0;
static cv::Mutex _icvInitFFMPEG_mutex;
#if defined _WIN32
static const HMODULE cv_GetCurrentModule()
{
HMODULE h = 0;
#if _WIN32_WINNT >= 0x0501
::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
reinterpret_cast<LPCTSTR>(cv_GetCurrentModule),
&h);
#endif
return h;
}
#endif
class icvInitFFMPEG
{
public:
static void Init()
{
cv::AutoLock al(_icvInitFFMPEG_mutex);
static icvInitFFMPEG init;
}
private:
#if defined _WIN32
HMODULE icvFFOpenCV;
~icvInitFFMPEG()
{
if (icvFFOpenCV)
{
FreeLibrary(icvFFOpenCV);
icvFFOpenCV = 0;
}
}
#endif
icvInitFFMPEG()
{
#if defined _WIN32
const wchar_t* module_name_ = L"opencv_ffmpeg"
CVAUX_STRW(CV_MAJOR_VERSION) CVAUX_STRW(CV_MINOR_VERSION) CVAUX_STRW(CV_SUBMINOR_VERSION)
#if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__)
L"_64"
#endif
L".dll";
# ifdef WINRT
icvFFOpenCV = LoadPackagedLibrary( module_name_, 0 );
# else
const std::wstring module_name(module_name_);
const wchar_t* ffmpeg_env_path = _wgetenv(L"OPENCV_FFMPEG_DLL_DIR");
std::wstring module_path =
ffmpeg_env_path
? ((std::wstring(ffmpeg_env_path) + L"\\") + module_name)
: module_name;
icvFFOpenCV = LoadLibraryW(module_path.c_str());
if(!icvFFOpenCV && !ffmpeg_env_path)
{
HMODULE m = cv_GetCurrentModule();
if (m)
{
wchar_t path[MAX_PATH];
const size_t path_size = sizeof(path)/sizeof(*path);
size_t sz = GetModuleFileNameW(m, path, path_size);
/* Don't handle paths longer than MAX_PATH until that becomes a real issue */
if (sz > 0 && sz < path_size)
{
wchar_t* s = wcsrchr(path, L'\\');
if (s)
{
s[0] = 0;
module_path = (std::wstring(path) + L"\\") + module_name;
icvFFOpenCV = LoadLibraryW(module_path.c_str());
}
}
}
}
# endif
if( icvFFOpenCV )
{
icvCreateFileCapture_FFMPEG_p =
(CvCreateFileCapture_Plugin)GetProcAddress(icvFFOpenCV, "cvCreateFileCapture_FFMPEG");
icvReleaseCapture_FFMPEG_p =
(CvReleaseCapture_Plugin)GetProcAddress(icvFFOpenCV, "cvReleaseCapture_FFMPEG");
icvGrabFrame_FFMPEG_p =
(CvGrabFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvGrabFrame_FFMPEG");
icvRetrieveFrame_FFMPEG_p =
(CvRetrieveFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvRetrieveFrame_FFMPEG");
icvSetCaptureProperty_FFMPEG_p =
(CvSetCaptureProperty_Plugin)GetProcAddress(icvFFOpenCV, "cvSetCaptureProperty_FFMPEG");
icvGetCaptureProperty_FFMPEG_p =
(CvGetCaptureProperty_Plugin)GetProcAddress(icvFFOpenCV, "cvGetCaptureProperty_FFMPEG");
icvCreateVideoWriter_FFMPEG_p =
(CvCreateVideoWriter_Plugin)GetProcAddress(icvFFOpenCV, "cvCreateVideoWriter_FFMPEG");
icvReleaseVideoWriter_FFMPEG_p =
(CvReleaseVideoWriter_Plugin)GetProcAddress(icvFFOpenCV, "cvReleaseVideoWriter_FFMPEG");
icvWriteFrame_FFMPEG_p =
(CvWriteFrame_Plugin)GetProcAddress(icvFFOpenCV, "cvWriteFrame_FFMPEG");
# endif // _WIN32
#if 0
if( icvCreateFileCapture_FFMPEG_p != 0 &&
icvReleaseCapture_FFMPEG_p != 0 &&
icvGrabFrame_FFMPEG_p != 0 &&
icvRetrieveFrame_FFMPEG_p != 0 &&
icvSetCaptureProperty_FFMPEG_p != 0 &&
icvGetCaptureProperty_FFMPEG_p != 0 &&
icvCreateVideoWriter_FFMPEG_p != 0 &&
icvReleaseVideoWriter_FFMPEG_p != 0 &&
icvWriteFrame_FFMPEG_p != 0 )
{
printf("Successfully initialized ffmpeg plugin!\n");
}
else
{
printf("Failed to load FFMPEG plugin: module handle=%p\n", icvFFOpenCV);
}
#endif
}
}
};
}} // namespace
#endif // HAVE_FFMPEG_WRAPPER
namespace cv { namespace cv {
namespace { namespace {
...@@ -247,11 +102,7 @@ public: ...@@ -247,11 +102,7 @@ public:
} }
virtual void close() virtual void close()
{ {
if (ffmpegCapture if (ffmpegCapture)
#if defined(HAVE_FFMPEG_WRAPPER)
&& icvReleaseCapture_FFMPEG_p
#endif
)
icvReleaseCapture_FFMPEG_p( &ffmpegCapture ); icvReleaseCapture_FFMPEG_p( &ffmpegCapture );
CV_Assert(ffmpegCapture == 0); CV_Assert(ffmpegCapture == 0);
ffmpegCapture = 0; ffmpegCapture = 0;
...@@ -268,11 +119,6 @@ protected: ...@@ -268,11 +119,6 @@ protected:
cv::Ptr<cv::IVideoCapture> cvCreateFileCapture_FFMPEG_proxy(const std::string &filename) cv::Ptr<cv::IVideoCapture> cvCreateFileCapture_FFMPEG_proxy(const std::string &filename)
{ {
#if defined(HAVE_FFMPEG_WRAPPER)
icvInitFFMPEG::Init();
if (!icvCreateFileCapture_FFMPEG_p)
return cv::Ptr<cv::IVideoCapture>();
#endif
cv::Ptr<CvCapture_FFMPEG_proxy> capture = cv::makePtr<CvCapture_FFMPEG_proxy>(filename); cv::Ptr<CvCapture_FFMPEG_proxy> capture = cv::makePtr<CvCapture_FFMPEG_proxy>(filename);
if (capture && capture->isOpened()) if (capture && capture->isOpened())
return capture; return capture;
...@@ -308,11 +154,7 @@ public: ...@@ -308,11 +154,7 @@ public:
virtual void close() virtual void close()
{ {
if (ffmpegWriter if (ffmpegWriter)
#if defined(HAVE_FFMPEG_WRAPPER)
&& icvReleaseVideoWriter_FFMPEG_p
#endif
)
icvReleaseVideoWriter_FFMPEG_p( &ffmpegWriter ); icvReleaseVideoWriter_FFMPEG_p( &ffmpegWriter );
CV_Assert(ffmpegWriter == 0); CV_Assert(ffmpegWriter == 0);
ffmpegWriter = 0; ffmpegWriter = 0;
...@@ -330,11 +172,6 @@ protected: ...@@ -330,11 +172,6 @@ protected:
cv::Ptr<cv::IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const std::string& filename, int fourcc, double fps, const cv::Size &frameSize, bool isColor) cv::Ptr<cv::IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const std::string& filename, int fourcc, double fps, const cv::Size &frameSize, bool isColor)
{ {
#if defined(HAVE_FFMPEG_WRAPPER)
icvInitFFMPEG::Init();
if (!icvCreateVideoWriter_FFMPEG_p)
return cv::Ptr<cv::IVideoWriter>();
#endif
cv::Ptr<CvVideoWriter_FFMPEG_proxy> writer = cv::makePtr<CvVideoWriter_FFMPEG_proxy>(filename, fourcc, fps, frameSize, isColor != 0); cv::Ptr<CvVideoWriter_FFMPEG_proxy> writer = cv::makePtr<CvVideoWriter_FFMPEG_proxy>(filename, fourcc, fps, frameSize, isColor != 0);
if (writer && writer->isOpened()) if (writer && writer->isOpened())
return writer; return writer;
...@@ -343,7 +180,7 @@ cv::Ptr<cv::IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const std::string& fi ...@@ -343,7 +180,7 @@ cv::Ptr<cv::IVideoWriter> cvCreateVideoWriter_FFMPEG_proxy(const std::string& fi
} // namespace } // namespace
#endif // defined(HAVE_FFMPEG)
//================================================================================================== //==================================================================================================
......
This diff is collapsed.
#ifndef __OPENCV_FFMPEG_H__ // This file is part of OpenCV project.
#define __OPENCV_FFMPEG_H__ // It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef __OPENCV_FFMPEG_LEGACY_API_H__
#define __OPENCV_FFMPEG_LEGACY_API_H__
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
...@@ -7,7 +10,7 @@ extern "C" ...@@ -7,7 +10,7 @@ extern "C"
#endif #endif
#ifndef OPENCV_FFMPEG_API #ifndef OPENCV_FFMPEG_API
#if defined(__OPENCV_BUILD) || defined(BUILD_PLUGIN) #if defined(__OPENCV_BUILD)
# define OPENCV_FFMPEG_API # define OPENCV_FFMPEG_API
#elif defined _WIN32 #elif defined _WIN32
# define OPENCV_FFMPEG_API __declspec(dllexport) # define OPENCV_FFMPEG_API __declspec(dllexport)
...@@ -18,20 +21,6 @@ extern "C" ...@@ -18,20 +21,6 @@ extern "C"
#endif #endif
#endif #endif
enum
{
CV_FFMPEG_CAP_PROP_POS_MSEC=0,
CV_FFMPEG_CAP_PROP_POS_FRAMES=1,
CV_FFMPEG_CAP_PROP_POS_AVI_RATIO=2,
CV_FFMPEG_CAP_PROP_FRAME_WIDTH=3,
CV_FFMPEG_CAP_PROP_FRAME_HEIGHT=4,
CV_FFMPEG_CAP_PROP_FPS=5,
CV_FFMPEG_CAP_PROP_FOURCC=6,
CV_FFMPEG_CAP_PROP_FRAME_COUNT=7,
CV_FFMPEG_CAP_PROP_SAR_NUM=40,
CV_FFMPEG_CAP_PROP_SAR_DEN=41
};
typedef struct CvCapture_FFMPEG CvCapture_FFMPEG; typedef struct CvCapture_FFMPEG CvCapture_FFMPEG;
typedef struct CvVideoWriter_FFMPEG CvVideoWriter_FFMPEG; typedef struct CvVideoWriter_FFMPEG CvVideoWriter_FFMPEG;
...@@ -50,46 +39,8 @@ OPENCV_FFMPEG_API int cvWriteFrame_FFMPEG(struct CvVideoWriter_FFMPEG* writer, c ...@@ -50,46 +39,8 @@ OPENCV_FFMPEG_API int cvWriteFrame_FFMPEG(struct CvVideoWriter_FFMPEG* writer, c
int step, int width, int height, int cn, int origin); int step, int width, int height, int cn, int origin);
OPENCV_FFMPEG_API void cvReleaseVideoWriter_FFMPEG(struct CvVideoWriter_FFMPEG** writer); OPENCV_FFMPEG_API void cvReleaseVideoWriter_FFMPEG(struct CvVideoWriter_FFMPEG** writer);
typedef CvCapture_FFMPEG* (*CvCreateFileCapture_Plugin)( const char* filename );
typedef CvCapture_FFMPEG* (*CvCreateCameraCapture_Plugin)( int index );
typedef int (*CvGrabFrame_Plugin)( CvCapture_FFMPEG* capture_handle );
typedef int (*CvRetrieveFrame_Plugin)( CvCapture_FFMPEG* capture_handle, unsigned char** data, int* step,
int* width, int* height, int* cn );
typedef int (*CvSetCaptureProperty_Plugin)( CvCapture_FFMPEG* capture_handle, int prop_id, double value );
typedef double (*CvGetCaptureProperty_Plugin)( CvCapture_FFMPEG* capture_handle, int prop_id );
typedef void (*CvReleaseCapture_Plugin)( CvCapture_FFMPEG** capture_handle );
typedef CvVideoWriter_FFMPEG* (*CvCreateVideoWriter_Plugin)( const char* filename, int fourcc,
double fps, int width, int height, int iscolor );
typedef int (*CvWriteFrame_Plugin)( CvVideoWriter_FFMPEG* writer_handle, const unsigned char* data, int step,
int width, int height, int cn, int origin);
typedef void (*CvReleaseVideoWriter_Plugin)( CvVideoWriter_FFMPEG** writer );
/*
* For CUDA encoder
*/
OPENCV_FFMPEG_API struct OutputMediaStream_FFMPEG* create_OutputMediaStream_FFMPEG(const char* fileName, int width, int height, double fps);
OPENCV_FFMPEG_API void release_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream);
OPENCV_FFMPEG_API void write_OutputMediaStream_FFMPEG(struct OutputMediaStream_FFMPEG* stream, unsigned char* data, int size, int keyFrame);
typedef struct OutputMediaStream_FFMPEG* (*Create_OutputMediaStream_FFMPEG_Plugin)(const char* fileName, int width, int height, double fps);
typedef void (*Release_OutputMediaStream_FFMPEG_Plugin)(struct OutputMediaStream_FFMPEG* stream);
typedef void (*Write_OutputMediaStream_FFMPEG_Plugin)(struct OutputMediaStream_FFMPEG* stream, unsigned char* data, int size, int keyFrame);
/*
* For CUDA decoder
*/
OPENCV_FFMPEG_API struct InputMediaStream_FFMPEG* create_InputMediaStream_FFMPEG(const char* fileName, int* codec, int* chroma_format, int* width, int* height);
OPENCV_FFMPEG_API void release_InputMediaStream_FFMPEG(struct InputMediaStream_FFMPEG* stream);
OPENCV_FFMPEG_API int read_InputMediaStream_FFMPEG(struct InputMediaStream_FFMPEG* stream, unsigned char** data, int* size, int* endOfFile);
typedef struct InputMediaStream_FFMPEG* (*Create_InputMediaStream_FFMPEG_Plugin)(const char* fileName, int* codec, int* chroma_format, int* width, int* height);
typedef void (*Release_InputMediaStream_FFMPEG_Plugin)(struct InputMediaStream_FFMPEG* stream);
typedef int (*Read_InputMediaStream_FFMPEG_Plugin)(struct InputMediaStream_FFMPEG* stream, unsigned char** data, int* size, int* endOfFile);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif // __OPENCV_FFMPEG_LEGACY_API_H__
...@@ -46,7 +46,9 @@ ...@@ -46,7 +46,9 @@
#include "opencv2/videoio/legacy/constants_c.h" #include "opencv2/videoio/legacy/constants_c.h"
#include "opencv2/core/utility.hpp" #include "opencv2/core/utility.hpp"
#ifdef __OPENCV_BUILD
#include "opencv2/core/private.hpp" #include "opencv2/core/private.hpp"
#endif
#include <opencv2/core/utils/configuration.private.hpp> #include <opencv2/core/utils/configuration.private.hpp>
#include <opencv2/core/utils/logger.hpp> #include <opencv2/core/utils/logger.hpp>
......
...@@ -58,7 +58,7 @@ static const struct VideoBackendInfo builtin_backends[] = ...@@ -58,7 +58,7 @@ static const struct VideoBackendInfo builtin_backends[] =
{ {
#ifdef HAVE_FFMPEG #ifdef HAVE_FFMPEG
DECLARE_STATIC_BACKEND(CAP_FFMPEG, "FFMPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER, cvCreateFileCapture_FFMPEG_proxy, 0, cvCreateVideoWriter_FFMPEG_proxy), DECLARE_STATIC_BACKEND(CAP_FFMPEG, "FFMPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER, cvCreateFileCapture_FFMPEG_proxy, 0, cvCreateVideoWriter_FFMPEG_proxy),
#elif defined(ENABLE_PLUGINS) #elif defined(ENABLE_PLUGINS) || defined(HAVE_FFMPEG_WRAPPER)
DECLARE_DYNAMIC_BACKEND(CAP_FFMPEG, "FFMPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER), DECLARE_DYNAMIC_BACKEND(CAP_FFMPEG, "FFMPEG", MODE_CAPTURE_BY_FILENAME | MODE_WRITER),
#endif #endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment