From d4a4a49168bff11f94def0c2a716812db942f287 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Tue, 20 Nov 2012 15:50:56 +0100 Subject: [PATCH] vaapisink: compute and expose the supported set of YUV caps. Make vaapisink expose only the set of supported caps for raw YUV buffers. Add gst_vaapi_uploader_get_caps() helper function to determine the set of supported YUV caps as source (for images). This function actually tries to zero and upload each image to a 64x64 test surface. Of course, this relies on VA drivers to not claim success if vaPutImage() is not correctly supported. --- gst/vaapi/gstvaapisink.c | 33 +++++++++++++++ gst/vaapi/gstvaapiuploader.c | 96 ++++++++++++++++++++++++++++++++++++++++++++ gst/vaapi/gstvaapiuploader.h | 4 ++ 3 files changed, 133 insertions(+) diff --git a/gst/vaapi/gstvaapisink.c b/gst/vaapi/gstvaapisink.c index 916cd8e..b74927a 100644 --- a/gst/vaapi/gstvaapisink.c +++ b/gst/vaapi/gstvaapisink.c @@ -330,6 +330,20 @@ gst_vaapisink_ensure_display(GstVaapiSink *sink) } static gboolean +gst_vaapisink_ensure_uploader(GstVaapiSink *sink) +{ + if (!gst_vaapisink_ensure_display(sink)) + return FALSE; + + if (!sink->uploader) { + sink->uploader = gst_vaapi_uploader_new(sink->display); + if (!sink->uploader) + return FALSE; + } + return TRUE; +} + +static gboolean gst_vaapisink_ensure_render_rect(GstVaapiSink *sink, guint width, guint height) { GstVaapiRectangle * const display_rect = &sink->display_rect; @@ -590,6 +604,24 @@ gst_vaapisink_stop(GstBaseSink *base_sink) return TRUE; } +static GstCaps * +gst_vaapisink_get_caps(GstBaseSink *base_sink) +{ + GstVaapiSink * const sink = GST_VAAPISINK(base_sink); + GstCaps *out_caps, *yuv_caps; + + out_caps = gst_caps_from_string(GST_VAAPI_SURFACE_CAPS); + if (!out_caps) + return NULL; + + if (gst_vaapisink_ensure_uploader(sink)) { + yuv_caps = gst_vaapi_uploader_get_caps(sink->uploader); + if (yuv_caps) + gst_caps_append(out_caps, gst_caps_copy(yuv_caps)); + } + return out_caps; +} + static gboolean gst_vaapisink_set_caps(GstBaseSink *base_sink, GstCaps *caps) { @@ -1045,6 +1077,7 @@ gst_vaapisink_class_init(GstVaapiSinkClass *klass) basesink_class->start = gst_vaapisink_start; basesink_class->stop = gst_vaapisink_stop; + basesink_class->get_caps = gst_vaapisink_get_caps; basesink_class->set_caps = gst_vaapisink_set_caps; basesink_class->preroll = gst_vaapisink_show_frame; basesink_class->render = gst_vaapisink_show_frame; diff --git a/gst/vaapi/gstvaapiuploader.c b/gst/vaapi/gstvaapiuploader.c index d7ba1f9..451da71 100644 --- a/gst/vaapi/gstvaapiuploader.c +++ b/gst/vaapi/gstvaapiuploader.c @@ -21,6 +21,7 @@ */ #include "gst/vaapi/sysdeps.h" +#include #include #include #include @@ -48,6 +49,7 @@ G_DEFINE_TYPE(GstVaapiUploader, gst_vaapi_uploader, G_TYPE_OBJECT) struct _GstVaapiUploaderPrivate { GstVaapiDisplay *display; + GstCaps *allowed_caps; GstVaapiVideoPool *images; GstCaps *image_caps; guint image_width; @@ -70,6 +72,8 @@ gst_vaapi_uploader_destroy(GstVaapiUploader *uploader) GstVaapiUploaderPrivate * const priv = uploader->priv; gst_caps_replace(&priv->image_caps, NULL); + gst_caps_replace(&priv->allowed_caps, NULL); + g_clear_object(&priv->images); g_clear_object(&priv->surfaces); g_clear_object(&priv->display); @@ -90,6 +94,88 @@ ensure_display(GstVaapiUploader *uploader, GstVaapiDisplay *display) } static gboolean +ensure_image(GstVaapiImage *image) +{ + guint i, num_planes, width, height; + + /* Make the image fully dirty */ + if (!gst_vaapi_image_map(image)) + return FALSE; + + gst_vaapi_image_get_size(image, &width, &height); + + num_planes = gst_vaapi_image_get_plane_count(image); + for (i = 0; i < num_planes; i++) { + guchar * const plane = gst_vaapi_image_get_plane(image, i); + if (plane) + memset(plane, 0, height * gst_vaapi_image_get_pitch(image, i)); + } + + if (!gst_vaapi_image_unmap(image)) + gst_vaapi_image_unmap(image); + return TRUE; +} + +static gboolean +ensure_allowed_caps(GstVaapiUploader *uploader) +{ + GstVaapiUploaderPrivate * const priv = uploader->priv; + GstVaapiSurface *surface = NULL; + GstCaps *out_caps, *image_caps = NULL; + guint i, n_structures; + gboolean success = FALSE; + + enum { WIDTH = 64, HEIGHT = 64 }; + + if (priv->allowed_caps) + return TRUE; + + out_caps = gst_caps_new_empty(); + if (!out_caps) + return FALSE; + + image_caps = gst_vaapi_display_get_image_caps(priv->display); + if (!image_caps) + goto end; + + surface = gst_vaapi_surface_new(priv->display, + GST_VAAPI_CHROMA_TYPE_YUV420, WIDTH, HEIGHT); + if (!surface) + goto end; + + n_structures = gst_caps_get_size(image_caps); + for (i = 0; i < n_structures; i++) { + GstStructure * const structure = gst_caps_get_structure(image_caps, i); + GstVaapiImage *image; + GstVaapiImageFormat format; + guint32 fourcc; + + if (!gst_structure_get_fourcc(structure, "format", &fourcc)) + continue; + format = gst_vaapi_image_format_from_fourcc(fourcc); + if (!format) + continue; + image = gst_vaapi_image_new(priv->display, format, WIDTH, HEIGHT); + if (!image) + continue; + if (ensure_image(image) && gst_vaapi_surface_put_image(surface, image)) + gst_caps_append_structure(out_caps, gst_structure_copy(structure)); + gst_object_unref(image); + } + + gst_caps_replace(&priv->allowed_caps, out_caps); + success = TRUE; + +end: + gst_caps_unref(out_caps); + if (image_caps) + gst_caps_unref(image_caps); + if (surface) + gst_object_unref(surface); + return success; +} + +static gboolean ensure_image_pool(GstVaapiUploader *uploader, GstCaps *caps) { GstVaapiUploaderPrivate * const priv = uploader->priv; @@ -340,6 +426,16 @@ gst_vaapi_uploader_process( return TRUE; } +GstCaps * +gst_vaapi_uploader_get_caps(GstVaapiUploader *uploader) +{ + g_return_val_if_fail(GST_VAAPI_IS_UPLOADER(uploader), NULL); + + if (!ensure_allowed_caps(uploader)) + return NULL; + return uploader->priv->allowed_caps; +} + GstBuffer * gst_vaapi_uploader_get_buffer(GstVaapiUploader *uploader) { diff --git a/gst/vaapi/gstvaapiuploader.h b/gst/vaapi/gstvaapiuploader.h index 06f62d3..db2dcdb 100644 --- a/gst/vaapi/gstvaapiuploader.h +++ b/gst/vaapi/gstvaapiuploader.h @@ -99,6 +99,10 @@ gst_vaapi_uploader_process( ); G_GNUC_INTERNAL +GstCaps * +gst_vaapi_uploader_get_caps(GstVaapiUploader *uploader); + +G_GNUC_INTERNAL GstBuffer * gst_vaapi_uploader_get_buffer(GstVaapiUploader *uploader); -- 2.7.4