gl/overlaycompositor: add support for flipping the output
authorMatthew Waters <matthew@centricular.com>
Thu, 27 Sep 2018 03:31:09 +0000 (13:31 +1000)
committerMatthew Waters <matthew@centricular.com>
Thu, 4 Oct 2018 04:28:35 +0000 (14:28 +1000)
This is required to use gloverlaycompositor outside of glimagesink where
the output is not automatically flipped

gst-libs/gst/gl/gstgloverlaycompositor.c

index bb6dc16..61f342a 100644 (file)
@@ -91,6 +91,8 @@ struct _GstGLCompositionOverlay
   GLuint texture_id;
   GstGLMemory *gl_memory;
   GstVideoOverlayRectangle *rectangle;
+
+  gboolean yinvert;
 };
 
 struct _GstGLCompositionOverlayClass
@@ -247,6 +249,7 @@ gst_gl_composition_overlay_add_transformation (GstGLCompositionOverlay *
   guint comp_width, comp_height;
   GstVideoMeta *meta;
   guint width, height;
+  gfloat yswap;
 
   float rel_x, rel_y, rel_w, rel_h;
 
@@ -268,24 +271,27 @@ gst_gl_composition_overlay_add_transformation (GstGLCompositionOverlay *
   /* transform from [0,1] to [-1,1], invert y axis */
   rel_x = rel_x * 2.0 - 1.0;
   rel_y = (1.0 - rel_y) * 2.0 - 1.0;
+
   rel_w = rel_w * 2.0;
   rel_h = rel_h * 2.0;
 
+  yswap = overlay->yinvert ? -1. : 1.;
+
   /* initialize position array */
   overlay->positions[0] = rel_x + rel_w;
-  overlay->positions[1] = rel_y;
+  overlay->positions[1] = rel_y * yswap;
   overlay->positions[2] = 0.0;
   overlay->positions[3] = 1.0;
   overlay->positions[4] = rel_x;
-  overlay->positions[5] = rel_y;
+  overlay->positions[5] = rel_y * yswap;
   overlay->positions[6] = 0.0;
   overlay->positions[7] = 1.0;
   overlay->positions[8] = rel_x;
-  overlay->positions[9] = rel_y - rel_h;
+  overlay->positions[9] = (rel_y - rel_h) * yswap;
   overlay->positions[10] = 0.0;
   overlay->positions[11] = 1.0;
   overlay->positions[12] = rel_x + rel_w;
-  overlay->positions[13] = rel_y - rel_h;
+  overlay->positions[13] = (rel_y - rel_h) * yswap;
   overlay->positions[14] = 0.0;
   overlay->positions[15] = 1.0;
 
@@ -417,6 +423,16 @@ gst_gl_composition_overlay_draw (GstGLCompositionOverlay * overlay,
   gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
 }
 
+typedef struct
+{
+  gboolean yinvert;
+} GstGLOverlayCompositorPrivate;
+
+enum
+{
+  PROP_0,
+  PROP_YINVERT,
+};
 
 /********************************************************************
  * GstGLOverlayCompositor object, the public helper object to render
@@ -427,10 +443,20 @@ gst_gl_composition_overlay_draw (GstGLCompositionOverlay * overlay,
   GST_DEBUG_CATEGORY_INIT (gst_gl_overlay_compositor_debug, \
       "gloverlaycompositor", 0, "overlaycompositor");
 
+/* this matches what glimagesink does as this was publicized before being used
+ * in other elements that draw in different orientations */
+#define DEFAULT_YINVERT                 FALSE
+
 G_DEFINE_TYPE_WITH_CODE (GstGLOverlayCompositor, gst_gl_overlay_compositor,
-    GST_TYPE_OBJECT, DEBUG_INIT);
+    GST_TYPE_OBJECT, G_ADD_PRIVATE (GstGLOverlayCompositor);
+    DEBUG_INIT);
 
 static void gst_gl_overlay_compositor_finalize (GObject * object);
+static void gst_gl_overlay_compositor_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_gl_overlay_compositor_get_property (GObject * object,
+    guint prop_id, GValue * value, GParamSpec * pspec);
+
 static gboolean _is_rectangle_in_overlays (GList * overlays,
     GstVideoOverlayRectangle * rectangle);
 static gboolean _is_overlay_in_rectangles (GstVideoOverlayComposition *
@@ -439,12 +465,63 @@ static gboolean _is_overlay_in_rectangles (GstVideoOverlayComposition *
 static void
 gst_gl_overlay_compositor_class_init (GstGLOverlayCompositorClass * klass)
 {
-  G_OBJECT_CLASS (klass)->finalize = gst_gl_overlay_compositor_finalize;
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->finalize = gst_gl_overlay_compositor_finalize;
+  gobject_class->set_property = gst_gl_overlay_compositor_set_property;
+  gobject_class->get_property = gst_gl_overlay_compositor_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_YINVERT,
+      g_param_spec_boolean ("yinvert",
+          "Y-Invert",
+          "Whether to invert the output across a horizintal axis",
+          DEFAULT_YINVERT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 }
 
 static void
 gst_gl_overlay_compositor_init (GstGLOverlayCompositor * compositor)
 {
+  GstGLOverlayCompositorPrivate *priv =
+      gst_gl_overlay_compositor_get_instance_private (compositor);
+
+  priv->yinvert = DEFAULT_YINVERT;
+}
+
+static void
+gst_gl_overlay_compositor_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstGLOverlayCompositor *self = GST_GL_OVERLAY_COMPOSITOR (object);
+  GstGLOverlayCompositorPrivate *priv =
+      gst_gl_overlay_compositor_get_instance_private (self);
+
+  switch (prop_id) {
+    case PROP_YINVERT:
+      /* XXX: invalidiate all current rectangles on a change */
+      priv->yinvert = g_value_get_boolean (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_gl_overlay_compositor_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstGLOverlayCompositor *self = GST_GL_OVERLAY_COMPOSITOR (object);
+  GstGLOverlayCompositorPrivate *priv =
+      gst_gl_overlay_compositor_get_instance_private (self);
+
+  switch (prop_id) {
+    case PROP_YINVERT:
+      g_value_set_boolean (value, priv->yinvert);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
 }
 
 static void
@@ -540,7 +617,6 @@ _is_overlay_in_rectangles (GstVideoOverlayComposition * composition,
   return FALSE;
 }
 
-
 void
 gst_gl_overlay_compositor_free_overlays (GstGLOverlayCompositor * compositor)
 {
@@ -561,6 +637,8 @@ gst_gl_overlay_compositor_upload_overlays (GstGLOverlayCompositor * compositor,
     GstBuffer * buf)
 {
   GstVideoOverlayCompositionMeta *composition_meta;
+  GstGLOverlayCompositorPrivate *priv =
+      gst_gl_overlay_compositor_get_instance_private (compositor);
 
   composition_meta = gst_buffer_get_video_overlay_composition_meta (buf);
   if (composition_meta) {
@@ -583,6 +661,7 @@ gst_gl_overlay_compositor_upload_overlays (GstGLOverlayCompositor * compositor,
             gst_gl_composition_overlay_new (compositor->context, rectangle,
             compositor->position_attrib, compositor->texcoord_attrib);
         gst_object_ref_sink (overlay);
+        overlay->yinvert = priv->yinvert;
 
         gst_gl_composition_overlay_upload (overlay, buf);