GLuint texture_id;
GstGLMemory *gl_memory;
GstVideoOverlayRectangle *rectangle;
+
+ gboolean yinvert;
};
struct _GstGLCompositionOverlayClass
guint comp_width, comp_height;
GstVideoMeta *meta;
guint width, height;
+ gfloat yswap;
float rel_x, rel_y, rel_w, rel_h;
/* 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;
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
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 *
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
return FALSE;
}
-
void
gst_gl_overlay_compositor_free_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) {
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);