1
0
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:
Vadim Pisarevsky
2015-09-14 11:54:20 +00:00
15 changed files with 884 additions and 431 deletions
+2 -2
View File
@@ -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;
}