implemented core support & sample

fixed whitespaces
fixed issues
fixed issue
fixed module statement issues
fixed access mode
added initialization check
fixed warning
This commit is contained in:
Alexey Ershov
2015-08-12 11:59:05 +03:00
parent 09b9b0fb9e
commit a8656ea20f
11 changed files with 1002 additions and 0 deletions

View File

@@ -22,6 +22,10 @@ if((NOT ANDROID) AND HAVE_OPENGL)
add_subdirectory(opengl)
endif()
if(UNIX AND NOT ANDROID AND HAVE_VAAPI)
add_subdirectory(vaapi)
endif()
if(ANDROID AND BUILD_ANDROID_EXAMPLES)
add_subdirectory(android)
endif()

View File

@@ -0,0 +1,38 @@
SET(OPENCV_VAAPI_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_imgcodecs opencv_videoio opencv_highgui)
ocv_check_dependencies(${OPENCV_VAAPI_SAMPLES_REQUIRED_DEPS})
if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND)
set(project "vaapi")
string(TOUPPER "${project}" project_upper)
project("${project}_samples")
ocv_include_modules_recurse(${OPENCV_VAAPI_SAMPLES_REQUIRED_DEPS})
# ---------------------------------------------
# Define executable targets
# ---------------------------------------------
MACRO(OPENCV_DEFINE_VAAPI_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})
set_target_properties(${the_target} PROPERTIES
OUTPUT_NAME "${project}-example-${name}"
PROJECT_LABEL "(EXAMPLE_${project_upper}) ${name}")
if(ENABLE_SOLUTION_FOLDERS)
set_target_properties(${the_target} PROPERTIES FOLDER "samples//${project}")
endif()
ENDMACRO()
file(GLOB all_samples RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp)
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})
endforeach()
endif()

View File

@@ -0,0 +1,208 @@
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <va/va.h>
#include <va/va_drm.h>
#define VAAPI_PCI_DIR "/sys/bus/pci/devices"
#define VAAPI_DRI_DIR "/dev/dri/"
#define VAAPI_PCI_DISPLAY_CONTROLLER_CLASS 0x03
namespace va {
static unsigned readId(const char* devName, const char* idName);
static int findAdapter(unsigned desiredVendorId);
bool openDisplay();
void closeDisplay();
int drmfd = -1;
VADisplay display = NULL;
bool initialized = false;
class Directory
{
typedef int (*fsort)(const struct dirent**, const struct dirent**);
public:
Directory(const char* path)
{
dirEntries = 0;
numEntries = scandir(path, &dirEntries, filterFunc, (fsort)alphasort);
}
~Directory()
{
if (numEntries && dirEntries)
{
for (int i = 0; i < numEntries; ++i)
free(dirEntries[i]);
free(dirEntries);
}
}
int count() const
{
return numEntries;
}
const struct dirent* operator[](int index) const
{
return ((dirEntries != 0) && (index >= 0) && (index < numEntries)) ? dirEntries[index] : 0;
}
protected:
static int filterFunc(const struct dirent* dir)
{
if (!dir) return 0;
if (!strcmp(dir->d_name, ".")) return 0;
if (!strcmp(dir->d_name, "..")) return 0;
return 1;
}
private:
int numEntries;
struct dirent** dirEntries;
};
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);
FILE* file = fopen(fileName, "r");
if (file)
{
char str[16] = "";
if (fgets(str, sizeof(str), file))
id = strtol(str, NULL, 16);
fclose(file);
}
return (unsigned)id;
}
static int findAdapter(unsigned desiredVendorId)
{
int adapterIndex = -1;
int numAdapters = 0;
Directory dir(VAAPI_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)
{
unsigned vendorId = readId(name, "vendor");
if (vendorId == desiredVendorId)
{
adapterIndex = numAdapters;
break;
}
++numAdapters;
}
}
return adapterIndex;
}
class NodeInfo
{
enum { NUM_NODES = 2 };
public:
NodeInfo(int adapterIndex)
{
const char* names[NUM_NODES] = { "renderD", "card" };
int numbers[NUM_NODES];
numbers[0] = adapterIndex+128;
numbers[1] = adapterIndex;
for (int i = 0; i < NUM_NODES; ++i)
{
int sz = sizeof(VAAPI_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]);
}
}
~NodeInfo()
{
for (int i = 0; i < NUM_NODES; ++i)
{
delete paths[i];
paths[i] = 0;
}
}
int count() const
{
return NUM_NODES;
}
const char* path(int index) const
{
return ((index >= 0) && (index < NUM_NODES)) ? paths[index] : 0;
}
private:
char* paths[NUM_NODES];
};
bool openDisplay()
{
if (!initialized)
{
const unsigned IntelVendorID = 0x8086;
drmfd = -1;
display = 0;
int adapterIndex = findAdapter(IntelVendorID);
if (adapterIndex >= 0)
{
NodeInfo nodes(adapterIndex);
for (int i = 0; i < nodes.count(); ++i)
{
drmfd = open(nodes.path(i), O_RDWR);
if (drmfd >= 0)
{
display = vaGetDisplayDRM(drmfd);
if (display)
{
int majorVersion = 0, minorVersion = 0;
if (vaInitialize(display, &majorVersion, &minorVersion) == VA_STATUS_SUCCESS)
{
initialized = true;
return true;
}
display = 0;
}
close(drmfd);
drmfd = -1;
}
}
}
if (adapterIndex < 0)
return false; // Can't find Intel display adapter
if ((drmfd < 0) || !display)
return false; // Can't load VA display
}
return true;
}
void closeDisplay()
{
if (initialized)
{
if (display)
vaTerminate(display);
if (drmfd >= 0)
close(drmfd);
display = 0;
drmfd = -1;
initialized = false;
}
}
} // namespace va

View File

@@ -0,0 +1,315 @@
/* origin: libva-1.3.1/test/decode/mpeg2vldemo.cpp */
/*
* Copyright (c) 2007-2008 Intel Corporation. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <va/va.h>
#include "display.cpp.inc"
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/core/vaapi.hpp"
#define CHECK_VASTATUS(va_status,func) \
if (va_status != VA_STATUS_SUCCESS) { \
fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
exit(1); \
}
/* Data dump of a 16x16 MPEG2 video clip,it has one I frame
*/
static unsigned char mpeg2_clip[]={
0x00,0x00,0x01,0xb3,0x01,0x00,0x10,0x13,0xff,0xff,0xe0,0x18,0x00,0x00,0x01,0xb5,
0x14,0x8a,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0xb8,0x00,0x08,0x00,0x00,0x00,0x00,
0x01,0x00,0x00,0x0f,0xff,0xf8,0x00,0x00,0x01,0xb5,0x8f,0xff,0xf3,0x41,0x80,0x00,
0x00,0x01,0x01,0x13,0xe1,0x00,0x15,0x81,0x54,0xe0,0x2a,0x05,0x43,0x00,0x2d,0x60,
0x18,0x01,0x4e,0x82,0xb9,0x58,0xb1,0x83,0x49,0xa4,0xa0,0x2e,0x05,0x80,0x4b,0x7a,
0x00,0x01,0x38,0x20,0x80,0xe8,0x05,0xff,0x60,0x18,0xe0,0x1d,0x80,0x98,0x01,0xf8,
0x06,0x00,0x54,0x02,0xc0,0x18,0x14,0x03,0xb2,0x92,0x80,0xc0,0x18,0x94,0x42,0x2c,
0xb2,0x11,0x64,0xa0,0x12,0x5e,0x78,0x03,0x3c,0x01,0x80,0x0e,0x80,0x18,0x80,0x6b,
0xca,0x4e,0x01,0x0f,0xe4,0x32,0xc9,0xbf,0x01,0x42,0x69,0x43,0x50,0x4b,0x01,0xc9,
0x45,0x80,0x50,0x01,0x38,0x65,0xe8,0x01,0x03,0xf3,0xc0,0x76,0x00,0xe0,0x03,0x20,
0x28,0x18,0x01,0xa9,0x34,0x04,0xc5,0xe0,0x0b,0x0b,0x04,0x20,0x06,0xc0,0x89,0xff,
0x60,0x12,0x12,0x8a,0x2c,0x34,0x11,0xff,0xf6,0xe2,0x40,0xc0,0x30,0x1b,0x7a,0x01,
0xa9,0x0d,0x00,0xac,0x64
};
/* hardcoded here without a bitstream parser helper
* please see picture mpeg2-I.jpg for bitstream details
*/
static VAPictureParameterBufferMPEG2 pic_param={
horizontal_size:16,
vertical_size:16,
forward_reference_picture:0xffffffff,
backward_reference_picture:0xffffffff,
picture_coding_type:1,
f_code:0xffff,
{
{
intra_dc_precision:0,
picture_structure:3,
top_field_first:0,
frame_pred_frame_dct:1,
concealment_motion_vectors:0,
q_scale_type:0,
intra_vlc_format:0,
alternate_scan:0,
repeat_first_field:0,
progressive_frame:1 ,
is_first_field:1
},
}
};
/* see MPEG2 spec65 for the defines of matrix */
static VAIQMatrixBufferMPEG2 iq_matrix = {
load_intra_quantiser_matrix:1,
load_non_intra_quantiser_matrix:1,
load_chroma_intra_quantiser_matrix:0,
load_chroma_non_intra_quantiser_matrix:0,
intra_quantiser_matrix:{
8, 16, 16, 19, 16, 19, 22, 22,
22, 22, 22, 22, 26, 24, 26, 27,
27, 27, 26, 26, 26, 26, 27, 27,
27, 29, 29, 29, 34, 34, 34, 29,
29, 29, 27, 27, 29, 29, 32, 32,
34, 34, 37, 38, 37, 35, 35, 34,
35, 38, 38, 40, 40, 40, 48, 48,
46, 46, 56, 56, 58, 69, 69, 83
},
non_intra_quantiser_matrix:{16},
chroma_intra_quantiser_matrix:{0},
chroma_non_intra_quantiser_matrix:{0}
};
#if 1
static VASliceParameterBufferMPEG2 slice_param={
slice_data_size:150,
slice_data_offset:0,
slice_data_flag:0,
macroblock_offset:38, /* 4byte + 6bits=38bits */
slice_horizontal_position:0,
slice_vertical_position:0,
quantiser_scale_code:2,
intra_slice_flag:0
};
#endif
#define CLIP_WIDTH 16
#define CLIP_HEIGHT 16
static void dumpSurface(VADisplay display, VASurfaceID surface_id, const char* fileName)
{
VAStatus va_status;
va_status = vaSyncSurface(display, surface_id);
CHECK_VASTATUS(va_status, "vaSyncSurface");
VAImage image;
va_status = vaDeriveImage(display, surface_id, &image);
CHECK_VASTATUS(va_status, "vaDeriveImage");
unsigned char* buffer = 0;
va_status = vaMapBuffer(display, image.buf, (void **)&buffer);
CHECK_VASTATUS(va_status, "vaMapBuffer");
CV_Assert(image.format.fourcc == VA_FOURCC_NV12);
/*
printf("image.format.fourcc = 0x%08x\n", image.format.fourcc);
printf("image.[width x height] = %d x %d\n", image.width, image.height);
printf("image.data_size = %d\n", image.data_size);
printf("image.num_planes = %d\n", image.num_planes);
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");
if (!out)
{
perror(fileName);
exit(1);
}
fwrite(buffer, 1, image.data_size, out);
fclose(out);
vaUnmapBuffer(display, image.buf);
CHECK_VASTATUS(va_status, "vaUnmapBuffer");
vaDestroyImage(display, image.image_id);
CHECK_VASTATUS(va_status, "vaDestroyImage");
}
int main(int argc,char **argv)
{
(void)argc; (void)argv;
VAEntrypoint entrypoints[5];
int num_entrypoints,vld_entrypoint;
VAConfigAttrib attrib;
VAConfigID config_id;
VASurfaceID surface_id;
VAContextID context_id;
VABufferID pic_param_buf,iqmatrix_buf,slice_param_buf,slice_data_buf;
VAStatus va_status;
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);
va_status = vaQueryConfigEntrypoints(va::display, VAProfileMPEG2Main, entrypoints,
&num_entrypoints);
CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
for (vld_entrypoint = 0; vld_entrypoint < num_entrypoints; vld_entrypoint++) {
if (entrypoints[vld_entrypoint] == VAEntrypointVLD)
break;
}
if (vld_entrypoint == num_entrypoints) {
/* not find VLD entry point */
assert(0);
}
/* Assuming finding VLD, find out the format for the render target */
attrib.type = VAConfigAttribRTFormat;
vaGetConfigAttributes(va::display, VAProfileMPEG2Main, VAEntrypointVLD,
&attrib, 1);
if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) {
/* not find desired YUV420 RT format */
assert(0);
}
va_status = vaCreateConfig(va::display, VAProfileMPEG2Main, VAEntrypointVLD,
&attrib, 1,&config_id);
CHECK_VASTATUS(va_status, "vaCreateConfig");
va_status = vaCreateSurfaces(
va::display,
VA_RT_FORMAT_YUV420, CLIP_WIDTH, CLIP_HEIGHT,
&surface_id, 1,
NULL, 0
);
CHECK_VASTATUS(va_status, "vaCreateSurfaces");
/* Create a context for this decode pipe */
va_status = vaCreateContext(va::display, config_id,
CLIP_WIDTH,
((CLIP_HEIGHT+15)/16)*16,
VA_PROGRESSIVE,
&surface_id,
1,
&context_id);
CHECK_VASTATUS(va_status, "vaCreateContext");
va_status = vaCreateBuffer(va::display, context_id,
VAPictureParameterBufferType,
sizeof(VAPictureParameterBufferMPEG2),
1, &pic_param,
&pic_param_buf);
CHECK_VASTATUS(va_status, "vaCreateBuffer");
va_status = vaCreateBuffer(va::display, context_id,
VAIQMatrixBufferType,
sizeof(VAIQMatrixBufferMPEG2),
1, &iq_matrix,
&iqmatrix_buf );
CHECK_VASTATUS(va_status, "vaCreateBuffer");
va_status = vaCreateBuffer(va::display, context_id,
VASliceParameterBufferType,
sizeof(VASliceParameterBufferMPEG2),
1,
&slice_param, &slice_param_buf);
CHECK_VASTATUS(va_status, "vaCreateBuffer");
va_status = vaCreateBuffer(va::display, context_id,
VASliceDataBufferType,
0xc4-0x2f+1,
1,
mpeg2_clip+0x2f,
&slice_data_buf);
CHECK_VASTATUS(va_status, "vaCreateBuffer");
va_status = vaBeginPicture(va::display, context_id, surface_id);
CHECK_VASTATUS(va_status, "vaBeginPicture");
va_status = vaRenderPicture(va::display,context_id, &pic_param_buf, 1);
CHECK_VASTATUS(va_status, "vaRenderPicture");
va_status = vaRenderPicture(va::display,context_id, &iqmatrix_buf, 1);
CHECK_VASTATUS(va_status, "vaRenderPicture");
va_status = vaRenderPicture(va::display,context_id, &slice_param_buf, 1);
CHECK_VASTATUS(va_status, "vaRenderPicture");
va_status = vaRenderPicture(va::display,context_id, &slice_data_buf, 1);
CHECK_VASTATUS(va_status, "vaRenderPicture");
va_status = vaEndPicture(va::display,context_id);
CHECK_VASTATUS(va_status, "vaEndPicture");
va_status = vaSyncSurface(va::display, surface_id);
CHECK_VASTATUS(va_status, "vaSyncSurface");
dumpSurface(va::display, surface_id, argv[1]);
cv::Size size(CLIP_WIDTH,CLIP_HEIGHT);
cv::UMat u;
cv::vaapi::convertFromVASurface(surface_id, size, u);
cv::blur(u, u, cv::Size(7, 7), cv::Point(-3, -3));
cv::vaapi::convertToVASurface(u, surface_id, size);
dumpSurface(va::display, surface_id, argv[2]);
vaDestroySurfaces(va::display,&surface_id,1);
vaDestroyConfig(va::display,config_id);
vaDestroyContext(va::display,context_id);
vaTerminate(va::display);
va::closeDisplay();
return 0;
}