From 74486ab7e17385655d4fa01367afe661a1cb9d93 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Sat, 15 Aug 2015 15:12:27 +0200 Subject: gtkglsink: Add overlay composition support Rendering composition overlay in GL with additional high resolution overlay being added. --- ext/gtk/gstgtkglsink.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ ext/gtk/gstgtkglsink.h | 4 +++ ext/gtk/gtkgstglwidget.c | 10 ++++++ 3 files changed, 93 insertions(+) diff --git a/ext/gtk/gstgtkglsink.c b/ext/gtk/gstgtkglsink.c index cecad05fc..16797d32c 100644 --- a/ext/gtk/gstgtkglsink.c +++ b/ext/gtk/gstgtkglsink.c @@ -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_propose_allocation (GstBaseSink * bsink, GstQuery * query); +static GstCaps *gst_gtk_gl_sink_get_caps (GstBaseSink * bsink, + GstCaps * filter); static GstStaticPadTemplate gst_gtk_gl_sink_template = 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->start = gst_gtk_gl_sink_start; 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->window_title = "Gtk+ GL renderer"; @@ -133,6 +136,31 @@ gst_gtk_gl_sink_query (GstBaseSink * bsink, GstQuery * query) 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 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 */ 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)) return FALSE; @@ -191,6 +224,8 @@ gst_gtk_gl_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) GstCaps *caps; guint size; gboolean need_pool; + GstStructure *allocation_meta = NULL; + gint display_width, display_height; if (!gtk_sink->display || !gtk_sink->context) return FALSE; @@ -222,6 +257,25 @@ gst_gtk_gl_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) 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 */ gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, 0); @@ -247,3 +301,28 @@ config_failed: 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; +} diff --git a/ext/gtk/gstgtkglsink.h b/ext/gtk/gstgtkglsink.h index dee102478..789cf33f6 100644 --- a/ext/gtk/gstgtkglsink.h +++ b/ext/gtk/gstgtkglsink.h @@ -60,6 +60,10 @@ struct _GstGtkGLSink GstGLUpload *upload; GstBuffer *uploaded_buffer; + + /* read/write with object lock */ + gint display_width; + gint display_height; }; /** diff --git a/ext/gtk/gtkgstglwidget.c b/ext/gtk/gtkgstglwidget.c index dc24535aa..cdce3aa54 100644 --- a/ext/gtk/gtkgstglwidget.c +++ b/ext/gtk/gtkgstglwidget.c @@ -71,6 +71,7 @@ struct _GtkGstGLWidgetPrivate GLint attr_position; GLint attr_texture; GLuint current_tex; + GstGLOverlayCompositor *overlay_compositor; }; static const GLfloat vertices[] = { @@ -140,6 +141,9 @@ gtk_gst_gl_widget_init_redisplay (GtkGstGLWidget * gst_widget) gl->BindBuffer (GL_ARRAY_BUFFER, 0); + priv->overlay_compositor = + gst_gl_overlay_compositor_new (priv->other_context); + priv->initted = TRUE; } @@ -237,6 +241,8 @@ gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context) goto done; } + gst_gl_overlay_compositor_upload_overlays (priv->overlay_compositor, + buffer); sync_meta = gst_buffer_get_gl_sync_meta (buffer); if (sync_meta) { @@ -260,6 +266,7 @@ gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context) base_widget->buffer, context); _redraw_texture (GTK_GST_GL_WIDGET (widget), priv->current_tex); + gst_gl_overlay_compositor_draw_overlays (priv->overlay_compositor); done: if (priv->other_context) @@ -350,6 +357,9 @@ _reset_gl (GtkGstGLWidget * gst_widget) priv->shader = NULL; } + if (priv->overlay_compositor) + gst_object_unref (priv->overlay_compositor); + gst_gl_context_activate (priv->other_context, FALSE); gst_object_unref (priv->other_context); -- cgit v1.2.1