This example captures yuy2 frame directly to cl buffer object by the way
of dma, processed by OpenCL kernel, then convert to nv12 format and
shown by libva.

v2:
Close cl buffer's fd by clCloseMemObjectFdIntel instead of close
function.
v3:
Just use close function, no need of clCloseMemObjectFdIntel.
v4:
Some modifcation of examples/CMakeLists.txt after code rebase.

Signed-off-by: Chuanbo Weng <[email protected]>
---
 CMakeLists.txt                                     |  35 +-
 examples/CMakeLists.txt                            |  29 +-
 .../v4l2_buffer_sharing/v4l2_buffer_sharing.cpp    | 590 +++++++++++++++++++++
 kernels/runtime_yuy2_processing.cl                 |  15 +
 4 files changed, 645 insertions(+), 24 deletions(-)
 create mode 100644 examples/v4l2_buffer_sharing/v4l2_buffer_sharing.cpp
 create mode 100644 kernels/runtime_yuy2_processing.cl

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5474447..4f627cf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -216,23 +216,30 @@ IF(BUILD_EXAMPLES)
 IF(NOT X11_FOUND)
   MESSAGE(FATAL_ERROR "XLib is necessary for examples - not found")
 ENDIF(NOT X11_FOUND)
-# libva
-pkg_check_modules(LIBVA REQUIRED libva>=0.36.0)
-IF(LIBVA_FOUND)
+# libva & libva-x11
+#pkg_check_modules(LIBVA REQUIRED libva>=0.36.0)
+pkg_check_modules(LIBVA REQUIRED libva)
+pkg_check_modules(LIBVA-X11 REQUIRED libva-x11)
+set(LIBVA_BUF_SH_DEP false)
+set(V4L2_BUF_SH_DEP false)
+IF(LIBVA_FOUND AND LIBVA-X11_FOUND)
   MESSAGE(STATUS "Looking for LIBVA - found at ${LIBVA_PREFIX} 
${LIBVA_VERSION}")
-  INCLUDE_DIRECTORIES(${LIBVA_INCLUDE_DIRS})
-ELSE(LIBVA_FOUND)
-  MESSAGE(STATUS "Looking for LIBVA (>= 0.36.0) - not found")
-ENDIF(LIBVA_FOUND)
-
-# libva-x11
-pkg_check_modules(LIBVA-X11 REQUIRED libva-x11>=0.36.0)
-IF(LIBVA-X11_FOUND)
   MESSAGE(STATUS "Looking for LIBVA-X11 - found at ${LIBVA-X11_PREFIX} 
${LIBVA-X11_VERSION}")
+  INCLUDE_DIRECTORIES(${LIBVA_INCLUDE_DIRS})
   INCLUDE_DIRECTORIES(${LIBVA-X11_INCLUDE_DIRS})
-ELSE(LIBVA-X11_FOUND)
-  MESSAGE(STATUS "Looking for LIBVA-X11 (>= 0.36.0) - not found")
-ENDIF(LIBVA-X11_FOUND)
+  set(V4L2_BUF_SH_DEP true)
+  IF(LIBVA_VERSION VERSION_LESS "0.36.0" OR LIBVA-X11_VERSION VERSION_LESS 
"0.36.0")
+    IF(LIBVA_VERSION VERSION_LESS "0.36.0")
+      MESSAGE(STATUS "Looking for LIBVA (>= 0.36.0) - not found")
+    ENDIF(LIBVA_VERSION VERSION_LESS "0.36.0")
+    IF(LIBVA-X11_VERSION VERSION_LESS "0.36.0")
+      MESSAGE(STATUS "Looking for LIBVA-X11 (>= 0.36.0) - not found")
+    ENDIF(LIBVA-X11_VERSION VERSION_LESS "0.36.0")
+    MESSAGE(STATUS "Example libva_buffer_sharing will not be built")
+  ELSE(LIBVA_VERSION VERSION_LESS "0.36.0" OR LIBVA-X11_VERSION VERSION_LESS 
"0.36.0")
+    set(LIBVA_BUF_SH_DEP true)
+  ENDIF(LIBVA_VERSION VERSION_LESS "0.36.0" OR LIBVA-X11_VERSION VERSION_LESS 
"0.36.0")
+ENDIF(LIBVA_FOUND AND LIBVA-X11_FOUND)
 ENDIF(BUILD_EXAMPLES)
 
 ADD_SUBDIRECTORY(include)
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index fe4e5f6..850b3d9 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,3 +1,9 @@
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
+                    ${CMAKE_CURRENT_SOURCE_DIR}/../utests
+                    ${CMAKE_CURRENT_SOURCE_DIR}/../include
+                    ${X11_INCLUDE_DIR})
+
+IF(LIBVA_BUF_SH_DEP OR V4L2_BUF_SH_DEP)
 EXECUTE_PROCESS(COMMAND ls "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/libva" 
OUTPUT_VARIABLE LS_RESULT)
 IF ("LS_RESULT" STREQUAL "")
 EXECUTE_PROCESS(COMMAND git submodule init WORKING_DIRECTORY 
${CMAKE_CURRENT_SOURCE_DIR}/..)
@@ -5,17 +11,13 @@ EXECUTE_PROCESS(COMMAND git submodule update 
WORKING_DIRECTORY ${CMAKE_CURRENT_S
 EXECUTE_PROCESS(COMMAND git checkout master WORKING_DIRECTORY 
${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/libva)
 ENDIF ("LS_RESULT" STREQUAL "")
 
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
-                    ${CMAKE_CURRENT_SOURCE_DIR}/../utests
-                    ${CMAKE_CURRENT_SOURCE_DIR}/../include
-                    ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/libva/va
-                    ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/libva/test/common
-                    ${X11_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/libva/va
+                    ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/libva/test/common)
 
 link_directories (${LIBVA_LIBDIR}
                   ${LIBVA-X11_LIBDIR})
 
-set (examples_sources
+set (va_ocl_basic_sources
   ../utests/utest_error.c
   ../utests/utest_assert.cpp
   ../utests/utest_file_map.cpp
@@ -23,13 +25,20 @@ set (examples_sources
   ./thirdparty/libva/test/common/va_display.c
   ./thirdparty/libva/test/common/va_display_x11.c)
 
-
 ADD_DEFINITIONS(-DHAVE_VA_X11)
-ADD_DEFINITIONS(-DINPUT_NV12_DEFAULT="${CMAKE_CURRENT_SOURCE_DIR}/libva_buffer_sharing/256_128.nv12")
 
-ADD_LIBRARY(va_ocl_basic SHARED ${examples_sources})
+ADD_LIBRARY(va_ocl_basic SHARED ${va_ocl_basic_sources})
 
 TARGET_LINK_LIBRARIES(va_ocl_basic cl m va va-x11 ${X11_X11_LIB})
 
+IF(LIBVA_BUF_SH_DEP)
+ADD_DEFINITIONS(-DINPUT_NV12_DEFAULT="${CMAKE_CURRENT_SOURCE_DIR}/libva_buffer_sharing/256_128.nv12")
 ADD_EXECUTABLE(example-libva_buffer_sharing 
./libva_buffer_sharing/libva_buffer_sharing.cpp)
 TARGET_LINK_LIBRARIES(example-libva_buffer_sharing va_ocl_basic)
+ENDIF(LIBVA_BUF_SH_DEP)
+
+IF(V4L2_BUF_SH_DEP)
+ADD_EXECUTABLE(example-v4l2_buffer_sharing 
./v4l2_buffer_sharing/v4l2_buffer_sharing.cpp)
+TARGET_LINK_LIBRARIES(example-v4l2_buffer_sharing va_ocl_basic)
+ENDIF(V4L2_BUF_SH_DEP)
+ENDIF(LIBVA_BUF_SH_DEP OR V4L2_BUF_SH_DEP)
diff --git a/examples/v4l2_buffer_sharing/v4l2_buffer_sharing.cpp 
b/examples/v4l2_buffer_sharing/v4l2_buffer_sharing.cpp
new file mode 100644
index 0000000..42ab642
--- /dev/null
+++ b/examples/v4l2_buffer_sharing/v4l2_buffer_sharing.cpp
@@ -0,0 +1,590 @@
+/*
+ ** Copyright (c) 2012, 2015 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 <getopt.h>
+#include <errno.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <linux/videodev2.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include <inttypes.h>
+#include <ctype.h>
+
+#include <va/va.h>
+#include <va/va_drmcommon.h>
+
+#include "va_display.h"
+#include "utest_helper.hpp"
+
+using namespace std;
+
+#define BUFFER_NUM_DEFAULT 5
+#define VIDEO_NODE_DEFAULT "/dev/video0"
+#define WIDTH_DEFAULT 640
+#define HEIGHT_DEFAULT 480
+
+#define CHECK_VASTATUS(va_status,func)                                  \
+  if (va_status != VA_STATUS_SUCCESS) {                                   \
+    fprintf(stderr, "status = %d, %s: %s(line %d) failed, exit\n",va_status, 
__func__, func, __LINE__); \
+    exit(1);                                                            \
+  }
+
+#define CHECK_CLSTATUS(status,func)                                  \
+  if (status != CL_SUCCESS) {                                   \
+    fprintf(stderr, "status = %d, %s: %s(line %d) failed, exit\n", status, 
__func__, func, __LINE__); \
+    exit(1);                                                            \
+  }
+
+#define CHECK_V4L2ERROR(ret, STR)                               \
+  if (ret){                             \
+    fprintf(stderr, STR);            \
+    perror(" ");                            \
+    fprintf(stderr, "ret = %d, %s: %s(line %d) failed, exit\n", ret, __func__, 
STR, __LINE__);      \
+    exit(1);                                  \
+  }
+
+VADisplay      va_dpy;
+cl_int cl_status;
+VAStatus va_status;
+VASurfaceID nv12_surface_id;
+VAImage nv12_image;
+
+int dev_fd;
+uint64_t image_size;
+unsigned int pitch;
+cl_mem *import_buf = NULL;
+typedef cl_int (OCLGETMEMOBJECTFD)(cl_context, cl_mem, int *);
+OCLGETMEMOBJECTFD *oclGetMemObjectFd = NULL;
+
+int frame_count = 0;
+struct v4l2_options{
+  const char *dev_name;
+  unsigned int width, height;
+  unsigned int spec_res;
+  unsigned int buffer_num;
+  unsigned int do_list;
+} vo;
+int *import_buf_fd = NULL;
+
+static const char short_options[] = "d:r:b:lh";
+
+static const struct option
+long_options[] = {
+  { "device", required_argument, NULL, 'd' },
+  { "help",   no_argument,       NULL, 'h' },
+  { "resolution", required_argument,       NULL, 'r' },
+  { "buffer_num",  required_argument, NULL, 'b' },
+  { "list",  no_argument, NULL, 'l' },
+  { 0, 0, 0, 0 }
+};
+
+static void usage(FILE *fp, int argc, char **argv)
+{
+  fprintf(fp,
+      "This example aims to demostrate the usage of DMABUF buffer sharing 
between v4l2 and Beignet.\n"
+      "For more details, please read 
docs/howto/v4l2-buffer-sharing-howto.mdwn.\n"
+      "Usage: %s [options]\n\n"
+      "Options:\n"
+      "-d | --device=<dev>  Specify device by <dev> instead of /dev/video0\n"
+      "-h | --help          Print this message\n"
+      "-r | --resolution=<width,height>    Set image resolution\n"
+      "-b | --buffer_num=<num>  Set number of buffers\n"
+      "-l | --list  List available resolution of format 'V4L2_PIX_FMT_YUYV'\n"
+      "",
+      argv[0]);
+}
+
+static void list_resolution(){
+  int ret;
+  struct v4l2_capability cap;
+  struct v4l2_frmsizeenum frm_sz;
+
+  dev_fd = open(vo.dev_name, O_RDWR | O_NONBLOCK, 0);
+  if (dev_fd < 0) {
+    fprintf(stderr, "Can not open %s: %s\n",
+        vo.dev_name, strerror(errno));
+    exit(1);
+  }
+
+  memset(&cap, 0, sizeof(cap));
+  ret = ioctl(dev_fd, VIDIOC_QUERYCAP, &cap);
+  CHECK_V4L2ERROR(ret, "VIDIOC_QUERYCAP");
+
+  if(!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)){
+    fprintf(stderr, "The device is not video capture device\n");
+    exit(1);
+  }
+  if(!(cap.capabilities & V4L2_CAP_STREAMING)){
+    fprintf(stderr, "The device does not support streaming i/o\n");
+    exit(1);
+  }
+
+  printf("Supported resolution under pixel format 'V4L2_PIX_FMT_YUYV':\n");
+  frm_sz.pixel_format = V4L2_PIX_FMT_YUYV;
+  frm_sz.index = 0;
+  bool extra_info = true;
+  while (ioctl(dev_fd, VIDIOC_ENUM_FRAMESIZES, &frm_sz) == 0) {
+    if (frm_sz.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
+      if(extra_info){
+        printf("(width, height) = \n");
+        extra_info = false;
+      }
+      printf("(%d, %d)", frm_sz.discrete.width, frm_sz.discrete.height);
+      printf("\n");
+    }
+    else if (frm_sz.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
+      printf("(width, height) from (%d, %d) to (%d, %d) with step (%d, %d)",
+          frm_sz.stepwise.min_width,
+          frm_sz.stepwise.min_height,
+          frm_sz.stepwise.max_width,
+          frm_sz.stepwise.max_height,
+          frm_sz.stepwise.step_width,
+          frm_sz.stepwise.step_height);
+      continue;
+    }
+    frm_sz.index++;
+  }
+
+  ret = close(dev_fd);
+  if (ret) {
+    fprintf(stderr, "Failed to close %s: %s\n",
+        vo.dev_name, strerror(errno));
+    exit(1);
+  }
+}
+
+static void analyse_args(int argc, char *argv[])
+{
+  vo.dev_name = NULL;
+  vo.width = 0;
+  vo.height = 0;
+  vo.spec_res = 0;
+  vo.buffer_num = BUFFER_NUM_DEFAULT;
+  vo.do_list = 0;
+
+  int c, idx;
+  for (;;) {
+
+    c = getopt_long(argc, argv,
+        short_options, long_options, &idx);
+
+    if (-1 == c)
+      break;
+
+    switch (c) {
+      case 0:
+        break;
+
+      case 'd':
+        vo.dev_name = optarg;
+        break;
+
+      case '?':
+      case 'h':
+        usage(stdout, argc, argv);
+        exit(0);
+
+      case 'r':
+        sscanf(optarg, "%d,%d", &vo.width, &vo.height);
+        vo.spec_res = 1;
+        break;
+
+      case 'b':
+        vo.buffer_num = strtoul(optarg, NULL, 0);
+        break;
+
+      case 'l':
+        vo.do_list = 1;
+        break;
+
+      default:
+        usage(stderr, argc, argv);
+        exit(1);
+    }
+  }
+
+  if(!vo.dev_name){
+    printf("Haven't specified device, use default device: %s\n",
+        VIDEO_NODE_DEFAULT);
+  }
+  if(!vo.dev_name)
+    vo.dev_name = VIDEO_NODE_DEFAULT;
+  if(vo.do_list){
+    list_resolution();
+    exit(0);
+  }
+  if(!vo.spec_res){
+    printf("Haven't specified resolution, use default resolution: 
(width,height) = (%d, %d)\n",
+        WIDTH_DEFAULT, HEIGHT_DEFAULT);
+    vo.width = WIDTH_DEFAULT;
+    vo.height = HEIGHT_DEFAULT;
+  }
+  return;
+}
+
+static void initialize_va_ocl(){
+  int major_ver, minor_ver;
+
+  printf("\n***********************libva info: ***********************\n");
+  fflush(stdout);
+  va_dpy = va_open_display();
+  va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
+  CHECK_VASTATUS(va_status, "vaInitialize");
+
+  VASurfaceAttrib forcc;
+  forcc.type =VASurfaceAttribPixelFormat;
+  forcc.flags=VA_SURFACE_ATTRIB_SETTABLE;
+  forcc.value.type=VAGenericValueTypeInteger;
+  forcc.value.value.i = VA_FOURCC_NV12;
+  va_status = vaCreateSurfaces(va_dpy, VA_RT_FORMAT_YUV420,
+                               vo.width, vo.height,
+                               &nv12_surface_id, 1, &forcc, 1);
+  CHECK_VASTATUS(va_status, "vaCreateSurfaces");
+
+  VAImageFormat image_fmt;
+  image_fmt.fourcc = VA_FOURCC_NV12;
+  image_fmt.byte_order = VA_LSB_FIRST;
+  image_fmt.bits_per_pixel = 12;
+  va_status = vaCreateImage(va_dpy, &image_fmt, vo.width, vo.height, 
&nv12_image);
+  CHECK_VASTATUS(va_status, "vaCreateImage");
+
+  //ocl initialization: basic & create kernel & get extension
+  printf("\n***********************OpenCL info: ***********************\n");
+  if ((cl_status = cl_test_init("runtime_yuy2_processing.cl", 
"runtime_yuy2_processing", SOURCE)) != 0){
+    fprintf(stderr, "cl_test_init error\n");
+    exit(1);
+  }
+
+#ifdef CL_VERSION_1_2
+  oclGetMemObjectFd = (OCLGETMEMOBJECTFD 
*)clGetExtensionFunctionAddressForPlatform(platform, "clGetMemObjectFdIntel");
+#else
+  oclGetMemObjectFd = (OCLGETMEMOBJECTFD 
*)clGetExtensionFunctionAddress("clGetMemObjectFdIntel");
+#endif
+  if(!oclGetMemObjectFd){
+    fprintf(stderr, "Failed to get extension clGetMemObjectFdIntel\n");
+    exit(1);
+  }
+  printf("\n***********************************************************\n");
+}
+
+static void create_dmasharing_buffers()
+{
+  if(import_buf_fd == NULL)
+    import_buf_fd = (int *)malloc(sizeof(int) * vo.buffer_num);
+  if(import_buf == NULL){
+    import_buf = (cl_mem *)malloc(sizeof(cl_mem) * vo.buffer_num);
+  }
+
+  for (unsigned int i = 0; i < vo.buffer_num; ++i){
+    import_buf[i] = clCreateBuffer(ctx, CL_MEM_READ_WRITE, image_size, NULL, 
&cl_status);
+    CHECK_CLSTATUS(cl_status, "clCreateBuffer");
+
+    //get cl buffer object's fd
+    cl_status = oclGetMemObjectFd(ctx, import_buf[i], &import_buf_fd[i]);
+    CHECK_CLSTATUS(cl_status, "clGetMemObjectFdIntel");
+  }
+}
+
+static void release_va_ocl(){
+  va_status = vaDestroySurfaces(va_dpy,&nv12_surface_id,1);
+  CHECK_VASTATUS(va_status, "vaDestroySurfaces");
+  va_status = vaDestroyImage(va_dpy, nv12_image.image_id);
+  CHECK_VASTATUS(va_status, "vaDestroyImage");
+  va_status = vaTerminate(va_dpy);
+  CHECK_VASTATUS(va_status, "vaTerminate");
+  va_close_display(va_dpy);
+
+  int ret;
+  for (unsigned int i = 0; i < vo.buffer_num; ++i) {
+    ret = close(import_buf_fd[i]);
+    if (ret) {
+      fprintf(stderr, "Failed to close import_buf[%u]'s fd: %s\n", i, 
strerror(errno));
+    }
+    cl_status = clReleaseMemObject(import_buf[i]);
+    CHECK_CLSTATUS(cl_status, "clReleaseMemObject");
+  }
+}
+
+static void process_show_frame(int index)
+{
+  //process import_buf[index] by ocl
+  size_t global_size[2];
+  global_size[0] = vo.width * 2 / 4;
+  global_size[1] = vo.height;
+  cl_status = clSetKernelArg(kernel, 0, sizeof(cl_mem), &import_buf[index]);
+  CHECK_CLSTATUS(cl_status, "clSetKernelArg");
+  cl_status = clSetKernelArg(kernel, 1, sizeof(int), &vo.height);
+  CHECK_CLSTATUS(cl_status, "clSetKernelArg");
+  cl_status = clSetKernelArg(kernel, 2, sizeof(int), &pitch);
+  CHECK_CLSTATUS(cl_status, "clSetKernelArg");
+  cl_status = clEnqueueNDRangeKernel(queue, kernel, 2, NULL,
+                                     global_size, NULL, 0, NULL, NULL);
+  CHECK_CLSTATUS(cl_status, "clEnqueueNDRangeKernel");
+  cl_status = clFinish(queue);
+  CHECK_CLSTATUS(cl_status, "clFinish");
+
+  //create corresponding VASurface
+  VASurfaceID yuy2_surface_id;
+  VASurfaceAttrib sa[2];
+  sa[0].type = VASurfaceAttribMemoryType;
+  sa[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
+  sa[0].value.type = VAGenericValueTypeInteger;
+  sa[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
+  sa[1].type = VASurfaceAttribExternalBufferDescriptor;
+  sa[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
+  sa[1].value.type = VAGenericValueTypePointer;
+  VASurfaceAttribExternalBuffers sa_eb;
+  sa_eb.pixel_format = VA_FOURCC_YUY2;
+  sa_eb.width = vo.width;
+  sa_eb.height = vo.height;
+  sa_eb.data_size = image_size;
+  sa_eb.num_planes = 1;
+  sa_eb.pitches[0] = pitch;
+  sa_eb.offsets[0] = 0;
+  sa_eb.num_buffers = 1;
+  sa_eb.buffers = (unsigned long *)malloc(sizeof(unsigned long) * 
sa_eb.num_buffers);
+  sa_eb.buffers[0] = import_buf_fd[index];
+  sa_eb.flags = 0;
+  sa[1].value.value.p = &sa_eb;
+  va_status = vaCreateSurfaces(va_dpy, VA_RT_FORMAT_YUV422,
+                               vo.width, vo.height,
+                               &yuy2_surface_id, 1, sa, 2);
+  CHECK_VASTATUS(va_status, "vaCreateSurfaces");
+
+  //convert to NV12 format
+  va_status = vaGetImage (va_dpy, yuy2_surface_id, 0, 0,
+                          vo.width, vo.height, nv12_image.image_id);
+  CHECK_VASTATUS(va_status, "vaGetImage");
+  va_status = vaPutImage(va_dpy, nv12_surface_id, nv12_image.image_id,
+                         0, 0, vo.width, vo.height, 0, 0,
+                         vo.width, vo.height);
+  CHECK_VASTATUS(va_status, "vaPutImage");
+
+  //show by vaPutsurface
+  VARectangle src_rect, dst_rect;
+  src_rect.x      = 0;
+  src_rect.y      = 0;
+  src_rect.width  = vo.width;
+  src_rect.height = vo.height;
+  dst_rect        = src_rect;
+  va_status = va_put_surface(va_dpy, nv12_surface_id, &src_rect, &dst_rect);
+  CHECK_VASTATUS(va_status, "vaPutSurface");
+
+  vaDestroySurfaces(va_dpy,&yuy2_surface_id,1);
+  CHECK_VASTATUS(va_status, "vaDestroySurfaces");
+  free(sa_eb.buffers);
+  return;
+}
+
+static void init_dmabuf(void){
+  int ret;
+  struct v4l2_requestbuffers reqbuf;
+
+  memset(&reqbuf, 0, sizeof(reqbuf));
+  reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+  reqbuf.memory = V4L2_MEMORY_DMABUF;
+  reqbuf.count = vo.buffer_num;
+
+  ret = ioctl(dev_fd, VIDIOC_REQBUFS, &reqbuf);
+  if(ret == -1 && errno == EINVAL){
+    fprintf(stderr, "Video capturing or DMABUF streaming is not supported\n");
+    exit(1);
+  }
+  else
+    CHECK_V4L2ERROR(ret, "VIDIOC_REQBUFS");
+
+  create_dmasharing_buffers();
+  printf("Succeed to create %d dma buffers \n", vo.buffer_num);
+
+}
+
+static void init_device(void){
+
+  int ret;
+  struct v4l2_capability cap;
+  struct v4l2_format format;
+
+  dev_fd = open(vo.dev_name, O_RDWR | O_NONBLOCK, 0);
+  if (dev_fd < 0) {
+    fprintf(stderr, "Can not open %s: %s\n",
+        vo.dev_name, strerror(errno));
+    exit(1);
+  }
+
+  memset(&cap, 0, sizeof(cap));
+  ret = ioctl(dev_fd, VIDIOC_QUERYCAP, &cap);
+  CHECK_V4L2ERROR(ret, "VIDIOC_QUERYCAP");
+  if(!(cap.capabilities & V4L2_CAP_STREAMING)){
+    fprintf(stderr, "The device does not support streaming i/o\n");
+    exit(1);
+  }
+
+  memset(&format, 0, sizeof(format));
+  format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+  format.fmt.pix.width = vo.width;
+  format.fmt.pix.height = vo.height;
+  format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+  format.fmt.pix.field = V4L2_FIELD_ANY;
+
+  ret = ioctl(dev_fd, VIDIOC_S_FMT, &format);
+  CHECK_V4L2ERROR(ret, "VIDIOC_S_FMT");
+
+  ret = ioctl(dev_fd, VIDIOC_G_FMT, &format);
+  CHECK_V4L2ERROR(ret, "VIDIOC_G_FMT");
+  if(format.fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV){
+    fprintf(stderr, "V4L2_PIX_FMT_YUYV format is not supported by %s\n", 
vo.dev_name);
+    exit(1);
+  }
+  if(format.fmt.pix.width != vo.width  || format.fmt.pix.height != vo.height){
+    fprintf(stderr, "This resolution is not supported, please go through 
supported resolution by command './main -l'\n");
+    exit(1);
+  }
+  printf("Input image format: (width, height) = (%u, %u), pixel format = 
%.4s\n",
+      format.fmt.pix.width, format.fmt.pix.height, 
(char*)&format.fmt.pix.pixelformat);
+  image_size = format.fmt.pix.sizeimage;
+       pitch = format.fmt.pix.bytesperline;
+}
+
+static void start_capturing(void){
+  int ret;
+  for (unsigned int i = 0; i < vo.buffer_num; ++i) {
+    struct v4l2_buffer buf;
+
+    memset(&buf, 0, sizeof(buf));
+    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    buf.memory = V4L2_MEMORY_DMABUF;
+    buf.index = i;
+    buf.m.fd = import_buf_fd[i];
+    ret = ioctl(dev_fd, VIDIOC_QBUF, &buf);
+    CHECK_V4L2ERROR(ret, "VIDIOC_QBUF");
+  }
+
+  int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+  ret = ioctl(dev_fd, VIDIOC_STREAMON, &type);
+  CHECK_V4L2ERROR(ret, "VIDIOC_STREAMON");
+}
+
+static void mainloop(void){
+  int ret;
+  struct v4l2_buffer buf;
+  int index;
+
+  while (1) {
+    frame_count++;
+    printf("******************Frame %d\n", frame_count);
+    fd_set fds;
+    struct timeval tv;
+    int r;
+
+    FD_ZERO(&fds);
+    FD_SET(dev_fd, &fds);
+
+    /* Timeout. */
+    tv.tv_sec = 2;
+    tv.tv_usec = 0;
+
+
+    r = select(dev_fd + 1, &fds, NULL, NULL, &tv);
+
+    if (-1 == r) {
+      if (EINTR == errno)
+        continue;
+      perror("select");
+    }
+
+    if(r == 0){
+      fprintf(stderr, "Select timeout\n");
+      exit(1);
+    }
+
+    memset(&buf, 0, sizeof(buf));
+    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    buf.memory = V4L2_MEMORY_DMABUF;
+    ret = ioctl(dev_fd, VIDIOC_DQBUF, &buf);
+    CHECK_V4L2ERROR(ret, "VIDIOC_DQBUF");
+    index = buf.index;
+
+    //process by ocl and show on screen by libva
+    process_show_frame(index);
+
+    //Then queue this buffer(buf.index) by QBUF
+    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    buf.memory = V4L2_MEMORY_DMABUF;
+    buf.m.fd = import_buf_fd[index];
+    buf.index = index;
+
+    ret = ioctl(dev_fd, VIDIOC_QBUF, &buf);
+    CHECK_V4L2ERROR(ret, "VIDIOC_QBUF");
+  }
+}
+
+static void stop_capturing(void)
+{
+  int ret;
+  int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+  ret = ioctl(dev_fd, VIDIOC_STREAMOFF, &type);
+  CHECK_V4L2ERROR(ret, "VIDIOC_STREAMOFF");
+}
+
+static void uninit_device(void){
+  free(import_buf_fd);
+  free(import_buf);
+  int ret = close(dev_fd);
+  if (ret) {
+    fprintf(stderr, "Failed to close %s: %s\n",
+        vo.dev_name, strerror(errno));
+    exit(1);
+  }
+}
+
+int main(int argc, char *argv[])
+{
+  analyse_args(argc, argv);
+
+  init_device();
+  initialize_va_ocl();
+  init_dmabuf();
+
+  start_capturing();
+  mainloop();
+
+  stop_capturing();
+  release_va_ocl();
+  uninit_device();
+
+  return 0;
+}
diff --git a/kernels/runtime_yuy2_processing.cl 
b/kernels/runtime_yuy2_processing.cl
new file mode 100644
index 0000000..1478e65
--- /dev/null
+++ b/kernels/runtime_yuy2_processing.cl
@@ -0,0 +1,15 @@
+__kernel void
+runtime_yuy2_processing(__global uchar *src,
+                        int image_height,
+                        int image_pitch)
+{
+  int gx = get_global_id(0);
+  int gy = get_global_id(1);
+
+  int src_y = image_height / 2 + gy;
+  int mirror_y = image_height - src_y;
+
+  uchar4 mirror_val = *(__global uchar4*)(src + mirror_y*image_pitch + gx*4);
+  *(__global uchar4*)(src + src_y*image_pitch + gx*4) = mirror_val;
+
+}
-- 
1.9.1

_______________________________________________
Beignet mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/beignet

Reply via email to