From 1cd4a8fc046d4774fa1d53534fbb4e3b14ab3c36 Mon Sep 17 00:00:00 2001 From: Holger Kaelberer Date: Tue, 15 May 2012 10:24:08 +0200 Subject: [PATCH] subpicture: add support for global-alpha. Add the necessary helpers in GstVaapiDisplay to determine whether subpictures with global alpha are supported or not. Also add accessors in GstVaapiSubpicture to address this feature. Signed-off-by: Gwenole Beauchesne --- gst-libs/gst/vaapi/gstvaapidisplay.c | 23 +++-- gst-libs/gst/vaapi/gstvaapidisplay.h | 3 +- gst-libs/gst/vaapi/gstvaapisubpicture.c | 148 ++++++++++++++++++++++++++++++-- gst-libs/gst/vaapi/gstvaapisubpicture.h | 12 ++- gst-libs/gst/vaapi/gstvaapisurface.c | 2 +- tests/image.c | 4 +- tests/test-subpicture.c | 2 +- 7 files changed, 178 insertions(+), 16 deletions(-) diff --git a/gst-libs/gst/vaapi/gstvaapidisplay.c b/gst-libs/gst/vaapi/gstvaapidisplay.c index a51c0b5..4677a79 100644 --- a/gst-libs/gst/vaapi/gstvaapidisplay.c +++ b/gst-libs/gst/vaapi/gstvaapidisplay.c @@ -719,14 +719,16 @@ gst_vaapi_display_create(GstVaapiDisplay *display) goto end; GST_DEBUG("%d subpicture formats", n); - for (i = 0; i < n; i++) + for (i = 0; i < n; i++) { GST_DEBUG(" %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS(formats[i].fourcc)); + flags[i] = to_GstVaapiSubpictureFlags(flags[i]); + } priv->subpicture_formats = g_array_new(FALSE, FALSE, sizeof(GstVaapiFormatInfo)); if (!priv->subpicture_formats) goto end; - append_formats(priv->subpicture_formats, formats, NULL, n); + append_formats(priv->subpicture_formats, formats, flags, n); g_array_sort(priv->subpicture_formats, compare_rgb_formats); if (!cached_info) { @@ -1404,21 +1406,32 @@ gst_vaapi_display_get_subpicture_caps(GstVaapiDisplay *display) * gst_vaapi_display_has_subpicture_format: * @display: a #GstVaapiDisplay * @format: a #GstVaapiFormat + * @flags: #GstVaapiSubpictureFlags, or zero * - * Returns whether VA @display supports @format subpicture format. + * Returns whether VA @display supports @format subpicture format with + * the supplied @flags. * * Return value: %TRUE if VA @display supports @format subpicture format */ gboolean gst_vaapi_display_has_subpicture_format( GstVaapiDisplay *display, - GstVaapiImageFormat format + GstVaapiImageFormat format, + guint *flags_ptr ) { + const GstVaapiFormatInfo *fip; + g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), FALSE); g_return_val_if_fail(format, FALSE); - return find_format(display->priv->subpicture_formats, format); + fip = find_format_info(display->priv->subpicture_formats, format); + if (!fip) + return FALSE; + + if (flags_ptr) + *flags_ptr = fip->flags; + return TRUE; } /** diff --git a/gst-libs/gst/vaapi/gstvaapidisplay.h b/gst-libs/gst/vaapi/gstvaapidisplay.h index d23b0ad..ddfb375 100644 --- a/gst-libs/gst/vaapi/gstvaapidisplay.h +++ b/gst-libs/gst/vaapi/gstvaapidisplay.h @@ -231,7 +231,8 @@ gst_vaapi_display_get_subpicture_caps(GstVaapiDisplay *display); gboolean gst_vaapi_display_has_subpicture_format( GstVaapiDisplay *display, - GstVaapiImageFormat format + GstVaapiImageFormat format, + guint *flags_ptr ); gboolean diff --git a/gst-libs/gst/vaapi/gstvaapisubpicture.c b/gst-libs/gst/vaapi/gstvaapisubpicture.c index a09f246..86d40dc 100644 --- a/gst-libs/gst/vaapi/gstvaapisubpicture.c +++ b/gst-libs/gst/vaapi/gstvaapisubpicture.c @@ -44,11 +44,15 @@ G_DEFINE_TYPE(GstVaapiSubpicture, gst_vaapi_subpicture, GST_VAAPI_TYPE_OBJECT) struct _GstVaapiSubpicturePrivate { GstVaapiImage *image; + guint flags; + gfloat global_alpha; }; enum { PROP_0, + PROP_FLAGS, + PROP_GLOBAL_ALPHA, PROP_IMAGE }; @@ -128,6 +132,13 @@ gst_vaapi_subpicture_set_property( GstVaapiSubpicture * const subpicture = GST_VAAPI_SUBPICTURE(object); switch (prop_id) { + case PROP_FLAGS: + subpicture->priv->flags = g_value_get_uint(value); + break; + case PROP_GLOBAL_ALPHA: + gst_vaapi_subpicture_set_global_alpha(subpicture, + g_value_get_float(value)); + break; case PROP_IMAGE: gst_vaapi_subpicture_set_image(subpicture, g_value_get_object(value)); break; @@ -148,6 +159,13 @@ gst_vaapi_subpicture_get_property( GstVaapiSubpicture * const subpicture = GST_VAAPI_SUBPICTURE(object); switch (prop_id) { + case PROP_FLAGS: + g_value_set_uint(value, subpicture->priv->flags); + break; + case PROP_GLOBAL_ALPHA: + g_value_set_float(value, + gst_vaapi_subpicture_get_global_alpha(subpicture)); + break; case PROP_IMAGE: g_value_set_object(value, gst_vaapi_subpicture_get_image(subpicture)); break; @@ -169,6 +187,34 @@ gst_vaapi_subpicture_class_init(GstVaapiSubpictureClass *klass) object_class->get_property = gst_vaapi_subpicture_get_property; /** + * GstVaapiSubpicture:flags: + * + * The #GstVaapiSubpictureFlags this subpicture requires. + */ + g_object_class_install_property + (object_class, + PROP_FLAGS, + g_param_spec_uint("flags", + "Flags", + "The GstVaapiSubpictureFlags this subpicture requires", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); + + /** + * GstVaapiSubpicture:global-alpha: + * + * The global-alpha value associated with this subpicture. + */ + g_object_class_install_property + (object_class, + PROP_GLOBAL_ALPHA, + g_param_spec_float("global-alpha", + "Global Alpha", + "The global-alpha value associated with this subpicture", + 0.0f, 1.0f, 1.0f, + G_PARAM_READWRITE)); + + /** * GstVaapiSubpicture:image: * * The #GstVaapiImage this subpicture is bound to. @@ -190,11 +236,13 @@ gst_vaapi_subpicture_init(GstVaapiSubpicture *subpicture) subpicture->priv = priv; priv->image = NULL; + priv->global_alpha = 1.0f; } /** * gst_vaapi_subpicture_new: * @image: a #GstVaapiImage + * @flags: #GstVaapiSubpictureFlags, or zero * * Creates a new #GstVaapiSubpicture with @image as source pixels. The * newly created object holds a reference on @image. @@ -202,17 +250,30 @@ gst_vaapi_subpicture_init(GstVaapiSubpicture *subpicture) * Return value: the newly allocated #GstVaapiSubpicture object */ GstVaapiSubpicture * -gst_vaapi_subpicture_new(GstVaapiImage *image) +gst_vaapi_subpicture_new(GstVaapiImage *image, guint flags) { + GstVaapiDisplay *display; + GstVaapiImageFormat format; + guint va_flags; + g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), NULL); GST_DEBUG("create from image %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(GST_VAAPI_OBJECT_ID(image))); + display = GST_VAAPI_OBJECT_DISPLAY(image); + format = gst_vaapi_image_get_format(image); + if (!gst_vaapi_display_has_subpicture_format(display, format, &va_flags)) + return NULL; + if (flags & ~va_flags) + return NULL; + return g_object_new(GST_VAAPI_TYPE_SUBPICTURE, - "display", GST_VAAPI_OBJECT_DISPLAY(image), - "id", GST_VAAPI_ID(VA_INVALID_ID), - "image", image, + "display", GST_VAAPI_OBJECT_DISPLAY(image), + "id", GST_VAAPI_ID(VA_INVALID_ID), + "flags", flags, + "global-alpha", 1.0f, + "image", image, NULL); } @@ -273,7 +334,7 @@ gst_vaapi_subpicture_new_from_overlay_rectangle( return NULL; } - subpicture = gst_vaapi_subpicture_new(image); + subpicture = gst_vaapi_subpicture_new(image, 0); g_object_unref(image); return subpicture; } @@ -295,6 +356,22 @@ gst_vaapi_subpicture_get_id(GstVaapiSubpicture *subpicture) } /** + * gst_vaapi_subpicture_get_flags: + * @subpicture: a #GstVaapiSubpicture + * + * Returns the @subpicture flags. + * + * Return value: the @subpicture flags + */ +guint +gst_vaapi_subpicture_get_flags(GstVaapiSubpicture *subpicture) +{ + g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), 0); + + return subpicture->priv->flags; +} + +/** * gst_vaapi_subpicture_get_image: * @subpicture: a #GstVaapiSubpicture * @@ -332,3 +409,64 @@ gst_vaapi_subpicture_set_image( subpicture->priv->image = g_object_ref(image); gst_vaapi_subpicture_create(subpicture); } + +/** + * gst_vaapi_subpicture_get_global_alpha: + * @subpicture: a #GstVaapiSubpicture + * + * Returns the value of global_alpha, set for this @subpicture. + * + * Return value: the global_alpha value of this @subpicture + */ +gfloat +gst_vaapi_subpicture_get_global_alpha(GstVaapiSubpicture *subpicture) +{ + g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), 1.0); + + return subpicture->priv->global_alpha; +} + +/** + * gst_vaapi_subpicture_set_global_alpha: + * @subpicture: a #GstVaapiSubpicture + * @global_alpha: value for global-alpha (range: 0.0 to 1.0, inclusive) + * + * Sets the global_alpha value of @subpicture. This function calls + * vaSetSubpictureGlobalAlpha() if the format of @subpicture, i.e. + * the current VA driver supports it. + * + * Return value: %TRUE if global_alpha could be set, %FALSE otherwise + */ +gboolean +gst_vaapi_subpicture_set_global_alpha(GstVaapiSubpicture *subpicture, + gfloat global_alpha) +{ + GstVaapiSubpicturePrivate *priv; + GstVaapiDisplay *display; + VAStatus status; + + g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), FALSE); + + priv = subpicture->priv; + + if (!(priv->flags & GST_VAAPI_SUBPICTURE_FLAG_GLOBAL_ALPHA)) + return FALSE; + + if (priv->global_alpha == global_alpha) + return TRUE; + + display = GST_VAAPI_OBJECT_DISPLAY(subpicture); + + GST_VAAPI_DISPLAY_LOCK(display); + status = vaSetSubpictureGlobalAlpha( + GST_VAAPI_DISPLAY_VADISPLAY(display), + GST_VAAPI_OBJECT_ID(subpicture), + global_alpha + ); + GST_VAAPI_DISPLAY_UNLOCK(display); + if (!vaapi_check_status(status, "vaSetSubpictureGlobalAlpha()")) + return FALSE; + + priv->global_alpha = global_alpha; + return TRUE; +} diff --git a/gst-libs/gst/vaapi/gstvaapisubpicture.h b/gst-libs/gst/vaapi/gstvaapisubpicture.h index 7a2bdae..80c05d3 100644 --- a/gst-libs/gst/vaapi/gstvaapisubpicture.h +++ b/gst-libs/gst/vaapi/gstvaapisubpicture.h @@ -99,7 +99,7 @@ GType gst_vaapi_subpicture_get_type(void) G_GNUC_CONST; GstVaapiSubpicture * -gst_vaapi_subpicture_new(GstVaapiImage *image); +gst_vaapi_subpicture_new(GstVaapiImage *image, guint flags); GstVaapiSubpicture * gst_vaapi_subpicture_new_from_overlay_rectangle( @@ -110,6 +110,9 @@ gst_vaapi_subpicture_new_from_overlay_rectangle( GstVaapiID gst_vaapi_subpicture_get_id(GstVaapiSubpicture *subpicture); +guint +gst_vaapi_subpicture_get_flags(GstVaapiSubpicture *subpicture); + GstVaapiImage * gst_vaapi_subpicture_get_image(GstVaapiSubpicture *subpicture); @@ -119,6 +122,13 @@ gst_vaapi_subpicture_set_image( GstVaapiImage *image ); +gfloat +gst_vaapi_subpicture_get_global_alpha(GstVaapiSubpicture *subpicture); + +gboolean +gst_vaapi_subpicture_set_global_alpha(GstVaapiSubpicture *subpicture, + gfloat global_alpha); + G_END_DECLS #endif /* GST_VAAPI_SUBPICTURE_H */ diff --git a/gst-libs/gst/vaapi/gstvaapisurface.c b/gst-libs/gst/vaapi/gstvaapisurface.c index 745495d..46ad45e 100644 --- a/gst-libs/gst/vaapi/gstvaapisurface.c +++ b/gst-libs/gst/vaapi/gstvaapisurface.c @@ -723,7 +723,7 @@ _gst_vaapi_surface_associate_subpicture( &surface_id, 1, src_rect->x, src_rect->y, src_rect->width, src_rect->height, dst_rect->x, dst_rect->y, dst_rect->width, dst_rect->height, - 0 + from_GstVaapiSubpictureFlags(gst_vaapi_subpicture_get_flags(subpicture)) ); GST_VAAPI_DISPLAY_UNLOCK(display); if (!vaapi_check_status(status, "vaAssociateSubpicture()")) diff --git a/tests/image.c b/tests/image.c index 39a8ac5..289e2a3 100644 --- a/tests/image.c +++ b/tests/image.c @@ -341,12 +341,12 @@ image_upload(GstVaapiImage *image, GstVaapiSurface *surface) g_print("could not upload %" GST_FOURCC_FORMAT" image to surface\n", GST_FOURCC_ARGS(format)); - if (!gst_vaapi_display_has_subpicture_format(display, format)) + if (!gst_vaapi_display_has_subpicture_format(display, format, NULL)) return FALSE; g_print("trying as a subpicture\n"); - subpicture = gst_vaapi_subpicture_new(image); + subpicture = gst_vaapi_subpicture_new(image, 0); if (!subpicture) g_error("could not create VA subpicture"); diff --git a/tests/test-subpicture.c b/tests/test-subpicture.c index 11d018b..6a1620c 100644 --- a/tests/test-subpicture.c +++ b/tests/test-subpicture.c @@ -192,7 +192,7 @@ main(int argc, char *argv[]) if (!gst_vaapi_image_update_from_buffer (subtitle_image, buffer, NULL)) g_error ("could not update VA image with subtitle data"); - subpicture = gst_vaapi_subpicture_new (subtitle_image); + subpicture = gst_vaapi_subpicture_new (subtitle_image, 0); /* We position it as a subtitle, centered at the bottom. */ sub_rect.x = (surf_width - subinfo.width) / 2; -- 2.7.4