From 6f20d84fa3e971acb335b0018de248e28495218f Mon Sep 17 00:00:00 2001 From: gb Date: Thu, 4 Mar 2010 17:39:01 +0000 Subject: [PATCH] Add VA surface, image, subpicture abstractions. Ported over from Gnash. --- gst-libs/gst/vaapi/Makefile.am | 23 +- gst-libs/gst/vaapi/gstvaapiimage.c | 423 +++++++++++++++++++++++++++++++ gst-libs/gst/vaapi/gstvaapiimage.h | 115 +++++++++ gst-libs/gst/vaapi/gstvaapiimageformat.c | 153 +++++++++++ gst-libs/gst/vaapi/gstvaapiimageformat.h | 65 +++++ gst-libs/gst/vaapi/gstvaapisurface.c | 314 +++++++++++++++++++++++ gst-libs/gst/vaapi/gstvaapisurface.h | 91 +++++++ 7 files changed, 1181 insertions(+), 3 deletions(-) create mode 100644 gst-libs/gst/vaapi/gstvaapiimage.c create mode 100644 gst-libs/gst/vaapi/gstvaapiimage.h create mode 100644 gst-libs/gst/vaapi/gstvaapiimageformat.c create mode 100644 gst-libs/gst/vaapi/gstvaapiimageformat.h create mode 100644 gst-libs/gst/vaapi/gstvaapisurface.c create mode 100644 gst-libs/gst/vaapi/gstvaapisurface.h diff --git a/gst-libs/gst/vaapi/Makefile.am b/gst-libs/gst/vaapi/Makefile.am index 3bb8981..edef4fa 100644 --- a/gst-libs/gst/vaapi/Makefile.am +++ b/gst-libs/gst/vaapi/Makefile.am @@ -1,20 +1,37 @@ lib_LTLIBRARIES = libgstvaapi-@GST_MAJORMINOR@.la -libgstvaapi_@GST_MAJORMINOR@_la_SOURCES = \ +libgstvaapi_source_c = \ gstvaapidisplay.c \ + gstvaapiimage.c \ + gstvaapiimageformat.c \ + gstvaapisubpicture.c \ + gstvaapisurface.c \ vaapi_utils.c \ $(NULL) -libgstvaapi_@GST_MAJORMINOR@include_HEADERS = \ +libgstvaapi_source_h = \ gstvaapidisplay.h \ + gstvaapiimage.h \ + gstvaapiimageformat.h \ + gstvaapisubpicture.h \ + gstvaapisurface.h \ vaapi_debug.h \ vaapi_utils.h \ $(NULL) -libgstvaapi_@GST_MAJORMINOR@includedir = \ +libgstvaapi_@GST_MAJORMINOR@_la_SOURCES = \ + $(libgstvaapi_source_c) \ + $(NULL) + +libgstvaapi_@GST_MAJORMINOR@include_HEADERS = \ + $(libgstvaapi_source_h) \ + $(NULL) + +libgstvaapi_@GST_MAJORMINOR@includedir = \ $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/vaapi libgstvaapi_@GST_MAJORMINOR@_la_CFLAGS = \ + -I$(top_srcdir)/gst-libs \ $(GST_BASE_CFLAGS) \ $(GST_CFLAGS) \ $(LIBVA_CFLAGS) \ diff --git a/gst-libs/gst/vaapi/gstvaapiimage.c b/gst-libs/gst/vaapi/gstvaapiimage.c new file mode 100644 index 0000000..2c6c8d8 --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapiimage.c @@ -0,0 +1,423 @@ +/* + * gstvaapiimage.c - VA image abstraction + * + * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include +#include "vaapi_utils.h" +#include "gstvaapiimage.h" +#include + +#define DEBUG 1 +#include "vaapi_debug.h" + +G_DEFINE_TYPE(GstVaapiImage, gst_vaapi_image, G_TYPE_OBJECT); + +#define GST_VAAPI_IMAGE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), \ + GST_VAAPI_TYPE_IMAGE, \ + GstVaapiImagePrivate)) + +struct _GstVaapiImagePrivate { + GstVaapiDisplay *display; + VAImage image; + guchar *image_data; + guint width; + guint height; + GstVaapiImageFormat format; +}; + +enum { + PROP_0, + + PROP_DISPLAY, + PROP_IMAGE_ID, + PROP_WIDTH, + PROP_HEIGHT, + PROP_FORMAT +}; + +static void +gst_vaapi_image_destroy(GstVaapiImage *image) +{ + GstVaapiImagePrivate * const priv = image->priv; + VADisplay dpy = gst_vaapi_display_get_display(priv->display); + VAStatus status; + + gst_vaapi_image_unmap(image); + + if (priv->image.image_id != VA_INVALID_ID) { + status = vaDestroyImage(dpy, priv->image.image_id); + if (!vaapi_check_status(status, "vaDestroyImage()")) + g_warning("failed to destroy image 0x%08x\n", priv->image.image_id); + priv->image.image_id = VA_INVALID_ID; + } + + if (priv->display) { + g_object_unref(priv->display); + priv->display = NULL; + } +} + +static gboolean +gst_vaapi_image_create(GstVaapiImage *image) +{ + GstVaapiImagePrivate * const priv = image->priv; + const VAImageFormat *format; + VAStatus status; + + if (!gst_vaapi_display_has_image_format(priv->display, priv->format)) + return FALSE; + + format = gst_vaapi_image_format_get_va_format(priv->format); + + g_return_val_if_fail(format, FALSE); + + status = vaCreateImage( + gst_vaapi_display_get_display(priv->display), + (VAImageFormat *)format, + priv->width, + priv->height, + &priv->image + ); + if (!vaapi_check_status(status, "vaCreateImage()")) + return FALSE; + + return TRUE; +} + +static void +gst_vaapi_image_finalize(GObject *object) +{ + gst_vaapi_image_destroy(GST_VAAPI_IMAGE(object)); + + G_OBJECT_CLASS(gst_vaapi_image_parent_class)->finalize(object); +} + +static void +gst_vaapi_image_set_property( + GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec +) +{ + GstVaapiImage * const image = GST_VAAPI_IMAGE(object); + GstVaapiImagePrivate * const priv = image->priv; + + switch (prop_id) { + case PROP_DISPLAY: + priv->display = g_object_ref(g_value_get_pointer(value)); + break; + case PROP_WIDTH: + priv->width = g_value_get_uint(value); + break; + case PROP_HEIGHT: + priv->height = g_value_get_uint(value); + break; + case PROP_FORMAT: + priv->format = g_value_get_uint(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +gst_vaapi_image_get_property( + GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec +) +{ + GstVaapiImage * const image = GST_VAAPI_IMAGE(object); + GstVaapiImagePrivate * const priv = image->priv; + + switch (prop_id) { + case PROP_DISPLAY: + g_value_set_pointer(value, g_object_ref(priv->display)); + break; + case PROP_IMAGE_ID: + g_value_set_uint(value, gst_vaapi_image_get_id(image)); + break; + case PROP_WIDTH: + g_value_set_uint(value, gst_vaapi_image_get_width(image)); + break; + case PROP_HEIGHT: + g_value_set_uint(value, gst_vaapi_image_get_height(image)); + break; + case PROP_FORMAT: + g_value_set_uint(value, gst_vaapi_image_get_format(image)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static GObject * +gst_vaapi_image_constructor( + GType type, + guint n_params, + GObjectConstructParam *params +) +{ + GstVaapiImage *image; + GObjectClass *parent_class; + GObject *object; + + D(bug("gst_vaapi_image_constructor()\n")); + + parent_class = G_OBJECT_CLASS(gst_vaapi_image_parent_class); + object = parent_class->constructor (type, n_params, params); + + if (object) { + image = GST_VAAPI_IMAGE(object); + if (!gst_vaapi_image_create(image)) { + gst_vaapi_image_destroy(image); + object = NULL; + } + } + return object; +} + +static void +gst_vaapi_image_class_init(GstVaapiImageClass *klass) +{ + GObjectClass * const object_class = G_OBJECT_CLASS(klass); + + g_type_class_add_private(klass, sizeof(GstVaapiImagePrivate)); + + object_class->finalize = gst_vaapi_image_finalize; + object_class->set_property = gst_vaapi_image_set_property; + object_class->get_property = gst_vaapi_image_get_property; + object_class->constructor = gst_vaapi_image_constructor; + + g_object_class_install_property + (object_class, + PROP_DISPLAY, + g_param_spec_object("display", + "display", + "GStreamer Va display", + GST_VAAPI_TYPE_DISPLAY, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, + PROP_IMAGE_ID, + g_param_spec_uint("id", + "VA image id", + "VA image id", + 0, G_MAXUINT32, VA_INVALID_ID, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, + PROP_WIDTH, + g_param_spec_uint("width", + "width", + "Image width", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, + PROP_HEIGHT, + g_param_spec_uint("height", + "height", + "Image height", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, + PROP_FORMAT, + g_param_spec_uint("format", + "format", + "Image format", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); +} + +static void +gst_vaapi_image_init(GstVaapiImage *image) +{ + GstVaapiImagePrivate *priv = GST_VAAPI_IMAGE_GET_PRIVATE(image); + + D(bug("gst_vaapi_image_init()\n")); + + image->priv = priv; + priv->display = NULL; + priv->image_data = NULL; + priv->width = 0; + priv->height = 0; + priv->format = 0; + + memset(&priv->image, 0, sizeof(priv->image)); + priv->image.image_id = VA_INVALID_ID; + priv->image.buf = VA_INVALID_ID; +} + +GstVaapiImage * +gst_vaapi_image_new( + GstVaapiDisplay *display, + guint width, + guint height, + GstVaapiImageFormat format +) +{ + D(bug("gst_vaapi_image_new(): size %ux%u, format 0x%x\n", + width, height, format)); + + return g_object_new(GST_VAAPI_TYPE_IMAGE, + "display", display, + "width", width, + "height", height, + "format", format, + NULL); +} + +VAImageID +gst_vaapi_image_get_id(GstVaapiImage *image) +{ + g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), VA_INVALID_ID); + + return image->priv->image.image_id; +} + +GstVaapiDisplay * +gst_vaapi_image_get_display(GstVaapiImage *image) +{ + g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL); + + return g_object_ref(image->priv->display); +} + +guint +gst_vaapi_image_get_width(GstVaapiImage *image) +{ + g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0); + + return image->priv->width; +} + +guint +gst_vaapi_image_get_height(GstVaapiImage *image) +{ + g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0); + + return image->priv->height; +} + +guint +gst_vaapi_image_get_format(GstVaapiImage *image) +{ + g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0); + + return image->priv->format; +} + +static inline gboolean +_gst_vaapi_image_is_mapped(GstVaapiImage *image) +{ + return image->priv->image_data != NULL; +} + +gboolean +gst_vaapi_image_is_mapped(GstVaapiImage *image) +{ + g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE); + + return _gst_vaapi_image_is_mapped(image); +} + +gboolean +gst_vaapi_image_map(GstVaapiImage *image) +{ + void *image_data; + VAStatus status; + + g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE); + + if (_gst_vaapi_image_is_mapped(image)) + return TRUE; + + status = vaMapBuffer( + gst_vaapi_display_get_display(image->priv->display), + image->priv->image.buf, + &image_data + ); + if (!vaapi_check_status(status, "vaMapBuffer()")) + return FALSE; + + image->priv->image_data = image_data; + return TRUE; +} + +gboolean +gst_vaapi_image_unmap(GstVaapiImage *image) +{ + VAStatus status; + + g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE); + + if (!_gst_vaapi_image_is_mapped(image)) + return FALSE; + + status = vaUnmapBuffer( + gst_vaapi_display_get_display(image->priv->display), + image->priv->image.buf + ); + if (!vaapi_check_status(status, "vaUnmapBuffer()")) + return FALSE; + + image->priv->image_data = NULL; + return TRUE; +} + +guint +gst_vaapi_image_get_plane_count(GstVaapiImage *image) +{ + g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0); + g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0); + + return image->priv->image.num_planes; +} + +guchar * +gst_vaapi_image_get_plane(GstVaapiImage *image, guint plane) +{ + g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL); + g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), NULL); + g_return_val_if_fail(plane < image->priv->image.num_planes, NULL); + + return image->priv->image_data + image->priv->image.offsets[plane]; +} + +guint +gst_vaapi_image_get_pitch(GstVaapiImage *image, guint plane) +{ + g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), 0); + g_return_val_if_fail(_gst_vaapi_image_is_mapped(image), 0); + g_return_val_if_fail(plane < image->priv->image.num_planes, 0); + + return image->priv->image.pitches[plane]; +} diff --git a/gst-libs/gst/vaapi/gstvaapiimage.h b/gst-libs/gst/vaapi/gstvaapiimage.h new file mode 100644 index 0000000..aa92314 --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapiimage.h @@ -0,0 +1,115 @@ +/* + * gstvaapiimage.h - VA image abstraction + * + * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef GST_VAAPI_IMAGE_H +#define GST_VAAPI_IMAGE_H + +#include +#include + +G_BEGIN_DECLS + +#define GST_VAAPI_TYPE_IMAGE \ + (gst_vaapi_image_get_type()) + +#define GST_VAAPI_IMAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + GST_VAAPI_TYPE_IMAGE, \ + GstVaapiImage)) + +#define GST_VAAPI_IMAGE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), \ + GST_VAAPI_TYPE_IMAGE, \ + GstVaapiImageClass)) + +#define GST_VAAPI_IS_IMAGE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_IMAGE)) + +#define GST_VAAPI_IS_IMAGE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_IMAGE)) + +#define GST_VAAPI_IMAGE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), \ + GST_VAAPI_TYPE_IMAGE, \ + GstVaapiImage)) + +typedef struct _GstVaapiImage GstVaapiImage; +typedef struct _GstVaapiImagePrivate GstVaapiImagePrivate; +typedef struct _GstVaapiImageClass GstVaapiImageClass; + +struct _GstVaapiImage { + /*< private >*/ + GObject parent_instance; + + GstVaapiImagePrivate *priv; +}; + +struct _GstVaapiImageClass { + /*< private >*/ + GObjectClass parent_class; +}; + +GType +gst_vaapi_image_get_type(void); + +GstVaapiImage * +gst_vaapi_image_new( + GstVaapiDisplay *display, + guint width, + guint height, + GstVaapiImageFormat format +); + +VAImageID +gst_vaapi_image_get_id(GstVaapiImage *image); + +GstVaapiDisplay * +gst_vaapi_image_get_display(GstVaapiImage *image); + +guint +gst_vaapi_image_get_width(GstVaapiImage *image); + +guint +gst_vaapi_image_get_height(GstVaapiImage *image); + +guint +gst_vaapi_image_get_format(GstVaapiImage *image); + +gboolean +gst_vaapi_image_is_mapped(GstVaapiImage *image); + +gboolean +gst_vaapi_image_map(GstVaapiImage *image); + +gboolean +gst_vaapi_image_unmap(GstVaapiImage *image); + +guint +gst_vaapi_image_get_plane_count(GstVaapiImage *image); + +guchar * +gst_vaapi_image_get_plane(GstVaapiImage *image, guint plane); + +guint +gst_vaapi_image_get_pitch(GstVaapiImage *image, guint plane); + +G_END_DECLS + +#endif /* GST_VAAPI_IMAGE_H */ diff --git a/gst-libs/gst/vaapi/gstvaapiimageformat.c b/gst-libs/gst/vaapi/gstvaapiimageformat.c new file mode 100644 index 0000000..3303063 --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapiimageformat.c @@ -0,0 +1,153 @@ +/* + * gstvaapiimageformat.c - VA image format abstraction + * + * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include +#include "gstvaapiimageformat.h" + +typedef enum _GstVaapiImageFormatType GstVaapiImageFormatType; +typedef struct _GstVaapiImageFormatMap GstVaapiImageFormatMap; + +enum _GstVaapiImageFormatType { + GST_VAAPI_IMAGE_FORMAT_TYPE_YCBCR = 1, + GST_VAAPI_IMAGE_FORMAT_TYPE_RGB, + GST_VAAPI_IMAGE_FORMAT_TYPE_INDEXED +}; + +struct _GstVaapiImageFormatMap { + GstVaapiImageFormatType type; + GstVaapiImageFormat format; + VAImageFormat va_format; +}; + +#define DEF(TYPE, FORMAT) \ + GST_VAAPI_IMAGE_FORMAT_TYPE_##TYPE, GST_VAAPI_IMAGE_##FORMAT +#define DEF_YUV(FORMAT, FOURCC, ENDIAN, BPP) \ + { DEF(YCBCR, FORMAT), \ + { VA_FOURCC FOURCC, VA_##ENDIAN##_FIRST, BPP, }, } +#define DEF_RGB(FORMAT, FOURCC, ENDIAN, BPP, DEPTH, R,G,B,A) \ + { DEF(RGB, FORMAT), \ + { VA_FOURCC FOURCC, VA_##ENDIAN##_FIRST, BPP, DEPTH, R,G,B,A }, } +#define DEF_IDX(FORMAT, FOURCC, ENDIAN, BPP, NPE, EB, C0,C1,C2,C3) \ + { DEF(TYPE, FORMAT), \ + { VA_FOURCC FOURCC, VA_##ENDIAN##_FIRST, BPP, } + +static const GstVaapiImageFormatMap gst_vaapi_image_formats[] = { + DEF_YUV(NV12, ('N','V','1','2'), LSB, 12), + DEF_YUV(YV12, ('Y','V','1','2'), LSB, 12), + DEF_YUV(I420, ('I','4','2','0'), LSB, 12), +#if G_BYTE_ORDER == G_BIG_ENDIAN + DEF_RGB(ARGB, ('A','R','G','B'), MSB, 32, + 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000), + DEF_RGB(ABGR, ('A','B','G','R'), MSB, 32, + 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000), +#elif G_BYTE_ORDER == G_LITTLE_ENDIAN + DEF_RGB(BGRA, ('B','G','R','A'), LSB, 32, + 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000), + DEF_RGB(RGBA, ('R','G','B','A'), LSB, 32, + 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000), +#endif + { 0, } +}; + +#undef DEF_IDX +#undef DEF_RGB +#undef DEF_YUV +#undef DEF + +static const GstVaapiImageFormatMap *get_map(const VAImageFormat *va_format) +{ + const GstVaapiImageFormatMap *m; + + for (m = gst_vaapi_image_formats; m->format; m++) + if (m->va_format.fourcc == va_format->fourcc && + (m->type == GST_VAAPI_IMAGE_FORMAT_TYPE_RGB ? + (m->va_format.byte_order == va_format->byte_order && + m->va_format.red_mask == va_format->red_mask && + m->va_format.green_mask == va_format->green_mask && + m->va_format.blue_mask == va_format->blue_mask && + m->va_format.alpha_mask == va_format->alpha_mask) : + TRUE)) + return m; + return NULL; +} + +static const GstVaapiImageFormatMap * +get_map_from_gst_vaapi_image_format(GstVaapiImageFormat format) +{ + const GstVaapiImageFormatMap *m; + + for (m = gst_vaapi_image_formats; m->format; m++) + if (m->format == format) + return m; + return NULL; +} + +gboolean +gst_vaapi_image_format_is_rgb(GstVaapiImageFormat format) +{ + const GstVaapiImageFormatMap *m; + + m = get_map_from_gst_vaapi_image_format(format); + + g_return_val_if_fail(m, FALSE); + + return m->type == GST_VAAPI_IMAGE_FORMAT_TYPE_RGB; +} + +gboolean +gst_vaapi_image_format_is_yuv(GstVaapiImageFormat format) +{ + const GstVaapiImageFormatMap *m; + + m = get_map_from_gst_vaapi_image_format(format); + + g_return_val_if_fail(m, FALSE); + + return m->type == GST_VAAPI_IMAGE_FORMAT_TYPE_YCBCR; +} + +GstVaapiImageFormat +gst_vaapi_image_format(const VAImageFormat *va_format) +{ + const GstVaapiImageFormatMap * const m = get_map(va_format); + + g_return_val_if_fail(m, 0); + + return m->format; +} + +GstVaapiImageFormat +gst_vaapi_image_format_from_fourcc(guint32 fourcc) +{ + return (GstVaapiImageFormat)fourcc; +} + +const VAImageFormat * +gst_vaapi_image_format_get_va_format(GstVaapiImageFormat format) +{ + const GstVaapiImageFormatMap *m; + + m = get_map_from_gst_vaapi_image_format(format); + + g_return_val_if_fail(m, NULL); + + return &m->va_format; +} diff --git a/gst-libs/gst/vaapi/gstvaapiimageformat.h b/gst-libs/gst/vaapi/gstvaapiimageformat.h new file mode 100644 index 0000000..8998733 --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapiimageformat.h @@ -0,0 +1,65 @@ +/* + * gstvaapiimageformat.h - VA image format abstraction + * + * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef GST_VAAPI_IMAGE_FORMAT_H +#define GST_VAAPI_IMAGE_FORMAT_H + +#include +#include + +G_BEGIN_DECLS + +typedef enum _GstVaapiImageFormat GstVaapiImageFormat; + +enum _GstVaapiImageFormat { + /** Planar YUV 4:2:0, 12-bit, 1 plane for Y and 1 plane for UV */ + GST_VAAPI_IMAGE_NV12 = VA_FOURCC('N','V','1','2'), + /** Planar YUV 4:2:0, 12-bit, 3 planes for Y V U */ + GST_VAAPI_IMAGE_YV12 = VA_FOURCC('Y','V','1','2'), + /** Planar YUV 4:2:0, 12-bit, 3 planes for Y U V */ + GST_VAAPI_IMAGE_I420 = VA_FOURCC('I','4','2','0'), + /** Packed RGB 8:8:8, 32-bit, A R G B */ + GST_VAAPI_IMAGE_ARGB = VA_FOURCC('A','R','G','B'), + /** Packed RGB 8:8:8, 32-bit, R G B A */ + GST_VAAPI_IMAGE_RGBA = VA_FOURCC('R','G','B','A'), + /** Packed RGB 8:8:8, 32-bit, A R G B */ + GST_VAAPI_IMAGE_ABGR = VA_FOURCC('A','B','G','R'), + /** Packed RGB 8:8:8, 32-bit, R G B A */ + GST_VAAPI_IMAGE_BGRA = VA_FOURCC('B','G','R','A'), +}; + +gboolean +gst_vaapi_image_format_is_rgb(GstVaapiImageFormat format); + +gboolean +gst_vaapi_image_format_is_yuv(GstVaapiImageFormat format); + +GstVaapiImageFormat +gst_vaapi_image_format(const VAImageFormat *va_format); + +GstVaapiImageFormat +gst_vaapi_image_format_from_fourcc(guint32 fourcc); + +const VAImageFormat * +gst_vaapi_image_format_get_va_format(GstVaapiImageFormat format); + +G_END_DECLS + +#endif /* GST_GST_VAAPI_IMAGE_H */ diff --git a/gst-libs/gst/vaapi/gstvaapisurface.c b/gst-libs/gst/vaapi/gstvaapisurface.c new file mode 100644 index 0000000..2f52850 --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapisurface.c @@ -0,0 +1,314 @@ +/* + * gstvaapisurface.c - VA surface abstraction + * + * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include "vaapi_utils.h" +#include "gstvaapisurface.h" +#include + +#define DEBUG 1 +#include "vaapi_debug.h" + +G_DEFINE_TYPE(GstVaapiSurface, gst_vaapi_surface, G_TYPE_OBJECT); + +#define GST_VAAPI_SURFACE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), \ + GST_VAAPI_TYPE_SURFACE, \ + GstVaapiSurfacePrivate)) + +struct _GstVaapiSurfacePrivate { + GstVaapiDisplay *display; + VASurfaceID surface_id; + guint width; + guint height; + guint format; +}; + +enum { + PROP_0, + + PROP_DISPLAY, + PROP_SURFACE_ID, + PROP_WIDTH, + PROP_HEIGHT, + PROP_FORMAT +}; + +static void +gst_vaapi_surface_destroy(GstVaapiSurface *surface) +{ + GstVaapiSurfacePrivate * const priv = surface->priv; + VADisplay dpy = gst_vaapi_display_get_display(priv->display); + VAStatus status; + + if (priv->surface_id != VA_INVALID_SURFACE) { + status = vaDestroySurfaces(dpy, &priv->surface_id, 1); + if (!vaapi_check_status(status, "vaDestroySurfaces()")) + g_warning("failed to destroy surface 0x%08x\n", priv->surface_id); + priv->surface_id = VA_INVALID_SURFACE; + } + + if (priv->display) { + g_object_unref(priv->display); + priv->display = NULL; + } +} + +static gboolean +gst_vaapi_surface_create(GstVaapiSurface *surface) +{ + GstVaapiSurfacePrivate * const priv = surface->priv; + VASurfaceID surface_id; + VAStatus status; + + status = vaCreateSurfaces( + gst_vaapi_display_get_display(priv->display), + priv->width, + priv->height, + priv->format, + 1, &surface_id + ); + if (!vaapi_check_status(status, "vaCreateSurfaces()")) + return FALSE; + + priv->surface_id = surface_id; + return TRUE; +} + +static void +gst_vaapi_surface_finalize(GObject *object) +{ + gst_vaapi_surface_destroy(GST_VAAPI_SURFACE(object)); + + G_OBJECT_CLASS(gst_vaapi_surface_parent_class)->finalize(object); +} + +static void +gst_vaapi_surface_set_property(GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GstVaapiSurface * const surface = GST_VAAPI_SURFACE(object); + GstVaapiSurfacePrivate * const priv = surface->priv; + + switch (prop_id) { + case PROP_DISPLAY: + priv->display = g_object_ref(g_value_get_pointer(value)); + break; + case PROP_WIDTH: + priv->width = g_value_get_uint(value); + break; + case PROP_HEIGHT: + priv->height = g_value_get_uint(value); + break; + case PROP_FORMAT: + priv->format = g_value_get_uint(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +gst_vaapi_surface_get_property(GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GstVaapiSurface * const surface = GST_VAAPI_SURFACE(object); + GstVaapiSurfacePrivate * const priv = surface->priv; + + switch (prop_id) { + case PROP_DISPLAY: + g_value_set_pointer(value, g_object_ref(priv->display)); + break; + case PROP_SURFACE_ID: + g_value_set_uint(value, gst_vaapi_surface_get_id(surface)); + break; + case PROP_WIDTH: + g_value_set_uint(value, gst_vaapi_surface_get_width(surface)); + break; + case PROP_HEIGHT: + g_value_set_uint(value, gst_vaapi_surface_get_height(surface)); + break; + case PROP_FORMAT: + g_value_set_uint(value, gst_vaapi_surface_get_format(surface)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static GObject * +gst_vaapi_surface_constructor(GType type, + guint n_params, + GObjectConstructParam *params) +{ + GstVaapiSurface *surface; + GObjectClass *parent_class; + GObject *object; + + D(bug("gst_vaapi_surface_constructor()\n")); + + parent_class = G_OBJECT_CLASS(gst_vaapi_surface_parent_class); + object = parent_class->constructor (type, n_params, params); + + if (object) { + surface = GST_VAAPI_SURFACE(object); + if (!gst_vaapi_surface_create(surface)) { + gst_vaapi_surface_destroy(surface); + object = NULL; + } + } + return object; +} + +static void +gst_vaapi_surface_class_init(GstVaapiSurfaceClass *klass) +{ + GObjectClass * const object_class = G_OBJECT_CLASS(klass); + + g_type_class_add_private(klass, sizeof(GstVaapiSurfacePrivate)); + + object_class->finalize = gst_vaapi_surface_finalize; + object_class->set_property = gst_vaapi_surface_set_property; + object_class->get_property = gst_vaapi_surface_get_property; + object_class->constructor = gst_vaapi_surface_constructor; + + g_object_class_install_property + (object_class, + PROP_DISPLAY, + g_param_spec_object("display", + "display", + "GStreamer Va display", + GST_VAAPI_TYPE_DISPLAY, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, + PROP_SURFACE_ID, + g_param_spec_uint("id", + "VA surface id", + "VA surface id", + 0, G_MAXUINT32, VA_INVALID_SURFACE, + G_PARAM_READABLE)); + + g_object_class_install_property + (object_class, + PROP_WIDTH, + g_param_spec_uint("width", + "width", + "VA surface width", + 0, G_MAXINT32, 0, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, + PROP_HEIGHT, + g_param_spec_uint("height", + "height", + "VA surface height", + 0, G_MAXINT32, 0, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, + PROP_FORMAT, + g_param_spec_uint("format", + "format", + "VA surface format", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); +} + +static void +gst_vaapi_surface_init(GstVaapiSurface *surface) +{ + GstVaapiSurfacePrivate *priv = GST_VAAPI_SURFACE_GET_PRIVATE(surface); + + D(bug("gst_vaapi_surface_init()\n")); + + surface->priv = priv; + priv->display = NULL; + priv->surface_id = VA_INVALID_SURFACE; + priv->width = 0; + priv->height = 0; + priv->format = 0; +} + +GstVaapiSurface * +gst_vaapi_surface_new(GstVaapiDisplay *display, + guint width, + guint height, + guint format) +{ + D(bug("gst_vaapi_surface_new(): size %ux%u, format 0x%x\n", + width, height, format)); + + return g_object_new(GST_VAAPI_TYPE_SURFACE, + "display", display, + "width", width, + "height", height, + "format", format, + NULL); +} + +VASurfaceID +gst_vaapi_surface_get_id(GstVaapiSurface *surface) +{ + GstVaapiSurfacePrivate * const priv = surface->priv; + + g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), VA_INVALID_SURFACE); + + return priv->surface_id; +} + +guint +gst_vaapi_surface_get_width(GstVaapiSurface *surface) +{ + GstVaapiSurfacePrivate * const priv = surface->priv; + + g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), 0); + + return priv->width; +} + +guint +gst_vaapi_surface_get_height(GstVaapiSurface *surface) +{ + GstVaapiSurfacePrivate * const priv = surface->priv; + + g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), 0); + + return priv->height; +} + +guint +gst_vaapi_surface_get_format(GstVaapiSurface *surface) +{ + GstVaapiSurfacePrivate *priv = surface->priv; + + g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), 0); + + return priv->format; +} diff --git a/gst-libs/gst/vaapi/gstvaapisurface.h b/gst-libs/gst/vaapi/gstvaapisurface.h new file mode 100644 index 0000000..cbbd1ba --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapisurface.h @@ -0,0 +1,91 @@ +/* + * gstvaapisurface.h - VA surface abstraction + * + * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef GST_VAAPI_SURFACE_H +#define GST_VAAPI_SURFACE_H + +#include + +G_BEGIN_DECLS + +#define GST_VAAPI_TYPE_SURFACE \ + (gst_vaapi_surface_get_type()) + +#define GST_VAAPI_SURFACE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + GST_VAAPI_TYPE_SURFACE, \ + GstVaapiSurface)) + +#define GST_VAAPI_SURFACE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), \ + GST_VAAPI_TYPE_SURFACE, \ + GstVaapiSurfaceClass)) + +#define GST_VAAPI_IS_SURFACE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_SURFACE)) + +#define GST_VAAPI_IS_SURFACE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_SURFACE)) + +#define GST_VAAPI_SURFACE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), \ + GST_VAAPI_TYPE_SURFACE, \ + GstVaapiSurface)) + +typedef struct _GstVaapiSurface GstVaapiSurface; +typedef struct _GstVaapiSurfacePrivate GstVaapiSurfacePrivate; +typedef struct _GstVaapiSurfaceClass GstVaapiSurfaceClass; + +struct _GstVaapiSurface { + /*< private >*/ + GObject parent_instance; + + GstVaapiSurfacePrivate *priv; +}; + +struct _GstVaapiSurfaceClass { + /*< private >*/ + GObjectClass parent_class; +}; + +GType +gst_vaapi_surface_get_type(void); + +GstVaapiSurface * +gst_vaapi_surface_new(GstVaapiDisplay *display, + guint width, + guint height, + guint format); + +VASurfaceID +gst_vaapi_surface_get_id(GstVaapiSurface *surface); + +guint +gst_vaapi_surface_get_width(GstVaapiSurface *surface); + +guint +gst_vaapi_surface_get_height(GstVaapiSurface *surface); + +guint +gst_vaapi_surface_get_format(GstVaapiSurface *surface); + +G_END_DECLS + +#endif /* GST_VAAPI_SURFACE_H */ -- 2.7.4