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.
This commit is contained in:
Gwenole Beauchesne 2012-11-20 15:50:56 +01:00
parent 499e0dd981
commit d4a4a49168
3 changed files with 133 additions and 0 deletions

View file

@ -329,6 +329,20 @@ gst_vaapisink_ensure_display(GstVaapiSink *sink)
return TRUE;
}
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)
{
@ -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;

View file

@ -21,6 +21,7 @@
*/
#include "gst/vaapi/sysdeps.h"
#include <string.h>
#include <gst/video/video.h>
#include <gst/vaapi/gstvaapisurface.h>
#include <gst/vaapi/gstvaapiimagepool.h>
@ -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);
@ -89,6 +93,88 @@ ensure_display(GstVaapiUploader *uploader, GstVaapiDisplay *display)
return TRUE;
}
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)
{
@ -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)
{

View file

@ -98,6 +98,10 @@ gst_vaapi_uploader_process(
GstBuffer *out_buffer
);
G_GNUC_INTERNAL
GstCaps *
gst_vaapi_uploader_get_caps(GstVaapiUploader *uploader);
G_GNUC_INTERNAL
GstBuffer *
gst_vaapi_uploader_get_buffer(GstVaapiUploader *uploader);