From: gb Date: Thu, 18 Mar 2010 15:28:59 +0000 (+0000) Subject: Add gst_vaapi_surface_derive_image() API. X-Git-Tag: accepted/trunk/20120822.173359~689 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ea2c6c502ccd49e84a28fa2574b8395c36e5b348;p=profile%2Fivi%2Fgstreamer-vaapi.git Add gst_vaapi_surface_derive_image() API. --- diff --git a/gst-libs/gst/vaapi/gstvaapiimage.c b/gst-libs/gst/vaapi/gstvaapiimage.c index 78f582f..b9ad8dd 100644 --- a/gst-libs/gst/vaapi/gstvaapiimage.c +++ b/gst-libs/gst/vaapi/gstvaapiimage.c @@ -43,6 +43,7 @@ struct _GstVaapiImagePrivate { GstVaapiImageFormat format; guint width; guint height; + guint create_image : 1; guint is_constructed : 1; guint is_linear : 1; }; @@ -51,6 +52,7 @@ enum { PROP_0, PROP_DISPLAY, + PROP_IMAGE, PROP_IMAGE_ID, PROP_FORMAT, PROP_WIDTH, @@ -69,6 +71,75 @@ _gst_vaapi_image_map(GstVaapiImage *image); static gboolean _gst_vaapi_image_unmap(GstVaapiImage *image); +static gboolean +_gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image); + +/* + * VAImage wrapper + */ + +#define VAAPI_TYPE_IMAGE vaapi_image_get_type() + +static gpointer +vaapi_image_copy(gpointer va_image) +{ + return g_slice_dup(VAImage, va_image); +} + +static void +vaapi_image_free(gpointer va_image) +{ + if (G_LIKELY(va_image)) + g_slice_free(VAImage, va_image); +} + +static GType +vaapi_image_get_type(void) +{ + static GType type = 0; + + if (G_UNLIKELY(type == 0)) + type = g_boxed_type_register_static( + "VAImage", + vaapi_image_copy, + vaapi_image_free + ); + return type; +} + +static gboolean +vaapi_image_is_linear(const VAImage *va_image) +{ + guint i, width, height, width2, height2, data_size; + + for (i = 1; i < va_image->num_planes; i++) + if (va_image->offsets[i] < va_image->offsets[i - 1]) + return FALSE; + + width = va_image->width; + height = va_image->height; + width2 = (width + 1) / 2; + height2 = (height + 1) / 2; + + switch (va_image->format.fourcc) { + case VA_FOURCC('N','V','1','2'): + case VA_FOURCC('Y','V','1','2'): + case VA_FOURCC('I','4','2','0'): + data_size = width * height + 2 * width2 * height2; + break; + case VA_FOURCC('A','R','G','B'): + case VA_FOURCC('R','G','B','A'): + case VA_FOURCC('A','B','G','R'): + case VA_FOURCC('B','G','R','A'): + data_size = 4 * width * height; + break; + default: + g_error("FIXME: incomplete formats"); + break; + } + return va_image->data_size == data_size; +} + static void gst_vaapi_image_destroy(GstVaapiImage *image) { @@ -103,6 +174,10 @@ _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format) const VAImageFormat *va_format; VAStatus status; + if (!priv->create_image) + return (priv->image.image_id != VA_INVALID_ID && + priv->image.buf != VA_INVALID_ID); + if (!gst_vaapi_display_has_image_format(priv->display, format)) return FALSE; @@ -128,40 +203,6 @@ _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format) } static gboolean -_gst_vaapi_image_is_linear(GstVaapiImage *image) -{ - GstVaapiImagePrivate * const priv = image->priv; - guint i, width, height, width2, height2, data_size; - - for (i = 1; i < priv->image.num_planes; i++) - if (priv->image.offsets[i] < priv->image.offsets[i - 1]) - return FALSE; - - width = priv->width; - height = priv->height; - width2 = (width + 1) / 2; - height2 = (height + 1) / 2; - - switch (priv->internal_format) { - case GST_VAAPI_IMAGE_NV12: - case GST_VAAPI_IMAGE_YV12: - case GST_VAAPI_IMAGE_I420: - data_size = width * height + 2 * width2 * height2; - break; - case GST_VAAPI_IMAGE_ARGB: - case GST_VAAPI_IMAGE_RGBA: - case GST_VAAPI_IMAGE_ABGR: - case GST_VAAPI_IMAGE_BGRA: - data_size = 4 * width * height; - break; - default: - g_error("FIXME: incomplete formats"); - break; - } - return priv->image.data_size == data_size; -} - -static gboolean gst_vaapi_image_create(GstVaapiImage *image) { GstVaapiImagePrivate * const priv = image->priv; @@ -202,7 +243,7 @@ gst_vaapi_image_create(GstVaapiImage *image) } GST_DEBUG("image 0x%08x", priv->image.image_id); - priv->is_linear = _gst_vaapi_image_is_linear(image); + priv->is_linear = vaapi_image_is_linear(&priv->image); return TRUE; } @@ -229,6 +270,12 @@ gst_vaapi_image_set_property( case PROP_DISPLAY: priv->display = g_object_ref(g_value_get_object(value)); break; + case PROP_IMAGE: { + const VAImage * const va_image = g_value_get_boxed(value); + if (va_image) + _gst_vaapi_image_set_image(image, va_image); + break; + } case PROP_FORMAT: priv->format = g_value_get_uint(value); break; @@ -258,6 +305,9 @@ gst_vaapi_image_get_property( case PROP_DISPLAY: g_value_set_pointer(value, gst_vaapi_image_get_display(image)); break; + case PROP_IMAGE: + g_value_set_boxed(value, &image->priv->image); + break; case PROP_IMAGE_ID: g_value_set_uint(value, gst_vaapi_image_get_id(image)); break; @@ -312,6 +362,15 @@ gst_vaapi_image_class_init(GstVaapiImageClass *klass) g_object_class_install_property (object_class, + PROP_IMAGE, + g_param_spec_boxed("image", + "Image", + "The VA image", + VAAPI_TYPE_IMAGE, + 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", @@ -359,6 +418,7 @@ gst_vaapi_image_init(GstVaapiImage *image) priv->height = 0; priv->internal_format = 0; priv->format = 0; + priv->create_image = TRUE; priv->is_constructed = FALSE; priv->is_linear = FALSE; @@ -406,6 +466,37 @@ gst_vaapi_image_new( return image; } +GstVaapiImage * +gst_vaapi_image_new_with_image(GstVaapiDisplay *display, VAImage *va_image) +{ + GstVaapiImage *image; + + g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL); + g_return_val_if_fail(va_image, NULL); + g_return_val_if_fail(va_image->image_id != VA_INVALID_ID, NULL); + g_return_val_if_fail(va_image->buf != VA_INVALID_ID, NULL); + + GST_DEBUG("VA image 0x%08x, format %" GST_FOURCC_FORMAT ", size %ux%u", + va_image->image_id, + GST_FOURCC_ARGS(va_image->format.fourcc), + va_image->width, va_image->height); + + image = g_object_new( + GST_VAAPI_TYPE_IMAGE, + "display", display, + "image", va_image, + NULL + ); + if (!image) + return NULL; + + if (!image->priv->is_constructed) { + g_object_unref(image); + return NULL; + } + return image; +} + VAImageID gst_vaapi_image_get_id(GstVaapiImage *image) { @@ -427,6 +518,61 @@ gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image) return TRUE; } +gboolean +_gst_vaapi_image_set_image(GstVaapiImage *image, const VAImage *va_image) +{ + GstVaapiImagePrivate * const priv = image->priv; + GstVaapiImageFormat format; + VAImage alt_va_image; + const VAImageFormat *alt_va_format; + + if (!va_image) + return FALSE; + + format = gst_vaapi_image_format(&va_image->format); + if (!format) + return FALSE; + + priv->create_image = FALSE; + priv->internal_image = *va_image; + priv->internal_format = format; + priv->is_linear = vaapi_image_is_linear(va_image); + priv->image = *va_image; + priv->format = format; + priv->width = va_image->width; + priv->height = va_image->height; + + /* Try to linearize image */ + if (!priv->is_linear) { + switch (format) { + case GST_VAAPI_IMAGE_I420: + format = GST_VAAPI_IMAGE_YV12; + break; + case GST_VAAPI_IMAGE_YV12: + format = GST_VAAPI_IMAGE_I420; + break; + default: + format = 0; + break; + } + if (format && + (alt_va_format = gst_vaapi_image_format_get_va_format(format))) { + alt_va_image = *va_image; + alt_va_image.format = *alt_va_format; + SWAP_UINT(alt_va_image.offsets[1], alt_va_image.offsets[2]); + SWAP_UINT(alt_va_image.pitches[1], alt_va_image.pitches[2]); + if (vaapi_image_is_linear(&alt_va_image)) { + priv->image = alt_va_image; + priv->format = format; + priv->is_linear = TRUE; + GST_DEBUG("linearized image to %" GST_FOURCC_FORMAT " format", + GST_FOURCC_ARGS(format)); + } + } + } + return TRUE; +} + GstVaapiDisplay * gst_vaapi_image_get_display(GstVaapiImage *image) { diff --git a/gst-libs/gst/vaapi/gstvaapiimage.h b/gst-libs/gst/vaapi/gstvaapiimage.h index 322a151..bd9e53b 100644 --- a/gst-libs/gst/vaapi/gstvaapiimage.h +++ b/gst-libs/gst/vaapi/gstvaapiimage.h @@ -82,6 +82,9 @@ gst_vaapi_image_new( guint height ); +GstVaapiImage * +gst_vaapi_image_new_with_image(GstVaapiDisplay *display, VAImage *va_image); + VAImageID gst_vaapi_image_get_id(GstVaapiImage *image); diff --git a/gst-libs/gst/vaapi/gstvaapisurface.c b/gst-libs/gst/vaapi/gstvaapisurface.c index 40b5cde..79ab6e1 100644 --- a/gst-libs/gst/vaapi/gstvaapisurface.c +++ b/gst-libs/gst/vaapi/gstvaapisurface.c @@ -21,6 +21,7 @@ #include "config.h" #include "gstvaapiutils.h" #include "gstvaapisurface.h" +#include "gstvaapiimage.h" #include #define DEBUG 1 @@ -342,6 +343,32 @@ gst_vaapi_surface_get_size( *pheight = gst_vaapi_surface_get_height(surface); } +GstVaapiImage * +gst_vaapi_surface_derive_image(GstVaapiSurface *surface) +{ + VAImage va_image; + VAStatus status; + + g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), NULL); + + va_image.image_id = VA_INVALID_ID; + va_image.buf = VA_INVALID_ID; + + GST_VAAPI_DISPLAY_LOCK(surface->priv->display); + status = vaDeriveImage( + GST_VAAPI_DISPLAY_VADISPLAY(surface->priv->display), + surface->priv->surface_id, + &va_image + ); + GST_VAAPI_DISPLAY_UNLOCK(surface->priv->display); + if (!vaapi_check_status(status, "vaDeriveImage()")) + return NULL; + if (va_image.image_id == VA_INVALID_ID || va_image.buf == VA_INVALID_ID) + return NULL; + + return gst_vaapi_image_new_with_image(surface->priv->display, &va_image); +} + gboolean gst_vaapi_surface_get_image(GstVaapiSurface *surface, GstVaapiImage *image) { diff --git a/gst-libs/gst/vaapi/gstvaapisurface.h b/gst-libs/gst/vaapi/gstvaapisurface.h index 1d6d4f7..2fa56aa 100644 --- a/gst-libs/gst/vaapi/gstvaapisurface.h +++ b/gst-libs/gst/vaapi/gstvaapisurface.h @@ -107,6 +107,9 @@ gst_vaapi_surface_get_size( guint *pheight ); +GstVaapiImage * +gst_vaapi_surface_derive_image(GstVaapiSurface *surface); + gboolean gst_vaapi_surface_get_image(GstVaapiSurface *surface, GstVaapiImage *image);