diff --git a/common b/common index c3cafe123f..46dfcea233 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit c3cafe123f3a363d337a29ad32fdd6d3631f52c0 +Subproject commit 46dfcea233cf6df83e3771d8a8066e87d614f893 diff --git a/gst/gstbus.c b/gst/gstbus.c index e670af5590..4e0f34a95a 100644 --- a/gst/gstbus.c +++ b/gst/gstbus.c @@ -471,7 +471,7 @@ gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout, g_return_val_if_fail (GST_IS_BUS (bus), NULL); g_return_val_if_fail (types != 0, NULL); - g_return_val_if_fail (bus->priv->poll != NULL, NULL); + g_return_val_if_fail (timeout == 0 || bus->priv->poll != NULL, NULL); g_mutex_lock (bus->queue_lock); @@ -482,7 +482,8 @@ gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout, gst_atomic_queue_length (bus->queue)); while ((message = gst_atomic_queue_pop (bus->queue))) { - gst_poll_read_control (bus->priv->poll); + if (bus->priv->poll) + gst_poll_read_control (bus->priv->poll); GST_DEBUG_OBJECT (bus, "got message %p, %s, type mask is %u", message, GST_MESSAGE_TYPE_NAME (message), (guint) types); if ((GST_MESSAGE_TYPE (message) & types) != 0) { @@ -516,6 +517,8 @@ gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout, } } + /* only here in timeout case */ + g_assert (bus->priv->poll); g_mutex_unlock (bus->queue_lock); ret = gst_poll_wait (bus->priv->poll, timeout); g_mutex_lock (bus->queue_lock); diff --git a/gst/gstelementfactory.c b/gst/gstelementfactory.c index 6298c46e46..93ed64955b 100644 --- a/gst/gstelementfactory.c +++ b/gst/gstelementfactory.c @@ -305,8 +305,12 @@ gst_element_register (GstPlugin * plugin, const gchar * name, guint rank, if (plugin && plugin->desc.name) { GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = plugin->desc.name; + GST_PLUGIN_FEATURE_CAST (factory)->plugin = plugin; + g_object_add_weak_pointer ((GObject *) plugin, + (gpointer *) & GST_PLUGIN_FEATURE_CAST (factory)->plugin); } else { GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = "NULL"; + GST_PLUGIN_FEATURE_CAST (factory)->plugin = NULL; } gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE_CAST (factory), rank); GST_PLUGIN_FEATURE_CAST (factory)->loaded = TRUE; diff --git a/gst/gstpluginfeature.c b/gst/gstpluginfeature.c index 2c44034bf5..696988c0fe 100644 --- a/gst/gstpluginfeature.c +++ b/gst/gstpluginfeature.c @@ -67,6 +67,11 @@ gst_plugin_feature_finalize (GObject * object) GST_PLUGIN_FEATURE_NAME (feature)); g_free (feature->name); + if (feature->plugin != NULL) { + g_object_remove_weak_pointer ((GObject *) feature->plugin, + (gpointer *) & feature->plugin); + } + G_OBJECT_CLASS (gst_plugin_feature_parent_class)->finalize (object); } diff --git a/gst/gstpluginfeature.h b/gst/gstpluginfeature.h index ee615d9537..b731a86710 100644 --- a/gst/gstpluginfeature.h +++ b/gst/gstpluginfeature.h @@ -84,9 +84,10 @@ struct _GstPluginFeature { guint rank; const gchar *plugin_name; + GstPlugin *plugin; /* weak ref */ /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; + gpointer _gst_reserved[GST_PADDING - 1]; }; struct _GstPluginFeatureClass { diff --git a/gst/gstregistry.c b/gst/gstregistry.c index a750175efa..5b6df92f3b 100644 --- a/gst/gstregistry.c +++ b/gst/gstregistry.c @@ -468,22 +468,20 @@ gst_registry_remove_features_for_plugin_unlocked (GstRegistry * registry, GstPlugin * plugin) { GList *f; - const gchar *name; g_return_if_fail (GST_IS_REGISTRY (registry)); g_return_if_fail (GST_IS_PLUGIN (plugin)); - name = gst_plugin_get_name (plugin); - /* Remove all features for this plugin */ f = registry->features; while (f != NULL) { GList *next = g_list_next (f); GstPluginFeature *feature = f->data; - if (G_UNLIKELY (feature && !strcmp (feature->plugin_name, name))) { - GST_DEBUG_OBJECT (registry, "removing feature %p (%s) for plugin %s", - feature, gst_plugin_feature_get_name (feature), name); + if (G_UNLIKELY (feature && feature->plugin == plugin)) { + GST_DEBUG_OBJECT (registry, "removing feature %p (%s) for plugin %p (%s)", + feature, gst_plugin_feature_get_name (feature), plugin, + plugin->desc.name); registry->features = g_list_delete_link (registry->features, f); g_hash_table_remove (registry->feature_hash, feature->name); @@ -1134,7 +1132,7 @@ gst_registry_scan_path_level (GstRegistryScanContext * context, if (file_status.st_mode & S_IFDIR) { if (G_UNLIKELY (is_blacklisted_hidden_directory (dirent))) { - GST_LOG_OBJECT (context->registry, "ignoring %s directory", dirent); + GST_TRACE_OBJECT (context->registry, "ignoring %s directory", dirent); g_free (filename); continue; } @@ -1153,7 +1151,7 @@ gst_registry_scan_path_level (GstRegistryScanContext * context, continue; } if (!(file_status.st_mode & S_IFREG)) { - GST_LOG_OBJECT (context->registry, "%s is not a regular file, ignoring", + GST_TRACE_OBJECT (context->registry, "%s is not a regular file, ignoring", filename); g_free (filename); continue; @@ -1163,7 +1161,7 @@ gst_registry_scan_path_level (GstRegistryScanContext * context, && !g_str_has_suffix (dirent, GST_EXTRA_MODULE_SUFFIX) #endif ) { - GST_LOG_OBJECT (context->registry, + GST_TRACE_OBJECT (context->registry, "extension is not recognized as module file, ignoring file %s", filename); g_free (filename); diff --git a/gst/gstregistrychunks.c b/gst/gstregistrychunks.c index 0ced3a089d..d57bf0d799 100644 --- a/gst/gstregistrychunks.c +++ b/gst/gstregistrychunks.c @@ -519,15 +519,18 @@ fail: */ static gboolean gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in, - gchar * end, const gchar * plugin_name) + gchar * end, GstPlugin * plugin) { GstRegistryChunkPluginFeature *pf = NULL; GstPluginFeature *feature = NULL; const gchar *const_str, *type_name; + const gchar *plugin_name; gchar *str, *feature_name; GType type; guint i; + plugin_name = plugin->desc.name; + /* unpack plugin feature strings */ unpack_string_nocopy (*in, type_name, end, fail); @@ -668,9 +671,13 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in, feature->rank = pf->rank; feature->plugin_name = plugin_name; + feature->plugin = plugin; + g_object_add_weak_pointer ((GObject *) plugin, + (gpointer *) & feature->plugin); gst_registry_add_feature (registry, feature); - GST_DEBUG ("Added feature %s", feature->name); + GST_DEBUG ("Added feature %s, plugin %p %s", feature->name, plugin, + plugin_name); return TRUE; @@ -823,7 +830,7 @@ _priv_gst_registry_chunks_load_plugin (GstRegistry * registry, gchar ** in, /* Load plugin features */ for (i = 0; i < n; i++) { if (G_UNLIKELY (!gst_registry_chunks_load_feature (registry, in, end, - plugin->desc.name))) { + plugin))) { GST_ERROR ("Error while loading binary feature for plugin '%s'", GST_STR_NULL (plugin->desc.name)); gst_registry_remove_plugin (registry, plugin); diff --git a/gst/gsttypefind.c b/gst/gsttypefind.c index 62867a5a1b..1f0b16d001 100644 --- a/gst/gsttypefind.c +++ b/gst/gsttypefind.c @@ -99,8 +99,12 @@ gst_type_find_register (GstPlugin * plugin, const gchar * name, guint rank, factory->user_data_notify = data_notify; if (plugin && plugin->desc.name) { GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = plugin->desc.name; /* interned string */ + GST_PLUGIN_FEATURE_CAST (factory)->plugin = plugin; + g_object_add_weak_pointer ((GObject *) plugin, + (gpointer *) & GST_PLUGIN_FEATURE_CAST (factory)->plugin); } else { GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = "NULL"; + GST_PLUGIN_FEATURE_CAST (factory)->plugin = NULL; } GST_PLUGIN_FEATURE_CAST (factory)->loaded = TRUE; diff --git a/gst/gstutils.c b/gst/gstutils.c index b920a2369c..075bb3f6ba 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -3947,7 +3947,7 @@ gst_util_greatest_common_divisor (gint a, gint b) * @src_d: Fraction denominator #gint * @dest: (out): pointer to a #gdouble for the result * - * Transforms a #gdouble to a fraction and simplifies the result. + * Transforms a fraction to a #gdouble. * * Since: 0.10.26 */ diff --git a/libs/gst/base/gstbasetransform.c b/libs/gst/base/gstbasetransform.c index 5649d7c58d..ea9be074ed 100644 --- a/libs/gst/base/gstbasetransform.c +++ b/libs/gst/base/gstbasetransform.c @@ -1716,6 +1716,7 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size, GstBaseTransformClass *klass; GstBaseTransformPrivate *priv; GstFlowReturn res; + gboolean alloced = FALSE; gboolean proxy, suggest, same_caps; GstCaps *sink_suggest = NULL; gsize size_suggest; @@ -1921,6 +1922,7 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size, res = gst_pad_alloc_buffer (trans->srcpad, offset, size, caps, buf); if (res != GST_FLOW_OK) goto alloc_failed; + alloced = TRUE; /* check if the caps changed */ newcaps = GST_BUFFER_CAPS (*buf); @@ -1966,7 +1968,7 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size, if (sink_suggest) gst_caps_unref (sink_suggest); - if (res == GST_FLOW_OK) { + if (res == GST_FLOW_OK && alloced) { /* just alloc'ed a buffer, so we only want to do this again if we * received a buffer */ GST_DEBUG_OBJECT (trans, "Cleaning force alloc"); diff --git a/tests/check/gst/gstbin.c b/tests/check/gst/gstbin.c index 3adfd9fb87..c81fdeba68 100644 --- a/tests/check/gst/gstbin.c +++ b/tests/check/gst/gstbin.c @@ -1006,10 +1006,12 @@ GST_START_TEST (test_link_structure_change) gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); /* the state change will be done on src only if the pipeline correctly resyncs - * after that filesrc has been linked to identity */ + * after that fakesrc has been linked to identity */ gst_element_get_state (src, &state, NULL, 0); fail_unless_equals_int (state, GST_STATE_READY); + /* clean up */ + gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (bus); gst_object_unref (pipeline); } diff --git a/tests/check/gst/gstpipeline.c b/tests/check/gst/gstpipeline.c index 17cc33687a..02b6dc2b2f 100644 --- a/tests/check/gst/gstpipeline.c +++ b/tests/check/gst/gstpipeline.c @@ -528,6 +528,38 @@ GST_START_TEST (test_concurrent_create) GST_END_TEST; +GST_START_TEST (test_pipeline_in_pipeline) +{ + GstElement *pipeline, *bin, *fakesrc, *fakesink; + GstMessage *msg; + + pipeline = gst_element_factory_make ("pipeline", "pipeline"); + bin = gst_element_factory_make ("pipeline", "pipeline-as-bin"); + fakesrc = gst_element_factory_make ("fakesrc", "fakesrc"); + fakesink = gst_element_factory_make ("fakesink", "fakesink"); + + fail_unless (pipeline && bin && fakesrc && fakesink); + + g_object_set (fakesrc, "num-buffers", 100, NULL); + + gst_bin_add (GST_BIN (pipeline), bin); + gst_bin_add_many (GST_BIN (bin), fakesrc, fakesink, NULL); + gst_element_link (fakesrc, fakesink); + + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING), + GST_STATE_CHANGE_ASYNC); + + msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipeline), -1, + GST_MESSAGE_EOS); + gst_message_unref (msg); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + static Suite * gst_pipeline_suite (void) { @@ -544,6 +576,7 @@ gst_pipeline_suite (void) tcase_add_test (tc_chain, test_bus); tcase_add_test (tc_chain, test_base_time); tcase_add_test (tc_chain, test_concurrent_create); + tcase_add_test (tc_chain, test_pipeline_in_pipeline); return s; }