mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-19 20:46:22 +00:00
gtkglsink: Add overlay composition support
Rendering composition overlay in GL with additional high resolution overlay being added.
This commit is contained in:
parent
cf44f5013a
commit
aaf14659c1
3 changed files with 93 additions and 0 deletions
|
@ -38,6 +38,8 @@ static gboolean gst_gtk_gl_sink_stop (GstBaseSink * bsink);
|
||||||
static gboolean gst_gtk_gl_sink_query (GstBaseSink * bsink, GstQuery * query);
|
static gboolean gst_gtk_gl_sink_query (GstBaseSink * bsink, GstQuery * query);
|
||||||
static gboolean gst_gtk_gl_sink_propose_allocation (GstBaseSink * bsink,
|
static gboolean gst_gtk_gl_sink_propose_allocation (GstBaseSink * bsink,
|
||||||
GstQuery * query);
|
GstQuery * query);
|
||||||
|
static GstCaps *gst_gtk_gl_sink_get_caps (GstBaseSink * bsink,
|
||||||
|
GstCaps * filter);
|
||||||
|
|
||||||
static GstStaticPadTemplate gst_gtk_gl_sink_template =
|
static GstStaticPadTemplate gst_gtk_gl_sink_template =
|
||||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
@ -66,6 +68,7 @@ gst_gtk_gl_sink_class_init (GstGtkGLSinkClass * klass)
|
||||||
gstbasesink_class->propose_allocation = gst_gtk_gl_sink_propose_allocation;
|
gstbasesink_class->propose_allocation = gst_gtk_gl_sink_propose_allocation;
|
||||||
gstbasesink_class->start = gst_gtk_gl_sink_start;
|
gstbasesink_class->start = gst_gtk_gl_sink_start;
|
||||||
gstbasesink_class->stop = gst_gtk_gl_sink_stop;
|
gstbasesink_class->stop = gst_gtk_gl_sink_stop;
|
||||||
|
gstbasesink_class->get_caps = gst_gtk_gl_sink_get_caps;
|
||||||
|
|
||||||
gstgtkbasesink_class->create_widget = gtk_gst_gl_widget_new;
|
gstgtkbasesink_class->create_widget = gtk_gst_gl_widget_new;
|
||||||
gstgtkbasesink_class->window_title = "Gtk+ GL renderer";
|
gstgtkbasesink_class->window_title = "Gtk+ GL renderer";
|
||||||
|
@ -133,6 +136,31 @@ gst_gtk_gl_sink_query (GstBaseSink * bsink, GstQuery * query)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_size_changed_cb (GtkWidget * widget, GdkRectangle * rectangle,
|
||||||
|
GstGtkGLSink * gtk_sink)
|
||||||
|
{
|
||||||
|
gint scale_factor, width, height;
|
||||||
|
gboolean reconfigure;
|
||||||
|
|
||||||
|
scale_factor = gtk_widget_get_scale_factor (widget);
|
||||||
|
width = scale_factor * gtk_widget_get_allocated_width (widget);
|
||||||
|
height = scale_factor * gtk_widget_get_allocated_height (widget);
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (gtk_sink);
|
||||||
|
reconfigure =
|
||||||
|
(width != gtk_sink->display_width || height != gtk_sink->display_height);
|
||||||
|
gtk_sink->display_width = width;
|
||||||
|
gtk_sink->display_height = height;
|
||||||
|
GST_OBJECT_UNLOCK (gtk_sink);
|
||||||
|
|
||||||
|
if (reconfigure) {
|
||||||
|
GST_DEBUG_OBJECT (gtk_sink, "Sending reconfigure event on sinkpad.");
|
||||||
|
gst_pad_push_event (GST_BASE_SINK (gtk_sink)->sinkpad,
|
||||||
|
gst_event_new_reconfigure ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_gtk_gl_sink_start (GstBaseSink * bsink)
|
gst_gtk_gl_sink_start (GstBaseSink * bsink)
|
||||||
{
|
{
|
||||||
|
@ -146,6 +174,11 @@ gst_gtk_gl_sink_start (GstBaseSink * bsink)
|
||||||
/* After this point, gtk_sink->widget will always be set */
|
/* After this point, gtk_sink->widget will always be set */
|
||||||
gst_widget = GTK_GST_GL_WIDGET (base_sink->widget);
|
gst_widget = GTK_GST_GL_WIDGET (base_sink->widget);
|
||||||
|
|
||||||
|
/* Track the allocation size */
|
||||||
|
g_signal_connect (gst_widget, "size-allocate", G_CALLBACK (_size_changed_cb),
|
||||||
|
gtk_sink);
|
||||||
|
_size_changed_cb (GTK_WIDGET (gst_widget), NULL, gtk_sink);
|
||||||
|
|
||||||
if (!gtk_gst_gl_widget_init_winsys (gst_widget))
|
if (!gtk_gst_gl_widget_init_winsys (gst_widget))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -191,6 +224,8 @@ gst_gtk_gl_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
guint size;
|
guint size;
|
||||||
gboolean need_pool;
|
gboolean need_pool;
|
||||||
|
GstStructure *allocation_meta = NULL;
|
||||||
|
gint display_width, display_height;
|
||||||
|
|
||||||
if (!gtk_sink->display || !gtk_sink->context)
|
if (!gtk_sink->display || !gtk_sink->context)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -222,6 +257,25 @@ gst_gtk_gl_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
|
||||||
gst_object_unref (pool);
|
gst_object_unref (pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (gtk_sink);
|
||||||
|
display_width = gtk_sink->display_width;
|
||||||
|
display_height = gtk_sink->display_height;
|
||||||
|
GST_OBJECT_UNLOCK (gtk_sink);
|
||||||
|
|
||||||
|
if (display_width != 0 && display_height != 0) {
|
||||||
|
GST_DEBUG_OBJECT (gtk_sink, "sending alloc query with size %dx%d",
|
||||||
|
display_width, display_height);
|
||||||
|
allocation_meta = gst_structure_new ("GstVideoOverlayCompositionMeta",
|
||||||
|
"width", G_TYPE_UINT, display_width,
|
||||||
|
"height", G_TYPE_UINT, display_height, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_query_add_allocation_meta (query,
|
||||||
|
GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, allocation_meta);
|
||||||
|
|
||||||
|
if (allocation_meta)
|
||||||
|
gst_structure_free (allocation_meta);
|
||||||
|
|
||||||
/* we also support various metadata */
|
/* we also support various metadata */
|
||||||
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0);
|
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0);
|
||||||
|
|
||||||
|
@ -247,3 +301,28 @@ config_failed:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstCaps *
|
||||||
|
gst_gtk_gl_sink_get_caps (GstBaseSink * bsink, GstCaps * filter)
|
||||||
|
{
|
||||||
|
GstCaps *tmp = NULL;
|
||||||
|
GstCaps *result = NULL;
|
||||||
|
|
||||||
|
tmp = gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD (bsink));
|
||||||
|
|
||||||
|
if (filter) {
|
||||||
|
GST_DEBUG_OBJECT (bsink, "intersecting with filter caps %" GST_PTR_FORMAT,
|
||||||
|
filter);
|
||||||
|
|
||||||
|
result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
|
||||||
|
gst_caps_unref (tmp);
|
||||||
|
} else {
|
||||||
|
result = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = gst_gl_overlay_compositor_add_caps (result);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (bsink, "returning caps: %" GST_PTR_FORMAT, result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -60,6 +60,10 @@ struct _GstGtkGLSink
|
||||||
|
|
||||||
GstGLUpload *upload;
|
GstGLUpload *upload;
|
||||||
GstBuffer *uploaded_buffer;
|
GstBuffer *uploaded_buffer;
|
||||||
|
|
||||||
|
/* read/write with object lock */
|
||||||
|
gint display_width;
|
||||||
|
gint display_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -71,6 +71,7 @@ struct _GtkGstGLWidgetPrivate
|
||||||
GLint attr_position;
|
GLint attr_position;
|
||||||
GLint attr_texture;
|
GLint attr_texture;
|
||||||
GLuint current_tex;
|
GLuint current_tex;
|
||||||
|
GstGLOverlayCompositor *overlay_compositor;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const GLfloat vertices[] = {
|
static const GLfloat vertices[] = {
|
||||||
|
@ -140,6 +141,9 @@ gtk_gst_gl_widget_init_redisplay (GtkGstGLWidget * gst_widget)
|
||||||
|
|
||||||
gl->BindBuffer (GL_ARRAY_BUFFER, 0);
|
gl->BindBuffer (GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
priv->overlay_compositor =
|
||||||
|
gst_gl_overlay_compositor_new (priv->other_context);
|
||||||
|
|
||||||
priv->initted = TRUE;
|
priv->initted = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,6 +241,8 @@ gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_gl_overlay_compositor_upload_overlays (priv->overlay_compositor,
|
||||||
|
buffer);
|
||||||
|
|
||||||
sync_meta = gst_buffer_get_gl_sync_meta (buffer);
|
sync_meta = gst_buffer_get_gl_sync_meta (buffer);
|
||||||
if (sync_meta) {
|
if (sync_meta) {
|
||||||
|
@ -260,6 +266,7 @@ gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context)
|
||||||
base_widget->buffer, context);
|
base_widget->buffer, context);
|
||||||
|
|
||||||
_redraw_texture (GTK_GST_GL_WIDGET (widget), priv->current_tex);
|
_redraw_texture (GTK_GST_GL_WIDGET (widget), priv->current_tex);
|
||||||
|
gst_gl_overlay_compositor_draw_overlays (priv->overlay_compositor);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (priv->other_context)
|
if (priv->other_context)
|
||||||
|
@ -350,6 +357,9 @@ _reset_gl (GtkGstGLWidget * gst_widget)
|
||||||
priv->shader = NULL;
|
priv->shader = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->overlay_compositor)
|
||||||
|
gst_object_unref (priv->overlay_compositor);
|
||||||
|
|
||||||
gst_gl_context_activate (priv->other_context, FALSE);
|
gst_gl_context_activate (priv->other_context, FALSE);
|
||||||
|
|
||||||
gst_object_unref (priv->other_context);
|
gst_object_unref (priv->other_context);
|
||||||
|
|
Loading…
Reference in a new issue