diff options
author | Nicolas Dufresne <nicolas.dufresne@collabora.com> | 2015-07-15 14:32:42 -0400 |
---|---|---|
committer | Nicolas Dufresne <nicolas.dufresne@collabora.com> | 2015-07-16 17:05:36 -0400 |
commit | 0bc7e9a240dd55eb1b4bc34e730a8a6e28e2de53 (patch) | |
tree | ab70f3073307d240fbeac171777004e2bed33941 /ext/gtk/gtkgstwidget.c | |
parent | 53a431a3239918cd04763879845e09bc87bb8883 (diff) | |
download | gstreamer-plugins-bad-0bc7e9a240dd55eb1b4bc34e730a8a6e28e2de53.tar.gz |
gtk: Fix race between queue_draw and destroy
In GTK dispose can be called before the last ref is reached. This
happens when you close the container window. The dispose will be
explicitly called, and destroyed notify will be fired. This patch
fixes this race by properly tracking the widget state.
In the sink, we now set the widget pointer to NULL, so the widget
will properly get created again if you set your pipeline to NULL
state after the widget was destroy, and set it back to PLAYING.
https://bugzilla.gnome.org/show_bug.cgi?id=751104
Diffstat (limited to 'ext/gtk/gtkgstwidget.c')
-rw-r--r-- | ext/gtk/gtkgstwidget.c | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/ext/gtk/gtkgstwidget.c b/ext/gtk/gtkgstwidget.c index 3e2f9bb28..3fbb0ca4e 100644 --- a/ext/gtk/gtkgstwidget.c +++ b/ext/gtk/gtkgstwidget.c @@ -69,6 +69,10 @@ struct _GtkGstWidgetPrivate GstBuffer *buffer; GstCaps *caps; GstVideoInfo v_info; + + /* Pending queued idles callback */ + guint draw_id; + guint resize_id; }; static void @@ -226,6 +230,12 @@ gtk_gst_widget_finalize (GObject * object) gst_buffer_replace (&widget->priv->buffer, NULL); g_mutex_clear (&widget->priv->lock); + if (widget->priv->draw_id) + g_source_remove (widget->priv->draw_id); + + if (widget->priv->resize_id) + g_source_remove (widget->priv->resize_id); + G_OBJECT_CLASS (gtk_gst_widget_parent_class)->finalize (object); } @@ -331,6 +341,10 @@ gtk_gst_widget_new (void) static gboolean _queue_draw (GtkGstWidget * widget) { + g_mutex_lock (&widget->priv->lock); + widget->priv->draw_id = 0; + g_mutex_unlock (&widget->priv->lock); + gtk_widget_queue_draw (GTK_WIDGET (widget)); return G_SOURCE_REMOVE; @@ -339,8 +353,6 @@ _queue_draw (GtkGstWidget * widget) void gtk_gst_widget_set_buffer (GtkGstWidget * widget, GstBuffer * buffer) { - GMainContext *main_context = g_main_context_default (); - g_return_if_fail (GTK_IS_GST_WIDGET (widget)); g_return_if_fail (buffer == NULL || widget->priv->negotiated); @@ -348,14 +360,21 @@ gtk_gst_widget_set_buffer (GtkGstWidget * widget, GstBuffer * buffer) gst_buffer_replace (&widget->priv->buffer, buffer); - g_mutex_unlock (&widget->priv->lock); + if (!widget->priv->draw_id) { + widget->priv->draw_id = g_idle_add_full (G_PRIORITY_DEFAULT, + (GSourceFunc) _queue_draw, widget, NULL); + } - g_main_context_invoke (main_context, (GSourceFunc) _queue_draw, widget); + g_mutex_unlock (&widget->priv->lock); } static gboolean _queue_resize (GtkGstWidget * widget) { + g_mutex_lock (&widget->priv->lock); + widget->priv->resize_id = 0; + g_mutex_unlock (&widget->priv->lock); + gtk_widget_queue_resize (GTK_WIDGET (widget)); return G_SOURCE_REMOVE; @@ -424,7 +443,6 @@ _calculate_par (GtkGstWidget * widget, GstVideoInfo * info) gboolean gtk_gst_widget_set_caps (GtkGstWidget * widget, GstCaps * caps) { - GMainContext *main_context = g_main_context_default (); GstVideoInfo v_info; g_return_val_if_fail (GTK_IS_GST_WIDGET (widget), FALSE); @@ -455,15 +473,17 @@ gtk_gst_widget_set_caps (GtkGstWidget * widget, GstCaps * caps) return FALSE; } + gst_buffer_replace (&widget->priv->buffer, NULL); gst_caps_replace (&widget->priv->caps, caps); widget->priv->v_info = v_info; widget->priv->negotiated = TRUE; - g_mutex_unlock (&widget->priv->lock); - - gtk_widget_queue_resize (GTK_WIDGET (widget)); + if (!widget->priv->resize_id) { + widget->priv->resize_id = g_idle_add_full (G_PRIORITY_DEFAULT, + (GSourceFunc) _queue_resize, widget, NULL); + } - g_main_context_invoke (main_context, (GSourceFunc) _queue_resize, widget); + g_mutex_unlock (&widget->priv->lock); return TRUE; } |