surface: allow creation with explicit pixel format.
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>
Tue, 9 Jul 2013 17:08:37 +0000 (19:08 +0200)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Wed, 10 Jul 2013 15:03:47 +0000 (17:03 +0200)
Make it possible to create VA surfaces with a specific pixel format.
This is a new capability brought in by VA-API >= 0.34.0. If that
capability is not built-in (e.g. using VA-API < 0.34.0), then
gst_vaapi_surface_new_with_format() will return NULL.

docs/reference/libs/libs-sections.txt
gst-libs/gst/vaapi/gstvaapisurface.c
gst-libs/gst/vaapi/gstvaapisurface.h
gst-libs/gst/vaapi/gstvaapisurface_priv.h

index bd0229c..827067c 100644 (file)
@@ -209,8 +209,10 @@ GstVaapiSurfaceRenderFlags
 <TITLE>GstVaapiSurface</TITLE>
 GstVaapiSurface
 gst_vaapi_surface_new
+gst_vaapi_surface_new_with_format
 gst_vaapi_surface_get_id
 gst_vaapi_surface_get_chroma_type
+gst_vaapi_surface_get_format
 gst_vaapi_surface_get_width
 gst_vaapi_surface_get_height
 gst_vaapi_surface_get_size
index 9cd129d..1753516 100644 (file)
@@ -118,6 +118,7 @@ gst_vaapi_surface_create(GstVaapiSurface *surface,
     if (!vaapi_check_status(status, "vaCreateSurfaces()"))
         return FALSE;
 
+    surface->format = GST_VIDEO_FORMAT_ENCODED;
     surface->chroma_type = chroma_type;
     surface->width = width;
     surface->height = height;
@@ -132,6 +133,64 @@ error_unsupported_chroma_type:
     return FALSE;
 }
 
+static gboolean
+gst_vaapi_surface_create_with_format(GstVaapiSurface *surface,
+    GstVideoFormat format, guint width, guint height)
+{
+#if VA_CHECK_VERSION(0,34,0)
+    GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(surface);
+    VASurfaceID surface_id;
+    VAStatus status;
+    guint chroma_type, va_chroma_format;
+    const VAImageFormat *va_format;
+    VASurfaceAttrib attrib;
+
+    va_format = gst_video_format_to_va_format(format);
+    if (!va_format)
+        goto error_unsupported_format;
+
+    chroma_type = gst_video_format_get_chroma_type(format);
+    if (!chroma_type)
+        goto error_unsupported_format;
+
+    va_chroma_format = from_GstVaapiChromaType(chroma_type);
+    if (!va_chroma_format)
+        goto error_unsupported_format;
+
+    attrib.flags = VA_SURFACE_ATTRIB_SETTABLE;
+    attrib.type = VASurfaceAttribPixelFormat;
+    attrib.value.type = VAGenericValueTypeInteger;
+    attrib.value.value.i = va_format->fourcc;
+
+    GST_VAAPI_DISPLAY_LOCK(display);
+    status = vaCreateSurfaces(
+        GST_VAAPI_DISPLAY_VADISPLAY(display),
+        va_chroma_format, width, height,
+        &surface_id, 1,
+        &attrib, 1
+    );
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+    if (!vaapi_check_status(status, "vaCreateSurfaces()"))
+        return FALSE;
+
+    surface->format = format;
+    surface->chroma_type = chroma_type;
+    surface->width = width;
+    surface->height = height;
+
+    GST_DEBUG("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(surface_id));
+    GST_VAAPI_OBJECT_ID(surface) = surface_id;
+    return TRUE;
+
+    /* ERRORS */
+error_unsupported_format:
+    GST_ERROR("unsupported format %u", gst_video_format_to_string(format));
+    return FALSE;
+#else
+    return FALSE;
+#endif
+}
+
 #define gst_vaapi_surface_finalize gst_vaapi_surface_destroy
 GST_VAAPI_OBJECT_DEFINE_CLASS(GstVaapiSurface, gst_vaapi_surface)
 
@@ -173,6 +232,46 @@ error:
 }
 
 /**
+ * gst_vaapi_surface_new_with_format:
+ * @display: a #GstVaapiDisplay
+ * @format: the surface format
+ * @width: the requested surface width
+ * @height: the requested surface height
+ *
+ * Creates a new #GstVaapiSurface with the specified pixel format and
+ * dimensions.
+ *
+ * Return value: the newly allocated #GstVaapiSurface object, or %NULL
+ *   if creation of VA surface with explicit pixel format is not
+ *   supported or failed.
+ */
+GstVaapiSurface *
+gst_vaapi_surface_new_with_format(
+    GstVaapiDisplay    *display,
+    GstVideoFormat      format,
+    guint               width,
+    guint               height
+)
+{
+    GstVaapiSurface *surface;
+
+    GST_DEBUG("size %ux%u, format %s", width, height,
+              gst_video_format_to_string(format));
+
+    surface = gst_vaapi_object_new(gst_vaapi_surface_class(), display);
+    if (!surface)
+        return NULL;
+
+    if (!gst_vaapi_surface_create_with_format(surface, format, width, height))
+        goto error;
+    return surface;
+
+error:
+    gst_vaapi_object_unref(surface);
+    return NULL;
+}
+
+/**
  * gst_vaapi_surface_get_id:
  * @surface: a #GstVaapiSurface
  *
@@ -205,6 +304,24 @@ gst_vaapi_surface_get_chroma_type(GstVaapiSurface *surface)
 }
 
 /**
+ * gst_vaapi_surface_get_format:
+ * @surface: a #GstVaapiSurface
+ *
+ * Returns the #GstVideoFormat the @surface was created with.
+ *
+ * Return value: the #GstVideoFormat, or %GST_VIDEO_FORMAT_ENCODED if
+ *   the surface was not created with an explicit video format, or if
+ *   the underlying video format could not be determined
+ */
+GstVideoFormat
+gst_vaapi_surface_get_format(GstVaapiSurface *surface)
+{
+    g_return_val_if_fail(surface != NULL, 0);
+
+    return GST_VAAPI_SURFACE_FORMAT(surface);
+}
+
+/**
  * gst_vaapi_surface_get_width:
  * @surface: a #GstVaapiSurface
  *
index e6ceacc..13dbf4f 100644 (file)
@@ -27,6 +27,7 @@
 #include <gst/vaapi/gstvaapidisplay.h>
 #include <gst/vaapi/gstvaapiimage.h>
 #include <gst/vaapi/gstvaapisubpicture.h>
+#include <gst/video/video.h>
 #include <gst/video/video-overlay-composition.h>
 
 G_BEGIN_DECLS
@@ -53,9 +54,6 @@ G_BEGIN_DECLS
 
 /**
  * GstVaapiChromaType:
- * @GST_VAAPI_CHROMA_TYPE_YUV420: 4:2:0 chroma format
- * @GST_VAAPI_CHROMA_TYPE_YUV422: 4:2:2 chroma format
- * @GST_VAAPI_CHROMA_TYPE_YUV444: 4:4:4 chroma format
  * @GST_VAAPI_CHROMA_TYPE_YUV420: YUV 4:2:0 chroma format
  * @GST_VAAPI_CHROMA_TYPE_YUV422: YUV 4:2:2 chroma format
  * @GST_VAAPI_CHROMA_TYPE_YUV444: YUV 4:4:4 chroma format
@@ -139,12 +137,23 @@ gst_vaapi_surface_new(
     guint               height
 );
 
+GstVaapiSurface *
+gst_vaapi_surface_new_with_format(
+    GstVaapiDisplay    *display,
+    GstVideoFormat      format,
+    guint               width,
+    guint               height
+);
+
 GstVaapiID
 gst_vaapi_surface_get_id(GstVaapiSurface *surface);
 
 GstVaapiChromaType
 gst_vaapi_surface_get_chroma_type(GstVaapiSurface *surface);
 
+GstVideoFormat
+gst_vaapi_surface_get_format(GstVaapiSurface *surface);
+
 guint
 gst_vaapi_surface_get_width(GstVaapiSurface *surface);
 
index f7d04b8..2114d72 100644 (file)
@@ -37,6 +37,7 @@ struct _GstVaapiSurface {
     /*< private >*/
     GstVaapiObject      parent_instance;
 
+    GstVideoFormat      format;
     guint               width;
     guint               height;
     GstVaapiChromaType  chroma_type;
@@ -67,6 +68,18 @@ struct _GstVaapiSurfaceClass {
     GST_VAAPI_SURFACE(surface)->chroma_type
 
 /**
+ * GST_VAAPI_SURFACE_SURFACE_FORMAT:
+ * @surface: a #GstVaapiSurface
+ *
+ * Macro that evaluates to the @surface format.
+ *
+ * This is an internal macro that does not do any run-time type check.
+ */
+#undef  GST_VAAPI_SURFACE_FORMAT
+#define GST_VAAPI_SURFACE_FORMAT(surface) \
+    GST_VAAPI_SURFACE(surface)->format
+
+/**
  * GST_VAAPI_SURFACE_SURFACE_WIDTH:
  * @surface: a #GstVaapiSurface
  *