libs: blend: add surface generator API
authorU. Artie Eoff <ullysses.a.eoff@intel.com>
Fri, 10 Jan 2020 17:54:30 +0000 (09:54 -0800)
committerVíctor Manuel Jáquez Leal <vjaquez@igalia.com>
Tue, 14 Jan 2020 15:07:32 +0000 (15:07 +0000)
This new API allows the user to call a single method (process)
which handles the [display] lock/unlock logic internally for
them.

This API supersedes the risky begin, render, end API.
It eliminates the need for the user to call a lock method
(process_begin) before processing the input buffers
(process_render) and calling an unlock method (process_end)
afterwards.

See #219

gst-libs/gst/vaapi/gstvaapiblend.c
gst-libs/gst/vaapi/gstvaapiblend.h

index 6a407f3..426785e 100644 (file)
@@ -367,3 +367,101 @@ gst_vaapi_blend_process_end (GstVaapiBlend * blend)
 
   return TRUE;
 }
+
+static gboolean
+gst_vaapi_blend_process_unlocked (GstVaapiBlend * blend,
+    GstVaapiSurface * output, GstVaapiBlendSurfaceGenerator * generator)
+{
+  VAStatus va_status;
+  VADisplay va_display;
+  GstVaapiBlendSurface *current;
+
+  va_display = GST_VAAPI_DISPLAY_VADISPLAY (blend->display);
+
+  va_status = vaBeginPicture (va_display, blend->va_context,
+      GST_VAAPI_SURFACE_ID (output));
+  if (!vaapi_check_status (va_status, "vaBeginPicture()"))
+    return FALSE;
+
+  current = generator->next (generator);
+  for (; current; current = generator->next (generator)) {
+    VAProcPipelineParameterBuffer *param = NULL;
+    VABufferID id = VA_INVALID_ID;
+    VARectangle src_rect = { 0, };
+    VARectangle dst_rect = { 0, };
+#if VA_CHECK_VERSION(1,1,0)
+    VABlendState blend_state;
+#endif
+
+    if (!current->surface)
+      return FALSE;
+
+    /* Build surface region (source) */
+    src_rect.width = GST_VAAPI_SURFACE_WIDTH (current->surface);
+    src_rect.height = GST_VAAPI_SURFACE_HEIGHT (current->surface);
+    if (current->crop) {
+      if ((current->crop->x + current->crop->width > src_rect.width) ||
+          (current->crop->y + current->crop->height > src_rect.height))
+        return FALSE;
+      src_rect.x = current->crop->x;
+      src_rect.y = current->crop->y;
+      src_rect.width = current->crop->width;
+      src_rect.height = current->crop->height;
+    }
+
+    /* Build output region (target) */
+    dst_rect.x = current->target.x;
+    dst_rect.y = current->target.y;
+    dst_rect.width = current->target.width;
+    dst_rect.height = current->target.height;
+
+    if (!vaapi_create_buffer (va_display, blend->va_context,
+            VAProcPipelineParameterBufferType, sizeof (*param), NULL, &id,
+            (gpointer *) & param))
+      return FALSE;
+
+    memset (param, 0, sizeof (*param));
+
+    param->surface = GST_VAAPI_SURFACE_ID (current->surface);
+    param->surface_region = &src_rect;
+    param->output_region = &dst_rect;
+    param->output_background_color = 0xff000000;
+
+#if VA_CHECK_VERSION(1,1,0)
+    blend_state.flags = VA_BLEND_GLOBAL_ALPHA;
+    blend_state.global_alpha = current->alpha;
+    param->blend_state = &blend_state;
+#endif
+
+    vaapi_unmap_buffer (va_display, id, NULL);
+
+    va_status = vaRenderPicture (va_display, blend->va_context, &id, 1);
+    vaapi_destroy_buffer (va_display, &id);
+    if (!vaapi_check_status (va_status, "vaRenderPicture()"))
+      return FALSE;
+  }
+
+  va_status = vaEndPicture (va_display, blend->va_context);
+  if (!vaapi_check_status (va_status, "vaEndPicture()"))
+    return FALSE;
+
+  return TRUE;
+}
+
+gboolean
+gst_vaapi_blend_process (GstVaapiBlend * blend, GstVaapiSurface * output,
+    GstVaapiBlendSurfaceGenerator * generator)
+{
+  gboolean result;
+
+  g_return_val_if_fail (blend != NULL, FALSE);
+  g_return_val_if_fail (output != NULL, FALSE);
+  g_return_val_if_fail (generator != NULL, FALSE);
+  g_return_val_if_fail (generator->next != NULL, FALSE);
+
+  GST_VAAPI_DISPLAY_LOCK (blend->display);
+  result = gst_vaapi_blend_process_unlocked (blend, output, generator);
+  GST_VAAPI_DISPLAY_UNLOCK (blend->display);
+
+  return result;
+}
index 60c30c8..6119c79 100644 (file)
@@ -35,6 +35,21 @@ G_BEGIN_DECLS
   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_BLEND))
 
 typedef struct _GstVaapiBlend GstVaapiBlend;
+typedef struct _GstVaapiBlendSurface GstVaapiBlendSurface;
+typedef struct _GstVaapiBlendSurfaceGenerator GstVaapiBlendSurfaceGenerator;
+
+struct _GstVaapiBlendSurface
+{
+  GstVaapiSurface const *surface;
+  const GstVaapiRectangle *crop;
+  GstVaapiRectangle target;
+  gdouble alpha;
+};
+
+struct _GstVaapiBlendSurfaceGenerator
+{
+  GstVaapiBlendSurface* (*next)();
+};
 
 GstVaapiBlend *
 gst_vaapi_blend_new (GstVaapiDisplay * display);
@@ -44,6 +59,10 @@ gst_vaapi_blend_replace (GstVaapiBlend ** old_blend_ptr,
     GstVaapiBlend * new_blend);
 
 gboolean
+gst_vaapi_blend_process (GstVaapiBlend * blend, GstVaapiSurface * output,
+    GstVaapiBlendSurfaceGenerator * generator);
+
+gboolean
 gst_vaapi_blend_process_begin (GstVaapiBlend * blend,
     GstVaapiSurface * surface);