[Pkg-gstreamer-commits] [gstreamer-vaapi] 160/176: context: move overlay composition to separate files.

Vincent Cheng vcheng at moszumanska.debian.org
Tue Jun 3 08:09:37 UTC 2014


This is an automated email from the git hooks/post-receive script.

vcheng pushed a commit to branch upstream
in repository gstreamer-vaapi.

commit 3b714c8913ff43370f7d7bd6ec0fdb85ef72328d
Author: Gwenole Beauchesne <gwenole.beauchesne at intel.com>
Date:   Thu Jan 23 10:59:20 2014 +0100

    context: move overlay composition to separate files.
    
    Move GstVideoOverlayComposition handling to separate source files.
    This helps keeing GstVaapiContext core implementation to the bare
    minimal, i.e. simpy helpers to create a VA context and handle pool
    of associated VA surfaces.
---
 gst-libs/gst/vaapi/Makefile.am               |   2 +
 gst-libs/gst/vaapi/gstvaapicontext.c         | 403 +-----------------------
 gst-libs/gst/vaapi/gstvaapicontext.h         |   6 -
 gst-libs/gst/vaapi/gstvaapicontext_overlay.c | 451 +++++++++++++++++++++++++++
 gst-libs/gst/vaapi/gstvaapicontext_overlay.h |  52 +++
 gst-libs/gst/vaapi/gstvaapisurface.c         |   1 +
 6 files changed, 511 insertions(+), 404 deletions(-)

diff --git a/gst-libs/gst/vaapi/Makefile.am b/gst-libs/gst/vaapi/Makefile.am
index 11efb4b..92b875a 100644
--- a/gst-libs/gst/vaapi/Makefile.am
+++ b/gst-libs/gst/vaapi/Makefile.am
@@ -47,6 +47,7 @@ libgstvaapi_libs =				\
 libgstvaapi_source_c =				\
 	gstvaapicodec_objects.c			\
 	gstvaapicontext.c			\
+	gstvaapicontext_overlay.c		\
 	gstvaapidecoder.c			\
 	gstvaapidecoder_dpb.c			\
 	gstvaapidecoder_h264.c			\
@@ -110,6 +111,7 @@ libgstvaapi_source_priv_h =			\
 	gstvaapicodec_objects.h			\
 	gstvaapicompat.h			\
 	gstvaapicontext.h			\
+	gstvaapicontext_overlay.h		\
 	gstvaapidebug.h				\
 	gstvaapidecoder_dpb.h			\
 	gstvaapidecoder_objects.h		\
diff --git a/gst-libs/gst/vaapi/gstvaapicontext.c b/gst-libs/gst/vaapi/gstvaapicontext.c
index a4cc1fb..8651e90 100644
--- a/gst-libs/gst/vaapi/gstvaapicontext.c
+++ b/gst-libs/gst/vaapi/gstvaapicontext.c
@@ -30,6 +30,7 @@
 #include "sysdeps.h"
 #include "gstvaapicompat.h"
 #include "gstvaapicontext.h"
+#include "gstvaapicontext_overlay.h"
 #include "gstvaapidisplay_priv.h"
 #include "gstvaapiobject_priv.h"
 #include "gstvaapisurface.h"
@@ -37,324 +38,11 @@
 #include "gstvaapisurfacepool.h"
 #include "gstvaapisurfaceproxy.h"
 #include "gstvaapivideopool_priv.h"
-#include "gstvaapiimage.h"
-#include "gstvaapisubpicture.h"
 #include "gstvaapiutils.h"
 
 #define DEBUG 1
 #include "gstvaapidebug.h"
 
-typedef struct _GstVaapiOverlayRectangle GstVaapiOverlayRectangle;
-struct _GstVaapiOverlayRectangle
-{
-  GstVaapiContext *context;
-  GstVaapiSubpicture *subpicture;
-  GstVaapiRectangle render_rect;
-  guint seq_num;
-  guint layer_id;
-  GstBuffer *rect_buffer;
-  GstVideoOverlayRectangle *rect;
-  guint is_associated:1;
-};
-
-static inline void
-gst_video_overlay_rectangle_replace (GstVideoOverlayRectangle ** old_rect_ptr,
-    GstVideoOverlayRectangle * new_rect)
-{
-  gst_mini_object_replace ((GstMiniObject **) old_rect_ptr,
-      GST_MINI_OBJECT_CAST (new_rect));
-}
-
-#define overlay_rectangle_ref(overlay) \
-    gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(overlay))
-
-#define overlay_rectangle_unref(overlay) \
-    gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(overlay))
-
-#define overlay_rectangle_replace(old_overlay_ptr, new_overlay) \
-    gst_vaapi_mini_object_replace((GstVaapiMiniObject **)(old_overlay_ptr), \
-        (GstVaapiMiniObject *)(new_overlay))
-
-static void overlay_rectangle_finalize (GstVaapiOverlayRectangle * overlay);
-
-static gboolean
-overlay_rectangle_associate (GstVaapiOverlayRectangle * overlay);
-
-static gboolean
-overlay_rectangle_deassociate (GstVaapiOverlayRectangle * overlay);
-
-static inline const GstVaapiMiniObjectClass *
-overlay_rectangle_class (void)
-{
-  static const GstVaapiMiniObjectClass GstVaapiOverlayRectangleClass = {
-    sizeof (GstVaapiOverlayRectangle),
-    (GDestroyNotify) overlay_rectangle_finalize
-  };
-  return &GstVaapiOverlayRectangleClass;
-}
-
-static GstVaapiOverlayRectangle *
-overlay_rectangle_new (GstVideoOverlayRectangle * rect,
-    GstVaapiContext * context, guint layer_id)
-{
-  GstVaapiOverlayRectangle *overlay;
-  GstVaapiRectangle *render_rect;
-  guint width, height, flags;
-  gint x, y;
-
-  overlay = (GstVaapiOverlayRectangle *)
-      gst_vaapi_mini_object_new0 (overlay_rectangle_class ());
-  if (!overlay)
-    return NULL;
-
-  overlay->context = context;
-  overlay->seq_num = gst_video_overlay_rectangle_get_seqnum (rect);
-  overlay->layer_id = layer_id;
-  overlay->rect = gst_video_overlay_rectangle_ref (rect);
-
-  flags = gst_video_overlay_rectangle_get_flags (rect);
-  gst_buffer_replace (&overlay->rect_buffer,
-      gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect, flags));
-  if (!overlay->rect_buffer)
-    goto error;
-
-  overlay->subpicture =
-      gst_vaapi_subpicture_new_from_overlay_rectangle (GST_VAAPI_OBJECT_DISPLAY
-      (context), rect);
-  if (!overlay->subpicture)
-    goto error;
-
-  gst_video_overlay_rectangle_get_render_rectangle (rect,
-      &x, &y, &width, &height);
-  render_rect = &overlay->render_rect;
-  render_rect->x = x;
-  render_rect->y = y;
-  render_rect->width = width;
-  render_rect->height = height;
-  return overlay;
-
-error:
-  overlay_rectangle_unref (overlay);
-  return NULL;
-}
-
-static void
-overlay_rectangle_finalize (GstVaapiOverlayRectangle * overlay)
-{
-  gst_buffer_replace (&overlay->rect_buffer, NULL);
-  gst_video_overlay_rectangle_unref (overlay->rect);
-
-  if (overlay->subpicture) {
-    overlay_rectangle_deassociate (overlay);
-    gst_vaapi_object_unref (overlay->subpicture);
-    overlay->subpicture = NULL;
-  }
-}
-
-static gboolean
-overlay_rectangle_associate (GstVaapiOverlayRectangle * overlay)
-{
-  GstVaapiSubpicture *const subpicture = overlay->subpicture;
-  GPtrArray *const surfaces = overlay->context->surfaces;
-  guint i, n_associated;
-
-  if (overlay->is_associated)
-    return TRUE;
-
-  n_associated = 0;
-  for (i = 0; i < surfaces->len; i++) {
-    GstVaapiSurface *const surface = g_ptr_array_index (surfaces, i);
-    if (gst_vaapi_surface_associate_subpicture (surface, subpicture,
-            NULL, &overlay->render_rect))
-      n_associated++;
-  }
-
-  overlay->is_associated = TRUE;
-  return n_associated == surfaces->len;
-}
-
-static gboolean
-overlay_rectangle_deassociate (GstVaapiOverlayRectangle * overlay)
-{
-  GstVaapiSubpicture *const subpicture = overlay->subpicture;
-  GPtrArray *const surfaces = overlay->context->surfaces;
-  guint i, n_associated;
-
-  if (!overlay->is_associated)
-    return TRUE;
-
-  n_associated = surfaces->len;
-  for (i = 0; i < surfaces->len; i++) {
-    GstVaapiSurface *const surface = g_ptr_array_index (surfaces, i);
-    if (gst_vaapi_surface_deassociate_subpicture (surface, subpicture))
-      n_associated--;
-  }
-
-  overlay->is_associated = FALSE;
-  return n_associated == 0;
-}
-
-static gboolean
-overlay_rectangle_changed_pixels (GstVaapiOverlayRectangle * overlay,
-    GstVideoOverlayRectangle * rect)
-{
-  guint flags;
-  GstBuffer *buffer;
-
-  if (overlay->seq_num == gst_video_overlay_rectangle_get_seqnum (rect))
-    return FALSE;
-
-  flags =
-      to_GstVideoOverlayFormatFlags (gst_vaapi_subpicture_get_flags
-      (overlay->subpicture));
-
-  buffer = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect, flags);
-  if (!buffer)
-    return FALSE;
-#if GST_CHECK_VERSION(1,0,0)
-  {
-    const guint n_blocks = gst_buffer_n_memory (buffer);
-    gsize ofs;
-    guint i;
-
-    if (buffer == overlay->rect_buffer)
-      return TRUE;
-
-    if (n_blocks != gst_buffer_n_memory (overlay->rect_buffer))
-      return FALSE;
-
-    for (i = 0; i < n_blocks; i++) {
-      GstMemory *const mem1 = gst_buffer_peek_memory (buffer, i);
-      GstMemory *const mem2 = gst_buffer_peek_memory (overlay->rect_buffer, i);
-      if (!gst_memory_is_span (mem1, mem2, &ofs))
-        return FALSE;
-    }
-  }
-#else
-  if (GST_BUFFER_DATA (overlay->rect_buffer) != GST_BUFFER_DATA (buffer))
-    return FALSE;
-#endif
-  return TRUE;
-}
-
-static gboolean
-overlay_rectangle_changed_render_rect (GstVaapiOverlayRectangle * overlay,
-    GstVideoOverlayRectangle * rect)
-{
-  GstVaapiRectangle *const render_rect = &overlay->render_rect;
-  guint width, height;
-  gint x, y;
-
-  gst_video_overlay_rectangle_get_render_rectangle (rect,
-      &x, &y, &width, &height);
-
-  if (x == render_rect->x &&
-      y == render_rect->y &&
-      width == render_rect->width && height == render_rect->height)
-    return FALSE;
-
-  render_rect->x = x;
-  render_rect->y = y;
-  render_rect->width = width;
-  render_rect->height = height;
-  return TRUE;
-}
-
-static inline gboolean
-overlay_rectangle_update_global_alpha (GstVaapiOverlayRectangle * overlay,
-    GstVideoOverlayRectangle * rect)
-{
-#ifdef HAVE_GST_VIDEO_OVERLAY_HWCAPS
-  const guint flags = gst_video_overlay_rectangle_get_flags (rect);
-  if (!(flags & GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA))
-    return TRUE;
-#endif
-  return gst_vaapi_subpicture_set_global_alpha (overlay->subpicture,
-      gst_video_overlay_rectangle_get_global_alpha (rect));
-}
-
-static gboolean
-overlay_rectangle_update (GstVaapiOverlayRectangle * overlay,
-    GstVideoOverlayRectangle * rect, gboolean * reassociate_ptr)
-{
-  if (overlay_rectangle_changed_pixels (overlay, rect))
-    return FALSE;
-  if (overlay_rectangle_changed_render_rect (overlay, rect))
-    *reassociate_ptr = TRUE;
-  if (!overlay_rectangle_update_global_alpha (overlay, rect))
-    return FALSE;
-  gst_video_overlay_rectangle_replace (&overlay->rect, rect);
-  return TRUE;
-}
-
-static inline GPtrArray *
-overlay_new (void)
-{
-  return g_ptr_array_new_with_free_func (
-      (GDestroyNotify) gst_vaapi_mini_object_unref);
-}
-
-static void
-overlay_destroy (GPtrArray ** overlay_ptr)
-{
-  GPtrArray *const overlay = *overlay_ptr;
-
-  if (!overlay)
-    return;
-  g_ptr_array_unref (overlay);
-  *overlay_ptr = NULL;
-}
-
-static void
-overlay_clear (GPtrArray * overlay)
-{
-  if (overlay && overlay->len > 0)
-    g_ptr_array_remove_range (overlay, 0, overlay->len);
-}
-
-static GstVaapiOverlayRectangle *
-overlay_lookup (GPtrArray * overlays, GstVideoOverlayRectangle * rect)
-{
-  guint i;
-
-  for (i = 0; i < overlays->len; i++) {
-    GstVaapiOverlayRectangle *const overlay = g_ptr_array_index (overlays, i);
-
-    if (overlay->rect == rect)
-      return overlay;
-  }
-  return NULL;
-}
-
-static gboolean
-overlay_reassociate (GPtrArray * overlays)
-{
-  guint i;
-
-  for (i = 0; i < overlays->len; i++)
-    overlay_rectangle_deassociate (g_ptr_array_index (overlays, i));
-
-  for (i = 0; i < overlays->len; i++) {
-    if (!overlay_rectangle_associate (g_ptr_array_index (overlays, i)))
-      return FALSE;
-  }
-  return TRUE;
-}
-
-static void
-context_clear_overlay (GstVaapiContext * context)
-{
-  overlay_clear (context->overlays[0]);
-  overlay_clear (context->overlays[1]);
-  context->overlay_id = 0;
-}
-
-static inline void
-context_destroy_overlay (GstVaapiContext * context)
-{
-  context_clear_overlay (context);
-}
-
 static void
 unref_surface_cb (GstVaapiSurface * surface)
 {
@@ -365,7 +53,7 @@ unref_surface_cb (GstVaapiSurface * surface)
 static void
 context_destroy_surfaces (GstVaapiContext * context)
 {
-  context_destroy_overlay (context);
+  gst_vaapi_context_overlay_reset (context);
 
   if (context->surfaces) {
     g_ptr_array_unref (context->surfaces);
@@ -406,16 +94,6 @@ context_destroy (GstVaapiContext * context)
 }
 
 static gboolean
-context_create_overlay (GstVaapiContext * context)
-{
-  if (!context->overlays[0] || !context->overlays[1])
-    return FALSE;
-
-  context_clear_overlay (context);
-  return TRUE;
-}
-
-static gboolean
 context_create_surfaces (GstVaapiContext * context)
 {
   const GstVaapiContextInfo *const cip = &context->info;
@@ -426,7 +104,7 @@ context_create_surfaces (GstVaapiContext * context)
   /* Number of scratch surfaces beyond those used as reference */
   const guint SCRATCH_SURFACES_COUNT = 4;
 
-  if (!context_create_overlay (context))
+  if (!gst_vaapi_context_overlay_reset (context))
     return FALSE;
 
   num_surfaces = cip->ref_frames + SCRATCH_SURFACES_COUNT;
@@ -556,17 +234,15 @@ gst_vaapi_context_init (GstVaapiContext * context,
 {
   context->info = *cip;
   context->va_config = VA_INVALID_ID;
-  context->overlays[0] = overlay_new ();
-  context->overlays[1] = overlay_new ();
+  gst_vaapi_context_overlay_init (context);
 }
 
 static void
 gst_vaapi_context_finalize (GstVaapiContext * context)
 {
-  overlay_destroy (&context->overlays[0]);
-  overlay_destroy (&context->overlays[1]);
   context_destroy (context);
   context_destroy_surfaces (context);
+  gst_vaapi_context_overlay_finalize (context);
 }
 
 GST_VAAPI_OBJECT_DEFINE_CLASS (GstVaapiContext, gst_vaapi_context);
@@ -719,75 +395,6 @@ gst_vaapi_context_get_surface_count (GstVaapiContext * context)
 }
 
 /**
- * gst_vaapi_context_apply_composition:
- * @context: a #GstVaapiContext
- * @composition: a #GstVideoOverlayComposition
- *
- * Applies video composition planes to all surfaces bound to @context.
- * This helper function resets any additional subpictures the user may
- * have associated himself. A %NULL @composition will also clear all
- * the existing subpictures.
- *
- * Return value: %TRUE if all composition planes could be applied,
- *   %FALSE otherwise
- */
-gboolean
-gst_vaapi_context_apply_composition (GstVaapiContext * context,
-    GstVideoOverlayComposition * composition)
-{
-  GPtrArray *curr_overlay, *next_overlay;
-  guint i, n_rectangles;
-  gboolean reassociate = FALSE;
-
-  g_return_val_if_fail (context != NULL, FALSE);
-
-  if (!context->surfaces)
-    return FALSE;
-
-  if (!composition) {
-    context_clear_overlay (context);
-    return TRUE;
-  }
-
-  curr_overlay = context->overlays[context->overlay_id];
-  next_overlay = context->overlays[context->overlay_id ^ 1];
-  overlay_clear (next_overlay);
-
-  n_rectangles = gst_video_overlay_composition_n_rectangles (composition);
-  for (i = 0; i < n_rectangles; i++) {
-    GstVideoOverlayRectangle *const rect =
-        gst_video_overlay_composition_get_rectangle (composition, i);
-    GstVaapiOverlayRectangle *overlay;
-
-    overlay = overlay_lookup (curr_overlay, rect);
-    if (overlay && overlay_rectangle_update (overlay, rect, &reassociate)) {
-      overlay_rectangle_ref (overlay);
-      if (overlay->layer_id != i)
-        reassociate = TRUE;
-    } else {
-      overlay = overlay_rectangle_new (rect, context, i);
-      if (!overlay) {
-        GST_WARNING ("could not create VA overlay rectangle");
-        goto error;
-      }
-      reassociate = TRUE;
-    }
-    g_ptr_array_add (next_overlay, overlay);
-  }
-
-  overlay_clear (curr_overlay);
-  context->overlay_id ^= 1;
-
-  if (reassociate && !overlay_reassociate (next_overlay))
-    return FALSE;
-  return TRUE;
-
-error:
-  context_clear_overlay (context);
-  return FALSE;
-}
-
-/**
  * gst_vaapi_context_get_attribute:
  * @context: a #GstVaapiContext
  * @type: a VA config attribute type
diff --git a/gst-libs/gst/vaapi/gstvaapicontext.h b/gst-libs/gst/vaapi/gstvaapicontext.h
index 4888a83..8112fd4 100644
--- a/gst-libs/gst/vaapi/gstvaapicontext.h
+++ b/gst-libs/gst/vaapi/gstvaapicontext.h
@@ -25,7 +25,6 @@
 #ifndef GST_VAAPI_CONTEXT_H
 #define GST_VAAPI_CONTEXT_H
 
-#include <gst/video/video-overlay-composition.h>
 #include "gstvaapiobject.h"
 #include "gstvaapiobject_priv.h"
 #include "gstvaapiprofile.h"
@@ -117,11 +116,6 @@ gst_vaapi_context_get_surface_count (GstVaapiContext * context);
 
 G_GNUC_INTERNAL
 gboolean
-gst_vaapi_context_apply_composition (GstVaapiContext * context,
-    GstVideoOverlayComposition * composition);
-
-G_GNUC_INTERNAL
-gboolean
 gst_vaapi_context_get_attribute (GstVaapiContext * context,
     VAConfigAttribType type, guint * out_value_ptr);
 
diff --git a/gst-libs/gst/vaapi/gstvaapicontext_overlay.c b/gst-libs/gst/vaapi/gstvaapicontext_overlay.c
new file mode 100644
index 0000000..b38e62e
--- /dev/null
+++ b/gst-libs/gst/vaapi/gstvaapicontext_overlay.c
@@ -0,0 +1,451 @@
+/*
+ *  gstvaapicontext_overlay.c - VA context abstraction (overlay composition)
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *    Author: Gwenole Beauchesne <gwenole.beauchesne at splitted-desktop.com>
+ *  Copyright (C) 2011-2014 Intel Corporation
+ *    Author: Gwenole Beauchesne <gwenole.beauchesne at intel.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#include "sysdeps.h"
+#include "gstvaapicontext_overlay.h"
+#include "gstvaapiutils.h"
+#include "gstvaapiimage.h"
+#include "gstvaapisubpicture.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+typedef struct _GstVaapiOverlayRectangle GstVaapiOverlayRectangle;
+struct _GstVaapiOverlayRectangle
+{
+  GstVaapiContext *context;
+  GstVaapiSubpicture *subpicture;
+  GstVaapiRectangle render_rect;
+  guint seq_num;
+  guint layer_id;
+  GstBuffer *rect_buffer;
+  GstVideoOverlayRectangle *rect;
+  guint is_associated:1;
+};
+
+static inline void
+gst_video_overlay_rectangle_replace (GstVideoOverlayRectangle ** old_rect_ptr,
+    GstVideoOverlayRectangle * new_rect)
+{
+  gst_mini_object_replace ((GstMiniObject **) old_rect_ptr,
+      GST_MINI_OBJECT_CAST (new_rect));
+}
+
+#define overlay_rectangle_ref(overlay) \
+    gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(overlay))
+
+#define overlay_rectangle_unref(overlay) \
+    gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(overlay))
+
+#define overlay_rectangle_replace(old_overlay_ptr, new_overlay) \
+    gst_vaapi_mini_object_replace((GstVaapiMiniObject **)(old_overlay_ptr), \
+        (GstVaapiMiniObject *)(new_overlay))
+
+static void overlay_rectangle_finalize (GstVaapiOverlayRectangle * overlay);
+
+static gboolean
+overlay_rectangle_associate (GstVaapiOverlayRectangle * overlay);
+
+static gboolean
+overlay_rectangle_deassociate (GstVaapiOverlayRectangle * overlay);
+
+static inline const GstVaapiMiniObjectClass *
+overlay_rectangle_class (void)
+{
+  static const GstVaapiMiniObjectClass GstVaapiOverlayRectangleClass = {
+    sizeof (GstVaapiOverlayRectangle),
+    (GDestroyNotify) overlay_rectangle_finalize
+  };
+  return &GstVaapiOverlayRectangleClass;
+}
+
+static GstVaapiOverlayRectangle *
+overlay_rectangle_new (GstVideoOverlayRectangle * rect,
+    GstVaapiContext * context, guint layer_id)
+{
+  GstVaapiOverlayRectangle *overlay;
+  GstVaapiRectangle *render_rect;
+  guint width, height, flags;
+  gint x, y;
+
+  overlay = (GstVaapiOverlayRectangle *)
+      gst_vaapi_mini_object_new0 (overlay_rectangle_class ());
+  if (!overlay)
+    return NULL;
+
+  overlay->context = context;
+  overlay->seq_num = gst_video_overlay_rectangle_get_seqnum (rect);
+  overlay->layer_id = layer_id;
+  overlay->rect = gst_video_overlay_rectangle_ref (rect);
+
+  flags = gst_video_overlay_rectangle_get_flags (rect);
+  gst_buffer_replace (&overlay->rect_buffer,
+      gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect, flags));
+  if (!overlay->rect_buffer)
+    goto error;
+
+  overlay->subpicture =
+      gst_vaapi_subpicture_new_from_overlay_rectangle (GST_VAAPI_OBJECT_DISPLAY
+      (context), rect);
+  if (!overlay->subpicture)
+    goto error;
+
+  gst_video_overlay_rectangle_get_render_rectangle (rect,
+      &x, &y, &width, &height);
+  render_rect = &overlay->render_rect;
+  render_rect->x = x;
+  render_rect->y = y;
+  render_rect->width = width;
+  render_rect->height = height;
+  return overlay;
+
+error:
+  overlay_rectangle_unref (overlay);
+  return NULL;
+}
+
+static void
+overlay_rectangle_finalize (GstVaapiOverlayRectangle * overlay)
+{
+  gst_buffer_replace (&overlay->rect_buffer, NULL);
+  gst_video_overlay_rectangle_unref (overlay->rect);
+
+  if (overlay->subpicture) {
+    overlay_rectangle_deassociate (overlay);
+    gst_vaapi_object_unref (overlay->subpicture);
+    overlay->subpicture = NULL;
+  }
+}
+
+static gboolean
+overlay_rectangle_associate (GstVaapiOverlayRectangle * overlay)
+{
+  GstVaapiSubpicture *const subpicture = overlay->subpicture;
+  GPtrArray *const surfaces = overlay->context->surfaces;
+  guint i, n_associated;
+
+  if (overlay->is_associated)
+    return TRUE;
+
+  n_associated = 0;
+  for (i = 0; i < surfaces->len; i++) {
+    GstVaapiSurface *const surface = g_ptr_array_index (surfaces, i);
+    if (gst_vaapi_surface_associate_subpicture (surface, subpicture,
+            NULL, &overlay->render_rect))
+      n_associated++;
+  }
+
+  overlay->is_associated = TRUE;
+  return n_associated == surfaces->len;
+}
+
+static gboolean
+overlay_rectangle_deassociate (GstVaapiOverlayRectangle * overlay)
+{
+  GstVaapiSubpicture *const subpicture = overlay->subpicture;
+  GPtrArray *const surfaces = overlay->context->surfaces;
+  guint i, n_associated;
+
+  if (!overlay->is_associated)
+    return TRUE;
+
+  n_associated = surfaces->len;
+  for (i = 0; i < surfaces->len; i++) {
+    GstVaapiSurface *const surface = g_ptr_array_index (surfaces, i);
+    if (gst_vaapi_surface_deassociate_subpicture (surface, subpicture))
+      n_associated--;
+  }
+
+  overlay->is_associated = FALSE;
+  return n_associated == 0;
+}
+
+static gboolean
+overlay_rectangle_changed_pixels (GstVaapiOverlayRectangle * overlay,
+    GstVideoOverlayRectangle * rect)
+{
+  guint flags;
+  GstBuffer *buffer;
+
+  if (overlay->seq_num == gst_video_overlay_rectangle_get_seqnum (rect))
+    return FALSE;
+
+  flags =
+      to_GstVideoOverlayFormatFlags (gst_vaapi_subpicture_get_flags
+      (overlay->subpicture));
+
+  buffer = gst_video_overlay_rectangle_get_pixels_unscaled_raw (rect, flags);
+  if (!buffer)
+    return FALSE;
+#if GST_CHECK_VERSION(1,0,0)
+  {
+    const guint n_blocks = gst_buffer_n_memory (buffer);
+    gsize ofs;
+    guint i;
+
+    if (buffer == overlay->rect_buffer)
+      return TRUE;
+
+    if (n_blocks != gst_buffer_n_memory (overlay->rect_buffer))
+      return FALSE;
+
+    for (i = 0; i < n_blocks; i++) {
+      GstMemory *const mem1 = gst_buffer_peek_memory (buffer, i);
+      GstMemory *const mem2 = gst_buffer_peek_memory (overlay->rect_buffer, i);
+      if (!gst_memory_is_span (mem1, mem2, &ofs))
+        return FALSE;
+    }
+  }
+#else
+  if (GST_BUFFER_DATA (overlay->rect_buffer) != GST_BUFFER_DATA (buffer))
+    return FALSE;
+#endif
+  return TRUE;
+}
+
+static gboolean
+overlay_rectangle_changed_render_rect (GstVaapiOverlayRectangle * overlay,
+    GstVideoOverlayRectangle * rect)
+{
+  GstVaapiRectangle *const render_rect = &overlay->render_rect;
+  guint width, height;
+  gint x, y;
+
+  gst_video_overlay_rectangle_get_render_rectangle (rect,
+      &x, &y, &width, &height);
+
+  if (x == render_rect->x &&
+      y == render_rect->y &&
+      width == render_rect->width && height == render_rect->height)
+    return FALSE;
+
+  render_rect->x = x;
+  render_rect->y = y;
+  render_rect->width = width;
+  render_rect->height = height;
+  return TRUE;
+}
+
+static inline gboolean
+overlay_rectangle_update_global_alpha (GstVaapiOverlayRectangle * overlay,
+    GstVideoOverlayRectangle * rect)
+{
+#ifdef HAVE_GST_VIDEO_OVERLAY_HWCAPS
+  const guint flags = gst_video_overlay_rectangle_get_flags (rect);
+  if (!(flags & GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA))
+    return TRUE;
+#endif
+  return gst_vaapi_subpicture_set_global_alpha (overlay->subpicture,
+      gst_video_overlay_rectangle_get_global_alpha (rect));
+}
+
+static gboolean
+overlay_rectangle_update (GstVaapiOverlayRectangle * overlay,
+    GstVideoOverlayRectangle * rect, gboolean * reassociate_ptr)
+{
+  if (overlay_rectangle_changed_pixels (overlay, rect))
+    return FALSE;
+  if (overlay_rectangle_changed_render_rect (overlay, rect))
+    *reassociate_ptr = TRUE;
+  if (!overlay_rectangle_update_global_alpha (overlay, rect))
+    return FALSE;
+  gst_video_overlay_rectangle_replace (&overlay->rect, rect);
+  return TRUE;
+}
+
+static inline GPtrArray *
+overlay_new (void)
+{
+  return g_ptr_array_new_with_free_func (
+      (GDestroyNotify) gst_vaapi_mini_object_unref);
+}
+
+static void
+overlay_destroy (GPtrArray ** overlay_ptr)
+{
+  GPtrArray *const overlay = *overlay_ptr;
+
+  if (!overlay)
+    return;
+  g_ptr_array_unref (overlay);
+  *overlay_ptr = NULL;
+}
+
+static void
+overlay_clear (GPtrArray * overlay)
+{
+  if (overlay && overlay->len > 0)
+    g_ptr_array_remove_range (overlay, 0, overlay->len);
+}
+
+static GstVaapiOverlayRectangle *
+overlay_lookup (GPtrArray * overlays, GstVideoOverlayRectangle * rect)
+{
+  guint i;
+
+  for (i = 0; i < overlays->len; i++) {
+    GstVaapiOverlayRectangle *const overlay = g_ptr_array_index (overlays, i);
+
+    if (overlay->rect == rect)
+      return overlay;
+  }
+  return NULL;
+}
+
+static gboolean
+overlay_reassociate (GPtrArray * overlays)
+{
+  guint i;
+
+  for (i = 0; i < overlays->len; i++)
+    overlay_rectangle_deassociate (g_ptr_array_index (overlays, i));
+
+  for (i = 0; i < overlays->len; i++) {
+    if (!overlay_rectangle_associate (g_ptr_array_index (overlays, i)))
+      return FALSE;
+  }
+  return TRUE;
+}
+
+static gboolean
+overlay_ensure (GPtrArray ** overlay_ptr)
+{
+  GPtrArray *overlay = *overlay_ptr;
+
+  if (!overlay) {
+    overlay = overlay_new ();
+    if (!overlay)
+      return FALSE;
+    *overlay_ptr = overlay;
+  }
+  return TRUE;
+}
+
+/** Initializes overlay resources */
+gboolean
+gst_vaapi_context_overlay_init (GstVaapiContext * context)
+{
+  if (!overlay_ensure (&context->overlays[0]))
+    return FALSE;
+  if (!overlay_ensure (&context->overlays[1]))
+    return FALSE;
+  return TRUE;
+}
+
+/** Destroys overlay resources */
+void
+gst_vaapi_context_overlay_finalize (GstVaapiContext * context)
+{
+  overlay_destroy (&context->overlays[0]);
+  overlay_destroy (&context->overlays[1]);
+}
+
+/** Resets overlay resources to a clean state */
+gboolean
+gst_vaapi_context_overlay_reset (GstVaapiContext * context)
+{
+  guint num_errors = 0;
+
+  if (overlay_ensure (&context->overlays[0]))
+    overlay_clear (context->overlays[0]);
+  else
+    num_errors++;
+
+  if (overlay_ensure (&context->overlays[1]))
+    overlay_clear (context->overlays[1]);
+  else
+    num_errors++;
+
+  context->overlay_id = 0;
+  return num_errors == 0;
+}
+
+/**
+ * gst_vaapi_context_apply_composition:
+ * @context: a #GstVaapiContext
+ * @composition: a #GstVideoOverlayComposition
+ *
+ * Applies video composition planes to all surfaces bound to @context.
+ * This helper function resets any additional subpictures the user may
+ * have associated himself. A %NULL @composition will also clear all
+ * the existing subpictures.
+ *
+ * Return value: %TRUE if all composition planes could be applied,
+ *   %FALSE otherwise
+ */
+gboolean
+gst_vaapi_context_apply_composition (GstVaapiContext * context,
+    GstVideoOverlayComposition * composition)
+{
+  GPtrArray *curr_overlay, *next_overlay;
+  guint i, n_rectangles;
+  gboolean reassociate = FALSE;
+
+  g_return_val_if_fail (context != NULL, FALSE);
+
+  if (!context->surfaces)
+    return FALSE;
+
+  if (!composition) {
+    gst_vaapi_context_overlay_reset (context);
+    return TRUE;
+  }
+
+  curr_overlay = context->overlays[context->overlay_id];
+  next_overlay = context->overlays[context->overlay_id ^ 1];
+  overlay_clear (next_overlay);
+
+  n_rectangles = gst_video_overlay_composition_n_rectangles (composition);
+  for (i = 0; i < n_rectangles; i++) {
+    GstVideoOverlayRectangle *const rect =
+        gst_video_overlay_composition_get_rectangle (composition, i);
+    GstVaapiOverlayRectangle *overlay;
+
+    overlay = overlay_lookup (curr_overlay, rect);
+    if (overlay && overlay_rectangle_update (overlay, rect, &reassociate)) {
+      overlay_rectangle_ref (overlay);
+      if (overlay->layer_id != i)
+        reassociate = TRUE;
+    } else {
+      overlay = overlay_rectangle_new (rect, context, i);
+      if (!overlay) {
+        GST_WARNING ("could not create VA overlay rectangle");
+        goto error;
+      }
+      reassociate = TRUE;
+    }
+    g_ptr_array_add (next_overlay, overlay);
+  }
+
+  overlay_clear (curr_overlay);
+  context->overlay_id ^= 1;
+
+  if (reassociate && !overlay_reassociate (next_overlay))
+    return FALSE;
+  return TRUE;
+
+error:
+  gst_vaapi_context_overlay_reset (context);
+  return FALSE;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapicontext_overlay.h b/gst-libs/gst/vaapi/gstvaapicontext_overlay.h
new file mode 100644
index 0000000..85440e9
--- /dev/null
+++ b/gst-libs/gst/vaapi/gstvaapicontext_overlay.h
@@ -0,0 +1,52 @@
+/*
+ *  gstvaapicontext_overlay.h - VA context abstraction (overlay composition)
+ *
+ *  Copyright (C) 2010-2011 Splitted-Desktop Systems
+ *    Author: Gwenole Beauchesne <gwenole.beauchesne at splitted-desktop.com>
+ *  Copyright (C) 2011-2014 Intel Corporation
+ *    Author: Gwenole Beauchesne <gwenole.beauchesne at intel.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_CONTEXT_OVERLAY_H
+#define GST_VAAPI_CONTEXT_OVERLAY_H
+
+#include <gst/video/video-overlay-composition.h>
+#include "gstvaapicontext.h"
+
+G_BEGIN_DECLS
+
+G_GNUC_INTERNAL
+gboolean
+gst_vaapi_context_overlay_init (GstVaapiContext * context);
+
+G_GNUC_INTERNAL
+void
+gst_vaapi_context_overlay_finalize (GstVaapiContext * context);
+
+G_GNUC_INTERNAL
+gboolean
+gst_vaapi_context_overlay_reset (GstVaapiContext * context);
+
+G_GNUC_INTERNAL
+gboolean
+gst_vaapi_context_apply_composition (GstVaapiContext * context,
+    GstVideoOverlayComposition * composition);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_CONTEXT_OVERLAY_H */
diff --git a/gst-libs/gst/vaapi/gstvaapisurface.c b/gst-libs/gst/vaapi/gstvaapisurface.c
index 40745ba..ba848cb 100644
--- a/gst-libs/gst/vaapi/gstvaapisurface.c
+++ b/gst-libs/gst/vaapi/gstvaapisurface.c
@@ -35,6 +35,7 @@
 #include "gstvaapicontext.h"
 #include "gstvaapiimage.h"
 #include "gstvaapiimage_priv.h"
+#include "gstvaapicontext_overlay.h"
 
 #define DEBUG 1
 #include "gstvaapidebug.h"

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-gstreamer/gstreamer-vaapi.git



More information about the Pkg-gstreamer-commits mailing list