mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 15:53:03 +04:00
Merge pull request #5272 from avershov:opencl-vaapi-fallback
This commit is contained in:
@@ -22,8 +22,8 @@ if((NOT ANDROID) AND HAVE_OPENGL)
|
||||
add_subdirectory(opengl)
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT ANDROID AND HAVE_VAAPI)
|
||||
add_subdirectory(vaapi)
|
||||
if(UNIX AND NOT ANDROID AND (HAVE_VA OR HAVE_VA_INTEL))
|
||||
add_subdirectory(va_intel)
|
||||
endif()
|
||||
|
||||
if(ANDROID AND BUILD_ANDROID_EXAMPLES)
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
SET(OPENCV_VAAPI_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_imgcodecs opencv_videoio opencv_highgui)
|
||||
SET(OPENCV_VA_INTEL_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_imgcodecs opencv_videoio opencv_highgui)
|
||||
|
||||
ocv_check_dependencies(${OPENCV_VAAPI_SAMPLES_REQUIRED_DEPS})
|
||||
ocv_check_dependencies(${OPENCV_VA_INTEL_SAMPLES_REQUIRED_DEPS})
|
||||
|
||||
if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND)
|
||||
set(project "vaapi")
|
||||
set(project "va_intel")
|
||||
string(TOUPPER "${project}" project_upper)
|
||||
|
||||
project("${project}_samples")
|
||||
|
||||
ocv_include_modules_recurse(${OPENCV_VAAPI_SAMPLES_REQUIRED_DEPS})
|
||||
ocv_include_modules_recurse(${OPENCV_VA_INTEL_SAMPLES_REQUIRED_DEPS})
|
||||
|
||||
# ---------------------------------------------
|
||||
# Define executable targets
|
||||
# ---------------------------------------------
|
||||
MACRO(OPENCV_DEFINE_VAAPI_EXAMPLE name srcs)
|
||||
MACRO(OPENCV_DEFINE_VA_INTEL_EXAMPLE name srcs)
|
||||
set(the_target "example_${project}_${name}")
|
||||
add_executable(${the_target} ${srcs})
|
||||
|
||||
ocv_target_link_libraries(${the_target} ${OPENCV_LINKER_LIBS} ${OPENCV_VAAPI_SAMPLES_REQUIRED_DEPS} ${VAAPI_EXTRA_LIBS})
|
||||
ocv_target_link_libraries(${the_target} ${OPENCV_LINKER_LIBS} ${OPENCV_VA_INTEL_SAMPLES_REQUIRED_DEPS} ${VA_LIBRARIES} ${VA_INTEL_LIBRARIES})
|
||||
|
||||
set_target_properties(${the_target} PROPERTIES
|
||||
OUTPUT_NAME "${project}-example-${name}"
|
||||
@@ -33,6 +33,6 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND)
|
||||
foreach(sample_filename ${all_samples})
|
||||
get_filename_component(sample ${sample_filename} NAME_WE)
|
||||
file(GLOB sample_srcs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${sample}.*)
|
||||
OPENCV_DEFINE_VAAPI_EXAMPLE(${sample} ${sample_srcs})
|
||||
OPENCV_DEFINE_VA_INTEL_EXAMPLE(${sample} ${sample_srcs})
|
||||
endforeach()
|
||||
endif()
|
||||
@@ -7,25 +7,39 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <va/va.h>
|
||||
#include <va/va_drm.h>
|
||||
#include "cvconfig.h"
|
||||
|
||||
#define VAAPI_PCI_DIR "/sys/bus/pci/devices"
|
||||
#define VAAPI_DRI_DIR "/dev/dri/"
|
||||
#define VAAPI_PCI_DISPLAY_CONTROLLER_CLASS 0x03
|
||||
#include <va/va.h>
|
||||
#if defined(HAVE_VA_INTEL)
|
||||
# include <va/va_drm.h>
|
||||
#elif defined(HAVE_VA)
|
||||
# include <va/va_x11.h>
|
||||
# include <X11/Xlib.h>
|
||||
#endif //HAVE_VA_INTEL / HAVE_VA
|
||||
|
||||
namespace va {
|
||||
|
||||
static unsigned readId(const char* devName, const char* idName);
|
||||
static int findAdapter(unsigned desiredVendorId);
|
||||
#if defined(HAVE_VA_INTEL) || defined(HAVE_VA)
|
||||
|
||||
bool openDisplay();
|
||||
void closeDisplay();
|
||||
|
||||
int drmfd = -1;
|
||||
VADisplay display = NULL;
|
||||
bool initialized = false;
|
||||
|
||||
#endif //HAVE_VA_INTEL || HAVE_VA
|
||||
|
||||
#if defined(HAVE_VA_INTEL)
|
||||
|
||||
#define VA_INTEL_PCI_DIR "/sys/bus/pci/devices"
|
||||
#define VA_INTEL_DRI_DIR "/dev/dri/"
|
||||
#define VA_INTEL_PCI_DISPLAY_CONTROLLER_CLASS 0x03
|
||||
|
||||
static unsigned readId(const char* devName, const char* idName);
|
||||
static int findAdapter(unsigned desiredVendorId);
|
||||
|
||||
int drmfd = -1;
|
||||
|
||||
class Directory
|
||||
{
|
||||
typedef int (*fsort)(const struct dirent**, const struct dirent**);
|
||||
@@ -70,7 +84,7 @@ static unsigned readId(const char* devName, const char* idName)
|
||||
long int id = 0;
|
||||
|
||||
char fileName[256];
|
||||
snprintf(fileName, sizeof(fileName), "%s/%s/%s", VAAPI_PCI_DIR, devName, idName);
|
||||
snprintf(fileName, sizeof(fileName), "%s/%s/%s", VA_INTEL_PCI_DIR, devName, idName);
|
||||
|
||||
FILE* file = fopen(fileName, "r");
|
||||
if (file)
|
||||
@@ -88,14 +102,14 @@ static int findAdapter(unsigned desiredVendorId)
|
||||
int adapterIndex = -1;
|
||||
int numAdapters = 0;
|
||||
|
||||
Directory dir(VAAPI_PCI_DIR);
|
||||
Directory dir(VA_INTEL_PCI_DIR);
|
||||
|
||||
for (int i = 0; i < dir.count(); ++i)
|
||||
{
|
||||
const char* name = dir[i]->d_name;
|
||||
|
||||
unsigned classId = readId(name, "class");
|
||||
if ((classId >> 16) == VAAPI_PCI_DISPLAY_CONTROLLER_CLASS)
|
||||
if ((classId >> 16) == VA_INTEL_PCI_DISPLAY_CONTROLLER_CLASS)
|
||||
{
|
||||
unsigned vendorId = readId(name, "vendor");
|
||||
if (vendorId == desiredVendorId)
|
||||
@@ -122,9 +136,9 @@ public:
|
||||
numbers[1] = adapterIndex;
|
||||
for (int i = 0; i < NUM_NODES; ++i)
|
||||
{
|
||||
int sz = sizeof(VAAPI_DRI_DIR) + strlen(names[i]) + 3;
|
||||
int sz = sizeof(VA_INTEL_DRI_DIR) + strlen(names[i]) + 3;
|
||||
paths[i] = new char [sz];
|
||||
snprintf(paths[i], sz, "%s%s%d", VAAPI_DRI_DIR, names[i], numbers[i]);
|
||||
snprintf(paths[i], sz, "%s%s%d", VA_INTEL_DRI_DIR, names[i], numbers[i]);
|
||||
}
|
||||
}
|
||||
~NodeInfo()
|
||||
@@ -205,4 +219,53 @@ void closeDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(HAVE_VA)
|
||||
|
||||
static Display* x11Display = 0;
|
||||
|
||||
bool openDisplay()
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
display = 0;
|
||||
|
||||
x11Display = XOpenDisplay("");
|
||||
if (x11Display != 0)
|
||||
{
|
||||
display = vaGetDisplay(x11Display);
|
||||
if (display)
|
||||
{
|
||||
int majorVersion = 0, minorVersion = 0;
|
||||
if (vaInitialize(display, &majorVersion, &minorVersion) == VA_STATUS_SUCCESS)
|
||||
{
|
||||
initialized = true;
|
||||
return true;
|
||||
}
|
||||
display = 0;
|
||||
}
|
||||
XCloseDisplay(x11Display);
|
||||
x11Display = 0;
|
||||
}
|
||||
|
||||
return false; // Can't initialize X11/VA display
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void closeDisplay()
|
||||
{
|
||||
if (initialized)
|
||||
{
|
||||
if (display)
|
||||
vaTerminate(display);
|
||||
if (x11Display)
|
||||
XCloseDisplay(x11Display);
|
||||
display = 0;
|
||||
x11Display = 0;
|
||||
initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAVE_VA_INTEL / HAVE_VA
|
||||
|
||||
} // namespace va
|
||||
@@ -24,6 +24,8 @@
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@@ -39,11 +41,12 @@
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/core/vaapi.hpp"
|
||||
#include "opencv2/core/va_intel.hpp"
|
||||
#include "cvconfig.h"
|
||||
|
||||
#define CHECK_VASTATUS(va_status,func) \
|
||||
if (va_status != VA_STATUS_SUCCESS) { \
|
||||
fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
|
||||
fprintf(stderr,"%s:%s (%d) failed(status=0x%08x),exit\n", __func__, func, __LINE__, va_status); \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
@@ -129,7 +132,55 @@ static VASliceParameterBufferMPEG2 slice_param={
|
||||
#define CLIP_WIDTH 16
|
||||
#define CLIP_HEIGHT 16
|
||||
|
||||
static void dumpSurface(VADisplay display, VASurfaceID surface_id, const char* fileName)
|
||||
class Timer
|
||||
{
|
||||
public:
|
||||
enum UNITS
|
||||
{
|
||||
USEC = 0,
|
||||
MSEC,
|
||||
SEC
|
||||
};
|
||||
|
||||
Timer() : m_t0(0), m_diff(0)
|
||||
{
|
||||
m_tick_frequency = (float)cv::getTickFrequency();
|
||||
|
||||
m_unit_mul[USEC] = 1000000;
|
||||
m_unit_mul[MSEC] = 1000;
|
||||
m_unit_mul[SEC] = 1;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_t0 = m_diff = 0;
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
m_t0 = cv::getTickCount();
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
m_diff = cv::getTickCount() - m_t0;
|
||||
}
|
||||
|
||||
float time(UNITS u = MSEC)
|
||||
{
|
||||
float sec = m_diff / m_tick_frequency;
|
||||
|
||||
return sec * m_unit_mul[u];
|
||||
}
|
||||
|
||||
public:
|
||||
float m_tick_frequency;
|
||||
int64 m_t0;
|
||||
int64 m_diff;
|
||||
int m_unit_mul[3];
|
||||
};
|
||||
|
||||
static void dumpSurface(VADisplay display, VASurfaceID surface_id, const char* fileName, bool doInterop)
|
||||
{
|
||||
VAStatus va_status;
|
||||
|
||||
@@ -153,7 +204,8 @@ static void dumpSurface(VADisplay display, VASurfaceID surface_id, const char* f
|
||||
printf("image.pitches[0..2] = 0x%08x 0x%08x 0x%08x\n", image.pitches[0], image.pitches[1], image.pitches[2]);
|
||||
printf("image.offsets[0..2] = 0x%08x 0x%08x 0x%08x\n", image.offsets[0], image.offsets[1], image.offsets[2]);
|
||||
*/
|
||||
FILE* out = fopen(fileName, "wb");
|
||||
std::string fn = std::string(fileName) + std::string(doInterop ? ".on" : ".off");
|
||||
FILE* out = fopen(fn.c_str(), "wb");
|
||||
if (!out)
|
||||
{
|
||||
perror(fileName);
|
||||
@@ -169,10 +221,8 @@ static void dumpSurface(VADisplay display, VASurfaceID surface_id, const char* f
|
||||
CHECK_VASTATUS(va_status, "vaDestroyImage");
|
||||
}
|
||||
|
||||
int main(int argc,char **argv)
|
||||
static float run(const char* fn1, const char* fn2, bool doInterop)
|
||||
{
|
||||
(void)argc; (void)argv;
|
||||
|
||||
VAEntrypoint entrypoints[5];
|
||||
int num_entrypoints,vld_entrypoint;
|
||||
VAConfigAttrib attrib;
|
||||
@@ -181,24 +231,9 @@ int main(int argc,char **argv)
|
||||
VAContextID context_id;
|
||||
VABufferID pic_param_buf,iqmatrix_buf,slice_param_buf,slice_data_buf;
|
||||
VAStatus va_status;
|
||||
Timer t;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: vaapi_interop file1 file2\n\n"
|
||||
"where: file1 is to be created, contains original surface data (NV12)\n"
|
||||
" file2 is to be created, contains processed surface data (NV12)\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!va::openDisplay())
|
||||
{
|
||||
fprintf(stderr, "Failed to open VA display for CL-VA interoperability\n");
|
||||
exit(1);
|
||||
}
|
||||
fprintf(stderr, "VA display opened successfully\n");
|
||||
|
||||
cv::vaapi::ocl::initializeContextFromVA(va::display);
|
||||
cv::va_intel::ocl::initializeContextFromVA(va::display, doInterop);
|
||||
|
||||
va_status = vaQueryConfigEntrypoints(va::display, VAProfileMPEG2Main, entrypoints,
|
||||
&num_entrypoints);
|
||||
@@ -294,22 +329,113 @@ int main(int argc,char **argv)
|
||||
va_status = vaSyncSurface(va::display, surface_id);
|
||||
CHECK_VASTATUS(va_status, "vaSyncSurface");
|
||||
|
||||
dumpSurface(va::display, surface_id, argv[1]);
|
||||
dumpSurface(va::display, surface_id, fn1, doInterop);
|
||||
|
||||
cv::Size size(CLIP_WIDTH,CLIP_HEIGHT);
|
||||
cv::UMat u;
|
||||
|
||||
cv::vaapi::convertFromVASurface(surface_id, size, u);
|
||||
cv::va_intel::convertFromVASurface(va::display, surface_id, size, u);
|
||||
cv::blur(u, u, cv::Size(7, 7), cv::Point(-3, -3));
|
||||
cv::vaapi::convertToVASurface(u, surface_id, size);
|
||||
cv::va_intel::convertToVASurface(va::display, u, surface_id, size);
|
||||
t.start();
|
||||
cv::va_intel::convertFromVASurface(va::display, surface_id, size, u);
|
||||
cv::blur(u, u, cv::Size(7, 7), cv::Point(-3, -3));
|
||||
cv::va_intel::convertToVASurface(va::display, u, surface_id, size);
|
||||
t.stop();
|
||||
|
||||
dumpSurface(va::display, surface_id, argv[2]);
|
||||
dumpSurface(va::display, surface_id, fn2, doInterop);
|
||||
|
||||
vaDestroySurfaces(va::display,&surface_id,1);
|
||||
vaDestroyConfig(va::display,config_id);
|
||||
vaDestroyContext(va::display,context_id);
|
||||
|
||||
vaTerminate(va::display);
|
||||
return t.time(Timer::MSEC);
|
||||
}
|
||||
|
||||
class CmdlineParser
|
||||
{
|
||||
public:
|
||||
CmdlineParser(int argc, char** argv):
|
||||
m_argc(argc), m_argv(argv)
|
||||
{}
|
||||
// true => go, false => usage/exit; extra args/unknown options are ignored for simplicity
|
||||
bool run()
|
||||
{
|
||||
int n = 0;
|
||||
m_files[0] = m_files[1] = 0;
|
||||
#if defined(HAVE_VA_INTEL)
|
||||
m_interop = true;
|
||||
#elif defined(HAVE_VA)
|
||||
m_interop = false;
|
||||
#endif //HAVE_VA_INTEL / HAVE_VA
|
||||
for (int i = 1; i < m_argc; ++i)
|
||||
{
|
||||
const char *arg = m_argv[i];
|
||||
if (arg[0] == '-') // option
|
||||
{
|
||||
#if defined(HAVE_VA_INTEL)
|
||||
if (!strcmp(arg, "-f"))
|
||||
m_interop = false;
|
||||
#endif //HAVE_VA_INTEL
|
||||
}
|
||||
else // parameter
|
||||
{
|
||||
if (n < 2)
|
||||
m_files[n++] = arg;
|
||||
}
|
||||
}
|
||||
return bool(n >= 2);
|
||||
}
|
||||
bool isInterop() const
|
||||
{
|
||||
return m_interop;
|
||||
}
|
||||
const char* getFile(int n) const
|
||||
{
|
||||
return ((n >= 0) && (n < 2)) ? m_files[n] : 0;
|
||||
}
|
||||
private:
|
||||
int m_argc;
|
||||
char** m_argv;
|
||||
const char* m_files[2];
|
||||
bool m_interop;
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
CmdlineParser cmd(argc, argv);
|
||||
if (!cmd.run())
|
||||
{
|
||||
fprintf(stderr,
|
||||
#if defined(HAVE_VA_INTEL)
|
||||
"Usage: va_intel_interop [-f] file1 file2\n\n"
|
||||
"Interop ON/OFF version\n\n"
|
||||
"where: -f option indicates interop is off (fallback mode); interop is on by default\n"
|
||||
#elif defined(HAVE_VA)
|
||||
"Usage: va_intel_interop file1 file2\n\n"
|
||||
"Interop OFF only version\n\n"
|
||||
"where:\n"
|
||||
#endif //HAVE_VA_INTEL / HAVE_VA
|
||||
" file1 is to be created, contains original surface data (NV12)\n"
|
||||
" file2 is to be created, contains processed surface data (NV12)\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!va::openDisplay())
|
||||
{
|
||||
fprintf(stderr, "Failed to open VA display for CL-VA interoperability\n");
|
||||
exit(1);
|
||||
}
|
||||
fprintf(stderr, "VA display opened successfully\n");
|
||||
|
||||
const char* file0 = cmd.getFile(0);
|
||||
const char* file1 = cmd.getFile(1);
|
||||
bool doInterop = cmd.isInterop();
|
||||
|
||||
float time = run(file0, file1, doInterop);
|
||||
|
||||
fprintf(stderr, "Interop %s: processing time, msec: %7.3f\n", (doInterop ? "ON " : "OFF"), time);
|
||||
|
||||
va::closeDisplay();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user