Adds a sunxi-cedrus-drv-video libVA backend

This VA backend uses v4l2's Frame API proposal to interface with the
"sunxi-cedrus" video driver on Allwinner SoC. Only a few parts of the
code are really dependent on sunxi-cedrus and this VA backend could be
reused for other v4l drivers using the Frame API.
This commit is contained in:
Florent Revest
2016-08-05 12:23:15 +02:00
commit e263c9542c
28 changed files with 2805 additions and 0 deletions
+45
View File
@@ -0,0 +1,45 @@
# Object files
*.o
*.ko
# Libraries
*.lib
*.a
*.lo
*.la
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Misc
*~
*.orig
*.rej
*.loT
*.bin
*.pc
*.g[4-7]s
.deps
.libs
install-sh
libtool
ltmain.sh
compile
missing
Makefile
Makefile.in
config.h
config.h.in
stamp-h1
aclocal.m4
autom4te.cache
config.guess
config.log
config.status
config.sub
configure
depcomp
TAGS
+1
View File
@@ -0,0 +1 @@
Florent Revest <florent.revest@free-electrons.com>
+19
View File
@@ -0,0 +1,19 @@
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.
+9
View File
@@ -0,0 +1,9 @@
AUTOMAKE_OPTIONS = foreign
SUBDIRS = src
# Extra clean files so that maintainer-clean removes *everything*
MAINTAINERCLEANFILES = \
aclocal.m4 compile config.guess config.sub \
configure depcomp install-sh ltmain.sh \
Makefile.in missing
+12
View File
@@ -0,0 +1,12 @@
Sunxi Cedrus VA backend
=======================
This libVA video driver is designed to work with the v4l2 "sunxi-cedrus" kernel
driver. However, the only sunxi-cedrus specific part is the format conversion
from tiled to planar, otherwise it would be generic enough to be used with other
v4l2 drivers using the "Frame API".
You can try this driver with VLC but don't forget to tell libVA to use this
backend:
export LIBVA_DRIVER_NAME=sunxi_cedrus
Executable
+7
View File
@@ -0,0 +1,7 @@
#! /bin/sh
autoreconf -v --install
if test -z "$NOCONFIGURE"; then
./configure "$@"
fi
+118
View File
@@ -0,0 +1,118 @@
# intel-driver package version number
m4_define([sunxi_cedrus_major_version], [1])
m4_define([sunxi_cedrus_minor_version], [0])
m4_define([sunxi_cedrus_micro_version], [0])
m4_define([sunxi_cedrus_pre_version], [0])
m4_define([sunxi_cedrus_version],
[sunxi_cedrus_major_version.sunxi_cedrus_minor_version.sunxi_cedrus_micro_version])
m4_if(sunxi_cedrus_pre_version, [0], [], [
m4_append([sunxi_cedrus_version], sunxi_cedrus_pre_version, [.pre])
])
# libva minimum version requirement
m4_define([libva_package_version], [1.2.2])
m4_define([va_api_version], [0.34.0])
# libdrm minimum version requirement
m4_define([libdrm_version], [2.4.45])
AC_PREREQ([2.60])
AC_INIT([liva_wrapper], [sunxi_cedrus_version],
[florent.revest@free-electrons.com], [sunxi_cedrus])
AC_CONFIG_SRCDIR([Makefile.am])
AM_INIT_AUTOMAKE([1.9 tar-ustar])
AC_CONFIG_HEADERS([src/config.h])
SUNXI_CEDRUS_MAJOR_VERSION=sunxi_cedrus_major_version
SUNXI_CEDRUS_MINOR_VERSION=sunxi_cedrus_minor_version
SUNXI_CEDRUS_MICRO_VERSION=sunxi_cedrus_micro_version
AC_DEFINE([SUNXI_CEDRUS_MAJOR_VERSION], [sunxi_cedrus_major_version], [Major version of the driver])
AC_DEFINE([SUNXI_CEDRUS_MINOR_VERSION], [sunxi_cedrus_minor_version], [Minor version of the driver])
AC_DEFINE([SUNXI_CEDRUS_MICRO_VERSION], [sunxi_cedrus_micro_version], [Micro version of the driver])
AC_DEFINE([SUNXI_CEDRUS_PRE_VERSION], [sunxi_cedrus_pre_version], [Preversion of the driver])
SUNXI_CEDRUS_LT_LDFLAGS="-avoid-version"
AC_SUBST(SUNXI_CEDRUS_LT_LDFLAGS)
dnl Use pretty build output with automake >= 1.11
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])], [
AM_DEFAULT_VERBOSITY=1
AC_SUBST(AM_DEFAULT_VERBOSITY)
])
AC_DISABLE_STATIC
AC_PROG_LIBTOOL
AC_PROG_CC
AM_PROG_CC_C_O
AM_PROG_AS
AC_C_BIGENDIAN
AC_HEADER_STDC
AC_SYS_LARGEFILE
AC_CHECK_LIB([m], [sin])
LIBVA_PACKAGE_VERSION=libva_package_version
AC_SUBST(LIBVA_PACKAGE_VERSION)
dnl Check for recent enough DRM
LIBDRM_VERSION=libdrm_version
PKG_CHECK_MODULES([DRM], [libdrm >= $LIBDRM_VERSION])
AC_SUBST(LIBDRM_VERSION)
dnl Check for gen4asm
PKG_CHECK_MODULES(GEN4ASM, [intel-gen4asm >= 1.3], [gen4asm=yes], [gen4asm=no])
AM_CONDITIONAL(HAVE_GEN4ASM, test x$gen4asm = xyes)
AC_PATH_PROG([GEN4ASM], [intel-gen4asm])
dnl Check for VA-API
PKG_CHECK_MODULES(LIBVA_DEPS, [libva >= va_api_version])
PKG_CHECK_MODULES(X11_DEPS, [x11])
dnl Check for VA/DRM API
PKG_CHECK_MODULES(LIBVA_DRM_DEPS, [libva-drm],
[AC_DEFINE([HAVE_VA_DRM], [1], [Defined to 1 if VA/DRM API is enabled])],
[USE_DRM="no"])
# Check for <drm_fourcc.h>
if test "$USE_DRM" = "yes"; then
saved_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $DRM_CFLAGS"
AC_CHECK_HEADERS([drm_fourcc.h], [:], [USE_DRM="no"])
CPPFLAGS="$saved_CPPFLAGS"
fi
VA_VERSION=`$PKG_CONFIG --modversion libva`
VA_MAJOR_VERSION=`echo "$VA_VERSION" | cut -d'.' -f1`
VA_MINOR_VERSION=`echo "$VA_VERSION" | cut -d'.' -f2`
VA_MICRO_VERSION=`echo "$VA_VERSION" | cut -d'.' -f3`
VA_VERSION_STR="$VA_VERSION"
va_full_version_int=`expr ${VA_MAJOR_VERSION:-0} "*" 1000000 + \
${VA_MINOR_VERSION:-0} "*" 10000 + \
${VA_MICRO_VERSION:-0} "*" 100 + \
0`
VA_DRIVER_INIT_FUNC="__vaDriverInit_${VA_MAJOR_VERSION}_${VA_MINOR_VERSION}"
AC_DEFINE_UNQUOTED([VA_DRIVER_INIT_FUNC], [$VA_DRIVER_INIT_FUNC],
[Define driver entry-point])
dnl Check for VA-API drivers path
AC_MSG_CHECKING([for VA drivers path])
LIBVA_DRIVERS_PATH=`$PKG_CONFIG libva --variable driverdir`
if test -z "$LIBVA_DRIVERS_PATH"; then
LIBVA_DRIVERS_PATH="/usr/lib/dri/"
fi
AC_MSG_RESULT([$LIBVA_DRIVERS_PATH])
AC_SUBST(LIBVA_DRIVERS_PATH)
AC_OUTPUT([
Makefile
src/Makefile
])
echo
echo $PACKAGE configuration summary:
echo
echo VA-API version ................... : $VA_VERSION_STR
echo VA-API drivers path .............. : $LIBVA_DRIVERS_PATH
echo
+40
View File
@@ -0,0 +1,40 @@
AM_CPPFLAGS = \
-DPTHREADS \
$(X11_DEPS_CFLAGS)\
$(DRM_CFLAGS) \
$(LIBVA_DEPS_CFLAGS)
driver_cflags = \
-Wall \
-fvisibility=hidden
driver_ldflags = \
-module -avoid-version \
-no-undefined \
-Wl,--no-undefined
driver_libs = \
-lpthread -ldl \
$(DRM_LIBS) \
$(X11_DEPS_LIBS) \
$(LIBVA_DEPS_LIBS)
source_c = sunxi_cedrus_drv_video.c object_heap.c buffer.c va_config.c \
context.c image.c picture.c subpicture.c surface.c
source_s = \
tiled_yuv.S
source_h = sunxi_cedrus_drv_video.h object_heap.h buffer.h va_config.h \
context.h image.h picture.h subpicture.h surface.h \
tiled_yuv.h
sunxi_cedrus_drv_video_la_LTLIBRARIES = sunxi_cedrus_drv_video.la
sunxi_cedrus_drv_video_ladir = $(LIBVA_DRIVERS_PATH)
sunxi_cedrus_drv_video_la_CFLAGS = $(driver_cflags)
sunxi_cedrus_drv_video_la_LDFLAGS = $(driver_ldflags)
sunxi_cedrus_drv_video_la_LIBADD = $(driver_libs)
sunxi_cedrus_drv_video_la_SOURCES = $(source_c) $(source_s)
noinst_HEADERS = $(source_h)
MAINTAINERCLEANFILES = Makefile.in config.h.in
+196
View File
@@ -0,0 +1,196 @@
/*
* Copyright (c) 2016 Florent Revest, <florent.revest@free-electrons.com>
* 2007 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 "sunxi_cedrus_drv_video.h"
#include "buffer.h"
#include "context.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
/*
* A Buffer is a memory zone used to handle all kind of data, for example an IQ
* matrix or image buffer (which are allocated using realloc) or slice data
* (which are mmapped from v4l's kernel space)
*/
VAStatus sunxi_cedrus_CreateBuffer(VADriverContextP ctx, VAContextID context,
VABufferType type, unsigned int size, unsigned int num_elements,
void *data, VABufferID *buf_id)
{
INIT_DRIVER_DATA
VAStatus vaStatus = VA_STATUS_SUCCESS;
int bufferID;
struct v4l2_plane plane[1];
object_buffer_p obj_buffer;
/* Validate type */
switch (type)
{
case VAPictureParameterBufferType:
case VAIQMatrixBufferType: /* Ignored */
case VASliceParameterBufferType:
case VASliceDataBufferType:
case VAImageBufferType:
/* Ok */
break;
default:
vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
return vaStatus;
}
bufferID = object_heap_allocate(&driver_data->buffer_heap);
obj_buffer = BUFFER(bufferID);
if (NULL == obj_buffer)
{
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
return vaStatus;
}
obj_buffer->buffer_data = NULL;
obj_buffer->type = type;
if(obj_buffer->type == VASliceDataBufferType) {
object_context_p obj_context;
obj_context = CONTEXT(context);
assert(obj_context);
struct v4l2_buffer buf;
memset(&(buf), 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = obj_context->num_rendered_surfaces%INPUT_BUFFERS_NB;
buf.length = 1;
buf.m.planes = plane;
assert(ioctl(driver_data->mem2mem_fd, VIDIOC_QUERYBUF, &buf)==0);
obj_buffer->buffer_data = mmap(NULL, size * num_elements,
PROT_READ | PROT_WRITE, MAP_SHARED,
driver_data->mem2mem_fd, buf.m.planes[0].m.mem_offset);
} else
obj_buffer->buffer_data = realloc(obj_buffer->buffer_data, size * num_elements);
if (obj_buffer->buffer_data == NULL)
return VA_STATUS_ERROR_ALLOCATION_FAILED;
if (VA_STATUS_SUCCESS == vaStatus)
{
obj_buffer->max_num_elements = num_elements;
obj_buffer->num_elements = num_elements;
obj_buffer->size = size;
if (data)
memcpy(obj_buffer->buffer_data, data,
size * num_elements);
}
if (VA_STATUS_SUCCESS == vaStatus)
*buf_id = bufferID;
return vaStatus;
}
VAStatus sunxi_cedrus_BufferSetNumElements(VADriverContextP ctx,
VABufferID buf_id, unsigned int num_elements)
{
INIT_DRIVER_DATA
VAStatus vaStatus = VA_STATUS_SUCCESS;
object_buffer_p obj_buffer = BUFFER(buf_id);
assert(obj_buffer);
if ((num_elements < 0) || (num_elements > obj_buffer->max_num_elements))
vaStatus = VA_STATUS_ERROR_UNKNOWN;
if (VA_STATUS_SUCCESS == vaStatus)
obj_buffer->num_elements = num_elements;
return vaStatus;
}
VAStatus sunxi_cedrus_MapBuffer(VADriverContextP ctx, VABufferID buf_id,
void **pbuf)
{
INIT_DRIVER_DATA
VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
object_buffer_p obj_buffer = BUFFER(buf_id);
assert(obj_buffer);
if (NULL == obj_buffer)
{
vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
return vaStatus;
}
if (NULL != obj_buffer->buffer_data)
{
*pbuf = obj_buffer->buffer_data;
vaStatus = VA_STATUS_SUCCESS;
}
return vaStatus;
}
VAStatus sunxi_cedrus_UnmapBuffer(VADriverContextP ctx, VABufferID buf_id)
{
/* Do nothing */
return VA_STATUS_SUCCESS;
}
void sunxi_cedrus_destroy_buffer(struct sunxi_cedrus_driver_data *driver_data,
object_buffer_p obj_buffer)
{
if (NULL != obj_buffer->buffer_data)
{
if(obj_buffer->type == VASliceDataBufferType)
munmap(obj_buffer->buffer_data, obj_buffer->size);
else
free(obj_buffer->buffer_data);
obj_buffer->buffer_data = NULL;
}
object_heap_free(&driver_data->buffer_heap, (object_base_p) obj_buffer);
}
VAStatus sunxi_cedrus_DestroyBuffer(VADriverContextP ctx, VABufferID buffer_id)
{
INIT_DRIVER_DATA
object_buffer_p obj_buffer = BUFFER(buffer_id);
assert(obj_buffer);
sunxi_cedrus_destroy_buffer(driver_data, obj_buffer);
return VA_STATUS_SUCCESS;
}
/* sunxi-cedrus doesn't support buffer info */
VAStatus sunxi_cedrus_BufferInfo(VADriverContextP ctx, VABufferID buf_id,
VABufferType *type, unsigned int *size,
unsigned int *num_elements)
{ return VA_STATUS_ERROR_UNIMPLEMENTED; }
+69
View File
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2016 Florent Revest, <florent.revest@free-electrons.com>
* 2007 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.
*/
#ifndef _BUFFER_H_
#define _BUFFER_H_
#include <va/va_backend.h>
#include "object_heap.h"
#include "sunxi_cedrus_drv_video.h"
#define BUFFER(id) ((object_buffer_p) object_heap_lookup(&driver_data->buffer_heap, id))
#define BUFFER_ID_OFFSET 0x08000000
struct object_buffer {
struct object_base base;
void *buffer_data;
int max_num_elements;
int num_elements;
VABufferType type;
unsigned int size;
};
typedef struct object_buffer *object_buffer_p;
VAStatus sunxi_cedrus_CreateBuffer(VADriverContextP ctx, VAContextID context,
VABufferType type, unsigned int size, unsigned int num_elements,
void *data, VABufferID *buf_id);
VAStatus sunxi_cedrus_BufferSetNumElements(VADriverContextP ctx,
VABufferID buf_id, unsigned int num_elements);
VAStatus sunxi_cedrus_MapBuffer(VADriverContextP ctx, VABufferID buf_id,
void **pbuf);
VAStatus sunxi_cedrus_UnmapBuffer(VADriverContextP ctx, VABufferID buf_id);
void sunxi_cedrus_destroy_buffer(struct sunxi_cedrus_driver_data *driver_data,
object_buffer_p obj_buffer);
VAStatus sunxi_cedrus_DestroyBuffer(VADriverContextP ctx, VABufferID buffer_id);
VAStatus sunxi_cedrus_BufferInfo(VADriverContextP ctx, VABufferID buf_id,
VABufferType *type, unsigned int *size,
unsigned int *num_elements);
#endif /* _BUFFER_H_ */
+167
View File
@@ -0,0 +1,167 @@
/*
* Copyright (c) 2016 Florent Revest, <florent.revest@free-electrons.com>
* 2007 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 "sunxi_cedrus_drv_video.h"
#include "context.h"
#include "va_config.h"
#include "surface.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
/*
* A Context is a global data structure used for rendering a video of a certain
* format. When a context is created, input buffers are created and v4l's output
* (which is the compressed data input queue, since capture is the real output)
* format is set.
*/
VAStatus sunxi_cedrus_CreateContext(VADriverContextP ctx, VAConfigID config_id,
int picture_width, int picture_height, int flag,
VASurfaceID *render_targets, int num_render_targets,
VAContextID *context)
{
INIT_DRIVER_DATA
VAStatus vaStatus = VA_STATUS_SUCCESS;
object_config_p obj_config;
int i;
struct v4l2_create_buffers create_bufs;
struct v4l2_format fmt;
enum v4l2_buf_type type;
obj_config = CONFIG(config_id);
if (NULL == obj_config)
{
vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
return vaStatus;
}
int contextID = object_heap_allocate(&driver_data->context_heap);
object_context_p obj_context = CONTEXT(contextID);
if (NULL == obj_context)
{
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
return vaStatus;
}
obj_context->context_id = contextID;
*context = contextID;
obj_context->current_render_target = -1;
obj_context->config_id = config_id;
obj_context->picture_width = picture_width;
obj_context->picture_height = picture_height;
obj_context->num_render_targets = num_render_targets;
obj_context->render_targets = (VASurfaceID *) malloc(num_render_targets * sizeof(VASurfaceID));
obj_context->num_rendered_surfaces = 0;
if (obj_context->render_targets == NULL)
{
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
return vaStatus;
}
for(i = 0; i < num_render_targets; i++)
{
if (NULL == SURFACE(render_targets[i]))
{
vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
break;
}
obj_context->render_targets[i] = render_targets[i];
}
obj_context->flags = flag;
/* Error recovery */
if (VA_STATUS_SUCCESS != vaStatus)
{
obj_context->context_id = -1;
obj_context->config_id = -1;
free(obj_context->render_targets);
obj_context->render_targets = NULL;
obj_context->num_render_targets = 0;
obj_context->flags = 0;
object_heap_free(&driver_data->context_heap, (object_base_p) obj_context);
}
memset(&(fmt), 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
fmt.fmt.pix_mp.width = picture_width;
fmt.fmt.pix_mp.height = picture_height;
fmt.fmt.pix_mp.plane_fmt[0].sizeimage = INPUT_BUFFER_MAX_SIZE;
switch(obj_config->profile) {
default:
vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
return vaStatus;
break;
}
fmt.fmt.pix_mp.field = V4L2_FIELD_ANY;
fmt.fmt.pix_mp.num_planes = 1;
assert(ioctl(driver_data->mem2mem_fd, VIDIOC_S_FMT, &fmt)==0);
memset (&create_bufs, 0, sizeof (struct v4l2_create_buffers));
create_bufs.count = INPUT_BUFFERS_NB;
create_bufs.memory = V4L2_MEMORY_MMAP;
create_bufs.format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
assert(ioctl(driver_data->mem2mem_fd, VIDIOC_G_FMT, &create_bufs.format)==0);
assert(ioctl(driver_data->mem2mem_fd, VIDIOC_CREATE_BUFS, &create_bufs)==0);
type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
assert(ioctl(driver_data->mem2mem_fd, VIDIOC_STREAMON, &type)==0);
type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
assert(ioctl(driver_data->mem2mem_fd, VIDIOC_STREAMON, &type)==0);
return vaStatus;
}
VAStatus sunxi_cedrus_DestroyContext(VADriverContextP ctx, VAContextID context)
{
INIT_DRIVER_DATA
object_context_p obj_context = CONTEXT(context);
assert(obj_context);
obj_context->context_id = -1;
obj_context->config_id = -1;
obj_context->picture_width = 0;
obj_context->picture_height = 0;
if (obj_context->render_targets)
free(obj_context->render_targets);
obj_context->render_targets = NULL;
obj_context->num_render_targets = 0;
obj_context->flags = 0;
obj_context->current_render_target = -1;
object_heap_free(&driver_data->context_heap, (object_base_p) obj_context);
return VA_STATUS_SUCCESS;
}
+64
View File
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2016 Florent Revest, <florent.revest@free-electrons.com>
* 2007 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.
*/
#ifndef _CONTEXT_H_
#define _CONTEXT_H_
#include <va/va_backend.h>
#include "object_heap.h"
/* We can't dynamically call VIDIOC_REQBUFS for every MPEG slice we create.
* Indeed, the queue might be busy processing a previous buffer, so we need to
* pre-allocate a set of buffers with a max size */
#define INPUT_BUFFER_MAX_SIZE 131072
#define INPUT_BUFFERS_NB 4
#define CONTEXT(id) ((object_context_p) object_heap_lookup(&driver_data->context_heap, id))
#define CONTEXT_ID_OFFSET 0x02000000
struct object_context {
struct object_base base;
VAContextID context_id;
VAConfigID config_id;
VASurfaceID current_render_target;
int picture_width;
int picture_height;
int num_render_targets;
int flags;
VASurfaceID *render_targets;
uint32_t num_rendered_surfaces;
};
typedef struct object_context *object_context_p;
VAStatus sunxi_cedrus_CreateContext(VADriverContextP ctx, VAConfigID config_id,
int picture_width, int picture_height, int flag,
VASurfaceID *render_targets, int num_render_targets,
VAContextID *context);
VAStatus sunxi_cedrus_DestroyContext(VADriverContextP ctx, VAContextID context);
#endif /* _CONTEXT_H_ */
+138
View File
@@ -0,0 +1,138 @@
/*
* Copyright (c) 2016 Florent Revest, <florent.revest@free-electrons.com>
* 2007 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 "sunxi_cedrus_drv_video.h"
#include "image.h"
#include "surface.h"
#include "buffer.h"
#include <assert.h>
#include "tiled_yuv.h"
/*
* An Image is a standard data structure containing rendered frames in a usable
* pixel format. Here we only use NV12 buffers which are converted from sunxi's
* proprietary tiled pixel format with tiled_yuv when deriving an Image from a
* Surface.
*/
VAStatus sunxi_cedrus_QueryImageFormats(VADriverContextP ctx,
VAImageFormat *format_list, int *num_formats)
{
format_list[0].fourcc = VA_FOURCC_NV12;
*num_formats = 1;
return VA_STATUS_SUCCESS;
}
VAStatus sunxi_cedrus_CreateImage(VADriverContextP ctx, VAImageFormat *format,
int width, int height, VAImage *image)
{
INIT_DRIVER_DATA
int sizeY, sizeUV;
object_image_p obj_img;
image->format = *format;
image->buf = VA_INVALID_ID;
image->width = width;
image->height = height;
sizeY = image->width * image->height;
sizeUV = ((image->width+1) * (image->height+1)/2);
image->num_planes = 2;
image->pitches[0] = (image->width+31)&~31;
image->pitches[1] = (image->width+31)&~31;
image->offsets[0] = 0;
image->offsets[1] = sizeY;
image->data_size = sizeY + sizeUV;
image->image_id = object_heap_allocate(&driver_data->image_heap);
if (image->image_id == VA_INVALID_ID)
return VA_STATUS_ERROR_ALLOCATION_FAILED;
obj_img = IMAGE(image->image_id);
if (sunxi_cedrus_CreateBuffer(ctx, 0, VAImageBufferType, image->data_size,
1, NULL, &image->buf) != VA_STATUS_SUCCESS)
return VA_STATUS_ERROR_ALLOCATION_FAILED;
obj_img->buf = image->buf;
return VA_STATUS_SUCCESS;
}
VAStatus sunxi_cedrus_DeriveImage(VADriverContextP ctx, VASurfaceID surface,
VAImage *image)
{
INIT_DRIVER_DATA
object_surface_p obj_surface;
VAImageFormat fmt;
object_buffer_p obj_buffer;
VAStatus ret;
obj_surface = SURFACE(surface);
fmt.fourcc = VA_FOURCC_NV12;
ret = sunxi_cedrus_CreateImage(ctx, &fmt, obj_surface->width,
obj_surface->height, image);
if(ret != VA_STATUS_SUCCESS)
return ret;
obj_buffer = BUFFER(image->buf);
if (NULL == obj_buffer)
return VA_STATUS_ERROR_ALLOCATION_FAILED;
/* TODO: Use an appropriate DRM plane instead */
tiled_to_planar(driver_data->luma_bufs[obj_surface->output_buf_index], obj_buffer->buffer_data, image->pitches[0], image->width, image->height);
tiled_to_planar(driver_data->chroma_bufs[obj_surface->output_buf_index], obj_buffer->buffer_data + image->width*image->height, image->pitches[1], image->width, image->height/2);
return VA_STATUS_SUCCESS;
}
VAStatus sunxi_cedrus_DestroyImage(VADriverContextP ctx, VAImageID image)
{
INIT_DRIVER_DATA
object_image_p obj_img;
obj_img = IMAGE(image);
assert(obj_img);
sunxi_cedrus_DestroyBuffer(ctx, obj_img->buf);
return VA_STATUS_SUCCESS;
}
VAStatus sunxi_cedrus_SetImagePalette(VADriverContextP ctx, VAImageID image,
unsigned char *palette)
{ return VA_STATUS_SUCCESS; }
VAStatus sunxi_cedrus_GetImage(VADriverContextP ctx, VASurfaceID surface,
int x, int y, unsigned int width, unsigned int height,
VAImageID image)
{ return VA_STATUS_SUCCESS; }
VAStatus sunxi_cedrus_PutImage(VADriverContextP ctx, VASurfaceID surface,
VAImageID image, int src_x, int src_y, unsigned int src_width,
unsigned int src_height, int dest_x, int dest_y,
unsigned int dest_width, unsigned int dest_height)
{ return VA_STATUS_SUCCESS; }
+66
View File
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2016 Florent Revest, <florent.revest@free-electrons.com>
* 2007 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.
*/
#ifndef _IMAGE_H_
#define _IMAGE_H_
#include <va/va_backend.h>
#include "object_heap.h"
#define IMAGE(id) ((object_image_p) object_heap_lookup(&driver_data->image_heap, id))
#define IMAGE_ID_OFFSET 0x10000000
struct object_image {
struct object_base base;
VABufferID buf;
};
typedef struct object_image *object_image_p;
VAStatus sunxi_cedrus_QueryImageFormats(VADriverContextP ctx,
VAImageFormat *format_list, int *num_formats);
VAStatus sunxi_cedrus_CreateImage(VADriverContextP ctx, VAImageFormat *format,
int width, int height, VAImage *image);
VAStatus sunxi_cedrus_DeriveImage(VADriverContextP ctx, VASurfaceID surface,
VAImage *image);
VAStatus sunxi_cedrus_DestroyImage(VADriverContextP ctx, VAImageID image);
VAStatus sunxi_cedrus_SetImagePalette(VADriverContextP ctx, VAImageID image,
unsigned char *palette);
VAStatus sunxi_cedrus_GetImage(VADriverContextP ctx, VASurfaceID surface,
int x, int y, unsigned int width, unsigned int height,
VAImageID image);
VAStatus sunxi_cedrus_PutImage(VADriverContextP ctx, VASurfaceID surface,
VAImageID image, int src_x, int src_y, unsigned int src_width,
unsigned int src_height, int dest_x, int dest_y,
unsigned int dest_width, unsigned int dest_height);
#endif /* _IMAGE_H_ */
+255
View File
@@ -0,0 +1,255 @@
/*
* Copyright (c) 2007 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 <stdlib.h>
#include <assert.h>
#include "object_heap.h"
#define ASSERT assert
#define LAST_FREE -1
#define ALLOCATED -2
/*
* Expands the heap
* Return 0 on success, -1 on error
*/
static int object_heap_expand(object_heap_p heap)
{
int i;
void *new_heap_index;
int next_free;
int new_heap_size = heap->heap_size + heap->heap_increment;
int bucket_index = new_heap_size / heap->heap_increment - 1;
if (bucket_index >= heap->num_buckets) {
int new_num_buckets = heap->num_buckets + 8;
void **new_bucket;
new_bucket = realloc(heap->bucket, new_num_buckets * sizeof(void *));
if (NULL == new_bucket) {
return -1;
}
heap->num_buckets = new_num_buckets;
heap->bucket = new_bucket;
}
new_heap_index = (void *) malloc(heap->heap_increment * heap->object_size);
if (NULL == new_heap_index) {
return -1; /* Out of memory */
}
heap->bucket[bucket_index] = new_heap_index;
next_free = heap->next_free;
for (i = new_heap_size; i-- > heap->heap_size;) {
object_base_p obj = (object_base_p)(new_heap_index + (i - heap->heap_size) * heap->object_size);
obj->id = i + heap->id_offset;
obj->next_free = next_free;
next_free = i;
}
heap->next_free = next_free;
heap->heap_size = new_heap_size;
return 0; /* Success */
}
/*
* Return 0 on success, -1 on error
*/
int object_heap_init(object_heap_p heap, int object_size, int id_offset)
{
pthread_mutex_init(&heap->mutex, NULL);
heap->object_size = object_size;
heap->id_offset = id_offset & OBJECT_HEAP_OFFSET_MASK;
heap->heap_size = 0;
heap->heap_increment = 16;
heap->next_free = LAST_FREE;
heap->num_buckets = 0;
heap->bucket = NULL;
return object_heap_expand(heap);
}
/*
* Allocates an object
* Returns the object ID on success, returns -1 on error
*/
static int object_heap_allocate_unlocked(object_heap_p heap)
{
object_base_p obj;
int bucket_index, obj_index;
if (LAST_FREE == heap->next_free) {
if (-1 == object_heap_expand(heap)) {
return -1; /* Out of memory */
}
}
ASSERT(heap->next_free >= 0);
bucket_index = heap->next_free / heap->heap_increment;
obj_index = heap->next_free % heap->heap_increment;
obj = (object_base_p)(heap->bucket[bucket_index] + obj_index * heap->object_size);
heap->next_free = obj->next_free;
obj->next_free = ALLOCATED;
return obj->id;
}
int object_heap_allocate(object_heap_p heap)
{
int ret;
pthread_mutex_lock(&heap->mutex);
ret = object_heap_allocate_unlocked(heap);
pthread_mutex_unlock(&heap->mutex);
return ret;
}
/*
* Lookup an object by object ID
* Returns a pointer to the object on success, returns NULL on error
*/
static object_base_p object_heap_lookup_unlocked(object_heap_p heap, int id)
{
object_base_p obj;
int bucket_index, obj_index;
if ((id < heap->id_offset) || (id > (heap->heap_size + heap->id_offset))) {
return NULL;
}
id &= OBJECT_HEAP_ID_MASK;
bucket_index = id / heap->heap_increment;
obj_index = id % heap->heap_increment;
obj = (object_base_p)(heap->bucket[bucket_index] + obj_index * heap->object_size);
/* Check if the object has in fact been allocated */
if (obj->next_free != ALLOCATED) {
return NULL;
}
return obj;
}
object_base_p object_heap_lookup(object_heap_p heap, int id)
{
object_base_p obj;
pthread_mutex_lock(&heap->mutex);
obj = object_heap_lookup_unlocked(heap, id);
pthread_mutex_unlock(&heap->mutex);
return obj;
}
/*
* Iterate over all objects in the heap.
* Returns a pointer to the first object on the heap, returns NULL if heap is empty.
*/
object_base_p object_heap_first(object_heap_p heap, object_heap_iterator *iter)
{
*iter = -1;
return object_heap_next(heap, iter);
}
/*
* Iterate over all objects in the heap.
* Returns a pointer to the next object on the heap, returns NULL if heap is empty.
*/
static object_base_p object_heap_next_unlocked(object_heap_p heap, object_heap_iterator *iter)
{
object_base_p obj;
int bucket_index, obj_index;
int i = *iter + 1;
while (i < heap->heap_size) {
bucket_index = i / heap->heap_increment;
obj_index = i % heap->heap_increment;
obj = (object_base_p)(heap->bucket[bucket_index] + obj_index * heap->object_size);
if (obj->next_free == ALLOCATED) {
*iter = i;
return obj;
}
i++;
}
*iter = i;
return NULL;
}
object_base_p object_heap_next(object_heap_p heap, object_heap_iterator *iter)
{
object_base_p obj;
pthread_mutex_lock(&heap->mutex);
obj = object_heap_next_unlocked(heap, iter);
pthread_mutex_unlock(&heap->mutex);
return obj;
}
/*
* Frees an object
*/
static void object_heap_free_unlocked(object_heap_p heap, object_base_p obj)
{
/* Check if the object has in fact been allocated */
ASSERT(obj->next_free == ALLOCATED);
obj->next_free = heap->next_free;
heap->next_free = obj->id & OBJECT_HEAP_ID_MASK;
}
void object_heap_free(object_heap_p heap, object_base_p obj)
{
if (!obj)
return;
pthread_mutex_lock(&heap->mutex);
object_heap_free_unlocked(heap, obj);
pthread_mutex_unlock(&heap->mutex);
}
/*
* Destroys a heap, the heap must be empty.
*/
void object_heap_destroy(object_heap_p heap)
{
object_base_p obj;
int bucket_index, obj_index, i;
/* Check if heap is empty */
for (i = 0; i < heap->heap_size; i++) {
/* Check if object is not still allocated */
bucket_index = i / heap->heap_increment;
obj_index = i % heap->heap_increment;
obj = (object_base_p)(heap->bucket[bucket_index] + obj_index * heap->object_size);
ASSERT(obj->next_free != ALLOCATED);
}
for (i = 0; i < heap->heap_size / heap->heap_increment; i++) {
free(heap->bucket[i]);
}
pthread_mutex_destroy(&heap->mutex);
free(heap->bucket);
heap->bucket = NULL;
heap->heap_size = 0;
heap->next_free = LAST_FREE;
}
+93
View File
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2007 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.
*/
#ifndef OBJECT_HEAP_H
#define OBJECT_HEAP_H
#include <pthread.h>
#define OBJECT_HEAP_OFFSET_MASK 0x7F000000
#define OBJECT_HEAP_ID_MASK 0x00FFFFFF
typedef struct object_base *object_base_p;
typedef struct object_heap *object_heap_p;
struct object_base {
int id;
int next_free;
};
struct object_heap {
pthread_mutex_t mutex;
int object_size;
int id_offset;
int next_free;
int heap_size;
int heap_increment;
void **bucket;
int num_buckets;
};
typedef int object_heap_iterator;
/*
* Return 0 on success, -1 on error
*/
int object_heap_init(object_heap_p heap, int object_size, int id_offset);
/*
* Allocates an object
* Returns the object ID on success, returns -1 on error
*/
int object_heap_allocate(object_heap_p heap);
/*
* Lookup an allocated object by object ID
* Returns a pointer to the object on success, returns NULL on error
*/
object_base_p object_heap_lookup(object_heap_p heap, int id);
/*
* Iterate over all objects in the heap.
* Returns a pointer to the first object on the heap, returns NULL if heap is empty.
*/
object_base_p object_heap_first(object_heap_p heap, object_heap_iterator *iter);
/*
* Iterate over all objects in the heap.
* Returns a pointer to the next object on the heap, returns NULL if heap is empty.
*/
object_base_p object_heap_next(object_heap_p heap, object_heap_iterator *iter);
/*
* Frees an object
*/
void object_heap_free(object_heap_p heap, object_base_p obj);
/*
* Destroys a heap, the heap must be empty.
*/
void object_heap_destroy(object_heap_p heap);
#endif /* OBJECT_HEAP_H */
+190
View File
@@ -0,0 +1,190 @@
/*
* Copyright (c) 2016 Florent Revest, <florent.revest@free-electrons.com>
* 2007 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 "sunxi_cedrus_drv_video.h"
#include "picture.h"
#include "buffer.h"
#include "context.h"
#include "surface.h"
#include "va_config.h"
#include <assert.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
/*
* A Picture is an encoded input frame made of several buffers. A single input
* can contain slice data, headers and IQ matrix. Each Picture is assigned a
* request ID when created and each corresponding buffer might be turned into a
* v4l buffers or extended control when rendered. Finally they are submitted to
* kernel space when reaching EndPicture.
*/
VAStatus sunxi_cedrus_BeginPicture(VADriverContextP ctx, VAContextID context,
VASurfaceID render_target)
{
INIT_DRIVER_DATA
VAStatus vaStatus = VA_STATUS_SUCCESS;
object_context_p obj_context;
object_surface_p obj_surface;
obj_context = CONTEXT(context);
assert(obj_context);
obj_surface = SURFACE(render_target);
assert(obj_surface);
if(obj_surface->status == VASurfaceRendering)
sunxi_cedrus_SyncSurface(ctx, render_target);
obj_surface->status = VASurfaceRendering;
obj_surface->request = (obj_context->num_rendered_surfaces)%INPUT_BUFFERS_NB+1;
obj_surface->input_buf_index = obj_context->num_rendered_surfaces%INPUT_BUFFERS_NB;
obj_context->num_rendered_surfaces ++;
obj_context->current_render_target = obj_surface->base.id;
return vaStatus;
}
VAStatus sunxi_cedrus_RenderPicture(VADriverContextP ctx, VAContextID context,
VABufferID *buffers, int num_buffers)
{
INIT_DRIVER_DATA
VAStatus vaStatus = VA_STATUS_SUCCESS;
object_context_p obj_context;
object_surface_p obj_surface;
object_config_p obj_config;
int i;
obj_context = CONTEXT(context);
assert(obj_context);
obj_config = CONFIG(obj_context->config_id);
if (NULL == obj_config)
{
vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
return vaStatus;
}
obj_surface = SURFACE(obj_context->current_render_target);
assert(obj_surface);
/* verify that we got valid buffer references */
for(i = 0; i < num_buffers; i++)
{
object_buffer_p obj_buffer = BUFFER(buffers[i]);
assert(obj_buffer);
if (NULL == obj_buffer)
{
vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
break;
}
}
return vaStatus;
}
VAStatus sunxi_cedrus_EndPicture(VADriverContextP ctx, VAContextID context)
{
INIT_DRIVER_DATA
VAStatus vaStatus = VA_STATUS_SUCCESS;
object_context_p obj_context;
object_surface_p obj_surface;
struct v4l2_buffer out_buf, cap_buf;
struct v4l2_plane plane[1];
struct v4l2_plane planes[2];
struct v4l2_ext_control ctrl;
struct v4l2_ext_controls extCtrls;
object_config_p obj_config;
obj_context = CONTEXT(context);
assert(obj_context);
obj_surface = SURFACE(obj_context->current_render_target);
assert(obj_surface);
obj_config = CONFIG(obj_context->config_id);
if (NULL == obj_config)
{
vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
return vaStatus;
}
memset(&(out_buf), 0, sizeof(out_buf));
out_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
out_buf.memory = V4L2_MEMORY_MMAP;
out_buf.index = obj_surface->input_buf_index;
out_buf.length = 1;
out_buf.m.planes = plane;
out_buf.request = obj_surface->request;
switch(obj_config->profile) {
default:
out_buf.m.planes[0].bytesused = 0;
ctrl.id = V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR;
ctrl.ptr = NULL;
ctrl.size = 0;
break;
}
memset(&(cap_buf), 0, sizeof(cap_buf));
cap_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
cap_buf.memory = V4L2_MEMORY_MMAP;
cap_buf.index = obj_surface->output_buf_index;
cap_buf.length = 2;
cap_buf.m.planes = planes;
assert(ioctl(driver_data->mem2mem_fd, VIDIOC_QUERYBUF, &cap_buf)==0);
extCtrls.controls = &ctrl;
extCtrls.count = 1;
extCtrls.request = obj_surface->request;
assert(ioctl(driver_data->mem2mem_fd, VIDIOC_S_EXT_CTRLS, &extCtrls)==0);
if(ioctl(driver_data->mem2mem_fd, VIDIOC_QBUF, &cap_buf)) {
obj_surface->status = VASurfaceSkipped;
sunxi_cedrus_msg("Error when queuing output: %s\n", strerror(errno));
return VA_STATUS_ERROR_UNKNOWN;
}
if(ioctl(driver_data->mem2mem_fd, VIDIOC_QBUF, &out_buf)) {
obj_surface->status = VASurfaceSkipped;
sunxi_cedrus_msg("Error when queuing input: %s\n", strerror(errno));
ioctl(driver_data->mem2mem_fd, VIDIOC_DQBUF, &cap_buf);
return VA_STATUS_ERROR_UNKNOWN;
}
/* For now, assume that we are done with rendering right away */
obj_context->current_render_target = -1;
return vaStatus;
}
+41
View File
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2016 Florent Revest, <florent.revest@free-electrons.com>
* 2007 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.
*/
#ifndef _PICTURE_H_
#define _PICTURE_H_
#include <va/va_backend.h>
#include "object_heap.h"
VAStatus sunxi_cedrus_BeginPicture(VADriverContextP ctx, VAContextID context,
VASurfaceID render_target);
VAStatus sunxi_cedrus_RenderPicture(VADriverContextP ctx, VAContextID context,
VABufferID *buffers, int num_buffers);
VAStatus sunxi_cedrus_EndPicture(VADriverContextP ctx, VAContextID context);
#endif /* _PICTURE_H_ */
+75
View File
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2016 Florent Revest, <florent.revest@free-electrons.com>
* 2007 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 "sunxi_cedrus_drv_video.h"
#include "subpicture.h"
/*
* Subpictures aren't supported yet
*/
VAStatus sunxi_cedrus_QuerySubpictureFormats(VADriverContextP ctx,
VAImageFormat *format_list, unsigned int *flags,
unsigned int *num_formats)
{ return VA_STATUS_SUCCESS; }
VAStatus sunxi_cedrus_CreateSubpicture(VADriverContextP ctx, VAImageID image,
VASubpictureID *subpicture)
{ return VA_STATUS_SUCCESS; }
VAStatus sunxi_cedrus_DestroySubpicture(VADriverContextP ctx,
VASubpictureID subpicture)
{ return VA_STATUS_SUCCESS; }
VAStatus sunxi_cedrus_SetSubpictureImage(VADriverContextP ctx,
VASubpictureID subpicture, VAImageID image)
{ return VA_STATUS_SUCCESS; }
VAStatus sunxi_cedrus_SetSubpicturePalette(VADriverContextP ctx,
VASubpictureID subpicture, unsigned char *palette)
{ return VA_STATUS_SUCCESS; }
VAStatus sunxi_cedrus_SetSubpictureChromakey(VADriverContextP ctx,
VASubpictureID subpicture, unsigned int chromakey_min,
unsigned int chromakey_max, unsigned int chromakey_mask)
{ return VA_STATUS_SUCCESS; }
VAStatus sunxi_cedrus_SetSubpictureGlobalAlpha(VADriverContextP ctx,
VASubpictureID subpicture, float global_alpha)
{ return VA_STATUS_SUCCESS; }
VAStatus sunxi_cedrus_AssociateSubpicture(VADriverContextP ctx,
VASubpictureID subpicture, VASurfaceID *target_surfaces,
int num_surfaces, short src_x, short src_y,
unsigned short src_width, unsigned short src_height,
short dest_x, short dest_y, unsigned short dest_width,
unsigned short dest_height, unsigned int flags)
{ return VA_STATUS_SUCCESS; }
VAStatus sunxi_cedrus_DeassociateSubpicture(VADriverContextP ctx,
VASubpictureID subpicture, VASurfaceID *target_surfaces,
int num_surfaces)
{ return VA_STATUS_SUCCESS; }
+65
View File
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2016 Florent Revest, <florent.revest@free-electrons.com>
* 2007 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.
*/
#ifndef _SUBPICTURE_H_
#define _SUBPICTURE_H_
#include <va/va_backend.h>
VAStatus sunxi_cedrus_QuerySubpictureFormats(VADriverContextP ctx,
VAImageFormat *format_list, unsigned int *flags,
unsigned int *num_formats);
VAStatus sunxi_cedrus_CreateSubpicture(VADriverContextP ctx, VAImageID image,
VASubpictureID *subpicture);
VAStatus sunxi_cedrus_DestroySubpicture(VADriverContextP ctx,
VASubpictureID subpicture);
VAStatus sunxi_cedrus_SetSubpictureImage(VADriverContextP ctx,
VASubpictureID subpicture, VAImageID image);
VAStatus sunxi_cedrus_SetSubpicturePalette(VADriverContextP ctx,
VASubpictureID subpicture, unsigned char *palette);
VAStatus sunxi_cedrus_SetSubpictureChromakey(VADriverContextP ctx,
VASubpictureID subpicture, unsigned int chromakey_min,
unsigned int chromakey_max, unsigned int chromakey_mask);
VAStatus sunxi_cedrus_SetSubpictureGlobalAlpha(VADriverContextP ctx,
VASubpictureID subpicture, float global_alpha);
VAStatus sunxi_cedrus_AssociateSubpicture(VADriverContextP ctx,
VASubpictureID subpicture, VASurfaceID *target_surfaces,
int num_surfaces, short src_x, short src_y,
unsigned short src_width, unsigned short src_height,
short dest_x, short dest_y, unsigned short dest_width,
unsigned short dest_height, unsigned int flags);
VAStatus sunxi_cedrus_DeassociateSubpicture(VADriverContextP ctx,
VASubpictureID subpicture, VASurfaceID *target_surfaces,
int num_surfaces);
#endif /* _SUBPICTURE_H_ */
+197
View File
@@ -0,0 +1,197 @@
/*
* Copyright (c) 2016 Florent Revest, <florent.revest@free-electrons.com>
* 2007 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 "buffer.h"
#include "context.h"
#include "image.h"
#include "picture.h"
#include "subpicture.h"
#include "surface.h"
#include "va_config.h"
#include <va/va_backend.h>
#include "sunxi_cedrus_drv_video.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdarg.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
/* We need to use stderr if we want to be heard */
void sunxi_cedrus_msg(const char *msg, ...)
{
va_list args;
fprintf(stderr, "sunxi_cedrus_drv_video: ");
va_start(args, msg);
vfprintf(stderr, msg, args);
va_end(args);
}
/* Free memory and close v4l device */
VAStatus sunxi_cedrus_Terminate(VADriverContextP ctx)
{
INIT_DRIVER_DATA
object_buffer_p obj_buffer;
object_config_p obj_config;
object_heap_iterator iter;
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
ioctl(driver_data->mem2mem_fd, VIDIOC_STREAMOFF, &type);
type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
ioctl(driver_data->mem2mem_fd, VIDIOC_STREAMOFF, &type);
close(driver_data->mem2mem_fd);
/* Clean up left over buffers */
obj_buffer = (object_buffer_p) object_heap_first(&driver_data->buffer_heap, &iter);
while (obj_buffer)
{
sunxi_cedrus_msg("vaTerminate: bufferID %08x still allocated, destroying\n", obj_buffer->base.id);
sunxi_cedrus_destroy_buffer(driver_data, obj_buffer);
obj_buffer = (object_buffer_p) object_heap_next(&driver_data->buffer_heap, &iter);
}
object_heap_destroy(&driver_data->buffer_heap);
object_heap_destroy(&driver_data->surface_heap);
object_heap_destroy(&driver_data->context_heap);
/* Clean up configIDs */
obj_config = (object_config_p) object_heap_first(&driver_data->config_heap, &iter);
while (obj_config)
{
object_heap_free(&driver_data->config_heap, (object_base_p) obj_config);
obj_config = (object_config_p) object_heap_next(&driver_data->config_heap, &iter);
}
object_heap_destroy(&driver_data->config_heap);
free(ctx->pDriverData);
ctx->pDriverData = NULL;
return VA_STATUS_SUCCESS;
}
/* Only expose the init function */
VAStatus __attribute__((visibility("default")))
VA_DRIVER_INIT_FUNC(VADriverContextP ctx);
/* Setup a bunch of function pointers for VA */
VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP ctx)
{
struct VADriverVTable * const vtable = ctx->vtable;
struct sunxi_cedrus_driver_data *driver_data;
struct v4l2_capability cap;
ctx->version_major = VA_MAJOR_VERSION;
ctx->version_minor = VA_MINOR_VERSION;
ctx->max_profiles = SUNXI_CEDRUS_MAX_PROFILES;
ctx->max_entrypoints = SUNXI_CEDRUS_MAX_ENTRYPOINTS;
ctx->max_attributes = SUNXI_CEDRUS_MAX_CONFIG_ATTRIBUTES;
ctx->max_image_formats = SUNXI_CEDRUS_MAX_IMAGE_FORMATS;
ctx->max_subpic_formats = SUNXI_CEDRUS_MAX_SUBPIC_FORMATS;
ctx->max_display_attributes = SUNXI_CEDRUS_MAX_DISPLAY_ATTRIBUTES;
ctx->str_vendor = SUNXI_CEDRUS_STR_VENDOR;
vtable->vaTerminate = sunxi_cedrus_Terminate;
vtable->vaQueryConfigEntrypoints = sunxi_cedrus_QueryConfigEntrypoints;
vtable->vaQueryConfigProfiles = sunxi_cedrus_QueryConfigProfiles;
vtable->vaQueryConfigEntrypoints = sunxi_cedrus_QueryConfigEntrypoints;
vtable->vaQueryConfigAttributes = sunxi_cedrus_QueryConfigAttributes;
vtable->vaCreateConfig = sunxi_cedrus_CreateConfig;
vtable->vaDestroyConfig = sunxi_cedrus_DestroyConfig;
vtable->vaGetConfigAttributes = sunxi_cedrus_GetConfigAttributes;
vtable->vaCreateSurfaces = sunxi_cedrus_CreateSurfaces;
vtable->vaDestroySurfaces = sunxi_cedrus_DestroySurfaces;
vtable->vaCreateContext = sunxi_cedrus_CreateContext;
vtable->vaDestroyContext = sunxi_cedrus_DestroyContext;
vtable->vaCreateBuffer = sunxi_cedrus_CreateBuffer;
vtable->vaBufferSetNumElements = sunxi_cedrus_BufferSetNumElements;
vtable->vaMapBuffer = sunxi_cedrus_MapBuffer;
vtable->vaUnmapBuffer = sunxi_cedrus_UnmapBuffer;
vtable->vaDestroyBuffer = sunxi_cedrus_DestroyBuffer;
vtable->vaBeginPicture = sunxi_cedrus_BeginPicture;
vtable->vaRenderPicture = sunxi_cedrus_RenderPicture;
vtable->vaEndPicture = sunxi_cedrus_EndPicture;
vtable->vaSyncSurface = sunxi_cedrus_SyncSurface;
vtable->vaQuerySurfaceStatus = sunxi_cedrus_QuerySurfaceStatus;
vtable->vaPutSurface = sunxi_cedrus_PutSurface;
vtable->vaQueryImageFormats = sunxi_cedrus_QueryImageFormats;
vtable->vaCreateImage = sunxi_cedrus_CreateImage;
vtable->vaDeriveImage = sunxi_cedrus_DeriveImage;
vtable->vaDestroyImage = sunxi_cedrus_DestroyImage;
vtable->vaSetImagePalette = sunxi_cedrus_SetImagePalette;
vtable->vaGetImage = sunxi_cedrus_GetImage;
vtable->vaPutImage = sunxi_cedrus_PutImage;
vtable->vaQuerySubpictureFormats = sunxi_cedrus_QuerySubpictureFormats;
vtable->vaCreateSubpicture = sunxi_cedrus_CreateSubpicture;
vtable->vaDestroySubpicture = sunxi_cedrus_DestroySubpicture;
vtable->vaSetSubpictureImage = sunxi_cedrus_SetSubpictureImage;
vtable->vaSetSubpictureChromakey = sunxi_cedrus_SetSubpictureChromakey;
vtable->vaSetSubpictureGlobalAlpha = sunxi_cedrus_SetSubpictureGlobalAlpha;
vtable->vaAssociateSubpicture = sunxi_cedrus_AssociateSubpicture;
vtable->vaDeassociateSubpicture = sunxi_cedrus_DeassociateSubpicture;
vtable->vaQueryDisplayAttributes = sunxi_cedrus_QueryDisplayAttributes;
vtable->vaGetDisplayAttributes = sunxi_cedrus_GetDisplayAttributes;
vtable->vaSetDisplayAttributes = sunxi_cedrus_SetDisplayAttributes;
vtable->vaLockSurface = sunxi_cedrus_LockSurface;
vtable->vaUnlockSurface = sunxi_cedrus_UnlockSurface;
vtable->vaBufferInfo = sunxi_cedrus_BufferInfo;
driver_data = (struct sunxi_cedrus_driver_data *) malloc(sizeof(*driver_data));
ctx->pDriverData = (void *) driver_data;
assert(object_heap_init(&driver_data->config_heap,
sizeof(struct object_config), CONFIG_ID_OFFSET)==0);
assert(object_heap_init(&driver_data->context_heap,
sizeof(struct object_context), CONTEXT_ID_OFFSET)==0);
assert(object_heap_init(&driver_data->surface_heap,
sizeof(struct object_surface), SURFACE_ID_OFFSET)==0);
assert(object_heap_init(&driver_data->buffer_heap,
sizeof(struct object_buffer), BUFFER_ID_OFFSET)==0);
assert(object_heap_init(&driver_data->image_heap,
sizeof(struct object_image), IMAGE_ID_OFFSET)==0);
driver_data->mem2mem_fd = open("/dev/video0", O_RDWR | O_NONBLOCK, 0);
assert(driver_data->mem2mem_fd >= 0);
assert(ioctl(driver_data->mem2mem_fd, VIDIOC_QUERYCAP, &cap)==0);
if (!(cap.capabilities & V4L2_CAP_VIDEO_M2M_MPLANE))
{
sunxi_cedrus_msg("/dev/video0 does not support m2m_mplane\n");
return VA_STATUS_ERROR_OPERATION_FAILED;
}
return VA_STATUS_SUCCESS;
}
+59
View File
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2016 Florent Revest, <florent.revest@free-electrons.com>
* 2007 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.
*/
#ifndef _SUNXI_CEDRUS_DRV_VIDEO_H_
#define _SUNXI_CEDRUS_DRV_VIDEO_H_
#include <va/va.h>
#include "object_heap.h"
#include <linux/videodev2.h>
#define INIT_DRIVER_DATA struct sunxi_cedrus_driver_data * const driver_data = (struct sunxi_cedrus_driver_data *) ctx->pDriverData;
#define SUNXI_CEDRUS_STR_VENDOR "Sunxi Cedrus Driver 1.0"
#define SUNXI_CEDRUS_MAX_PROFILES 11
#define SUNXI_CEDRUS_MAX_ENTRYPOINTS 5
#define SUNXI_CEDRUS_MAX_CONFIG_ATTRIBUTES 10
#define SUNXI_CEDRUS_MAX_IMAGE_FORMATS 10
#define SUNXI_CEDRUS_MAX_SUBPIC_FORMATS 4
#define SUNXI_CEDRUS_MAX_DISPLAY_ATTRIBUTES 4
void sunxi_cedrus_msg(const char *msg, ...);
struct sunxi_cedrus_driver_data {
struct object_heap config_heap;
struct object_heap context_heap;
struct object_heap surface_heap;
struct object_heap buffer_heap;
struct object_heap image_heap;
char *luma_bufs[VIDEO_MAX_FRAME];
char *chroma_bufs[VIDEO_MAX_FRAME];
unsigned int num_dst_bufs;
int mem2mem_fd;
};
#endif /* _SUNXI_CEDRUS_DRV_VIDEO_H_ */
+281
View File
@@ -0,0 +1,281 @@
/*
* Copyright (c) 2016 Florent Revest, <florent.revest@free-electrons.com>
* 2007 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 "sunxi_cedrus_drv_video.h"
#include "surface.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <X11/Xlib.h>
/*
* A Surface is an internal data structure never handled by the VA's user
* containing the output of a rendering. Usualy, a bunch of surfaces are created
* at the begining of decoding and they are then used alternatively. When
* created, a surface is assigned a corresponding v4l capture buffer and it is
* kept until the end of decoding. Syncing a surface waits for the v4l buffer to
* be available and then dequeue it.
*
* Note: since a Surface is kept private from the VA's user, it can ask to
* directly render a Surface on screen in an X Drawable. Some kind of
* implementation is available in PutSurface but this is only for development
* purpose.
*/
VAStatus sunxi_cedrus_CreateSurfaces(VADriverContextP ctx, int width,
int height, int format, int num_surfaces, VASurfaceID *surfaces)
{
INIT_DRIVER_DATA
VAStatus vaStatus = VA_STATUS_SUCCESS;
int i;
struct v4l2_buffer buf;
struct v4l2_plane planes[2];
struct v4l2_create_buffers create_bufs;
struct v4l2_format fmt;
/* We only support one format */
if (VA_RT_FORMAT_YUV420 != format)
return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
/* Set format for capture */
memset(&(fmt), 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
fmt.fmt.pix_mp.width = width;
fmt.fmt.pix_mp.height = height;
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_SUNXI;
fmt.fmt.pix_mp.field = V4L2_FIELD_ANY;
fmt.fmt.pix_mp.num_planes = 2;
assert(ioctl(driver_data->mem2mem_fd, VIDIOC_S_FMT, &fmt)==0);
memset (&create_bufs, 0, sizeof (struct v4l2_create_buffers));
create_bufs.count = num_surfaces;
create_bufs.memory = V4L2_MEMORY_MMAP;
create_bufs.format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
assert(ioctl(driver_data->mem2mem_fd, VIDIOC_G_FMT, &create_bufs.format)==0);
assert(ioctl(driver_data->mem2mem_fd, VIDIOC_CREATE_BUFS, &create_bufs)==0);
driver_data->num_dst_bufs = create_bufs.count;
for (i = 0; i < create_bufs.count; i++)
{
int surfaceID = object_heap_allocate(&driver_data->surface_heap);
object_surface_p obj_surface = SURFACE(surfaceID);
if (NULL == obj_surface)
{
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
break;
}
obj_surface->surface_id = surfaceID;
surfaces[i] = surfaceID;
memset(&(buf), 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = create_bufs.index + i;
buf.length = 2;
buf.m.planes = planes;
assert(ioctl(driver_data->mem2mem_fd, VIDIOC_QUERYBUF, &buf)==0);
driver_data->luma_bufs[buf.index] = mmap(NULL, buf.m.planes[0].length,
PROT_READ | PROT_WRITE, MAP_SHARED,
driver_data->mem2mem_fd, buf.m.planes[0].m.mem_offset);
assert(driver_data->luma_bufs[buf.index] != MAP_FAILED);
driver_data->chroma_bufs[buf.index] = mmap(NULL, buf.m.planes[1].length,
PROT_READ | PROT_WRITE, MAP_SHARED,
driver_data->mem2mem_fd, buf.m.planes[1].m.mem_offset);
assert(driver_data->chroma_bufs[buf.index] != MAP_FAILED);
obj_surface->input_buf_index = 0;
obj_surface->output_buf_index = create_bufs.index + i;
obj_surface->width = width;
obj_surface->height = height;
obj_surface->status = VASurfaceReady;
}
/* Error recovery */
if (VA_STATUS_SUCCESS != vaStatus)
{
/* surfaces[i-1] was the last successful allocation */
for(; i--;)
{
object_surface_p obj_surface = SURFACE(surfaces[i]);
surfaces[i] = VA_INVALID_SURFACE;
assert(obj_surface);
object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
}
}
return vaStatus;
}
VAStatus sunxi_cedrus_DestroySurfaces(VADriverContextP ctx,
VASurfaceID *surface_list, int num_surfaces)
{
INIT_DRIVER_DATA
int i;
for(i = num_surfaces; i--;)
{
object_surface_p obj_surface = SURFACE(surface_list[i]);
assert(obj_surface);
object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
}
return VA_STATUS_SUCCESS;
}
VAStatus sunxi_cedrus_SyncSurface(VADriverContextP ctx,
VASurfaceID render_target)
{
INIT_DRIVER_DATA
object_surface_p obj_surface;
struct v4l2_buffer buf;
struct v4l2_plane plane[1];
fd_set read_fds;
struct timeval tv = {0, 300000};
obj_surface = SURFACE(render_target);
assert(obj_surface);
FD_ZERO(&read_fds);
FD_SET(driver_data->mem2mem_fd, &read_fds);
if(obj_surface->status != VASurfaceSkipped)
select(driver_data->mem2mem_fd + 1, &read_fds, NULL, NULL, &tv);
else
return VA_STATUS_ERROR_UNKNOWN;
memset(&(buf), 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = obj_surface->input_buf_index;
buf.length = 1;
buf.m.planes = plane;
if(ioctl(driver_data->mem2mem_fd, VIDIOC_DQBUF, &buf)) {
sunxi_cedrus_msg("Error when dequeuing input: %s\n", strerror(errno));
return VA_STATUS_ERROR_UNKNOWN;
}
memset(&(buf), 0, sizeof(buf));
struct v4l2_plane planes[2];
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = obj_surface->output_buf_index;
buf.length = 2;
buf.m.planes = planes;
obj_surface->status = VASurfaceReady;
if(ioctl(driver_data->mem2mem_fd, VIDIOC_DQBUF, &buf)) {
sunxi_cedrus_msg("Error when dequeuing output: %s\n", strerror(errno));
return VA_STATUS_ERROR_UNKNOWN;
}
return VA_STATUS_SUCCESS;
}
VAStatus sunxi_cedrus_QuerySurfaceStatus(VADriverContextP ctx,
VASurfaceID render_target, VASurfaceStatus *status)
{
INIT_DRIVER_DATA
VAStatus vaStatus = VA_STATUS_SUCCESS;
object_surface_p obj_surface;
obj_surface = SURFACE(render_target);
assert(obj_surface);
*status = obj_surface->status;
return vaStatus;
}
/* WARNING: This is for development purpose only!!! */
VAStatus sunxi_cedrus_PutSurface(VADriverContextP ctx, VASurfaceID surface,
void *draw, short srcx, short srcy, unsigned short srcw,
unsigned short srch, short destx, short desty,
unsigned short destw, unsigned short desth,
VARectangle *cliprects, unsigned int number_cliprects,
unsigned int flags)
{
INIT_DRIVER_DATA
GC gc;
Display *display;
const XID xid = (XID)(uintptr_t)draw;
XColor xcolor;
int screen;
Colormap cm;
int colorratio = 65535 / 255;
int x, y;
object_surface_p obj_surface;
obj_surface = SURFACE(surface);
assert(obj_surface);
display = XOpenDisplay(getenv("DISPLAY"));
if (display == NULL) {
sunxi_cedrus_msg("Cannot connect to X server\n");
exit(1);
}
sunxi_cedrus_msg("warning: using vaPutSurface with sunxi-cedrus is not recommended\n");
screen = DefaultScreen(display);
gc = XCreateGC(display, RootWindow(display, screen), 0, NULL);
XSync(display, False);
cm = DefaultColormap(display, screen);
xcolor.flags = DoRed | DoGreen | DoBlue;
for(x=destx; x < destx+destw; x++) {
for(y=desty; y < desty+desth; y++) {
char lum = driver_data->luma_bufs[obj_surface->output_buf_index][x+srcw*y];
xcolor.red = xcolor.green = xcolor.blue = lum*colorratio;
XAllocColor(display, cm, &xcolor);
XSetForeground(display, gc, xcolor.pixel);
XDrawPoint(display, xid, gc, x, y);
}
}
XFlush(display);
XCloseDisplay(display);
return VA_STATUS_SUCCESS;
}
VAStatus sunxi_cedrus_LockSurface(VADriverContextP ctx, VASurfaceID surface,
unsigned int *fourcc, unsigned int *luma_stride,
unsigned int *chroma_u_stride, unsigned int *chroma_v_stride,
unsigned int *luma_offset, unsigned int *chroma_u_offset,
unsigned int *chroma_v_offset, unsigned int *buffer_name,
void **buffer)
{ return VA_STATUS_ERROR_UNIMPLEMENTED; }
VAStatus sunxi_cedrus_UnlockSurface(VADriverContextP ctx, VASurfaceID surface)
{ return VA_STATUS_ERROR_UNIMPLEMENTED; }
+77
View File
@@ -0,0 +1,77 @@
/*
* Copyright (c) 2016 Florent Revest, <florent.revest@free-electrons.com>
* 2007 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.
*/
#ifndef _SURFACES_H_
#define _SURFACES_H_
#include <va/va_backend.h>
#include "object_heap.h"
#define SURFACE(id) ((object_surface_p) object_heap_lookup(&driver_data->surface_heap, id))
#define SURFACE_ID_OFFSET 0x04000000
struct object_surface {
struct object_base base;
VASurfaceID surface_id;
uint32_t request;
uint32_t input_buf_index;
uint32_t output_buf_index;
int width;
int height;
VAStatus status;
};
typedef struct object_surface *object_surface_p;
VAStatus sunxi_cedrus_CreateSurfaces(VADriverContextP ctx, int width,
int height, int format, int num_surfaces, VASurfaceID *surfaces);
VAStatus sunxi_cedrus_DestroySurfaces(VADriverContextP ctx,
VASurfaceID *surface_list, int num_surfaces);
VAStatus sunxi_cedrus_SyncSurface(VADriverContextP ctx,
VASurfaceID render_target);
VAStatus sunxi_cedrus_QuerySurfaceStatus(VADriverContextP ctx,
VASurfaceID render_target, VASurfaceStatus *status);
VAStatus sunxi_cedrus_PutSurface(VADriverContextP ctx, VASurfaceID surface,
void *draw, short srcx, short srcy, unsigned short srcw,
unsigned short srch, short destx, short desty,
unsigned short destw, unsigned short desth,
VARectangle *cliprects, unsigned int number_cliprects,
unsigned int flags);
VAStatus sunxi_cedrus_LockSurface(VADriverContextP ctx, VASurfaceID surface,
unsigned int *fourcc, unsigned int *luma_stride,
unsigned int *chroma_u_stride, unsigned int *chroma_v_stride,
unsigned int *luma_offset, unsigned int *chroma_u_offset,
unsigned int *chroma_v_offset, unsigned int *buffer_name,
void **buffer);
VAStatus sunxi_cedrus_UnlockSurface(VADriverContextP ctx, VASurfaceID surface);
#endif /* _SURFACES_H_ */
+185
View File
@@ -0,0 +1,185 @@
/*
* Copyright (c) 2014 Jens Kuske <jenskuske@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* The Sunxi Video Engine outputs buffers in a specific format similar to NV12
* but with "tiles" of size 32x32. This code converts the data from this tiled
* format to two NV12 planes.
*/
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */
#endif
#ifndef __aarch64__
.text
.syntax unified
.arch armv7-a
.fpu neon
.thumb
.macro thumb_function fname
.global \fname
#ifdef __ELF__
.hidden \fname
.type \fname, %function
#endif
.thumb_func
\fname:
.endm
.macro end_function fname
#ifdef __ELF__
.size \fname, .-\fname
#endif
.endm
SRC .req r0
DST .req r1
PITCH .req r2
CNT .req r3
TLINE .req r4
HEIGHT .req r5
REST .req r6
NTILES .req r7
TMPSRC .req r8
DST2 .req r9
TSIZE .req r12
NEXTLIN .req lr
thumb_function tiled_to_planar
push {r4, r5, r6, r7, r8, lr}
ldr HEIGHT, [sp, #24]
add NEXTLIN, r3, #31
lsrs NTILES, r3, #5
bic NEXTLIN, NEXTLIN, #31
and REST, r3, #31
lsl NEXTLIN, NEXTLIN, #5
subs PITCH, r2, r3
movs TLINE, #32
rsb NEXTLIN, NEXTLIN, #32
mov TSIZE, #1024
/* y loop */
1: cbz NTILES, 3f
mov CNT, NTILES
/* x loop complete tiles */
2: pld [SRC, TSIZE]
vld1.8 {d0 - d3}, [SRC :256], TSIZE
subs CNT, #1
vst1.8 {d0 - d3}, [DST]!
bne 2b
3: cbnz REST, 4f
/* fix up dest pointer if pitch != width */
7: add DST, PITCH
/* fix up src pointer at end of line */
subs TLINE, #1
itee ne
addne SRC, NEXTLIN
subeq SRC, #992
moveq TLINE, #32
subs HEIGHT, #1
bne 1b
pop {r4, r5, r6, r7, r8, pc}
/* partly copy last tile of line */
4: mov TMPSRC, SRC
tst REST, #16
beq 5f
vld1.8 {d0 - d1}, [TMPSRC :128]!
vst1.8 {d0 - d1}, [DST]!
5: add SRC, TSIZE
ands CNT, REST, #15
beq 7b
6: vld1.8 {d0[0]}, [TMPSRC]!
subs CNT, #1
vst1.8 {d0[0]}, [DST]!
bne 6b
b 7b
end_function tiled_to_planar
thumb_function tiled_deinterleave_to_planar
push {r4, r5, r6, r7, r8, r9, lr}
mov DST2, r2
ldr HEIGHT, [sp, #32]
ldr r4, [sp, #28]
add NEXTLIN, r4, #31
lsrs NTILES, r4, #5
bic NEXTLIN, NEXTLIN, #31
ubfx REST, r4, #1, #4
lsl NEXTLIN, NEXTLIN, #5
sub PITCH, r3, r4, lsr #1
movs TLINE, #32
rsb NEXTLIN, NEXTLIN, #32
mov TSIZE, #1024
/* y loop */
1: cbz NTILES, 3f
mov CNT, NTILES
/* x loop complete tiles */
2: pld [SRC, TSIZE]
vld2.8 {d0 - d3}, [SRC :256], TSIZE
subs CNT, #1
vst1.8 {d0 - d1}, [DST]!
vst1.8 {d2 - d3}, [DST2]!
bne 2b
3: cbnz REST, 4f
/* fix up dest pointer if pitch != width */
7: add DST, PITCH
add DST2, PITCH
/* fix up src pointer at end of line */
subs TLINE, #1
itee ne
addne SRC, NEXTLIN
subeq SRC, #992
moveq TLINE, #32
subs HEIGHT, #1
bne 1b
pop {r4, r5, r6, r7, r8, r9, pc}
/* partly copy last tile of line */
4: mov TMPSRC, SRC
tst REST, #8
beq 5f
vld2.8 {d0 - d1}, [TMPSRC :128]!
vst1.8 {d0}, [DST]!
vst1.8 {d1}, [DST2]!
5: add SRC, TSIZE
ands CNT, REST, #7
beq 7b
6: vld2.8 {d0[0], d1[0]}, [TMPSRC]!
subs CNT, #1
vst1.8 {d0[0]}, [DST]!
vst1.8 {d1[0]}, [DST2]!
bne 6b
b 7b
end_function tiled_deinterleave_to_planar
#endif
+30
View File
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2014 Jens Kuske <jenskuske@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef __TILED_YUV_H__
#define __TILED_YUV_H__
void tiled_to_planar(void *src, void *dst, unsigned int dst_pitch,
unsigned int width, unsigned int height);
void tiled_deinterleave_to_planar(void *src, void *dst1, void *dst2,
unsigned int dst_pitch,
unsigned int width, unsigned int height);
#endif
+226
View File
@@ -0,0 +1,226 @@
/*
* Copyright (c) 2016 Florent Revest, <florent.revest@free-electrons.com>
* 2007 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 "sunxi_cedrus_drv_video.h"
#include "va_config.h"
#include <assert.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
/*
* This file provides generalities to VA's user regarding the file formats
* supported by the v4l driver. It uses VIDIOC_ENUM_FMT to make the
* correspondence between v4l and VA video formats.
*/
VAStatus sunxi_cedrus_QueryConfigProfiles(VADriverContextP ctx,
VAProfile *profile_list, int *num_profiles)
{
INIT_DRIVER_DATA
int i = 0;
struct v4l2_fmtdesc vid_fmtdesc;
memset(&vid_fmtdesc, 0, sizeof(vid_fmtdesc));
vid_fmtdesc.index = 0;
vid_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
while(ioctl(driver_data->mem2mem_fd, VIDIOC_ENUM_FMT, &vid_fmtdesc) == 0)
{
vid_fmtdesc.index++;
}
assert(i <= SUNXI_CEDRUS_MAX_PROFILES);
*num_profiles = i;
return VA_STATUS_SUCCESS;
}
VAStatus sunxi_cedrus_QueryConfigEntrypoints(VADriverContextP ctx,
VAProfile profile, VAEntrypoint *entrypoint_list,
int *num_entrypoints)
{
switch (profile) {
default:
*num_entrypoints = 0;
break;
}
assert(*num_entrypoints <= SUNXI_CEDRUS_MAX_ENTRYPOINTS);
return VA_STATUS_SUCCESS;
}
VAStatus sunxi_cedrus_GetConfigAttributes(VADriverContextP ctx,
VAProfile profile, VAEntrypoint entrypoint,
VAConfigAttrib *attrib_list, int num_attribs)
{
int i;
for (i = 0; i < num_attribs; i++)
{
switch (attrib_list[i].type)
{
case VAConfigAttribRTFormat:
attrib_list[i].value = VA_RT_FORMAT_YUV420;
break;
default:
/* Do nothing */
attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
break;
}
}
return VA_STATUS_SUCCESS;
}
VAStatus sunxi_cedrus_update_attribute(object_config_p obj_config,
VAConfigAttrib *attrib)
{
int i;
/* Check existing attributes */
for(i = 0; obj_config->attrib_count < i; i++)
{
if (obj_config->attrib_list[i].type == attrib->type)
{
/* Update existing attribute */
obj_config->attrib_list[i].value = attrib->value;
return VA_STATUS_SUCCESS;
}
}
if (obj_config->attrib_count < SUNXI_CEDRUS_MAX_CONFIG_ATTRIBUTES)
{
i = obj_config->attrib_count;
obj_config->attrib_list[i].type = attrib->type;
obj_config->attrib_list[i].value = attrib->value;
obj_config->attrib_count++;
return VA_STATUS_SUCCESS;
}
return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
}
VAStatus sunxi_cedrus_CreateConfig(VADriverContextP ctx, VAProfile profile,
VAEntrypoint entrypoint, VAConfigAttrib *attrib_list,
int num_attribs, VAConfigID *config_id)
{
INIT_DRIVER_DATA
VAStatus vaStatus;
int configID;
object_config_p obj_config;
int i;
/* Validate profile & entrypoint */
switch (profile) {
default:
vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
break;
}
if (VA_STATUS_SUCCESS != vaStatus)
return vaStatus;
configID = object_heap_allocate(&driver_data->config_heap);
obj_config = CONFIG(configID);
if (NULL == obj_config)
{
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
return vaStatus;
}
obj_config->profile = profile;
obj_config->entrypoint = entrypoint;
obj_config->attrib_list[0].type = VAConfigAttribRTFormat;
obj_config->attrib_list[0].value = VA_RT_FORMAT_YUV420;
obj_config->attrib_count = 1;
for(i = 0; i < num_attribs; i++)
{
vaStatus = sunxi_cedrus_update_attribute(obj_config, &(attrib_list[i]));
if (VA_STATUS_SUCCESS != vaStatus)
break;
}
/* Error recovery */
if (VA_STATUS_SUCCESS != vaStatus)
object_heap_free(&driver_data->config_heap, (object_base_p) obj_config);
else
*config_id = configID;
return vaStatus;
}
VAStatus sunxi_cedrus_DestroyConfig(VADriverContextP ctx, VAConfigID config_id)
{
INIT_DRIVER_DATA
VAStatus vaStatus;
object_config_p obj_config;
obj_config = CONFIG(config_id);
if (NULL == obj_config)
{
vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
return vaStatus;
}
object_heap_free(&driver_data->config_heap, (object_base_p) obj_config);
return VA_STATUS_SUCCESS;
}
VAStatus sunxi_cedrus_QueryConfigAttributes(VADriverContextP ctx,
VAConfigID config_id, VAProfile *profile,
VAEntrypoint *entrypoint, VAConfigAttrib *attrib_list,
int *num_attribs)
{
INIT_DRIVER_DATA
VAStatus vaStatus = VA_STATUS_SUCCESS;
object_config_p obj_config;
int i;
obj_config = CONFIG(config_id);
assert(obj_config);
*profile = obj_config->profile;
*entrypoint = obj_config->entrypoint;
*num_attribs = obj_config->attrib_count;
for(i = 0; i < obj_config->attrib_count; i++)
attrib_list[i] = obj_config->attrib_list[i];
return vaStatus;
}
/* sunxi-cedrus doesn't support display attributes */
VAStatus sunxi_cedrus_QueryDisplayAttributes (VADriverContextP ctx,
VADisplayAttribute *attr_list, int *num_attributes)
{ return VA_STATUS_ERROR_UNKNOWN; }
VAStatus sunxi_cedrus_GetDisplayAttributes (VADriverContextP ctx,
VADisplayAttribute *attr_list, int num_attributes)
{ return VA_STATUS_ERROR_UNKNOWN; }
VAStatus sunxi_cedrus_SetDisplayAttributes (VADriverContextP ctx,
VADisplayAttribute *attr_list, int num_attributes)
{ return VA_STATUS_ERROR_UNKNOWN; }
+80
View File
@@ -0,0 +1,80 @@
/*
* Copyright (c) 2016 Florent Revest, <florent.revest@free-electrons.com>
* 2007 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.
*/
#ifndef _CONFIG_H_
#define _CONFIG_H_
#include <va/va_backend.h>
#include "object_heap.h"
#define CONFIG(id) ((object_config_p) object_heap_lookup(&driver_data->config_heap, id))
#define CONFIG_ID_OFFSET 0x01000000
struct object_config {
struct object_base base;
VAProfile profile;
VAEntrypoint entrypoint;
VAConfigAttrib attrib_list[SUNXI_CEDRUS_MAX_CONFIG_ATTRIBUTES];
int attrib_count;
};
typedef struct object_config *object_config_p;
VAStatus sunxi_cedrus_QueryConfigProfiles(VADriverContextP ctx,
VAProfile *profile_list, int *num_profiles);
VAStatus sunxi_cedrus_QueryConfigEntrypoints(VADriverContextP ctx,
VAProfile profile, VAEntrypoint *entrypoint_list,
int *num_entrypoints);
VAStatus sunxi_cedrus_GetConfigAttributes(VADriverContextP ctx,
VAProfile profile, VAEntrypoint entrypoint,
VAConfigAttrib *attrib_list, int num_attribs);
VAStatus sunxi_cedrus_update_attribute(object_config_p obj_config,
VAConfigAttrib *attrib);
VAStatus sunxi_cedrus_CreateConfig(VADriverContextP ctx, VAProfile profile,
VAEntrypoint entrypoint, VAConfigAttrib *attrib_list,
int num_attribs, VAConfigID *config_id);
VAStatus sunxi_cedrus_DestroyConfig(VADriverContextP ctx, VAConfigID config_id);
VAStatus sunxi_cedrus_QueryConfigAttributes(VADriverContextP ctx,
VAConfigID config_id, VAProfile *profile,
VAEntrypoint *entrypoint, VAConfigAttrib *attrib_list,
int *num_attribs);
VAStatus sunxi_cedrus_QueryDisplayAttributes (VADriverContextP ctx,
VADisplayAttribute *attr_list, int *num_attributes);
VAStatus sunxi_cedrus_GetDisplayAttributes (VADriverContextP ctx,
VADisplayAttribute *attr_list, int num_attributes);
VAStatus sunxi_cedrus_SetDisplayAttributes (VADriverContextP ctx,
VADisplayAttribute *attr_list, int num_attributes);
#endif /* _CONFIG_H_ */