gloverlaycompositor: Add GstGLOverlayCompositor class
authorLubosz Sarnecki <lubosz.sarnecki@collabora.co.uk>
Tue, 30 Jun 2015 15:59:12 +0000 (17:59 +0200)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:32:06 +0000 (19:32 +0000)
Manages the GstGLCompositionOverlay objects,
caches already uploaded overlays and draws them.

https://bugzilla.gnome.org/show_bug.cgi?id=745107

gst-libs/gst/gl/Makefile.am
gst-libs/gst/gl/gl.h
gst-libs/gst/gl/gstgl_fwd.h
gst-libs/gst/gl/gstgloverlaycompositor.c [new file with mode: 0644]
gst-libs/gst/gl/gstgloverlaycompositor.h [new file with mode: 0644]

index 942638f..b6aab1d 100644 (file)
@@ -29,7 +29,8 @@ libgstgl_@GST_API_VERSION@_la_SOURCES = \
         gstglframebuffer.c \
         gstglsyncmeta.c \
         gstglviewconvert.c \
-        gstglcompositionoverlay.c
+        gstglcompositionoverlay.c \
+        gstgloverlaycompositor.c
 
 libgstgl_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/gl
 libgstgl_@GST_API_VERSION@include_HEADERS = \
@@ -54,6 +55,7 @@ libgstgl_@GST_API_VERSION@include_HEADERS = \
        gstglsyncmeta.h \
        gstglviewconvert.h \
        gstglcompositionoverlay.h \
+       gstgloverlaycompositor.c \
        gstgl_fwd.h \
        gl.h
 
index d6dcb51..4b1e8ef 100644 (file)
@@ -48,5 +48,6 @@
 #include <gst/gl/gstglfilter.h>
 #include <gst/gl/gstglshadervariables.h>
 #include <gst/gl/gstglsyncmeta.h>
+#include <gst/gl/gstgloverlaycompositor.h>
 
 #endif /* __GST_GL_H__ */
index 7c2bd34..aac40b7 100644 (file)
@@ -81,6 +81,9 @@ typedef struct _GstGLViewConvertPrivate GstGLViewConvertPrivate;
 typedef struct _GstGLCompositionOverlay GstGLCompositionOverlay;
 typedef struct _GstGLCompositionOverlayClass GstGLCompositionOverlayClass;
 
+typedef struct _GstGLOverlayCompositor GstGLOverlayCompositor;
+typedef struct _GstGLOverlayCompositorClass GstGLOverlayCompositorClass;
+
 G_END_DECLS
 
 #endif /* __GST_GL_FWD_H__ */
diff --git a/gst-libs/gst/gl/gstgloverlaycompositor.c b/gst-libs/gst/gl/gstgloverlaycompositor.c
new file mode 100644 (file)
index 0000000..4fd9be9
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * GStreamer
+ * Copyright (C) 2015 Lubosz Sarnecki <lubosz.sarnecki@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "gl.h"
+#include "gstgloverlaycompositor.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_gl_overlay_compositor_debug);
+#define GST_CAT_DEFAULT gst_gl_overlay_compositor_debug
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_gl_overlay_compositor_debug, \
+      "gloverlaycompositor", 0, "overlaycompositor");
+
+G_DEFINE_TYPE_WITH_CODE (GstGLOverlayCompositor, gst_gl_overlay_compositor,
+    GST_TYPE_OBJECT, DEBUG_INIT);
+
+static void gst_gl_overlay_compositor_finalize (GObject * object);
+static gboolean _is_rectangle_in_overlays (GList * overlays,
+    GstVideoOverlayRectangle * rectangle);
+static gboolean _is_overlay_in_rectangles (GstVideoOverlayComposition *
+    composition, GstGLCompositionOverlay * overlay);
+
+static void
+gst_gl_overlay_compositor_class_init (GstGLOverlayCompositorClass * klass)
+{
+  G_OBJECT_CLASS (klass)->finalize = gst_gl_overlay_compositor_finalize;
+}
+
+static void
+gst_gl_overlay_compositor_init (GstGLOverlayCompositor * compositor)
+{
+}
+
+GstGLOverlayCompositor *
+gst_gl_overlay_compositor_new (GstGLContext * context)
+{
+  GstGLOverlayCompositor *compositor =
+      g_object_new (GST_TYPE_GL_OVERLAY_COMPOSITOR, NULL);
+
+  compositor->context = gst_object_ref (context);
+
+  GST_DEBUG_OBJECT (compositor, "Created new GstGLOverlayCompositor");
+
+  return compositor;
+}
+
+static void
+gst_gl_overlay_compositor_finalize (GObject * object)
+{
+  GstGLOverlayCompositor *compositor;
+
+  compositor = GST_GL_OVERLAY_COMPOSITOR (object);
+
+  gst_gl_overlay_compositor_free_overlays (compositor);
+
+  if (compositor->context)
+    gst_object_unref (compositor->context);
+
+  G_OBJECT_CLASS (gst_gl_overlay_compositor_parent_class)->finalize (object);
+}
+
+static gboolean
+_is_rectangle_in_overlays (GList * overlays,
+    GstVideoOverlayRectangle * rectangle)
+{
+  for (GList * l = overlays; l != NULL; l = l->next) {
+    GstGLCompositionOverlay *overlay = (GstGLCompositionOverlay *) l->data;
+    if (overlay->rectangle == rectangle)
+      return TRUE;
+  }
+  return FALSE;
+}
+
+static gboolean
+_is_overlay_in_rectangles (GstVideoOverlayComposition * composition,
+    GstGLCompositionOverlay * overlay)
+{
+  for (guint i = 0;
+      i < gst_video_overlay_composition_n_rectangles (composition); i++) {
+    GstVideoOverlayRectangle *rectangle =
+        gst_video_overlay_composition_get_rectangle (composition, i);
+    if (overlay->rectangle == rectangle)
+      return TRUE;
+  }
+  return FALSE;
+}
+
+
+void
+gst_gl_overlay_compositor_free_overlays (GstGLOverlayCompositor * compositor)
+{
+  GList *l = compositor->overlays;
+  while (l != NULL) {
+    GList *next = l->next;
+    GstGLCompositionOverlay *overlay = (GstGLCompositionOverlay *) l->data;
+    compositor->overlays = g_list_delete_link (compositor->overlays, l);
+    gst_object_unref (overlay);
+    l = next;
+  }
+  g_list_free (compositor->overlays);
+  compositor->overlays = NULL;
+}
+
+void
+gst_gl_overlay_compositor_upload_overlays (GstGLOverlayCompositor * compositor,
+    GstBuffer * buf, GLint position_attrib, GLint texcoord_attrib,
+    guint window_width, guint window_height)
+{
+  GstVideoOverlayCompositionMeta *composition_meta;
+
+  if (compositor->last_window_width != window_width ||
+      compositor->last_window_height != window_height) {
+    gst_gl_overlay_compositor_free_overlays (compositor);
+    compositor->last_window_width = window_width;
+    compositor->last_window_height = window_height;
+    GST_DEBUG ("window size changed, freeing overlays");
+  }
+
+  composition_meta = gst_buffer_get_video_overlay_composition_meta (buf);
+  if (composition_meta) {
+    GstVideoOverlayComposition *composition = NULL;
+    guint num_overlays;
+    GList *l = compositor->overlays;
+
+    GST_DEBUG ("GstVideoOverlayCompositionMeta found.");
+
+    composition = composition_meta->overlay;
+    num_overlays = gst_video_overlay_composition_n_rectangles (composition);
+
+    /* add new overlays to list */
+    for (guint i = 0; i < num_overlays; i++) {
+      GstVideoOverlayRectangle *rectangle =
+          gst_video_overlay_composition_get_rectangle (composition, i);
+
+      if (!_is_rectangle_in_overlays (compositor->overlays, rectangle)) {
+        GstGLCompositionOverlay *overlay =
+            gst_gl_composition_overlay_new (compositor->context, rectangle,
+            position_attrib, texcoord_attrib);
+
+        gst_gl_composition_overlay_upload (overlay, buf,
+            window_width, window_height);
+        compositor->overlays = g_list_append (compositor->overlays, overlay);
+      }
+    }
+
+    /* remove old overlays from list */
+    while (l != NULL) {
+      GList *next = l->next;
+      GstGLCompositionOverlay *overlay = (GstGLCompositionOverlay *) l->data;
+      if (!_is_overlay_in_rectangles (composition, overlay)) {
+        compositor->overlays = g_list_delete_link (compositor->overlays, l);
+        gst_object_unref (overlay);
+      }
+      l = next;
+    }
+  } else {
+    gst_gl_overlay_compositor_free_overlays (compositor);
+  }
+}
+
+void
+gst_gl_overlay_compositor_draw_overlays (GstGLOverlayCompositor * compositor,
+    GstGLShader * shader)
+{
+  const GstGLFuncs *gl = compositor->context->gl_vtable;
+  if (compositor->overlays != NULL) {
+    glEnable (GL_BLEND);
+    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    for (GList * l = compositor->overlays; l != NULL; l = l->next) {
+      GstGLCompositionOverlay *overlay = (GstGLCompositionOverlay *) l->data;
+      gst_gl_composition_overlay_draw (overlay, shader);
+    }
+    gl->BindTexture (GL_TEXTURE_2D, 0);
+  }
+}
+
+GstCaps *
+gst_gl_overlay_compositor_add_caps (GstCaps * caps)
+{
+  GstCaps *composition_caps;
+
+  composition_caps = gst_caps_copy (caps);
+
+  for (int i = 0; i < gst_caps_get_size (composition_caps); i++) {
+    GstCapsFeatures *f = gst_caps_get_features (composition_caps, i);
+    gst_caps_features_add (f,
+        GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION);
+  }
+
+  caps = gst_caps_merge (composition_caps, caps);
+
+  return caps;
+}
diff --git a/gst-libs/gst/gl/gstgloverlaycompositor.h b/gst-libs/gst/gl/gstgloverlaycompositor.h
new file mode 100644 (file)
index 0000000..c0675b4
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * GStreamer
+ * Copyright (C) 2015 Lubosz Sarnecki <lubosz.sarnecki@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_GL_OVERLAY_COMPOSITOR_H__
+#define __GST_GL_OVERLAY_COMPOSITOR_H__
+
+#include <gst/video/video.h>
+#include <gst/gl/gstglcompositionoverlay.h>
+#include <gst/gl/gstgl_fwd.h>
+
+#define GST_TYPE_GL_OVERLAY_COMPOSITOR (gst_gl_overlay_compositor_get_type())
+#define GST_GL_OVERLAY_COMPOSITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_OVERLAY_COMPOSITOR,GstGLOverlayCompositor))
+#define GST_GL_OVERLAY_COMPOSITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GL_OVERLAY_COMPOSITOR,GstGLOverlayCompositorClass))
+#define GST_IS_GL_OVERLAY_COMPOSITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_OVERLAY_COMPOSITOR))
+#define GST_IS_GL_OVERLAY_COMPOSITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GL_OVERLAY_COMPOSITOR))
+#define GST_GL_OVERLAY_COMPOSITOR_CAST(obj) ((GstGLOverlayCompositor*)(obj))
+
+G_BEGIN_DECLS
+
+GType gst_gl_overlay_compositor_get_type (void);
+
+/**
+ * GstGLOverlayCompositor
+ *
+ * Opaque #GstGLOverlayCompositor object
+ */
+struct _GstGLOverlayCompositor
+{
+  GstObject parent;
+  GstGLContext *context;
+  guint last_window_width;
+  guint last_window_height;
+
+  GList * overlays;
+};
+
+/**
+ * GstGLOverlayCompositorClass:
+ *
+ */
+struct _GstGLOverlayCompositorClass
+{
+  GstObjectClass object_class;
+};
+
+GstGLOverlayCompositor *gst_gl_overlay_compositor_new (GstGLContext * context);
+
+void gst_gl_overlay_compositor_free_overlays (GstGLOverlayCompositor * compositor);
+
+void gst_gl_overlay_compositor_upload_overlays (GstGLOverlayCompositor * compositor,
+    GstBuffer * buf, GLint position_attrib, GLint texcoord_attrib,
+    guint window_width, guint window_height);
+
+void gst_gl_overlay_compositor_draw_overlays (GstGLOverlayCompositor * compositor,
+  GstGLShader *shader);
+
+GstCaps * gst_gl_overlay_compositor_add_caps(GstCaps * caps);
+
+G_END_DECLS
+#endif /* __GST_GL_OVERLAY_COMPOSITOR_H__ */