mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-28 20:51:13 +00:00
gl/overlaycompositor: add support for flipping the output
This is required to use gloverlaycompositor outside of glimagesink where the output is not automatically flipped
This commit is contained in:
parent
1359d0995e
commit
e9c519e5f3
1 changed files with 86 additions and 7 deletions
|
@ -91,6 +91,8 @@ struct _GstGLCompositionOverlay
|
||||||
GLuint texture_id;
|
GLuint texture_id;
|
||||||
GstGLMemory *gl_memory;
|
GstGLMemory *gl_memory;
|
||||||
GstVideoOverlayRectangle *rectangle;
|
GstVideoOverlayRectangle *rectangle;
|
||||||
|
|
||||||
|
gboolean yinvert;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstGLCompositionOverlayClass
|
struct _GstGLCompositionOverlayClass
|
||||||
|
@ -247,6 +249,7 @@ gst_gl_composition_overlay_add_transformation (GstGLCompositionOverlay *
|
||||||
guint comp_width, comp_height;
|
guint comp_width, comp_height;
|
||||||
GstVideoMeta *meta;
|
GstVideoMeta *meta;
|
||||||
guint width, height;
|
guint width, height;
|
||||||
|
gfloat yswap;
|
||||||
|
|
||||||
float rel_x, rel_y, rel_w, rel_h;
|
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 */
|
/* transform from [0,1] to [-1,1], invert y axis */
|
||||||
rel_x = rel_x * 2.0 - 1.0;
|
rel_x = rel_x * 2.0 - 1.0;
|
||||||
rel_y = (1.0 - rel_y) * 2.0 - 1.0;
|
rel_y = (1.0 - rel_y) * 2.0 - 1.0;
|
||||||
|
|
||||||
rel_w = rel_w * 2.0;
|
rel_w = rel_w * 2.0;
|
||||||
rel_h = rel_h * 2.0;
|
rel_h = rel_h * 2.0;
|
||||||
|
|
||||||
|
yswap = overlay->yinvert ? -1. : 1.;
|
||||||
|
|
||||||
/* initialize position array */
|
/* initialize position array */
|
||||||
overlay->positions[0] = rel_x + rel_w;
|
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[2] = 0.0;
|
||||||
overlay->positions[3] = 1.0;
|
overlay->positions[3] = 1.0;
|
||||||
overlay->positions[4] = rel_x;
|
overlay->positions[4] = rel_x;
|
||||||
overlay->positions[5] = rel_y;
|
overlay->positions[5] = rel_y * yswap;
|
||||||
overlay->positions[6] = 0.0;
|
overlay->positions[6] = 0.0;
|
||||||
overlay->positions[7] = 1.0;
|
overlay->positions[7] = 1.0;
|
||||||
overlay->positions[8] = rel_x;
|
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[10] = 0.0;
|
||||||
overlay->positions[11] = 1.0;
|
overlay->positions[11] = 1.0;
|
||||||
overlay->positions[12] = rel_x + rel_w;
|
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[14] = 0.0;
|
||||||
overlay->positions[15] = 1.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);
|
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
|
* 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, \
|
GST_DEBUG_CATEGORY_INIT (gst_gl_overlay_compositor_debug, \
|
||||||
"gloverlaycompositor", 0, "overlaycompositor");
|
"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,
|
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_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,
|
static gboolean _is_rectangle_in_overlays (GList * overlays,
|
||||||
GstVideoOverlayRectangle * rectangle);
|
GstVideoOverlayRectangle * rectangle);
|
||||||
static gboolean _is_overlay_in_rectangles (GstVideoOverlayComposition *
|
static gboolean _is_overlay_in_rectangles (GstVideoOverlayComposition *
|
||||||
|
@ -439,12 +465,63 @@ static gboolean _is_overlay_in_rectangles (GstVideoOverlayComposition *
|
||||||
static void
|
static void
|
||||||
gst_gl_overlay_compositor_class_init (GstGLOverlayCompositorClass * klass)
|
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
|
static void
|
||||||
gst_gl_overlay_compositor_init (GstGLOverlayCompositor * compositor)
|
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
|
static void
|
||||||
|
@ -540,7 +617,6 @@ _is_overlay_in_rectangles (GstVideoOverlayComposition * composition,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
gst_gl_overlay_compositor_free_overlays (GstGLOverlayCompositor * compositor)
|
gst_gl_overlay_compositor_free_overlays (GstGLOverlayCompositor * compositor)
|
||||||
{
|
{
|
||||||
|
@ -561,6 +637,8 @@ gst_gl_overlay_compositor_upload_overlays (GstGLOverlayCompositor * compositor,
|
||||||
GstBuffer * buf)
|
GstBuffer * buf)
|
||||||
{
|
{
|
||||||
GstVideoOverlayCompositionMeta *composition_meta;
|
GstVideoOverlayCompositionMeta *composition_meta;
|
||||||
|
GstGLOverlayCompositorPrivate *priv =
|
||||||
|
gst_gl_overlay_compositor_get_instance_private (compositor);
|
||||||
|
|
||||||
composition_meta = gst_buffer_get_video_overlay_composition_meta (buf);
|
composition_meta = gst_buffer_get_video_overlay_composition_meta (buf);
|
||||||
if (composition_meta) {
|
if (composition_meta) {
|
||||||
|
@ -583,6 +661,7 @@ gst_gl_overlay_compositor_upload_overlays (GstGLOverlayCompositor * compositor,
|
||||||
gst_gl_composition_overlay_new (compositor->context, rectangle,
|
gst_gl_composition_overlay_new (compositor->context, rectangle,
|
||||||
compositor->position_attrib, compositor->texcoord_attrib);
|
compositor->position_attrib, compositor->texcoord_attrib);
|
||||||
gst_object_ref_sink (overlay);
|
gst_object_ref_sink (overlay);
|
||||||
|
overlay->yinvert = priv->yinvert;
|
||||||
|
|
||||||
gst_gl_composition_overlay_upload (overlay, buf);
|
gst_gl_composition_overlay_upload (overlay, buf);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue