From 91ee7188d7ef11ab8c4732c83e21b386fa94f1e1 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 23 Jun 2006 16:45:50 +0000 Subject: [PATCH] gst/playback/gstdecodebin.c: Protect remove_fakesink using a mutex, so that we don't try and remove the fakesink simu... Original commit message from CVS: * gst/playback/gstdecodebin.c: (gst_decode_bin_class_init), (gst_decode_bin_init), (gst_decode_bin_finalize), (add_fakesink), (remove_fakesink), (pad_probe), (gst_decode_bin_change_state): Protect remove_fakesink using a mutex, so that we don't try and remove the fakesink simultaneously from multiple threads. When going from READY to PAUSED, restore the fakesink, so that it is there when decodebin gets reused. --- ChangeLog | 11 ++++++ gst/playback/gstdecodebin.c | 67 +++++++++++++++++++++++++++++++------ 2 files changed, 67 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 90fd303817..a76e75788e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2006-06-23 Jan Schmidt + + * gst/playback/gstdecodebin.c: (gst_decode_bin_class_init), + (gst_decode_bin_init), (gst_decode_bin_finalize), (add_fakesink), + (remove_fakesink), (pad_probe), (gst_decode_bin_change_state): + Protect remove_fakesink using a mutex, so that we don't try and + remove the fakesink simultaneously from multiple threads. + + When going from READY to PAUSED, restore the fakesink, so that + it is there when decodebin gets reused. + 2006-06-23 Tim-Philipp Müller * gst-libs/gst/rtp/gstbasertpaudiopayload.c: diff --git a/gst/playback/gstdecodebin.c b/gst/playback/gstdecodebin.c index 1ce8c318aa..086306e66a 100644 --- a/gst/playback/gstdecodebin.c +++ b/gst/playback/gstdecodebin.c @@ -73,6 +73,8 @@ struct _GstDecodeBin gboolean shutting_down; /* stop pluggin if we're shutting down */ GType queue_type; /* store the GType of queues, to aid in recognising them */ + + GMutex *cb_mutex; /* Mutex for multi-threaded callbacks, such as removing the fakesink */ }; struct _GstDecodeBinClass @@ -120,10 +122,14 @@ GstDynamic; static void gst_decode_bin_class_init (GstDecodeBinClass * klass); static void gst_decode_bin_init (GstDecodeBin * decode_bin); static void gst_decode_bin_dispose (GObject * object); +static void gst_decode_bin_finalize (GObject * object); static GstStateChangeReturn gst_decode_bin_change_state (GstElement * element, GstStateChange transition); +static void add_fakesink (GstDecodeBin * decode_bin); +static void remove_fakesink (GstDecodeBin * decode_bin); + static void free_dynamics (GstDecodeBin * decode_bin); static void type_found (GstElement * typefind, guint probability, GstCaps * caps, GstDecodeBin * decode_bin); @@ -208,6 +214,7 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass) GST_TYPE_PAD, GST_TYPE_CAPS); gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_decode_bin_dispose); + gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_decode_bin_finalize); gst_element_class_add_pad_template (gstelement_klass, gst_static_pad_template_get (&decoder_bin_sink_template)); @@ -293,6 +300,8 @@ gst_decode_bin_init (GstDecodeBin * decode_bin) { GList *factories; + decode_bin->cb_mutex = g_mutex_new (); + /* first filter out the interesting element factories */ factories = gst_default_registry_feature_filter ( (GstPluginFeatureFilter) gst_decode_bin_factory_filter, @@ -332,17 +341,7 @@ gst_decode_bin_init (GstDecodeBin * decode_bin) g_signal_connect (G_OBJECT (decode_bin->typefind), "have_type", G_CALLBACK (type_found), decode_bin); } - decode_bin->fakesink = gst_element_factory_make ("fakesink", "fakesink"); - if (!decode_bin->fakesink) { - g_warning ("can't find fakesink element, decodebin will not work"); - } else { - GST_OBJECT_FLAG_UNSET (decode_bin->fakesink, GST_ELEMENT_IS_SINK); - if (!gst_bin_add (GST_BIN (decode_bin), decode_bin->fakesink)) { - g_warning ("Could not add fakesink element, decodebin will not work"); - gst_object_unref (decode_bin->fakesink); - decode_bin->fakesink = NULL; - } - } + add_fakesink (decode_bin); decode_bin->dynamics = NULL; decode_bin->queues = NULL; @@ -370,6 +369,16 @@ gst_decode_bin_dispose (GObject * object) free_dynamics (decode_bin); } +static void +gst_decode_bin_finalize (GObject * object) +{ + GstDecodeBin *decode_bin = GST_DECODE_BIN (object); + + g_mutex_free (decode_bin->cb_mutex); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + static GstDynamic * dynamic_create (GstElement * element, GstDecodeBin * decode_bin) { @@ -491,9 +500,37 @@ free_pad_probes (GstDecodeBin * decode_bin) decode_bin->probes = NULL; } +static void +add_fakesink (GstDecodeBin * decode_bin) +{ + if (decode_bin->fakesink != NULL) + return; + + g_mutex_lock (decode_bin->cb_mutex); + + decode_bin->fakesink = gst_element_factory_make ("fakesink", "fakesink"); + if (!decode_bin->fakesink) { + g_warning ("can't find fakesink element, decodebin will not work"); + } else { + GST_OBJECT_FLAG_UNSET (decode_bin->fakesink, GST_ELEMENT_IS_SINK); + if (!gst_bin_add (GST_BIN (decode_bin), decode_bin->fakesink)) { + g_warning ("Could not add fakesink element, decodebin will not work"); + gst_object_unref (decode_bin->fakesink); + decode_bin->fakesink = NULL; + } + } + g_mutex_unlock (decode_bin->cb_mutex); +} + static void remove_fakesink (GstDecodeBin * decode_bin) { + gboolean removed_fakesink = FALSE; + + if (decode_bin->fakesink == NULL) + return; + + g_mutex_lock (decode_bin->cb_mutex); if (decode_bin->fakesink) { GST_DEBUG_OBJECT (decode_bin, "Removing fakesink and marking state dirty"); gst_object_ref (decode_bin->fakesink); @@ -506,6 +543,11 @@ remove_fakesink (GstDecodeBin * decode_bin) gst_object_unref (decode_bin->fakesink); decode_bin->fakesink = NULL; + removed_fakesink = TRUE; + } + g_mutex_unlock (decode_bin->cb_mutex); + + if (removed_fakesink) { free_pad_probes (decode_bin); gst_element_post_message (GST_ELEMENT_CAST (decode_bin), @@ -1462,6 +1504,9 @@ gst_decode_bin_change_state (GstElement * element, GstStateChange transition) GST_OBJECT_LOCK (decode_bin); decode_bin->shutting_down = FALSE; GST_OBJECT_UNLOCK (decode_bin); + + add_fakesink (decode_bin); + break; break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: case GST_STATE_CHANGE_PLAYING_TO_PAUSED: