mirror of
https://github.com/opencv/opencv.git
synced 2024-11-24 03:00:14 +08:00
core(parallel): plugins support
This commit is contained in:
parent
e5d78960c6
commit
cc73c36e32
@ -304,7 +304,9 @@ if(MSVC)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(cmake/OpenCVCompilerOptimizations.cmake)
|
if(PROJECT_NAME STREQUAL "OpenCV")
|
||||||
|
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVCompilerOptimizations.cmake")
|
||||||
|
endif()
|
||||||
if(COMMAND ocv_compiler_optimization_options)
|
if(COMMAND ocv_compiler_optimization_options)
|
||||||
ocv_compiler_optimization_options()
|
ocv_compiler_optimization_options()
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Search TBB library (4.1 - 4.4, 2017)
|
# Search TBB library: 4.1 - 4.4, 2017-2020, 2021+ (oneTBB)
|
||||||
#
|
#
|
||||||
# Own TBB (3rdparty/tbb):
|
# Own TBB (3rdparty/tbb):
|
||||||
# - set cmake option BUILD_TBB to ON
|
# - set cmake option BUILD_TBB to ON
|
||||||
|
127
cmake/OpenCVPluginStandalone.cmake
Normal file
127
cmake/OpenCVPluginStandalone.cmake
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
# Standalone OpenCV plugins build scripts
|
||||||
|
#
|
||||||
|
# Useful OpenCV common build variables:
|
||||||
|
# - CMAKE_BUILD_TYPE=Release/Debug
|
||||||
|
# - BUILD_WITH_DEBUG_INFO=ON
|
||||||
|
# - ENABLE_BUILD_HARDENING=ON
|
||||||
|
#
|
||||||
|
# Plugin configuration variables:
|
||||||
|
# - OPENCV_PLUGIN_DEPS - set of extra dependencies (modules), used for include dirs, target_link_libraries
|
||||||
|
# - OPENCV_PLUGIN_SUFFIX
|
||||||
|
# - OPENCV_PLUGIN_NAME
|
||||||
|
# - OPENCV_PLUGIN_OUTPUT_NAME_FULL (overrides both OPENCV_PLUGIN_NAME / OPENCV_PLUGIN_SUFFIX)
|
||||||
|
#
|
||||||
|
#=============================================
|
||||||
|
|
||||||
|
if(NOT OpenCV_SOURCE_DIR)
|
||||||
|
message(FATAL_ERROR "OpenCV_SOURCE_DIR must be set to build the plugin!")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_BUILD_TYPE)
|
||||||
|
set(CMAKE_BUILD_TYPE "Release")
|
||||||
|
endif()
|
||||||
|
message(STATUS "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
|
||||||
|
|
||||||
|
set(BUILD_SHARED_LIBS ON CACHE BOOL "")
|
||||||
|
if(NOT BUILD_SHARED_LIBS)
|
||||||
|
message(FATAL_ERROR "Static plugin build does not make sense")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# re-use OpenCV build scripts
|
||||||
|
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVUtils.cmake")
|
||||||
|
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVDetectCXXCompiler.cmake")
|
||||||
|
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVCompilerOptions.cmake")
|
||||||
|
|
||||||
|
function(ocv_create_plugin module default_name dependency_target dependency_target_desc)
|
||||||
|
|
||||||
|
set(OPENCV_PLUGIN_NAME ${default_name} CACHE STRING "")
|
||||||
|
set(OPENCV_PLUGIN_DESTINATION "" CACHE PATH "")
|
||||||
|
project(${OPENCV_PLUGIN_NAME} LANGUAGES CXX)
|
||||||
|
|
||||||
|
if(NOT TARGET ${dependency_target})
|
||||||
|
message(FATAL_ERROR "${dependency_target_desc} was not found! (missing target ${dependency_target})")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(modules_ROOT "${OpenCV_SOURCE_DIR}/modules")
|
||||||
|
set(module_ROOT "${modules_ROOT}/${module}")
|
||||||
|
|
||||||
|
foreach(src ${ARGN})
|
||||||
|
list(APPEND sources "${module_ROOT}/${src}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
add_library(${OPENCV_PLUGIN_NAME} MODULE
|
||||||
|
"${sources}"
|
||||||
|
${OPENCV_PLUGIN_EXTRA_SRC_FILES}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(OPENCV_PLUGIN_DEPS)
|
||||||
|
foreach(d ${OPENCV_PLUGIN_DEPS})
|
||||||
|
list(APPEND OPENCV_PLUGIN_EXTRA_INCLUDES "${modules_ROOT}/${d}/include")
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_include_directories(${OPENCV_PLUGIN_NAME} PRIVATE
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||||
|
"${module_ROOT}/src"
|
||||||
|
"${module_ROOT}/include"
|
||||||
|
${OPENCV_PLUGIN_EXTRA_INCLUDES}
|
||||||
|
)
|
||||||
|
target_compile_definitions(${OPENCV_PLUGIN_NAME} PRIVATE "BUILD_PLUGIN=1")
|
||||||
|
|
||||||
|
target_link_libraries(${OPENCV_PLUGIN_NAME} PRIVATE ${dependency_target})
|
||||||
|
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES
|
||||||
|
CXX_STANDARD 11
|
||||||
|
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 only, Linux/MacOS uses global symbol table (without exact .so binding)
|
||||||
|
if(WIN32)
|
||||||
|
find_package(OpenCV REQUIRED ${module} ${OPENCV_PLUGIN_DEPS})
|
||||||
|
target_link_libraries(${OPENCV_PLUGIN_NAME} PRIVATE ${OpenCV_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT OpenCV_FOUND) # build against sources (Linux)
|
||||||
|
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/opencv2/opencv_modules.hpp" "#pragma once")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
ocv_update(OPENCV_DEBUG_POSTFIX d)
|
||||||
|
endif()
|
||||||
|
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}")
|
||||||
|
|
||||||
|
if(DEFINED OPENCV_PLUGIN_SUFFIX)
|
||||||
|
# custom value
|
||||||
|
else()
|
||||||
|
if(WIN32)
|
||||||
|
ocv_update(OPENCV_PLUGIN_VERSION "${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}")
|
||||||
|
if(CMAKE_CXX_SIZEOF_DATA_PTR EQUAL 8)
|
||||||
|
ocv_update(OPENCV_PLUGIN_ARCH "_64")
|
||||||
|
else()
|
||||||
|
ocv_update(OPENCV_PLUGIN_ARCH "")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# empty
|
||||||
|
endif()
|
||||||
|
ocv_update(OPENCV_PLUGIN_SUFFIX "${OPENCV_PLUGIN_VERSION}${OPENCV_PLUGIN_ARCH}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(OPENCV_PLUGIN_DESTINATION)
|
||||||
|
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${OPENCV_PLUGIN_DESTINATION}")
|
||||||
|
message(STATUS "Output destination: ${OPENCV_PLUGIN_DESTINATION}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(OPENCV_PLUGIN_OUTPUT_NAME_FULL)
|
||||||
|
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES OUTPUT_NAME "${OPENCV_PLUGIN_OUTPUT_NAME_FULL}")
|
||||||
|
elseif(OPENCV_PLUGIN_OUTPUT_NAME)
|
||||||
|
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES OUTPUT_NAME "${OPENCV_PLUGIN_OUTPUT_NAME}${OPENCV_PLUGIN_SUFFIX}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(TARGETS ${OPENCV_PLUGIN_NAME} LIBRARY DESTINATION . COMPONENT plugins)
|
||||||
|
|
||||||
|
message(STATUS "Library name: ${OPENCV_PLUGIN_NAME}")
|
||||||
|
|
||||||
|
endfunction()
|
@ -573,7 +573,9 @@ macro(ocv_check_flag_support lang flag varname base_options)
|
|||||||
string(REGEX REPLACE "^(/|-)" "HAVE_${_lang}_" ${varname} "${${varname}}")
|
string(REGEX REPLACE "^(/|-)" "HAVE_${_lang}_" ${varname} "${${varname}}")
|
||||||
string(REGEX REPLACE " -|-|=| |\\.|," "_" ${varname} "${${varname}}")
|
string(REGEX REPLACE " -|-|=| |\\.|," "_" ${varname} "${${varname}}")
|
||||||
|
|
||||||
ocv_check_compiler_flag("${_lang}" "${base_options} ${flag}" ${${varname}} ${ARGN})
|
if(DEFINED CMAKE_${_lang}_COMPILER)
|
||||||
|
ocv_check_compiler_flag("${_lang}" "${base_options} ${flag}" ${${varname}} ${ARGN})
|
||||||
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
macro(ocv_check_runtime_flag flag result)
|
macro(ocv_check_runtime_flag flag result)
|
||||||
@ -1571,6 +1573,30 @@ function(ocv_add_library target)
|
|||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
|
||||||
|
function(ocv_add_external_target name inc link def)
|
||||||
|
if(BUILD_SHARED_LIBS)
|
||||||
|
set(imp IMPORTED)
|
||||||
|
endif()
|
||||||
|
add_library(ocv.3rdparty.${name} INTERFACE ${imp})
|
||||||
|
set_target_properties(ocv.3rdparty.${name} PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${inc}"
|
||||||
|
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${inc}"
|
||||||
|
INTERFACE_COMPILE_DEFINITIONS "${def}")
|
||||||
|
# When cmake version is greater than or equal to 3.11, INTERFACE_LINK_LIBRARIES no longer applies to interface library
|
||||||
|
# See https://github.com/opencv/opencv/pull/18658
|
||||||
|
if (CMAKE_VERSION VERSION_LESS 3.11)
|
||||||
|
set_target_properties(ocv.3rdparty.${name} PROPERTIES
|
||||||
|
INTERFACE_LINK_LIBRARIES "${link}")
|
||||||
|
else()
|
||||||
|
target_link_libraries(ocv.3rdparty.${name} INTERFACE ${link})
|
||||||
|
endif()
|
||||||
|
#
|
||||||
|
if(NOT BUILD_SHARED_LIBS)
|
||||||
|
install(TARGETS ocv.3rdparty.${name} EXPORT OpenCVModules)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
|
||||||
macro(ocv_get_libname var_name)
|
macro(ocv_get_libname var_name)
|
||||||
get_filename_component(__libname "${ARGN}" NAME)
|
get_filename_component(__libname "${ARGN}" NAME)
|
||||||
# libopencv_core.so.3.3 -> opencv_core
|
# libopencv_core.so.3.3 -> opencv_core
|
||||||
|
@ -17,6 +17,14 @@ ocv_add_dispatched_file_force_all(test_intrin128 TEST SSE2 SSE3 SSSE3 SSE4_1 SSE
|
|||||||
ocv_add_dispatched_file_force_all(test_intrin256 TEST AVX2 AVX512_SKX)
|
ocv_add_dispatched_file_force_all(test_intrin256 TEST AVX2 AVX512_SKX)
|
||||||
ocv_add_dispatched_file_force_all(test_intrin512 TEST AVX512_SKX)
|
ocv_add_dispatched_file_force_all(test_intrin512 TEST AVX512_SKX)
|
||||||
|
|
||||||
|
|
||||||
|
# parallel backends configuration
|
||||||
|
set(PARALLEL_ENABLE_PLUGINS "ON" CACHE BOOL "Allow building parallel plugin support")
|
||||||
|
# TODO building plugins with OpenCV is not supported yet
|
||||||
|
#set(PARALLEL_PLUGIN_LIST "" CACHE STRING "List of parallel backends to be compiled as plugins (tbb, openmp or special value 'all')")
|
||||||
|
#string(REPLACE "," ";" PARALLEL_PLUGIN_LIST "${PARALLEL_PLUGIN_LIST}") # support comma-separated list (,) too
|
||||||
|
|
||||||
|
|
||||||
ocv_add_module(core
|
ocv_add_module(core
|
||||||
OPTIONAL opencv_cudev
|
OPTIONAL opencv_cudev
|
||||||
WRAP java objc python js)
|
WRAP java objc python js)
|
||||||
@ -117,6 +125,14 @@ elseif(HAVE_CXX11 OR DEFINED OPENCV_ALLOCATOR_STATS_COUNTER_TYPE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
if(PARALLEL_ENABLE_PLUGINS)
|
||||||
|
ocv_append_source_file_compile_definitions(${CMAKE_CURRENT_SOURCE_DIR}/src/parallel/parallel.cpp "PARALLEL_ENABLE_PLUGINS=1")
|
||||||
|
if(OPENCV_DEBUG_POSTFIX)
|
||||||
|
ocv_append_source_file_compile_definitions("${CMAKE_CURRENT_LIST_DIR}/src/parallel/parallel.cpp" "DEBUG_POSTFIX=${OPENCV_DEBUG_POSTFIX}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
ocv_create_module(${extra_libs})
|
ocv_create_module(${extra_libs})
|
||||||
|
|
||||||
ocv_target_link_libraries(${the_module} PRIVATE
|
ocv_target_link_libraries(${the_module} PRIVATE
|
||||||
|
13
modules/core/cmake/parallel/detect_openmp.cmake
Normal file
13
modules/core/cmake/parallel/detect_openmp.cmake
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
if(CMAKE_VERSION VERSION_LESS "3.9")
|
||||||
|
message(STATUS "OpenMP detection requires CMake 3.9+") # OpenMP::OpenMP_CXX target
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(OpenMP)
|
||||||
|
if(OpenMP_FOUND)
|
||||||
|
if(TARGET OpenMP::OpenMP_CXX)
|
||||||
|
set(HAVE_OPENMP 1)
|
||||||
|
ocv_add_external_target(openmp "" "OpenMP::OpenMP_CXX" "HAVE_OPENMP=1")
|
||||||
|
else()
|
||||||
|
message(WARNING "OpenMP: missing OpenMP::OpenMP_CXX target")
|
||||||
|
endif()
|
||||||
|
endif()
|
5
modules/core/cmake/parallel/detect_tbb.cmake
Normal file
5
modules/core/cmake/parallel/detect_tbb.cmake
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVDetectTBB.cmake")
|
||||||
|
|
||||||
|
if(HAVE_TBB)
|
||||||
|
ocv_add_external_target(tbb "" "tbb" "HAVE_TBB=1")
|
||||||
|
endif()
|
8
modules/core/cmake/parallel/init.cmake
Normal file
8
modules/core/cmake/parallel/init.cmake
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
macro(ocv_add_core_parallel_backend backend_id cond_var)
|
||||||
|
if(${cond_var})
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/detect_${backend_id}.cmake")
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
ocv_add_core_parallel_backend("tbb" WITH_TBB)
|
||||||
|
ocv_add_core_parallel_backend("openmp" WITH_OPENMP)
|
@ -27,6 +27,14 @@ Using this approach OpenCV provides some basic low level functionality for exter
|
|||||||
#define CV_API_CALL
|
#define CV_API_CALL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CV_PLUGIN_EXPORTS
|
||||||
|
#if (defined _WIN32 || defined WINCE || defined __CYGWIN__)
|
||||||
|
# define CV_PLUGIN_EXPORTS __declspec(dllexport)
|
||||||
|
#elif defined __GNUC__ && __GNUC__ >= 4
|
||||||
|
# define CV_PLUGIN_EXPORTS __attribute__ ((visibility ("default")))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef enum cvResult
|
typedef enum cvResult
|
||||||
{
|
{
|
||||||
CV_ERROR_FAIL = -1, //!< Some error occurred (TODO Require to fill exception information)
|
CV_ERROR_FAIL = -1, //!< Some error occurred (TODO Require to fill exception information)
|
||||||
|
@ -19,9 +19,10 @@ namespace cv { namespace parallel {
|
|||||||
*
|
*
|
||||||
* Applications can replace OpenCV `parallel_for()` backend with own implementation (to reuse Application's thread pool).
|
* Applications can replace OpenCV `parallel_for()` backend with own implementation (to reuse Application's thread pool).
|
||||||
*
|
*
|
||||||
* @note This call is not thread-safe. Consider calling this function from the `main()` before any other OpenCV processing functions (and without any other created threads).
|
|
||||||
*
|
*
|
||||||
* #### Intel TBB usage example:
|
* ### Backend API usage examples
|
||||||
|
*
|
||||||
|
* #### Intel TBB
|
||||||
*
|
*
|
||||||
* - include header with simple implementation of TBB backend:
|
* - include header with simple implementation of TBB backend:
|
||||||
* @snippet parallel_backend/example-tbb.cpp tbb_include
|
* @snippet parallel_backend/example-tbb.cpp tbb_include
|
||||||
@ -29,13 +30,22 @@ namespace cv { namespace parallel {
|
|||||||
* @snippet parallel_backend/example-tbb.cpp tbb_backend
|
* @snippet parallel_backend/example-tbb.cpp tbb_backend
|
||||||
* - configuration of compiler/linker options is responsibility of Application's scripts
|
* - configuration of compiler/linker options is responsibility of Application's scripts
|
||||||
*
|
*
|
||||||
* #### OpenMP usage example:
|
* #### OpenMP
|
||||||
*
|
*
|
||||||
* - include header with simple implementation of OpenMP backend:
|
* - include header with simple implementation of OpenMP backend:
|
||||||
* @snippet parallel_backend/example-openmp.cpp openmp_include
|
* @snippet parallel_backend/example-openmp.cpp openmp_include
|
||||||
* - execute backend replacement code:
|
* - execute backend replacement code:
|
||||||
* @snippet parallel_backend/example-openmp.cpp openmp_backend
|
* @snippet parallel_backend/example-openmp.cpp openmp_backend
|
||||||
* - Configuration of compiler/linker options is responsibility of Application's scripts
|
* - Configuration of compiler/linker options is responsibility of Application's scripts
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* ### Plugins support
|
||||||
|
*
|
||||||
|
* Runtime configuration options:
|
||||||
|
* - change backend priority: `OPENCV_PARALLEL_PRIORITY_<backend>=9999`
|
||||||
|
* - disable backend: `OPENCV_PARALLEL_PRIORITY_<backend>=0`
|
||||||
|
* - specify list of backends with high priority (>100000): `OPENCV_PARALLEL_PRIORITY_LIST=TBB,OPENMP`. Unknown backends are registered as new plugins.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** Interface for parallel_for backends implementations
|
/** Interface for parallel_for backends implementations
|
||||||
@ -68,6 +78,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
CV_EXPORTS void setParallelForBackend(const std::shared_ptr<ParallelForAPI>& api, bool propagateNumThreads = true);
|
CV_EXPORTS void setParallelForBackend(const std::shared_ptr<ParallelForAPI>& api, bool propagateNumThreads = true);
|
||||||
|
|
||||||
|
/** @brief Change OpenCV parallel_for backend
|
||||||
|
*
|
||||||
|
* @note This call is not thread-safe. Consider calling this function from the `main()` before any other OpenCV processing functions (and without any other created threads).
|
||||||
|
*/
|
||||||
|
CV_EXPORTS_W bool setParallelForBackend(const std::string& backendName, bool propagateNumThreads = true);
|
||||||
|
|
||||||
//! @}
|
//! @}
|
||||||
}} // namespace
|
}} // namespace
|
||||||
#endif // OPENCV_CORE_PARALLEL_BACKEND_HPP
|
#endif // OPENCV_CORE_PARALLEL_BACKEND_HPP
|
||||||
|
@ -0,0 +1,163 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// 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_UTILS_PLUGIN_LOADER_HPP
|
||||||
|
#define OPENCV_UTILS_PLUGIN_LOADER_HPP
|
||||||
|
|
||||||
|
#include "opencv2/core/utils/filesystem.hpp"
|
||||||
|
#include "opencv2/core/utils/filesystem.private.hpp"
|
||||||
|
|
||||||
|
#if OPENCV_HAVE_FILESYSTEM_SUPPORT
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
#elif defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__HAIKU__) || defined(__GLIBC__)
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace cv { namespace plugin { namespace impl {
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
typedef HMODULE LibHandle_t;
|
||||||
|
typedef wchar_t FileSystemChar_t;
|
||||||
|
typedef std::wstring FileSystemPath_t;
|
||||||
|
|
||||||
|
// TODO wchar_t <=> UTF-8
|
||||||
|
static inline
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO wchar_t <=> UTF-8
|
||||||
|
static inline
|
||||||
|
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 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
|
||||||
|
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void* getSymbol_(LibHandle_t h, const char* symbolName)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
return (void*)GetProcAddress(h, symbolName);
|
||||||
|
#elif defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__HAIKU__) || defined(__GLIBC__)
|
||||||
|
return dlsym(h, symbolName);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
LibHandle_t libraryLoad_(const FileSystemPath_t& filename)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
# ifdef WINRT
|
||||||
|
return LoadPackagedLibrary(filename.c_str(), 0);
|
||||||
|
# else
|
||||||
|
return LoadLibraryW(filename.c_str());
|
||||||
|
#endif
|
||||||
|
#elif defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__HAIKU__) || defined(__GLIBC__)
|
||||||
|
return dlopen(filename.c_str(), RTLD_LAZY);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void libraryRelease_(LibHandle_t h)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
FreeLibrary(h);
|
||||||
|
#elif defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__HAIKU__) || defined(__GLIBC__)
|
||||||
|
dlclose(h);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
std::string libraryPrefix()
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
return "";
|
||||||
|
#else
|
||||||
|
return "lib";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
static inline
|
||||||
|
std::string librarySuffix()
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
const char* suffix = ""
|
||||||
|
CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION)
|
||||||
|
#if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__)
|
||||||
|
"_64"
|
||||||
|
#endif
|
||||||
|
#if defined(_DEBUG) && defined(DEBUG_POSTFIX)
|
||||||
|
CVAUX_STR(DEBUG_POSTFIX)
|
||||||
|
#endif
|
||||||
|
".dll";
|
||||||
|
return suffix;
|
||||||
|
#else
|
||||||
|
return ".so";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//============================
|
||||||
|
|
||||||
|
class CV_EXPORTS DynamicLib
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
LibHandle_t handle;
|
||||||
|
const FileSystemPath_t fname;
|
||||||
|
bool disableAutoUnloading_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DynamicLib(const FileSystemPath_t& filename);
|
||||||
|
~DynamicLib();
|
||||||
|
/** Do not automatically unload library in destructor */
|
||||||
|
inline void disableAutomaticLibraryUnloading()
|
||||||
|
{
|
||||||
|
disableAutoUnloading_ = true;
|
||||||
|
}
|
||||||
|
inline bool isLoaded() const
|
||||||
|
{
|
||||||
|
return handle != NULL;
|
||||||
|
}
|
||||||
|
void* getSymbol(const char* symbolName) const;
|
||||||
|
const std::string getName() const;
|
||||||
|
private:
|
||||||
|
void libraryLoad(const FileSystemPath_t& filename);
|
||||||
|
void libraryRelease();
|
||||||
|
|
||||||
|
private:
|
||||||
|
DynamicLib(const DynamicLib &) = delete;
|
||||||
|
DynamicLib &operator=(const DynamicLib &) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}}} // namespace
|
||||||
|
|
||||||
|
#endif // OPENCV_HAVE_FILESYSTEM_SUPPORT
|
||||||
|
|
||||||
|
#endif // OPENCV_UTILS_PLUGIN_LOADER_HPP
|
12
modules/core/misc/plugins/parallel_openmp/CMakeLists.txt
Normal file
12
modules/core/misc/plugins/parallel_openmp/CMakeLists.txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
project(opencv_core_parallel_openmp CXX)
|
||||||
|
|
||||||
|
get_filename_component(OpenCV_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../../.." ABSOLUTE)
|
||||||
|
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVPluginStandalone.cmake")
|
||||||
|
|
||||||
|
# scan dependencies
|
||||||
|
set(WITH_OPENMP ON)
|
||||||
|
include("${OpenCV_SOURCE_DIR}/modules/core/cmake/parallel/init.cmake")
|
||||||
|
|
||||||
|
message(STATUS "OpenMP: ${OPENMP_VERSION}")
|
||||||
|
ocv_create_plugin(core "opencv_core_parallel_openmp" "ocv.3rdparty.openmp" "OPENMP" "src/parallel/parallel_openmp.cpp")
|
12
modules/core/misc/plugins/parallel_tbb/CMakeLists.txt
Normal file
12
modules/core/misc/plugins/parallel_tbb/CMakeLists.txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
project(opencv_core_parallel_tbb CXX)
|
||||||
|
|
||||||
|
get_filename_component(OpenCV_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../../.." ABSOLUTE)
|
||||||
|
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVPluginStandalone.cmake")
|
||||||
|
|
||||||
|
# scan dependencies
|
||||||
|
set(WITH_TBB ON)
|
||||||
|
include("${OpenCV_SOURCE_DIR}/modules/core/cmake/parallel/init.cmake")
|
||||||
|
|
||||||
|
message(STATUS "TBB: ver ${TBB_VERSION_MAJOR}.${TBB_VERSION_MINOR} interface ${TBB_INTERFACE_VERSION}")
|
||||||
|
ocv_create_plugin(core "opencv_core_parallel_tbb" "ocv.3rdparty.tbb" "TBB" "src/parallel/parallel_tbb.cpp")
|
@ -46,6 +46,7 @@
|
|||||||
#include <opencv2/core/utils/trace.private.hpp>
|
#include <opencv2/core/utils/trace.private.hpp>
|
||||||
|
|
||||||
#include "opencv2/core/parallel/parallel_backend.hpp"
|
#include "opencv2/core/parallel/parallel_backend.hpp"
|
||||||
|
#include "parallel/parallel.hpp"
|
||||||
|
|
||||||
#if defined _WIN32 || defined WINCE
|
#if defined _WIN32 || defined WINCE
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -158,32 +159,6 @@ namespace cv {
|
|||||||
|
|
||||||
ParallelLoopBody::~ParallelLoopBody() {}
|
ParallelLoopBody::~ParallelLoopBody() {}
|
||||||
|
|
||||||
namespace parallel {
|
|
||||||
|
|
||||||
static int numThreads = -1;
|
|
||||||
|
|
||||||
static
|
|
||||||
std::shared_ptr<ParallelForAPI>& getCurrentParallelForAPI()
|
|
||||||
{
|
|
||||||
static std::shared_ptr<ParallelForAPI> g_currentParallelForAPI;
|
|
||||||
return g_currentParallelForAPI;
|
|
||||||
}
|
|
||||||
|
|
||||||
ParallelForAPI::~ParallelForAPI()
|
|
||||||
{
|
|
||||||
// nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void setParallelForBackend(const std::shared_ptr<ParallelForAPI>& api, bool propagateNumThreads)
|
|
||||||
{
|
|
||||||
getCurrentParallelForAPI() = api;
|
|
||||||
if (propagateNumThreads && api)
|
|
||||||
{
|
|
||||||
setNumThreads(numThreads);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
using namespace cv::parallel;
|
using namespace cv::parallel;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
48
modules/core/src/parallel/factory_parallel.hpp
Normal file
48
modules/core/src/parallel/factory_parallel.hpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// 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_CORE_PARALLEL_FACTORY_HPP
|
||||||
|
#define OPENCV_CORE_PARALLEL_FACTORY_HPP
|
||||||
|
|
||||||
|
#include "opencv2/core/parallel/parallel_backend.hpp"
|
||||||
|
|
||||||
|
namespace cv { namespace parallel {
|
||||||
|
|
||||||
|
class IParallelBackendFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IParallelBackendFactory() {}
|
||||||
|
virtual std::shared_ptr<cv::parallel::ParallelForAPI> create() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class StaticBackendFactory CV_FINAL: public IParallelBackendFactory
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::function<std::shared_ptr<cv::parallel::ParallelForAPI>(void)> create_fn_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
StaticBackendFactory(std::function<std::shared_ptr<cv::parallel::ParallelForAPI>(void)>&& create_fn)
|
||||||
|
: create_fn_(create_fn)
|
||||||
|
{
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
~StaticBackendFactory() CV_OVERRIDE {}
|
||||||
|
|
||||||
|
std::shared_ptr<cv::parallel::ParallelForAPI> create() const CV_OVERRIDE
|
||||||
|
{
|
||||||
|
return create_fn_();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// PluginBackendFactory is implemented in plugin_wrapper.cpp
|
||||||
|
//
|
||||||
|
|
||||||
|
std::shared_ptr<IParallelBackendFactory> createPluginParallelBackendFactory(const std::string& baseName);
|
||||||
|
|
||||||
|
}} // namespace
|
||||||
|
|
||||||
|
#endif // OPENCV_CORE_PARALLEL_FACTORY_HPP
|
173
modules/core/src/parallel/parallel.cpp
Normal file
173
modules/core/src/parallel/parallel.cpp
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// 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.
|
||||||
|
#include "../precomp.hpp"
|
||||||
|
#include "parallel.hpp"
|
||||||
|
|
||||||
|
#include <opencv2/core/utils/configuration.private.hpp>
|
||||||
|
#include <opencv2/core/utils/logger.defines.hpp>
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_DEBUG + 1
|
||||||
|
#else
|
||||||
|
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_VERBOSE + 1
|
||||||
|
#endif
|
||||||
|
#include <opencv2/core/utils/logger.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
#include "registry_parallel.hpp"
|
||||||
|
#include "registry_parallel.impl.hpp"
|
||||||
|
|
||||||
|
#include "plugin_parallel_api.hpp"
|
||||||
|
#include "plugin_parallel_wrapper.impl.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace cv { namespace parallel {
|
||||||
|
|
||||||
|
int numThreads = -1;
|
||||||
|
|
||||||
|
ParallelForAPI::~ParallelForAPI()
|
||||||
|
{
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
std::string& getParallelBackendName()
|
||||||
|
{
|
||||||
|
static std::string g_backendName = toUpperCase(cv::utils::getConfigurationParameterString("OPENCV_PARALLEL_BACKEND", ""));
|
||||||
|
return g_backendName;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool g_initializedParallelForAPI = false;
|
||||||
|
|
||||||
|
static
|
||||||
|
std::shared_ptr<ParallelForAPI> createParallelForAPI()
|
||||||
|
{
|
||||||
|
const std::string& name = getParallelBackendName();
|
||||||
|
bool isKnown = false;
|
||||||
|
const auto& backends = getParallelBackendsInfo();
|
||||||
|
if (!name.empty())
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "core(parallel): requested backend name: " << name);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < backends.size(); i++)
|
||||||
|
{
|
||||||
|
const auto& info = backends[i];
|
||||||
|
if (!name.empty())
|
||||||
|
{
|
||||||
|
if (name != info.name)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
isKnown = true;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "core(parallel): trying backend: " << info.name << " (priority=" << info.priority << ")");
|
||||||
|
CV_Assert(info.backendFactory);
|
||||||
|
std::shared_ptr<ParallelForAPI> backend = info.backendFactory->create();
|
||||||
|
if (!backend)
|
||||||
|
{
|
||||||
|
CV_LOG_VERBOSE(NULL, 0, "core(parallel): not available: " << info.name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
CV_LOG_INFO(NULL, "core(parallel): using backend: " << info.name << " (priority=" << info.priority << ")");
|
||||||
|
g_initializedParallelForAPI = true;
|
||||||
|
getParallelBackendName() = info.name;
|
||||||
|
return backend;
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
CV_LOG_WARNING(NULL, "core(parallel): can't initialize " << info.name << " backend: " << e.what());
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
CV_LOG_WARNING(NULL, "core(parallel): can't initialize " << info.name << " backend: Unknown C++ exception");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (name.empty())
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "core(parallel): fallback on builtin code");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!isKnown)
|
||||||
|
CV_LOG_INFO(NULL, "core(parallel): unknown backend: " << name);
|
||||||
|
}
|
||||||
|
g_initializedParallelForAPI = true;
|
||||||
|
return std::shared_ptr<ParallelForAPI>();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
std::shared_ptr<ParallelForAPI> createDefaultParallelForAPI()
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "core(parallel): Initializing parallel backend...");
|
||||||
|
return createParallelForAPI();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ParallelForAPI>& getCurrentParallelForAPI()
|
||||||
|
{
|
||||||
|
static std::shared_ptr<ParallelForAPI> g_currentParallelForAPI = createDefaultParallelForAPI();
|
||||||
|
return g_currentParallelForAPI;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setParallelForBackend(const std::shared_ptr<ParallelForAPI>& api, bool propagateNumThreads)
|
||||||
|
{
|
||||||
|
getCurrentParallelForAPI() = api;
|
||||||
|
if (propagateNumThreads && api)
|
||||||
|
{
|
||||||
|
setNumThreads(numThreads);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setParallelForBackend(const std::string& backendName, bool propagateNumThreads)
|
||||||
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
|
|
||||||
|
std::string backendName_u = toUpperCase(backendName);
|
||||||
|
if (g_initializedParallelForAPI)
|
||||||
|
{
|
||||||
|
// ... already initialized
|
||||||
|
if (getParallelBackendName() == backendName_u)
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "core(parallel): backend is already activated: " << (backendName.empty() ? "builtin(legacy)" : backendName));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ... re-create new
|
||||||
|
CV_LOG_DEBUG(NULL, "core(parallel): replacing parallel backend...");
|
||||||
|
getParallelBackendName() = backendName_u;
|
||||||
|
getCurrentParallelForAPI() = createParallelForAPI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ... no backend exists, just specify the name (initialization is triggered by getCurrentParallelForAPI() call)
|
||||||
|
getParallelBackendName() = backendName_u;
|
||||||
|
}
|
||||||
|
std::shared_ptr<ParallelForAPI> api = getCurrentParallelForAPI();
|
||||||
|
if (!api)
|
||||||
|
{
|
||||||
|
if (!backendName.empty())
|
||||||
|
{
|
||||||
|
CV_LOG_WARNING(NULL, "core(parallel): backend is not available: " << backendName << " (using builtin legacy code)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CV_LOG_WARNING(NULL, "core(parallel): switched to builtin code (legacy)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!backendName_u.empty())
|
||||||
|
{
|
||||||
|
CV_Assert(backendName_u == getParallelBackendName()); // data race?
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propagateNumThreads)
|
||||||
|
{
|
||||||
|
setNumThreads(numThreads);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}} // namespace
|
29
modules/core/src/parallel/parallel.hpp
Normal file
29
modules/core/src/parallel/parallel.hpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// 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_CORE_SRC_PARALLEL_PARALLEL_HPP
|
||||||
|
#define OPENCV_CORE_SRC_PARALLEL_PARALLEL_HPP
|
||||||
|
|
||||||
|
#include "opencv2/core/parallel/parallel_backend.hpp"
|
||||||
|
|
||||||
|
namespace cv { namespace parallel {
|
||||||
|
|
||||||
|
extern int numThreads;
|
||||||
|
|
||||||
|
std::shared_ptr<ParallelForAPI>& getCurrentParallelForAPI();
|
||||||
|
|
||||||
|
#ifndef BUILD_PLUGIN
|
||||||
|
|
||||||
|
#ifdef HAVE_TBB
|
||||||
|
std::shared_ptr<cv::parallel::ParallelForAPI> createParallelBackendTBB();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENMP
|
||||||
|
std::shared_ptr<cv::parallel::ParallelForAPI> createParallelBackendOpenMP();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // BUILD_PLUGIN
|
||||||
|
|
||||||
|
}} // namespace
|
||||||
|
|
||||||
|
#endif // OPENCV_CORE_SRC_PARALLEL_PARALLEL_HPP
|
72
modules/core/src/parallel/parallel_openmp.cpp
Normal file
72
modules/core/src/parallel/parallel_openmp.cpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// 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.
|
||||||
|
#include "../precomp.hpp"
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENMP
|
||||||
|
|
||||||
|
#include "parallel.hpp"
|
||||||
|
#include "opencv2/core/parallel/backend/parallel_for.openmp.hpp"
|
||||||
|
|
||||||
|
namespace cv { namespace parallel {
|
||||||
|
|
||||||
|
static
|
||||||
|
std::shared_ptr<cv::parallel::openmp::ParallelForBackend>& getInstance()
|
||||||
|
{
|
||||||
|
static std::shared_ptr<cv::parallel::openmp::ParallelForBackend> g_instance = std::make_shared<cv::parallel::openmp::ParallelForBackend>();
|
||||||
|
return g_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef BUILD_PLUGIN
|
||||||
|
std::shared_ptr<cv::parallel::ParallelForAPI> createParallelBackendOpenMP()
|
||||||
|
{
|
||||||
|
return getInstance();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}} // namespace
|
||||||
|
|
||||||
|
#ifdef BUILD_PLUGIN
|
||||||
|
|
||||||
|
#define ABI_VERSION 0
|
||||||
|
#define API_VERSION 0
|
||||||
|
#include "plugin_parallel_api.hpp"
|
||||||
|
|
||||||
|
static
|
||||||
|
CvResult cv_getInstance(CV_OUT CvPluginParallelBackendAPI* handle) CV_NOEXCEPT
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!handle)
|
||||||
|
return CV_ERROR_FAIL;
|
||||||
|
*handle = cv::parallel::getInstance().get();
|
||||||
|
return CV_ERROR_OK;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return CV_ERROR_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const OpenCV_Core_Parallel_Plugin_API plugin_api =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
sizeof(OpenCV_Core_Parallel_Plugin_API), ABI_VERSION, API_VERSION,
|
||||||
|
CV_VERSION_MAJOR, CV_VERSION_MINOR, CV_VERSION_REVISION, CV_VERSION_STATUS,
|
||||||
|
"OpenMP (" CVAUX_STR(_OPENMP) ") OpenCV parallel plugin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* 1*/cv_getInstance
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const OpenCV_Core_Parallel_Plugin_API* CV_API_CALL opencv_core_parallel_plugin_init_v0(int requested_abi_version, int requested_api_version, void* /*reserved=NULL*/) CV_NOEXCEPT
|
||||||
|
{
|
||||||
|
if (requested_abi_version == ABI_VERSION && requested_api_version <= API_VERSION)
|
||||||
|
return &plugin_api;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BUILD_PLUGIN
|
||||||
|
|
||||||
|
#endif // HAVE_TBB
|
74
modules/core/src/parallel/parallel_tbb.cpp
Normal file
74
modules/core/src/parallel/parallel_tbb.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// 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.
|
||||||
|
#include "../precomp.hpp"
|
||||||
|
|
||||||
|
#include "factory_parallel.hpp"
|
||||||
|
|
||||||
|
#ifdef HAVE_TBB
|
||||||
|
|
||||||
|
#include "parallel.hpp"
|
||||||
|
#include "opencv2/core/parallel/backend/parallel_for.tbb.hpp"
|
||||||
|
|
||||||
|
namespace cv { namespace parallel {
|
||||||
|
|
||||||
|
static
|
||||||
|
std::shared_ptr<cv::parallel::tbb::ParallelForBackend>& getInstance()
|
||||||
|
{
|
||||||
|
static std::shared_ptr<cv::parallel::tbb::ParallelForBackend> g_instance = std::make_shared<cv::parallel::tbb::ParallelForBackend>();
|
||||||
|
return g_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef BUILD_PLUGIN
|
||||||
|
std::shared_ptr<cv::parallel::ParallelForAPI> createParallelBackendTBB()
|
||||||
|
{
|
||||||
|
return getInstance();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}} // namespace
|
||||||
|
|
||||||
|
#ifdef BUILD_PLUGIN
|
||||||
|
|
||||||
|
#define ABI_VERSION 0
|
||||||
|
#define API_VERSION 0
|
||||||
|
#include "plugin_parallel_api.hpp"
|
||||||
|
|
||||||
|
static
|
||||||
|
CvResult cv_getInstance(CV_OUT CvPluginParallelBackendAPI* handle) CV_NOEXCEPT
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!handle)
|
||||||
|
return CV_ERROR_FAIL;
|
||||||
|
*handle = cv::parallel::getInstance().get();
|
||||||
|
return CV_ERROR_OK;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return CV_ERROR_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const OpenCV_Core_Parallel_Plugin_API plugin_api =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
sizeof(OpenCV_Core_Parallel_Plugin_API), ABI_VERSION, API_VERSION,
|
||||||
|
CV_VERSION_MAJOR, CV_VERSION_MINOR, CV_VERSION_REVISION, CV_VERSION_STATUS,
|
||||||
|
"TBB (interface " CVAUX_STR(TBB_INTERFACE_VERSION) ") OpenCV parallel plugin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* 1*/cv_getInstance
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const OpenCV_Core_Parallel_Plugin_API* CV_API_CALL opencv_core_parallel_plugin_init_v0(int requested_abi_version, int requested_api_version, void* /*reserved=NULL*/) CV_NOEXCEPT
|
||||||
|
{
|
||||||
|
if (requested_abi_version == ABI_VERSION && requested_api_version <= API_VERSION)
|
||||||
|
return &plugin_api;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BUILD_PLUGIN
|
||||||
|
|
||||||
|
#endif // HAVE_TBB
|
72
modules/core/src/parallel/plugin_parallel_api.hpp
Normal file
72
modules/core/src/parallel/plugin_parallel_api.hpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// 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 PARALLEL_PLUGIN_API_HPP
|
||||||
|
#define PARALLEL_PLUGIN_API_HPP
|
||||||
|
|
||||||
|
#include <opencv2/core/cvdef.h>
|
||||||
|
#include <opencv2/core/llapi/llapi.h>
|
||||||
|
|
||||||
|
#include "opencv2/core/parallel/parallel_backend.hpp"
|
||||||
|
|
||||||
|
#if !defined(BUILD_PLUGIN)
|
||||||
|
|
||||||
|
/// increased for backward-compatible changes, e.g. add new function
|
||||||
|
/// Caller API <= Plugin API -> plugin is fully compatible
|
||||||
|
/// Caller API > Plugin API -> plugin is not fully compatible, caller should use extra checks to use plugins with older API
|
||||||
|
#define API_VERSION 0 // preview
|
||||||
|
|
||||||
|
/// increased for incompatible changes, e.g. remove function argument
|
||||||
|
/// Caller ABI == Plugin ABI -> plugin is compatible
|
||||||
|
/// Caller ABI > Plugin ABI -> plugin is not compatible, caller should use shim code to use old ABI plugins (caller may know how lower ABI works, so it is possible)
|
||||||
|
/// Caller ABI < Plugin ABI -> plugin can't be used (plugin should provide interface with lower ABI to handle that)
|
||||||
|
#define ABI_VERSION 0 // preview
|
||||||
|
|
||||||
|
#else // !defined(BUILD_PLUGIN)
|
||||||
|
|
||||||
|
#if !defined(ABI_VERSION) || !defined(API_VERSION)
|
||||||
|
#error "Plugin must define ABI_VERSION and API_VERSION before including parallel_plugin_api.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // !defined(BUILD_PLUGIN)
|
||||||
|
|
||||||
|
typedef cv::parallel::ParallelForAPI* CvPluginParallelBackendAPI;
|
||||||
|
|
||||||
|
struct OpenCV_Core_Parallel_Plugin_API_v0_0_api_entries
|
||||||
|
{
|
||||||
|
/** @brief Get parallel backend API instance
|
||||||
|
|
||||||
|
@param[out] handle pointer on backend API handle
|
||||||
|
|
||||||
|
@note API-CALL 1, API-Version == 0
|
||||||
|
*/
|
||||||
|
CvResult (CV_API_CALL *getInstance)(CV_OUT CvPluginParallelBackendAPI* handle) CV_NOEXCEPT;
|
||||||
|
}; // OpenCV_Core_Parallel_Plugin_API_v0_0_api_entries
|
||||||
|
|
||||||
|
typedef struct OpenCV_Core_Parallel_Plugin_API_v0
|
||||||
|
{
|
||||||
|
OpenCV_API_Header api_header;
|
||||||
|
struct OpenCV_Core_Parallel_Plugin_API_v0_0_api_entries v0;
|
||||||
|
} OpenCV_Core_Parallel_Plugin_API_v0;
|
||||||
|
|
||||||
|
#if ABI_VERSION == 0 && API_VERSION == 0
|
||||||
|
typedef OpenCV_Core_Parallel_Plugin_API_v0 OpenCV_Core_Parallel_Plugin_API;
|
||||||
|
#else
|
||||||
|
#error "Not supported configuration: check ABI_VERSION/API_VERSION"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BUILD_PLUGIN
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
CV_PLUGIN_EXPORTS
|
||||||
|
const OpenCV_Core_Parallel_Plugin_API* CV_API_CALL opencv_core_parallel_plugin_init_v0
|
||||||
|
(int requested_abi_version, int requested_api_version, void* reserved /*NULL*/) CV_NOEXCEPT;
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
|
#else // BUILD_PLUGIN
|
||||||
|
typedef const OpenCV_Core_Parallel_Plugin_API* (CV_API_CALL *FN_opencv_core_parallel_plugin_init_t)
|
||||||
|
(int requested_abi_version, int requested_api_version, void* reserved /*NULL*/);
|
||||||
|
#endif // BUILD_PLUGIN
|
||||||
|
|
||||||
|
#endif // PARALLEL_PLUGIN_API_HPP
|
286
modules/core/src/parallel/plugin_parallel_wrapper.impl.hpp
Normal file
286
modules/core/src/parallel/plugin_parallel_wrapper.impl.hpp
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
//
|
||||||
|
// Not a standalone header, part of parallel.cpp
|
||||||
|
//
|
||||||
|
|
||||||
|
//==================================================================================================
|
||||||
|
// Dynamic backend implementation
|
||||||
|
|
||||||
|
#include "opencv2/core/utils/plugin_loader.private.hpp"
|
||||||
|
|
||||||
|
namespace cv { namespace impl {
|
||||||
|
|
||||||
|
using namespace cv::parallel;
|
||||||
|
|
||||||
|
#if OPENCV_HAVE_FILESYSTEM_SUPPORT && defined(PARALLEL_ENABLE_PLUGINS)
|
||||||
|
|
||||||
|
using namespace cv::plugin::impl; // plugin_loader.hpp
|
||||||
|
|
||||||
|
class PluginParallelBackend CV_FINAL: public std::enable_shared_from_this<PluginParallelBackend>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
void initPluginAPI()
|
||||||
|
{
|
||||||
|
const char* init_name = "opencv_core_parallel_plugin_init_v0";
|
||||||
|
FN_opencv_core_parallel_plugin_init_t fn_init = reinterpret_cast<FN_opencv_core_parallel_plugin_init_t>(lib_->getSymbol(init_name));
|
||||||
|
if (fn_init)
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "Found entry: '" << init_name << "'");
|
||||||
|
for (int supported_api_version = API_VERSION; supported_api_version >= 0; supported_api_version--)
|
||||||
|
{
|
||||||
|
plugin_api_ = fn_init(ABI_VERSION, supported_api_version, NULL);
|
||||||
|
if (plugin_api_)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!plugin_api_)
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "core(parallel): plugin is incompatible (can't be initialized): " << lib_->getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!checkCompatibility(plugin_api_->api_header, ABI_VERSION, API_VERSION, false))
|
||||||
|
{
|
||||||
|
plugin_api_ = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CV_LOG_INFO(NULL, "core(parallel): plugin is ready to use '" << plugin_api_->api_header.api_description << "'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "core(parallel): plugin is incompatible, missing init function: '" << init_name << "', file: " << lib_->getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool checkCompatibility(const OpenCV_API_Header& api_header, unsigned int abi_version, unsigned int api_version, bool checkMinorOpenCVVersion)
|
||||||
|
{
|
||||||
|
if (api_header.opencv_version_major != CV_VERSION_MAJOR)
|
||||||
|
{
|
||||||
|
CV_LOG_ERROR(NULL, "core(parallel): wrong OpenCV major version used by plugin '" << api_header.api_description << "': " <<
|
||||||
|
cv::format("%d.%d, OpenCV version is '" CV_VERSION "'", api_header.opencv_version_major, api_header.opencv_version_minor))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!checkMinorOpenCVVersion)
|
||||||
|
{
|
||||||
|
// no checks for OpenCV minor version
|
||||||
|
}
|
||||||
|
else if (api_header.opencv_version_minor != CV_VERSION_MINOR)
|
||||||
|
{
|
||||||
|
CV_LOG_ERROR(NULL, "core(parallel): wrong OpenCV minor version used by plugin '" << api_header.api_description << "': " <<
|
||||||
|
cv::format("%d.%d, OpenCV version is '" CV_VERSION "'", api_header.opencv_version_major, api_header.opencv_version_minor))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CV_LOG_DEBUG(NULL, "core(parallel): initialized '" << api_header.api_description << "': built with "
|
||||||
|
<< cv::format("OpenCV %d.%d (ABI/API = %d/%d)",
|
||||||
|
api_header.opencv_version_major, api_header.opencv_version_minor,
|
||||||
|
api_header.min_api_version, api_header.api_version)
|
||||||
|
<< ", current OpenCV version is '" CV_VERSION "' (ABI/API = " << abi_version << "/" << api_version << ")"
|
||||||
|
);
|
||||||
|
if (api_header.min_api_version != abi_version) // future: range can be here
|
||||||
|
{
|
||||||
|
// actually this should never happen due to checks in plugin's init() function
|
||||||
|
CV_LOG_ERROR(NULL, "core(parallel): plugin is not supported due to incompatible ABI = " << api_header.min_api_version);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (api_header.api_version != api_version)
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "core(parallel): NOTE: plugin is supported, but there is API version mismath: "
|
||||||
|
<< cv::format("plugin API level (%d) != OpenCV API level (%d)", api_header.api_version, api_version));
|
||||||
|
if (api_header.api_version < api_version)
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "core(parallel): NOTE: some functionality may be unavailable due to lack of support by plugin implementation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::shared_ptr<cv::plugin::impl::DynamicLib> lib_;
|
||||||
|
const OpenCV_Core_Parallel_Plugin_API* plugin_api_;
|
||||||
|
|
||||||
|
PluginParallelBackend(const std::shared_ptr<cv::plugin::impl::DynamicLib>& lib)
|
||||||
|
: lib_(lib)
|
||||||
|
, plugin_api_(NULL)
|
||||||
|
{
|
||||||
|
initPluginAPI();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<cv::parallel::ParallelForAPI> create() const
|
||||||
|
{
|
||||||
|
CV_Assert(plugin_api_);
|
||||||
|
|
||||||
|
CvPluginParallelBackendAPI instancePtr = NULL;
|
||||||
|
|
||||||
|
if (plugin_api_->v0.getInstance)
|
||||||
|
{
|
||||||
|
if (CV_ERROR_OK == plugin_api_->v0.getInstance(&instancePtr))
|
||||||
|
{
|
||||||
|
CV_Assert(instancePtr);
|
||||||
|
// TODO C++20 "aliasing constructor"
|
||||||
|
return std::shared_ptr<cv::parallel::ParallelForAPI>(instancePtr, [](cv::parallel::ParallelForAPI*){}); // empty deleter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::shared_ptr<cv::parallel::ParallelForAPI>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PluginParallelBackendFactory CV_FINAL: public IParallelBackendFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string baseName_;
|
||||||
|
std::shared_ptr<PluginParallelBackend> backend;
|
||||||
|
bool initialized;
|
||||||
|
public:
|
||||||
|
PluginParallelBackendFactory(const std::string& baseName)
|
||||||
|
: baseName_(baseName)
|
||||||
|
, initialized(false)
|
||||||
|
{
|
||||||
|
// nothing, plugins are loaded on demand
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<cv::parallel::ParallelForAPI> create() const CV_OVERRIDE
|
||||||
|
{
|
||||||
|
if (!initialized)
|
||||||
|
{
|
||||||
|
const_cast<PluginParallelBackendFactory*>(this)->initBackend();
|
||||||
|
}
|
||||||
|
if (backend)
|
||||||
|
return backend->create();
|
||||||
|
return std::shared_ptr<cv::parallel::ParallelForAPI>();
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
void initBackend()
|
||||||
|
{
|
||||||
|
AutoLock lock(getInitializationMutex());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!initialized)
|
||||||
|
loadPlugin();
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "core(parallel): exception during plugin loading: " << baseName_ << ". SKIP");
|
||||||
|
}
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
void loadPlugin();
|
||||||
|
};
|
||||||
|
|
||||||
|
static
|
||||||
|
std::vector<FileSystemPath_t> getPluginCandidates(const std::string& baseName)
|
||||||
|
{
|
||||||
|
using namespace cv::utils;
|
||||||
|
using namespace cv::utils::fs;
|
||||||
|
const std::string baseName_l = toLowerCase(baseName);
|
||||||
|
const std::string baseName_u = toUpperCase(baseName);
|
||||||
|
const FileSystemPath_t baseName_l_fs = toFileSystemPath(baseName_l);
|
||||||
|
std::vector<FileSystemPath_t> paths;
|
||||||
|
// TODO OPENCV_PLUGIN_PATH
|
||||||
|
const std::vector<std::string> paths_ = getConfigurationParameterPaths("OPENCV_CORE_PLUGIN_PATH", std::vector<std::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_CORE_PARALLEL_PLUGIN_SUBDIRECTORY
|
||||||
|
paths.push_back(binaryLocation);
|
||||||
|
#else
|
||||||
|
paths.push_back(binaryLocation + toFileSystemPath("/") + toFileSystemPath(CV_CORE_PARALLEL_PLUGIN_SUBDIRECTORY_STR));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const std::string default_expr = libraryPrefix() + "opencv_core_parallel_" + baseName_l + "*" + librarySuffix();
|
||||||
|
const std::string plugin_expr = getConfigurationParameterString((std::string("OPENCV_CORE_PARALLEL_PLUGIN_") + baseName_u).c_str(), default_expr.c_str());
|
||||||
|
std::vector<FileSystemPath_t> results;
|
||||||
|
#ifdef _WIN32
|
||||||
|
FileSystemPath_t moduleName = toFileSystemPath(libraryPrefix() + "opencv_core_parallel_" + baseName_l + librarySuffix());
|
||||||
|
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_DEBUG(NULL, "core(parallel): " << baseName << " plugin's glob is '" << plugin_expr << "', " << paths.size() << " location(s)");
|
||||||
|
for (const std::string& path : paths)
|
||||||
|
{
|
||||||
|
if (path.empty())
|
||||||
|
continue;
|
||||||
|
std::vector<std::string> candidates;
|
||||||
|
cv::glob(utils::fs::join(path, plugin_expr), candidates);
|
||||||
|
CV_LOG_DEBUG(NULL, " - " << path << ": " << candidates.size());
|
||||||
|
copy(candidates.begin(), candidates.end(), back_inserter(results));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
CV_LOG_DEBUG(NULL, "Found " << results.size() << " plugin(s) for " << baseName);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PluginParallelBackendFactory::loadPlugin()
|
||||||
|
{
|
||||||
|
for (const FileSystemPath_t& plugin : getPluginCandidates(baseName_))
|
||||||
|
{
|
||||||
|
auto lib = std::make_shared<cv::plugin::impl::DynamicLib>(plugin);
|
||||||
|
if (!lib->isLoaded())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto pluginBackend = std::make_shared<PluginParallelBackend>(lib);
|
||||||
|
if (!pluginBackend)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pluginBackend->plugin_api_ == NULL)
|
||||||
|
{
|
||||||
|
CV_LOG_ERROR(NULL, "core(parallel): no compatible plugin API for backend: " << baseName_ << " in " << toPrintablePath(plugin));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
// NB: we are going to use parallel backend, so prevent automatic library unloading
|
||||||
|
// (avoid uncontrolled crashes in worker threads of underlying libraries: libgomp, libtbb)
|
||||||
|
// details: https://github.com/opencv/opencv/pull/19470#pullrequestreview-589834777
|
||||||
|
lib->disableAutomaticLibraryUnloading();
|
||||||
|
#endif
|
||||||
|
backend = pluginBackend;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
CV_LOG_WARNING(NULL, "core(parallel): exception during plugin initialization: " << toPrintablePath(plugin) << ". SKIP");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // OPENCV_HAVE_FILESYSTEM_SUPPORT && defined(PARALLEL_ENABLE_PLUGINS)
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace parallel {
|
||||||
|
|
||||||
|
std::shared_ptr<IParallelBackendFactory> createPluginParallelBackendFactory(const std::string& baseName)
|
||||||
|
{
|
||||||
|
#if OPENCV_HAVE_FILESYSTEM_SUPPORT && defined(PARALLEL_ENABLE_PLUGINS)
|
||||||
|
return std::make_shared<impl::PluginParallelBackendFactory>(baseName);
|
||||||
|
#else
|
||||||
|
return std::shared_ptr<IParallelBackendFactory>();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}} // namespace
|
25
modules/core/src/parallel/registry_parallel.hpp
Normal file
25
modules/core/src/parallel/registry_parallel.hpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// 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_CORE_PARALLEL_REGISTRY_HPP
|
||||||
|
#define OPENCV_CORE_PARALLEL_REGISTRY_HPP
|
||||||
|
|
||||||
|
#include "factory_parallel.hpp"
|
||||||
|
|
||||||
|
namespace cv { namespace parallel {
|
||||||
|
|
||||||
|
struct ParallelBackendInfo
|
||||||
|
{
|
||||||
|
int priority; // 1000-<index*10> - default builtin priority
|
||||||
|
// 0 - disabled (OPENCV_PARALLEL_PRIORITY_<name> = 0)
|
||||||
|
// >10000 - prioritized list (OPENCV_PARALLEL_PRIORITY_LIST)
|
||||||
|
std::string name;
|
||||||
|
std::shared_ptr<IParallelBackendFactory> backendFactory;
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::vector<ParallelBackendInfo>& getParallelBackendsInfo();
|
||||||
|
|
||||||
|
}} // namespace
|
||||||
|
|
||||||
|
#endif // OPENCV_CORE_PARALLEL_REGISTRY_HPP
|
167
modules/core/src/parallel/registry_parallel.impl.hpp
Normal file
167
modules/core/src/parallel/registry_parallel.impl.hpp
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
//
|
||||||
|
// Not a standalone header, part of parallel.cpp
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace cv { namespace parallel {
|
||||||
|
|
||||||
|
#define DECLARE_DYNAMIC_BACKEND(name) \
|
||||||
|
ParallelBackendInfo { \
|
||||||
|
1000, name, createPluginParallelBackendFactory(name) \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DECLARE_STATIC_BACKEND(name, createBackendAPI) \
|
||||||
|
ParallelBackendInfo { \
|
||||||
|
1000, name, std::make_shared<cv::parallel::StaticBackendFactory>([=] () -> std::shared_ptr<cv::parallel::ParallelForAPI> { return createBackendAPI(); }) \
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
std::vector<ParallelBackendInfo>& getBuiltinParallelBackendsInfo()
|
||||||
|
{
|
||||||
|
static std::vector<ParallelBackendInfo> g_backends
|
||||||
|
{
|
||||||
|
#ifdef HAVE_TBB
|
||||||
|
DECLARE_STATIC_BACKEND("TBB", createParallelBackendTBB),
|
||||||
|
#elif defined(PARALLEL_ENABLE_PLUGINS)
|
||||||
|
DECLARE_DYNAMIC_BACKEND("ONETBB"), // dedicated oneTBB plugin (interface >= 12000, binary incompatibe with TBB 2017-2020)
|
||||||
|
DECLARE_DYNAMIC_BACKEND("TBB"), // generic TBB plugins
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENMP
|
||||||
|
DECLARE_STATIC_BACKEND("OPENMP", createParallelBackendOpenMP),
|
||||||
|
#elif defined(PARALLEL_ENABLE_PLUGINS)
|
||||||
|
DECLARE_DYNAMIC_BACKEND("OPENMP") // TODO Intel OpenMP?
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
return g_backends;
|
||||||
|
};
|
||||||
|
|
||||||
|
static
|
||||||
|
bool sortByPriority(const ParallelBackendInfo &lhs, const ParallelBackendInfo &rhs)
|
||||||
|
{
|
||||||
|
return lhs.priority > rhs.priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Manages list of enabled backends
|
||||||
|
*/
|
||||||
|
class ParallelBackendRegistry
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::vector<ParallelBackendInfo> enabledBackends;
|
||||||
|
ParallelBackendRegistry()
|
||||||
|
{
|
||||||
|
enabledBackends = getBuiltinParallelBackendsInfo();
|
||||||
|
int N = (int)enabledBackends.size();
|
||||||
|
for (int i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
ParallelBackendInfo& info = enabledBackends[i];
|
||||||
|
info.priority = 1000 - i * 10;
|
||||||
|
}
|
||||||
|
CV_LOG_DEBUG(NULL, "core(parallel): Builtin backends(" << N << "): " << dumpBackends());
|
||||||
|
if (readPrioritySettings())
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "core(parallel): Updated backends priorities: " << dumpBackends());
|
||||||
|
N = (int)enabledBackends.size();
|
||||||
|
}
|
||||||
|
int enabled = 0;
|
||||||
|
for (int i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
ParallelBackendInfo& info = enabledBackends[enabled];
|
||||||
|
if (enabled != i)
|
||||||
|
info = enabledBackends[i];
|
||||||
|
size_t param_priority = utils::getConfigurationParameterSizeT(cv::format("OPENCV_PARALLEL_PRIORITY_%s", info.name.c_str()).c_str(), (size_t)info.priority);
|
||||||
|
CV_Assert(param_priority == (size_t)(int)param_priority); // overflow check
|
||||||
|
if (param_priority > 0)
|
||||||
|
{
|
||||||
|
info.priority = (int)param_priority;
|
||||||
|
enabled++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "core(parallel): Disable backend: " << info.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enabledBackends.resize(enabled);
|
||||||
|
CV_LOG_DEBUG(NULL, "core(parallel): Available backends(" << enabled << "): " << dumpBackends());
|
||||||
|
std::sort(enabledBackends.begin(), enabledBackends.end(), sortByPriority);
|
||||||
|
CV_LOG_INFO(NULL, "core(parallel): Enabled backends(" << enabled << ", sorted by priority): " << (enabledBackends.empty() ? std::string("N/A") : dumpBackends()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::string> tokenize_string(const std::string& input, char token)
|
||||||
|
{
|
||||||
|
std::vector<std::string> result;
|
||||||
|
std::string::size_type prev_pos = 0, pos = 0;
|
||||||
|
while((pos = input.find(token, pos)) != std::string::npos)
|
||||||
|
{
|
||||||
|
result.push_back(input.substr(prev_pos, pos-prev_pos));
|
||||||
|
prev_pos = ++pos;
|
||||||
|
}
|
||||||
|
result.push_back(input.substr(prev_pos));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
bool readPrioritySettings()
|
||||||
|
{
|
||||||
|
bool hasChanges = false;
|
||||||
|
cv::String prioritized_backends = utils::getConfigurationParameterString("OPENCV_PARALLEL_PRIORITY_LIST", NULL);
|
||||||
|
if (prioritized_backends.empty())
|
||||||
|
return hasChanges;
|
||||||
|
CV_LOG_INFO(NULL, "core(parallel): Configured priority list (OPENCV_PARALLEL_PRIORITY_LIST): " << prioritized_backends);
|
||||||
|
const std::vector<std::string> names = tokenize_string(prioritized_backends, ',');
|
||||||
|
for (size_t i = 0; i < names.size(); i++)
|
||||||
|
{
|
||||||
|
const std::string& name = names[i];
|
||||||
|
int priority = (int)(100000 + (names.size() - i) * 1000);
|
||||||
|
bool found = false;
|
||||||
|
for (size_t k = 0; k < enabledBackends.size(); k++)
|
||||||
|
{
|
||||||
|
ParallelBackendInfo& info = enabledBackends[k];
|
||||||
|
if (name == info.name)
|
||||||
|
{
|
||||||
|
info.priority = priority;
|
||||||
|
CV_LOG_DEBUG(NULL, "core(parallel): New backend priority: '" << name << "' => " << info.priority);
|
||||||
|
found = true;
|
||||||
|
hasChanges = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "core(parallel): Adding parallel backend (plugin): '" << name << "'");
|
||||||
|
enabledBackends.push_back(ParallelBackendInfo{priority, name, createPluginParallelBackendFactory(name)});
|
||||||
|
hasChanges = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChanges;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
std::string dumpBackends() const
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
for (size_t i = 0; i < enabledBackends.size(); i++)
|
||||||
|
{
|
||||||
|
if (i > 0) os << "; ";
|
||||||
|
const ParallelBackendInfo& info = enabledBackends[i];
|
||||||
|
os << info.name << '(' << info.priority << ')';
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
static ParallelBackendRegistry& getInstance()
|
||||||
|
{
|
||||||
|
static ParallelBackendRegistry g_instance;
|
||||||
|
return g_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const std::vector<ParallelBackendInfo>& getEnabledBackends() const { return enabledBackends; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const std::vector<ParallelBackendInfo>& getParallelBackendsInfo()
|
||||||
|
{
|
||||||
|
return cv::parallel::ParallelBackendRegistry::getInstance().getEnabledBackends();
|
||||||
|
}
|
||||||
|
|
||||||
|
}} // namespace
|
@ -43,6 +43,10 @@
|
|||||||
#ifndef __OPENCV_PRECOMP_H__
|
#ifndef __OPENCV_PRECOMP_H__
|
||||||
#define __OPENCV_PRECOMP_H__
|
#define __OPENCV_PRECOMP_H__
|
||||||
|
|
||||||
|
#ifdef BUILD_PLUGIN
|
||||||
|
#include "opencv2/core/utility.hpp"
|
||||||
|
#else // BUILD_PLUGIN
|
||||||
|
|
||||||
#include "opencv2/opencv_modules.hpp"
|
#include "opencv2/opencv_modules.hpp"
|
||||||
#include "cvconfig.h"
|
#include "cvconfig.h"
|
||||||
|
|
||||||
@ -375,4 +379,5 @@ int cv_snprintf(char* buf, int len, const char* fmt, ...);
|
|||||||
int cv_vsnprintf(char* buf, int len, const char* fmt, va_list args);
|
int cv_vsnprintf(char* buf, int len, const char* fmt, va_list args);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*_CXCORE_INTERNAL_H_*/
|
#endif // BUILD_PLUGIN
|
||||||
|
#endif // __OPENCV_PRECOMP_H__
|
||||||
|
@ -587,3 +587,8 @@ cv::String getCacheDirectory(const char* /*sub_directory_name*/, const char* /*c
|
|||||||
#endif // OPENCV_HAVE_FILESYSTEM_SUPPORT
|
#endif // OPENCV_HAVE_FILESYSTEM_SUPPORT
|
||||||
|
|
||||||
}}} // namespace
|
}}} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
#if OPENCV_HAVE_FILESYSTEM_SUPPORT
|
||||||
|
#include "plugin_loader.impl.hpp"
|
||||||
|
#endif
|
||||||
|
80
modules/core/src/utils/plugin_loader.impl.hpp
Normal file
80
modules/core/src/utils/plugin_loader.impl.hpp
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
//
|
||||||
|
// Not a standalone header, part of filesystem.cpp
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "opencv2/core/utils/plugin_loader.private.hpp"
|
||||||
|
|
||||||
|
#if !OPENCV_HAVE_FILESYSTEM_SUPPORT
|
||||||
|
#error "Invalid build configuration"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0 // TODO
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_DEBUG + 1
|
||||||
|
#else
|
||||||
|
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_VERBOSE + 1
|
||||||
|
#endif
|
||||||
|
#include <opencv2/core/utils/logger.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace cv { namespace plugin { namespace impl {
|
||||||
|
|
||||||
|
DynamicLib::DynamicLib(const FileSystemPath_t& filename)
|
||||||
|
: handle(0), fname(filename), disableAutoUnloading_(false)
|
||||||
|
{
|
||||||
|
libraryLoad(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicLib::~DynamicLib()
|
||||||
|
{
|
||||||
|
if (!disableAutoUnloading_)
|
||||||
|
{
|
||||||
|
libraryRelease();
|
||||||
|
}
|
||||||
|
else if (handle)
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "skip auto unloading (disabled): " << toPrintablePath(fname));
|
||||||
|
handle = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* DynamicLib::getSymbol(const char* symbolName) const
|
||||||
|
{
|
||||||
|
if (!handle)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void* res = getSymbol_(handle, symbolName);
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "No symbol '" << symbolName << "' in " << toPrintablePath(fname));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string DynamicLib::getName() const
|
||||||
|
{
|
||||||
|
return toPrintablePath(fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicLib::libraryLoad(const FileSystemPath_t& filename)
|
||||||
|
{
|
||||||
|
handle = libraryLoad_(filename);
|
||||||
|
CV_LOG_INFO(NULL, "load " << toPrintablePath(filename) << " => " << (handle ? "OK" : "FAILED"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicLib::libraryRelease()
|
||||||
|
{
|
||||||
|
if (handle)
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "unload "<< toPrintablePath(fname));
|
||||||
|
libraryRelease_(handle);
|
||||||
|
handle = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}}} // namespace
|
@ -1,7 +1,6 @@
|
|||||||
set(VIDEOIO_PLUGIN_LIST "" CACHE STRING "List of videoio backends to be compiled as plugins (ffmpeg, gstreamer, mfx, msmf or special value 'all')")
|
set(VIDEOIO_PLUGIN_LIST "" CACHE STRING "List of videoio backends to be compiled as plugins (ffmpeg, gstreamer, mfx, msmf or special value 'all')")
|
||||||
set(VIDEOIO_ENABLE_PLUGINS "ON" CACHE BOOL "Allow building videoio plugin support")
|
set(VIDEOIO_ENABLE_PLUGINS "ON" CACHE BOOL "Allow building videoio plugin support")
|
||||||
set(VIDEOIO_ENABLE_STRICT_PLUGIN_CHECK "ON" CACHE BOOL "Make sure OpenCV version is the same in plugin and host code")
|
mark_as_advanced(VIDEOIO_PLUGIN_LIST VIDEOIO_ENABLE_PLUGINS)
|
||||||
mark_as_advanced(VIDEOIO_PLUGIN_LIST VIDEOIO_ENABLE_PLUGINS VIDEOIO_ENABLE_STRICT_PLUGIN_CHECK)
|
|
||||||
|
|
||||||
string(REPLACE "," ";" VIDEOIO_PLUGIN_LIST "${VIDEOIO_PLUGIN_LIST}") # support comma-separated list (,) too
|
string(REPLACE "," ";" VIDEOIO_PLUGIN_LIST "${VIDEOIO_PLUGIN_LIST}") # support comma-separated list (,) too
|
||||||
|
|
||||||
@ -212,10 +211,6 @@ if(VIDEOIO_ENABLE_PLUGINS)
|
|||||||
ocv_target_compile_definitions(${the_module} PRIVATE ENABLE_PLUGINS)
|
ocv_target_compile_definitions(${the_module} PRIVATE ENABLE_PLUGINS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(VIDEOIO_ENABLE_STRICT_PLUGIN_CHECK)
|
|
||||||
ocv_target_compile_definitions(${the_module} PRIVATE STRICT_PLUGIN_CHECK)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
ocv_target_link_libraries(${the_module} LINK_PRIVATE ${tgts})
|
ocv_target_link_libraries(${the_module} LINK_PRIVATE ${tgts})
|
||||||
|
|
||||||
# copy FFmpeg dll to the output folder
|
# copy FFmpeg dll to the output folder
|
||||||
|
@ -1,31 +1,19 @@
|
|||||||
macro(add_backend backend_id cond_var)
|
include(FindPkgConfig)
|
||||||
if(${cond_var})
|
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/detect_${backend_id}.cmake")
|
|
||||||
endif()
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
function(ocv_add_external_target name inc link def)
|
# FIXIT: stop using PARENT_SCOPE in dependencies
|
||||||
if(BUILD_SHARED_LIBS)
|
if(PROJECT_NAME STREQUAL "OpenCV")
|
||||||
set(imp IMPORTED)
|
macro(add_backend backend_id cond_var)
|
||||||
endif()
|
if(${cond_var})
|
||||||
add_library(ocv.3rdparty.${name} INTERFACE ${imp})
|
include("${CMAKE_CURRENT_LIST_DIR}/detect_${backend_id}.cmake")
|
||||||
set_target_properties(ocv.3rdparty.${name} PROPERTIES
|
endif()
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${inc}"
|
endmacro()
|
||||||
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${inc}"
|
else()
|
||||||
INTERFACE_COMPILE_DEFINITIONS "${def}")
|
function(add_backend backend_id cond_var)
|
||||||
# When cmake version is greater than or equal to 3.11, INTERFACE_LINK_LIBRARIES no longer applies to interface library
|
if(${cond_var})
|
||||||
# See https://github.com/opencv/opencv/pull/18658
|
include("${CMAKE_CURRENT_LIST_DIR}/detect_${backend_id}.cmake")
|
||||||
if (CMAKE_VERSION VERSION_LESS 3.11)
|
endif()
|
||||||
set_target_properties(ocv.3rdparty.${name} PROPERTIES
|
endfunction()
|
||||||
INTERFACE_LINK_LIBRARIES "${link}")
|
endif()
|
||||||
else()
|
|
||||||
target_link_libraries(ocv.3rdparty.${name} INTERFACE ${link})
|
|
||||||
endif()
|
|
||||||
#
|
|
||||||
if(NOT BUILD_SHARED_LIBS)
|
|
||||||
install(TARGETS ocv.3rdparty.${name} EXPORT OpenCVModules)
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
add_backend("ffmpeg" WITH_FFMPEG)
|
add_backend("ffmpeg" WITH_FFMPEG)
|
||||||
add_backend("gstreamer" WITH_GSTREAMER)
|
add_backend("gstreamer" WITH_GSTREAMER)
|
||||||
|
@ -1,80 +0,0 @@
|
|||||||
#=============================================
|
|
||||||
# standalone build
|
|
||||||
|
|
||||||
include(FindPkgConfig)
|
|
||||||
|
|
||||||
#=============================================
|
|
||||||
# build with OpenCV
|
|
||||||
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVUtils.cmake")
|
|
||||||
|
|
||||||
function(ocv_create_videoio_plugin default_name target target_desc videoio_src_file)
|
|
||||||
|
|
||||||
set(OPENCV_PLUGIN_NAME ${default_name} CACHE STRING "")
|
|
||||||
set(OPENCV_PLUGIN_DESTINATION "" CACHE PATH "")
|
|
||||||
project(${OPENCV_PLUGIN_NAME} LANGUAGES CXX)
|
|
||||||
|
|
||||||
set(BUILD_SHARED_LIBS ON CACHE BOOL "")
|
|
||||||
if(NOT BUILD_SHARED_LIBS)
|
|
||||||
message(FATAL_ERROR "Static plugin build does not make sense")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT OpenCV_SOURCE_DIR)
|
|
||||||
message(FATAL_ERROR "OpenCV_SOURCE_DIR must be set to build the plugin!")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include("${OpenCV_SOURCE_DIR}/modules/videoio/cmake/init.cmake")
|
|
||||||
|
|
||||||
if(NOT TARGET ${target})
|
|
||||||
message(FATAL_ERROR "${target_desc} was not found!")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
get_filename_component(modules_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../.." ABSOLUTE)
|
|
||||||
set(videoio_ROOT "${modules_ROOT}/videoio")
|
|
||||||
set(core_ROOT "${modules_ROOT}/core")
|
|
||||||
set(imgproc_ROOT "${modules_ROOT}/imgproc")
|
|
||||||
set(imgcodecs_ROOT "${modules_ROOT}/imgcodecs")
|
|
||||||
|
|
||||||
add_library(${OPENCV_PLUGIN_NAME} MODULE
|
|
||||||
"${videoio_ROOT}/src/${videoio_src_file}"
|
|
||||||
${OPENCV_PLUGIN_EXTRA_SRC_FILES}
|
|
||||||
)
|
|
||||||
target_include_directories(${OPENCV_PLUGIN_NAME} PRIVATE
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
|
||||||
"${videoio_ROOT}/src"
|
|
||||||
"${videoio_ROOT}/include"
|
|
||||||
"${core_ROOT}/include"
|
|
||||||
"${imgproc_ROOT}/include"
|
|
||||||
"${imgcodecs_ROOT}/include"
|
|
||||||
)
|
|
||||||
target_compile_definitions(${OPENCV_PLUGIN_NAME} PRIVATE BUILD_PLUGIN)
|
|
||||||
|
|
||||||
target_link_libraries(${OPENCV_PLUGIN_NAME} PRIVATE ${target})
|
|
||||||
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES
|
|
||||||
CXX_STANDARD 11
|
|
||||||
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
|
|
||||||
if(WIN32)
|
|
||||||
find_package(OpenCV REQUIRED core imgproc videoio)
|
|
||||||
target_link_libraries(${OPENCV_PLUGIN_NAME} PRIVATE ${OpenCV_LIBS})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT OpenCV_FOUND) # build against sources (Linux)
|
|
||||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/opencv2/opencv_modules.hpp" "#pragma once")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(OPENCV_PLUGIN_DESTINATION)
|
|
||||||
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${OPENCV_PLUGIN_DESTINATION}")
|
|
||||||
message(STATUS "Output destination: ${OPENCV_PLUGIN_DESTINATION}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
install(TARGETS ${OPENCV_PLUGIN_NAME} LIBRARY DESTINATION . COMPONENT plugins)
|
|
||||||
|
|
||||||
message(STATUS "Library name: ${OPENCV_PLUGIN_NAME}")
|
|
||||||
|
|
||||||
endfunction()
|
|
@ -1,10 +1,15 @@
|
|||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
set(OpenCV_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../..")
|
get_filename_component(OpenCV_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../.." ABSOLUTE)
|
||||||
|
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVPluginStandalone.cmake")
|
||||||
|
|
||||||
|
# scan dependencies
|
||||||
set(WITH_FFMPEG ON)
|
set(WITH_FFMPEG ON)
|
||||||
set(OPENCV_FFMPEG_SKIP_BUILD_CHECK ON)
|
set(OPENCV_FFMPEG_SKIP_BUILD_CHECK ON)
|
||||||
include("${OpenCV_SOURCE_DIR}/modules/videoio/cmake/plugin_standalone.cmake")
|
include("${OpenCV_SOURCE_DIR}/modules/videoio/cmake/init.cmake")
|
||||||
ocv_create_videoio_plugin("opencv_videoio_ffmpeg" "ocv.3rdparty.ffmpeg" "FFmpeg" "cap_ffmpeg.cpp")
|
|
||||||
|
set(OPENCV_PLUGIN_DEPS core imgproc imgcodecs)
|
||||||
|
ocv_create_plugin(videoio "opencv_videoio_ffmpeg" "ocv.3rdparty.ffmpeg" "FFmpeg" "src/cap_ffmpeg.cpp")
|
||||||
|
|
||||||
message(STATUS "FFMPEG_libavcodec_VERSION=${FFMPEG_libavcodec_VERSION}")
|
message(STATUS "FFMPEG_libavcodec_VERSION=${FFMPEG_libavcodec_VERSION}")
|
||||||
message(STATUS "FFMPEG_libavformat_VERSION=${FFMPEG_libavformat_VERSION}")
|
message(STATUS "FFMPEG_libavformat_VERSION=${FFMPEG_libavformat_VERSION}")
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
set(OpenCV_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../..")
|
get_filename_component(OpenCV_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../.." ABSOLUTE)
|
||||||
|
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVPluginStandalone.cmake")
|
||||||
|
|
||||||
|
# scan dependencies
|
||||||
set(WITH_GSTREAMER ON)
|
set(WITH_GSTREAMER ON)
|
||||||
include("${OpenCV_SOURCE_DIR}/modules/videoio/cmake/plugin_standalone.cmake")
|
include("${OpenCV_SOURCE_DIR}/modules/videoio/cmake/init.cmake")
|
||||||
ocv_create_videoio_plugin("opencv_videoio_gstreamer" "ocv.3rdparty.gstreamer" "GStreamer" "cap_gstreamer.cpp")
|
|
||||||
|
set(OPENCV_PLUGIN_DEPS core imgproc imgcodecs)
|
||||||
|
ocv_create_plugin(videoio "opencv_videoio_gstreamer" "ocv.3rdparty.gstreamer" "GStreamer" "src/cap_gstreamer.cpp")
|
||||||
|
|
||||||
message(STATUS "Using GStreamer: ${GSTREAMER_VERSION}")
|
message(STATUS "Using GStreamer: ${GSTREAMER_VERSION}")
|
||||||
|
@ -9,66 +9,26 @@
|
|||||||
#include "plugin_capture_api.hpp"
|
#include "plugin_capture_api.hpp"
|
||||||
#include "plugin_writer_api.hpp"
|
#include "plugin_writer_api.hpp"
|
||||||
|
|
||||||
#include "opencv2/core/utils/filesystem.hpp"
|
|
||||||
#include "opencv2/core/utils/configuration.private.hpp"
|
#include "opencv2/core/utils/configuration.private.hpp"
|
||||||
|
#include "opencv2/core/utils/logger.hpp"
|
||||||
|
|
||||||
#include "opencv2/core/private.hpp"
|
#include "opencv2/core/private.hpp"
|
||||||
#include "videoio_registry.hpp"
|
#include "videoio_registry.hpp"
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Dynamic backend implementation
|
// Dynamic backend implementation
|
||||||
|
|
||||||
#include "opencv2/core/utils/logger.hpp"
|
#include "opencv2/core/utils/plugin_loader.private.hpp"
|
||||||
#include <sstream>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#include <windows.h>
|
|
||||||
#elif defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__HAIKU__) || defined(__GLIBC__)
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "backend_plugin_legacy.impl.hpp"
|
#include "backend_plugin_legacy.impl.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace cv { namespace impl {
|
namespace cv { namespace impl {
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if OPENCV_HAVE_FILESYSTEM_SUPPORT && defined(ENABLE_PLUGINS)
|
||||||
typedef HMODULE LibHandle_t;
|
|
||||||
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 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
|
|
||||||
|
|
||||||
|
using namespace cv::plugin::impl; // plugin_loader.hpp
|
||||||
|
|
||||||
static Mutex& getInitializationMutex()
|
static Mutex& getInitializationMutex()
|
||||||
{
|
{
|
||||||
@ -76,125 +36,6 @@ static Mutex& getInitializationMutex()
|
|||||||
return initializationMutex;
|
return initializationMutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
|
||||||
void* getSymbol_(LibHandle_t h, const char* symbolName)
|
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
|
||||||
return (void*)GetProcAddress(h, symbolName);
|
|
||||||
#elif defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__HAIKU__) || defined(__GLIBC__)
|
|
||||||
return dlsym(h, symbolName);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline
|
|
||||||
LibHandle_t libraryLoad_(const FileSystemPath_t& filename)
|
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
|
||||||
# ifdef WINRT
|
|
||||||
return LoadPackagedLibrary(filename.c_str(), 0);
|
|
||||||
# else
|
|
||||||
return LoadLibraryW(filename.c_str());
|
|
||||||
#endif
|
|
||||||
#elif defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__HAIKU__) || defined(__GLIBC__)
|
|
||||||
return dlopen(filename.c_str(), RTLD_LAZY);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline
|
|
||||||
void libraryRelease_(LibHandle_t h)
|
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
|
||||||
FreeLibrary(h);
|
|
||||||
#elif defined(__linux__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__HAIKU__) || defined(__GLIBC__)
|
|
||||||
dlclose(h);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline
|
|
||||||
std::string libraryPrefix()
|
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
|
||||||
return "";
|
|
||||||
#else
|
|
||||||
return "lib";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
static inline
|
|
||||||
std::string librarySuffix()
|
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
|
||||||
const char* suffix = ""
|
|
||||||
CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION)
|
|
||||||
#if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__)
|
|
||||||
"_64"
|
|
||||||
#endif
|
|
||||||
#if defined(_DEBUG) && defined(DEBUG_POSTFIX)
|
|
||||||
CVAUX_STR(DEBUG_POSTFIX)
|
|
||||||
#endif
|
|
||||||
".dll";
|
|
||||||
return suffix;
|
|
||||||
#else
|
|
||||||
return ".so";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================
|
|
||||||
|
|
||||||
class DynamicLib
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
LibHandle_t handle;
|
|
||||||
const FileSystemPath_t fname;
|
|
||||||
|
|
||||||
public:
|
|
||||||
DynamicLib(const FileSystemPath_t& filename)
|
|
||||||
: handle(0), fname(filename)
|
|
||||||
{
|
|
||||||
libraryLoad(filename);
|
|
||||||
}
|
|
||||||
~DynamicLib()
|
|
||||||
{
|
|
||||||
libraryRelease();
|
|
||||||
}
|
|
||||||
bool isLoaded() const
|
|
||||||
{
|
|
||||||
return handle != NULL;
|
|
||||||
}
|
|
||||||
void* getSymbol(const char* symbolName) const
|
|
||||||
{
|
|
||||||
if (!handle)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
void * res = getSymbol_(handle, symbolName);
|
|
||||||
if (!res)
|
|
||||||
CV_LOG_DEBUG(NULL, "No symbol '" << symbolName << "' in " << toPrintablePath(fname));
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
const std::string getName() const { return toPrintablePath(fname); }
|
|
||||||
private:
|
|
||||||
void libraryLoad(const FileSystemPath_t& filename)
|
|
||||||
{
|
|
||||||
handle = libraryLoad_(filename);
|
|
||||||
CV_LOG_INFO(NULL, "load " << toPrintablePath(filename) << " => " << (handle ? "OK" : "FAILED"));
|
|
||||||
}
|
|
||||||
void libraryRelease()
|
|
||||||
{
|
|
||||||
if (handle)
|
|
||||||
{
|
|
||||||
CV_LOG_INFO(NULL, "unload "<< toPrintablePath(fname));
|
|
||||||
libraryRelease_(handle);
|
|
||||||
handle = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
DynamicLib(const DynamicLib &);
|
|
||||||
DynamicLib &operator=(const DynamicLib &);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//============================
|
|
||||||
|
|
||||||
class PluginBackend: public IBackend
|
class PluginBackend: public IBackend
|
||||||
{
|
{
|
||||||
@ -345,12 +186,12 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Ptr<DynamicLib> lib_;
|
Ptr<cv::plugin::impl::DynamicLib> lib_;
|
||||||
const OpenCV_VideoIO_Capture_Plugin_API* capture_api_;
|
const OpenCV_VideoIO_Capture_Plugin_API* capture_api_;
|
||||||
const OpenCV_VideoIO_Writer_Plugin_API* writer_api_;
|
const OpenCV_VideoIO_Writer_Plugin_API* writer_api_;
|
||||||
const OpenCV_VideoIO_Plugin_API_preview* plugin_api_; //!< deprecated
|
const OpenCV_VideoIO_Plugin_API_preview* plugin_api_; //!< deprecated
|
||||||
|
|
||||||
PluginBackend(const Ptr<DynamicLib>& lib)
|
PluginBackend(const Ptr<cv::plugin::impl::DynamicLib>& lib)
|
||||||
: lib_(lib)
|
: lib_(lib)
|
||||||
, capture_api_(NULL), writer_api_(NULL)
|
, capture_api_(NULL), writer_api_(NULL)
|
||||||
, plugin_api_(NULL)
|
, plugin_api_(NULL)
|
||||||
@ -416,11 +257,11 @@ 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 std::string baseName_l = toLowerCase(baseName);
|
||||||
const string baseName_u = toUpperCase(baseName);
|
const std::string baseName_u = toUpperCase(baseName);
|
||||||
const FileSystemPath_t baseName_l_fs = toFileSystemPath(baseName_l);
|
const FileSystemPath_t baseName_l_fs = toFileSystemPath(baseName_l);
|
||||||
vector<FileSystemPath_t> paths;
|
std::vector<FileSystemPath_t> paths;
|
||||||
const vector<string> paths_ = getConfigurationParameterPaths("OPENCV_VIDEOIO_PLUGIN_PATH", vector<string>());
|
const std::vector<std::string> paths_ = getConfigurationParameterPaths("OPENCV_VIDEOIO_PLUGIN_PATH", std::vector<std::string>());
|
||||||
if (paths_.size() != 0)
|
if (paths_.size() != 0)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < paths_.size(); i++)
|
for (size_t i = 0; i < paths_.size(); i++)
|
||||||
@ -441,9 +282,9 @@ std::vector<FileSystemPath_t> getPluginCandidates(const std::string& baseName)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const string default_expr = libraryPrefix() + "opencv_videoio_" + baseName_l + "*" + librarySuffix();
|
const std::string default_expr = libraryPrefix() + "opencv_videoio_" + baseName_l + "*" + librarySuffix();
|
||||||
const string plugin_expr = getConfigurationParameterString((std::string("OPENCV_VIDEOIO_PLUGIN_") + baseName_u).c_str(), default_expr.c_str());
|
const std::string plugin_expr = getConfigurationParameterString((std::string("OPENCV_VIDEOIO_PLUGIN_") + baseName_u).c_str(), default_expr.c_str());
|
||||||
vector<FileSystemPath_t> results;
|
std::vector<FileSystemPath_t> results;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
FileSystemPath_t moduleName = toFileSystemPath(libraryPrefix() + "opencv_videoio_" + baseName_l + librarySuffix());
|
FileSystemPath_t moduleName = toFileSystemPath(libraryPrefix() + "opencv_videoio_" + baseName_l + librarySuffix());
|
||||||
#ifndef WINRT
|
#ifndef WINRT
|
||||||
@ -480,12 +321,12 @@ std::vector<FileSystemPath_t> getPluginCandidates(const std::string& baseName)
|
|||||||
}
|
}
|
||||||
#endif // _DEBUG && DEBUG_POSTFIX
|
#endif // _DEBUG && DEBUG_POSTFIX
|
||||||
#else
|
#else
|
||||||
CV_LOG_INFO(NULL, "VideoIO pluigin (" << baseName << "): glob is '" << plugin_expr << "', " << paths.size() << " location(s)");
|
CV_LOG_INFO(NULL, "VideoIO plugin (" << baseName << "): glob is '" << plugin_expr << "', " << paths.size() << " location(s)");
|
||||||
for (const string & path : paths)
|
for (const std::string& path : paths)
|
||||||
{
|
{
|
||||||
if (path.empty())
|
if (path.empty())
|
||||||
continue;
|
continue;
|
||||||
vector<string> candidates;
|
std::vector<std::string> candidates;
|
||||||
cv::glob(utils::fs::join(path, plugin_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));
|
||||||
@ -499,7 +340,7 @@ void PluginBackendFactory::loadPlugin()
|
|||||||
{
|
{
|
||||||
for (const FileSystemPath_t& plugin : getPluginCandidates(baseName_))
|
for (const FileSystemPath_t& plugin : getPluginCandidates(baseName_))
|
||||||
{
|
{
|
||||||
Ptr<DynamicLib> lib = makePtr<DynamicLib>(plugin);
|
auto lib = makePtr<cv::plugin::impl::DynamicLib>(plugin);
|
||||||
if (!lib->isLoaded())
|
if (!lib->isLoaded())
|
||||||
continue;
|
continue;
|
||||||
try
|
try
|
||||||
@ -834,11 +675,17 @@ Ptr<IVideoWriter> PluginBackend::createWriter(const std::string& filename, int f
|
|||||||
return Ptr<IVideoWriter>();
|
return Ptr<IVideoWriter>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // OPENCV_HAVE_FILESYSTEM_SUPPORT && defined(ENABLE_PLUGINS)
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Ptr<IBackendFactory> createPluginBackendFactory(VideoCaptureAPIs id, const char* baseName)
|
Ptr<IBackendFactory> createPluginBackendFactory(VideoCaptureAPIs id, const char* baseName)
|
||||||
{
|
{
|
||||||
|
#if OPENCV_HAVE_FILESYSTEM_SUPPORT && defined(ENABLE_PLUGINS)
|
||||||
return makePtr<impl::PluginBackendFactory>(id, baseName); //.staticCast<IBackendFactory>();
|
return makePtr<impl::PluginBackendFactory>(id, baseName); //.staticCast<IBackendFactory>();
|
||||||
|
#else
|
||||||
|
return Ptr<IBackendFactory>();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -211,14 +211,6 @@ typedef struct OpenCV_VideoIO_Plugin_API_preview_v0 OpenCV_VideoIO_Plugin_API_pr
|
|||||||
|
|
||||||
#ifdef BUILD_PLUGIN
|
#ifdef BUILD_PLUGIN
|
||||||
|
|
||||||
#ifndef CV_PLUGIN_EXPORTS
|
|
||||||
#if (defined _WIN32 || defined WINCE || defined __CYGWIN__)
|
|
||||||
# define CV_PLUGIN_EXPORTS __declspec(dllexport)
|
|
||||||
#elif defined __GNUC__ && __GNUC__ >= 4
|
|
||||||
# define CV_PLUGIN_EXPORTS __attribute__ ((visibility ("default")))
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CV_PLUGIN_EXPORTS
|
CV_PLUGIN_EXPORTS
|
||||||
const OpenCV_VideoIO_Plugin_API_preview* CV_API_CALL opencv_videoio_plugin_init_v0
|
const OpenCV_VideoIO_Plugin_API_preview* CV_API_CALL opencv_videoio_plugin_init_v0
|
||||||
(int requested_abi_version, int requested_api_version, void* reserved /*NULL*/) CV_NOEXCEPT;
|
(int requested_abi_version, int requested_api_version, void* reserved /*NULL*/) CV_NOEXCEPT;
|
||||||
|
@ -144,14 +144,6 @@ typedef struct OpenCV_VideoIO_Capture_Plugin_API_v1_0 OpenCV_VideoIO_Capture_Plu
|
|||||||
|
|
||||||
#ifdef BUILD_PLUGIN
|
#ifdef BUILD_PLUGIN
|
||||||
|
|
||||||
#ifndef CV_PLUGIN_EXPORTS
|
|
||||||
#if (defined _WIN32 || defined WINCE || defined __CYGWIN__)
|
|
||||||
# define CV_PLUGIN_EXPORTS __declspec(dllexport)
|
|
||||||
#elif defined __GNUC__ && __GNUC__ >= 4
|
|
||||||
# define CV_PLUGIN_EXPORTS __attribute__ ((visibility ("default")))
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CV_PLUGIN_EXPORTS
|
CV_PLUGIN_EXPORTS
|
||||||
const OpenCV_VideoIO_Capture_Plugin_API* CV_API_CALL opencv_videoio_capture_plugin_init_v1
|
const OpenCV_VideoIO_Capture_Plugin_API* CV_API_CALL opencv_videoio_capture_plugin_init_v1
|
||||||
(int requested_abi_version, int requested_api_version, void* reserved /*NULL*/) CV_NOEXCEPT;
|
(int requested_abi_version, int requested_api_version, void* reserved /*NULL*/) CV_NOEXCEPT;
|
||||||
|
@ -146,14 +146,6 @@ typedef struct OpenCV_VideoIO_Writer_Plugin_API_v1_0 OpenCV_VideoIO_Writer_Plugi
|
|||||||
|
|
||||||
#ifdef BUILD_PLUGIN
|
#ifdef BUILD_PLUGIN
|
||||||
|
|
||||||
#ifndef CV_PLUGIN_EXPORTS
|
|
||||||
#if (defined _WIN32 || defined WINCE || defined __CYGWIN__)
|
|
||||||
# define CV_PLUGIN_EXPORTS __declspec(dllexport)
|
|
||||||
#elif defined __GNUC__ && __GNUC__ >= 4
|
|
||||||
# define CV_PLUGIN_EXPORTS __attribute__ ((visibility ("default")))
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CV_PLUGIN_EXPORTS
|
CV_PLUGIN_EXPORTS
|
||||||
const OpenCV_VideoIO_Writer_Plugin_API* CV_API_CALL opencv_videoio_writer_plugin_init_v1
|
const OpenCV_VideoIO_Writer_Plugin_API* CV_API_CALL opencv_videoio_writer_plugin_init_v1
|
||||||
(int requested_abi_version, int requested_api_version, void* reserved /*NULL*/) CV_NOEXCEPT;
|
(int requested_abi_version, int requested_api_version, void* reserved /*NULL*/) CV_NOEXCEPT;
|
||||||
|
Loading…
Reference in New Issue
Block a user