Skip to content

Commit db2cefd

Browse files
committed
Merge pull request opencv#19562 from alalek:libva_dynamic
2 parents 504ff97 + a40d308 commit db2cefd

File tree

6 files changed

+123
-25
lines changed

6 files changed

+123
-25
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,10 +395,10 @@ OCV_OPTION(WITH_OPENCL_D3D11_NV "Include NVIDIA OpenCL D3D11 support" WITH_DIREC
395395
OCV_OPTION(WITH_LIBREALSENSE "Include Intel librealsense support" OFF
396396
VISIBLE_IF NOT WITH_INTELPERC
397397
VERIFY HAVE_LIBREALSENSE)
398-
OCV_OPTION(WITH_VA "Include VA support" OFF
398+
OCV_OPTION(WITH_VA "Include VA support" ON
399399
VISIBLE_IF UNIX AND NOT ANDROID
400400
VERIFY HAVE_VA)
401-
OCV_OPTION(WITH_VA_INTEL "Include Intel VA-API/OpenCL support" OFF
401+
OCV_OPTION(WITH_VA_INTEL "Include Intel VA-API/OpenCL support" ON
402402
VISIBLE_IF UNIX AND NOT ANDROID
403403
VERIFY HAVE_VA_INTEL)
404404
OCV_OPTION(WITH_MFX "Include Intel Media SDK support" OFF

cmake/OpenCVFindVA.cmake

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,20 @@
22
# HAVE_VA - libva is available
33
# HAVE_VA_INTEL - OpenCL/libva Intel interoperability extension is available
44

5-
if(UNIX AND NOT ANDROID)
6-
find_path(
5+
find_path(
76
VA_INCLUDE_DIR
87
NAMES va/va.h
9-
PATHS "/usr/include"
8+
PATHS ${VA_ROOT_DIR}
109
PATH_SUFFIXES include
11-
DOC "Path to libva headers")
12-
endif()
10+
DOC "Path to libva headers"
11+
)
1312

1413
if(VA_INCLUDE_DIR)
1514
set(HAVE_VA TRUE)
16-
if(NOT DEFINED VA_LIBRARIES)
15+
if(NOT DEFINED VA_LIBRARIES AND NOT OPENCV_LIBVA_LINK)
1716
set(VA_LIBRARIES "va" "va-drm")
1817
endif()
1918
else()
2019
set(HAVE_VA FALSE)
21-
message(WARNING "libva installation is not found.")
20+
message(STATUS "libva: missing va.h header (VA_INCLUDE_DIR)")
2221
endif()

modules/core/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ endif()
9999
if(HAVE_VA_INTEL_OLD_HEADER)
100100
ocv_append_source_file_compile_definitions("${CMAKE_CURRENT_LIST_DIR}/src/va_intel.cpp" "HAVE_VA_INTEL_OLD_HEADER")
101101
endif()
102+
if(OPENCV_LIBVA_LINK)
103+
ocv_append_source_file_compile_definitions("${CMAKE_CURRENT_LIST_DIR}/src/va_intel.cpp" "OPENCV_LIBVA_LINK=1")
104+
endif()
102105

103106
option(OPENCV_ENABLE_ALLOCATOR_STATS "Enable Allocator metrics" ON)
104107

modules/core/src/va_intel.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ using namespace cv;
3333
#endif
3434
#endif
3535

36+
#ifdef HAVE_VA
37+
#ifndef OPENCV_LIBVA_LINK
38+
#include "va_wrapper.impl.hpp"
39+
#else
40+
namespace cv { namespace detail {
41+
static void init_libva() { /* nothing */ }
42+
}} // namespace
43+
#endif
44+
using namespace cv::detail;
45+
#endif
46+
3647
namespace cv { namespace va_intel {
3748

3849
#ifdef HAVE_VA_INTEL
@@ -54,6 +65,8 @@ Context& initializeContextFromVA(VADisplay display, bool tryInterop)
5465
#if !defined(HAVE_VA)
5566
NO_VA_SUPPORT_ERROR;
5667
#else // !HAVE_VA
68+
init_libva();
69+
5770
# ifdef HAVE_VA_INTEL
5871
contextInitialized = false;
5972
if (tryInterop)
@@ -507,6 +520,8 @@ void convertToVASurface(VADisplay display, InputArray src, VASurfaceID surface,
507520
#if !defined(HAVE_VA)
508521
NO_VA_SUPPORT_ERROR;
509522
#else // !HAVE_VA
523+
init_libva();
524+
510525
const int stype = CV_8UC3;
511526

512527
int srcType = src.type();
@@ -611,6 +626,8 @@ void convertFromVASurface(VADisplay display, VASurfaceID surface, Size size, Out
611626
#if !defined(HAVE_VA)
612627
NO_VA_SUPPORT_ERROR;
613628
#else // !HAVE_VA
629+
init_libva();
630+
614631
const int dtype = CV_8UC3;
615632

616633
// TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying!

modules/core/src/va_wrapper.impl.hpp

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// This file is part of OpenCV project.
2+
// It is subject to the license terms in the LICENSE file found in the top-level directory
3+
// of this distribution and at http://opencv.org/license.html.
4+
5+
//
6+
// Not a standalone header, part of va_intel.cpp
7+
//
8+
9+
#include "opencv2/core/utils/plugin_loader.private.hpp" // DynamicLib
10+
11+
namespace cv { namespace detail {
12+
13+
typedef VAStatus (*FN_vaDeriveImage)(VADisplay dpy, VASurfaceID surface, VAImage *image);
14+
typedef VAStatus (*FN_vaDestroyImage)(VADisplay dpy, VAImageID image);
15+
typedef VAStatus (*FN_vaMapBuffer)(VADisplay dpy, VABufferID buf_id, void **pbuf);
16+
typedef VAStatus (*FN_vaSyncSurface)(VADisplay dpy, VASurfaceID render_target);
17+
typedef VAStatus (*FN_vaUnmapBuffer)(VADisplay dpy, VABufferID buf_id);
18+
19+
static FN_vaDeriveImage fn_vaDeriveImage = NULL;
20+
static FN_vaDestroyImage fn_vaDestroyImage = NULL;
21+
static FN_vaMapBuffer fn_vaMapBuffer = NULL;
22+
static FN_vaSyncSurface fn_vaSyncSurface = NULL;
23+
static FN_vaUnmapBuffer fn_vaUnmapBuffer = NULL;
24+
25+
#define vaDeriveImage fn_vaDeriveImage
26+
#define vaDestroyImage fn_vaDestroyImage
27+
#define vaMapBuffer fn_vaMapBuffer
28+
#define vaSyncSurface fn_vaSyncSurface
29+
#define vaUnmapBuffer fn_vaUnmapBuffer
30+
31+
32+
static std::shared_ptr<cv::plugin::impl::DynamicLib> loadLibVA()
33+
{
34+
std::shared_ptr<cv::plugin::impl::DynamicLib> lib;
35+
const char* envPath = getenv("OPENCV_LIBVA_RUNTIME");
36+
if (envPath)
37+
{
38+
lib = std::make_shared<cv::plugin::impl::DynamicLib>(envPath);
39+
return lib;
40+
}
41+
static const char* const candidates[] = {
42+
"libva.so",
43+
"libva.so.2",
44+
"libva.so.1",
45+
};
46+
for (int i = 0; i < 3; ++i)
47+
{
48+
lib = std::make_shared<cv::plugin::impl::DynamicLib>(candidates[i]);
49+
if (lib->isLoaded())
50+
break;
51+
}
52+
return lib;
53+
}
54+
static void init_libva()
55+
{
56+
static bool initialized = false;
57+
static auto library = loadLibVA();
58+
if (!initialized)
59+
{
60+
if (!library || !library->isLoaded())
61+
{
62+
library.reset();
63+
CV_Error(cv::Error::StsBadFunc, "OpenCV can't load VA library (libva)");
64+
}
65+
auto& lib = *library.get();
66+
#define VA_LOAD_SYMBOL(name) fn_ ## name = reinterpret_cast<FN_ ## name>(lib.getSymbol(#name)); \
67+
if (!fn_ ## name) \
68+
{ \
69+
library.reset(); \
70+
initialized = true; \
71+
CV_Error_(cv::Error::StsBadFunc, ("OpenCV can't load VA library (libva), missing symbol: %s", #name)); \
72+
}
73+
74+
VA_LOAD_SYMBOL(vaDeriveImage);
75+
VA_LOAD_SYMBOL(vaDestroyImage);
76+
VA_LOAD_SYMBOL(vaMapBuffer);
77+
VA_LOAD_SYMBOL(vaSyncSurface);
78+
VA_LOAD_SYMBOL(vaUnmapBuffer);
79+
initialized = true;
80+
}
81+
if (!library)
82+
CV_Error(cv::Error::StsBadFunc, "OpenCV can't load/initialize VA library (libva)");
83+
}
84+
85+
}} // namespace

samples/va_intel/display.cpp.inc

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include <va/va.h>
1111
# include <va/va_drm.h>
1212

13+
#include "opencv2/core.hpp" // cv::format()
14+
1315
namespace va {
1416

1517
bool openDisplay();
@@ -70,10 +72,9 @@ static unsigned readId(const char* devName, const char* idName)
7072
{
7173
long int id = 0;
7274

73-
char fileName[256];
74-
snprintf(fileName, sizeof(fileName), "%s/%s/%s", VA_INTEL_PCI_DIR, devName, idName);
75+
std::string fileName = cv::format("%s/%s/%s", VA_INTEL_PCI_DIR, devName, idName);
7576

76-
FILE* file = fopen(fileName, "r");
77+
FILE* file = fopen(fileName.c_str(), "r");
7778
if (file)
7879
{
7980
char str[16] = "";
@@ -100,9 +101,8 @@ static int findAdapter(unsigned desiredVendorId)
100101
unsigned vendorId = readId(name, "vendor");
101102
if (vendorId == desiredVendorId)
102103
{
103-
char subdirName[256];
104-
snprintf(subdirName, sizeof(subdirName), "%s/%s/%s", VA_INTEL_PCI_DIR, name, "drm");
105-
Directory subdir(subdirName);
104+
std::string subdirName = cv::format("%s/%s/%s", VA_INTEL_PCI_DIR, name, "drm");
105+
Directory subdir(subdirName.c_str());
106106
for (int j = 0; j < subdir.count(); ++j)
107107
{
108108
if (!strncmp(subdir[j]->d_name, "card", 4))
@@ -130,29 +130,23 @@ public:
130130
numbers[1] = adapterIndex;
131131
for (int i = 0; i < NUM_NODES; ++i)
132132
{
133-
int sz = sizeof(VA_INTEL_DRI_DIR) + strlen(names[i]) + 3;
134-
paths[i] = new char [sz];
135-
snprintf(paths[i], sz, "%s%s%d", VA_INTEL_DRI_DIR, names[i], numbers[i]);
133+
paths[i] = cv::format("%s%s%d", VA_INTEL_DRI_DIR, names[i], numbers[i]);
136134
}
137135
}
138136
~NodeInfo()
139137
{
140-
for (int i = 0; i < NUM_NODES; ++i)
141-
{
142-
delete paths[i];
143-
paths[i] = 0;
144-
}
138+
// nothing
145139
}
146140
int count() const
147141
{
148142
return NUM_NODES;
149143
}
150144
const char* path(int index) const
151145
{
152-
return ((index >= 0) && (index < NUM_NODES)) ? paths[index] : 0;
146+
return ((index >= 0) && (index < NUM_NODES)) ? paths[index].c_str() : 0;
153147
}
154148
private:
155-
char* paths[NUM_NODES];
149+
std::string paths[NUM_NODES];
156150
};
157151

158152
static bool openDeviceIntel();

0 commit comments

Comments
 (0)