core(libva): use dynamic loader
authorAlexander Alekhin <alexander.a.alekhin@gmail.com>
Thu, 18 Feb 2021 13:36:07 +0000 (13:36 +0000)
committerAlexander Alekhin <alexander.a.alekhin@gmail.com>
Fri, 19 Feb 2021 10:32:59 +0000 (10:32 +0000)
CMakeLists.txt
cmake/OpenCVFindVA.cmake
modules/core/CMakeLists.txt
modules/core/src/va_intel.cpp
modules/core/src/va_wrapper.impl.hpp [new file with mode: 0644]

index e5d511c..39cbe99 100644 (file)
@@ -395,10 +395,10 @@ OCV_OPTION(WITH_OPENCL_D3D11_NV "Include NVIDIA OpenCL D3D11 support" WITH_DIREC
 OCV_OPTION(WITH_LIBREALSENSE "Include Intel librealsense support" OFF
   VISIBLE_IF NOT WITH_INTELPERC
   VERIFY HAVE_LIBREALSENSE)
-OCV_OPTION(WITH_VA "Include VA support" OFF
+OCV_OPTION(WITH_VA "Include VA support" ON
   VISIBLE_IF UNIX AND NOT ANDROID
   VERIFY HAVE_VA)
-OCV_OPTION(WITH_VA_INTEL "Include Intel VA-API/OpenCL support" OFF
+OCV_OPTION(WITH_VA_INTEL "Include Intel VA-API/OpenCL support" ON
   VISIBLE_IF UNIX AND NOT ANDROID
   VERIFY HAVE_VA_INTEL)
 OCV_OPTION(WITH_MFX "Include Intel Media SDK support" OFF
index 9d0ceec..08d034f 100644 (file)
@@ -2,21 +2,20 @@
 #   HAVE_VA - libva is available
 #   HAVE_VA_INTEL - OpenCL/libva Intel interoperability extension is available
 
-if(UNIX AND NOT ANDROID)
-    find_path(
+find_path(
     VA_INCLUDE_DIR
     NAMES va/va.h
-    PATHS "/usr/include"
+    PATHS ${VA_ROOT_DIR}
     PATH_SUFFIXES include
-    DOC "Path to libva headers")
-endif()
+    DOC "Path to libva headers"
+)
 
 if(VA_INCLUDE_DIR)
     set(HAVE_VA TRUE)
-    if(NOT DEFINED VA_LIBRARIES)
+    if(NOT DEFINED VA_LIBRARIES AND NOT OPENCV_LIBVA_LINK)
       set(VA_LIBRARIES "va" "va-drm")
     endif()
 else()
     set(HAVE_VA FALSE)
-    message(WARNING "libva installation is not found.")
+    message(STATUS "libva: missing va.h header (VA_INCLUDE_DIR)")
 endif()
index 7db7169..470f3b9 100644 (file)
@@ -99,6 +99,9 @@ endif()
 if(HAVE_VA_INTEL_OLD_HEADER)
   ocv_append_source_file_compile_definitions("${CMAKE_CURRENT_LIST_DIR}/src/va_intel.cpp" "HAVE_VA_INTEL_OLD_HEADER")
 endif()
+if(OPENCV_LIBVA_LINK)
+  ocv_append_source_file_compile_definitions("${CMAKE_CURRENT_LIST_DIR}/src/va_intel.cpp" "OPENCV_LIBVA_LINK=1")
+endif()
 
 option(OPENCV_ENABLE_ALLOCATOR_STATS "Enable Allocator metrics" ON)
 
index c640a08..c81e6f3 100644 (file)
@@ -33,6 +33,17 @@ using namespace cv;
 #endif
 #endif
 
+#ifdef HAVE_VA
+#ifndef OPENCV_LIBVA_LINK
+#include "va_wrapper.impl.hpp"
+#else
+namespace cv { namespace detail {
+static void init_libva() { /* nothing */ }
+}}  // namespace
+#endif
+using namespace cv::detail;
+#endif
+
 namespace cv { namespace va_intel {
 
 #ifdef HAVE_VA_INTEL
@@ -54,6 +65,8 @@ Context& initializeContextFromVA(VADisplay display, bool tryInterop)
 #if !defined(HAVE_VA)
     NO_VA_SUPPORT_ERROR;
 #else  // !HAVE_VA
+    init_libva();
+
 #   ifdef HAVE_VA_INTEL
     contextInitialized = false;
     if (tryInterop)
@@ -507,6 +520,8 @@ void convertToVASurface(VADisplay display, InputArray src, VASurfaceID surface,
 #if !defined(HAVE_VA)
     NO_VA_SUPPORT_ERROR;
 #else  // !HAVE_VA
+    init_libva();
+
     const int stype = CV_8UC3;
 
     int srcType = src.type();
@@ -611,6 +626,8 @@ void convertFromVASurface(VADisplay display, VASurfaceID surface, Size size, Out
 #if !defined(HAVE_VA)
     NO_VA_SUPPORT_ERROR;
 #else  // !HAVE_VA
+    init_libva();
+
     const int dtype = CV_8UC3;
 
     // TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying!
diff --git a/modules/core/src/va_wrapper.impl.hpp b/modules/core/src/va_wrapper.impl.hpp
new file mode 100644 (file)
index 0000000..260d3ba
--- /dev/null
@@ -0,0 +1,85 @@
+// 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 va_intel.cpp
+//
+
+#include "opencv2/core/utils/plugin_loader.private.hpp"  // DynamicLib
+
+namespace cv { namespace detail {
+
+typedef VAStatus (*FN_vaDeriveImage)(VADisplay dpy, VASurfaceID surface, VAImage *image);
+typedef VAStatus (*FN_vaDestroyImage)(VADisplay dpy, VAImageID image);
+typedef VAStatus (*FN_vaMapBuffer)(VADisplay dpy, VABufferID buf_id, void **pbuf);
+typedef VAStatus (*FN_vaSyncSurface)(VADisplay dpy, VASurfaceID render_target);
+typedef VAStatus (*FN_vaUnmapBuffer)(VADisplay dpy, VABufferID buf_id);
+
+static FN_vaDeriveImage fn_vaDeriveImage = NULL;
+static FN_vaDestroyImage fn_vaDestroyImage = NULL;
+static FN_vaMapBuffer fn_vaMapBuffer = NULL;
+static FN_vaSyncSurface fn_vaSyncSurface = NULL;
+static FN_vaUnmapBuffer fn_vaUnmapBuffer = NULL;
+
+#define vaDeriveImage fn_vaDeriveImage
+#define vaDestroyImage fn_vaDestroyImage
+#define vaMapBuffer fn_vaMapBuffer
+#define vaSyncSurface fn_vaSyncSurface
+#define vaUnmapBuffer fn_vaUnmapBuffer
+
+
+static std::shared_ptr<cv::plugin::impl::DynamicLib> loadLibVA()
+{
+    std::shared_ptr<cv::plugin::impl::DynamicLib> lib;
+    const char* envPath = getenv("OPENCV_LIBVA_RUNTIME");
+    if (envPath)
+    {
+        lib = std::make_shared<cv::plugin::impl::DynamicLib>(envPath);
+        return lib;
+    }
+    static const char* const candidates[] = {
+        "libva.so",
+        "libva.so.2",
+        "libva.so.1",
+    };
+    for (int i = 0; i < 3; ++i)
+    {
+        lib = std::make_shared<cv::plugin::impl::DynamicLib>(candidates[i]);
+        if (lib->isLoaded())
+            break;
+    }
+    return lib;
+}
+static void init_libva()
+{
+    static bool initialized = false;
+    static auto library = loadLibVA();
+    if (!initialized)
+    {
+        if (!library || !library->isLoaded())
+        {
+            library.reset();
+            CV_Error(cv::Error::StsBadFunc, "OpenCV can't load VA library (libva)");
+        }
+        auto& lib = *library.get();
+#define VA_LOAD_SYMBOL(name) fn_ ## name = reinterpret_cast<FN_ ## name>(lib.getSymbol(#name)); \
+        if (!fn_ ## name) \
+        { \
+            library.reset(); \
+            initialized = true; \
+            CV_Error_(cv::Error::StsBadFunc, ("OpenCV can't load VA library (libva), missing symbol: %s", #name)); \
+        }
+
+        VA_LOAD_SYMBOL(vaDeriveImage);
+        VA_LOAD_SYMBOL(vaDestroyImage);
+        VA_LOAD_SYMBOL(vaMapBuffer);
+        VA_LOAD_SYMBOL(vaSyncSurface);
+        VA_LOAD_SYMBOL(vaUnmapBuffer);
+        initialized = true;
+    }
+    if (!library)
+        CV_Error(cv::Error::StsBadFunc, "OpenCV can't load/initialize VA library (libva)");
+}
+
+}}  // namespace