diff -r 9b2c3c7a1a9c -r 567bb019e3e3 gstreamer_core/gst/gstelementfactory.c --- a/gstreamer_core/gst/gstelementfactory.c Wed Mar 31 22:03:18 2010 +0300 +++ b/gstreamer_core/gst/gstelementfactory.c Tue Aug 31 15:30:33 2010 +0300 @@ -40,13 +40,16 @@ * Using an element factory * * #include <gst/gst.h> + * * GstElement *src; * GstElementFactory *srcfactory; - * gst_init(&argc,&argv); - * srcfactory = gst_element_factory_find("filesrc"); - * g_return_if_fail(srcfactory != NULL); - * src = gst_element_factory_create(srcfactory,"src"); - * g_return_if_fail(src != NULL); + * + * gst_init (&argc, &argv); + * + * srcfactory = gst_element_factory_find ("filesrc"); + * g_return_if_fail (srcfactory != NULL); + * src = gst_element_factory_create (srcfactory, "src"); + * g_return_if_fail (src != NULL); * ... * * @@ -69,54 +72,33 @@ static void gst_element_factory_class_init (GstElementFactoryClass * klass); static void gst_element_factory_init (GstElementFactory * factory); static void gst_element_factory_finalize (GObject * object); +#ifdef __SYMBIAN32__ +IMPORT_C +#endif void __gst_element_details_clear (GstElementDetails * dp); static void gst_element_factory_cleanup (GstElementFactory * factory); static GstPluginFeatureClass *parent_class = NULL; /* static guint gst_element_factory_signals[LAST_SIGNAL] = { 0 }; */ -#ifdef __SYMBIAN32__ -EXPORT_C -#endif - -GType -gst_element_factory_get_type (void) -{ - static GType elementfactory_type = 0; +/* this is defined in gstelement.c */ +extern GQuark _gst_elementclass_factory; - if (G_UNLIKELY (elementfactory_type == 0)) { - static const GTypeInfo elementfactory_info = { - sizeof (GstElementFactoryClass), - NULL, - NULL, - (GClassInitFunc) gst_element_factory_class_init, - NULL, - NULL, - sizeof (GstElementFactory), - 0, - (GInstanceInitFunc) gst_element_factory_init, - NULL - }; +#define _do_init \ +{ \ + GST_DEBUG_CATEGORY_INIT (element_factory_debug, "GST_ELEMENT_FACTORY", \ + GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, \ + "element factories keep information about installed elements"); \ +} - elementfactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE, - "GstElementFactory", &elementfactory_info, 0); - GST_DEBUG_CATEGORY_INIT (element_factory_debug, "GST_ELEMENT_FACTORY", - GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, - "element factories keep information about installed elements"); - } - return elementfactory_type; -} +G_DEFINE_TYPE_WITH_CODE (GstElementFactory, gst_element_factory, + GST_TYPE_PLUGIN_FEATURE, _do_init); + static void gst_element_factory_class_init (GstElementFactoryClass * klass) { - GObjectClass *gobject_class; - GstObjectClass *gstobject_class; - GstPluginFeatureClass *gstpluginfeature_class; - - gobject_class = (GObjectClass *) klass; - gstobject_class = (GstObjectClass *) klass; - gstpluginfeature_class = (GstPluginFeatureClass *) klass; + GObjectClass *gobject_class = (GObjectClass *) klass; parent_class = g_type_class_peek_parent (klass); @@ -198,11 +180,12 @@ __src->__entry); \ __dest->__entry = g_strdup ("[ERROR: invalid UTF-8]"); \ } \ -} G_STMT_END - +}G_STMT_END #ifdef __SYMBIAN32__ EXPORT_C #endif + + void __gst_element_details_set (GstElementDetails * dest, const GstElementDetails * src) @@ -232,8 +215,7 @@ __gst_element_details_clear (&factory->details); if (factory->type) { - g_type_class_unref (g_type_class_peek (factory->type)); - factory->type = 0; + factory->type = G_TYPE_INVALID; } for (item = factory->staticpadtemplates; item; item = item->next) { @@ -292,6 +274,8 @@ gst_element_register (GstPlugin * plugin, const gchar * name, guint rank, GType type) { + GstPluginFeature *existing_feature; + GstRegistry *registry; GstElementFactory *factory; GType *interfaces; guint n_interfaces, i; @@ -301,8 +285,27 @@ g_return_val_if_fail (name != NULL, FALSE); g_return_val_if_fail (g_type_is_a (type, GST_TYPE_ELEMENT), FALSE); - factory = GST_ELEMENT_FACTORY (g_object_new (GST_TYPE_ELEMENT_FACTORY, NULL)); - gst_plugin_feature_set_name (GST_PLUGIN_FEATURE (factory), name); + registry = gst_registry_get_default (); + + /* check if feature already exists, if it exists there is no need to update it + * when the registry is getting updated, outdated plugins and all there + * feature are removed and readded. + */ + existing_feature = gst_registry_lookup_feature (registry, name); + if (existing_feature) { + GST_DEBUG_OBJECT (registry, "update existing feature %p (%s)", + existing_feature, name); + factory = GST_ELEMENT_FACTORY_CAST (existing_feature); + factory->type = type; + existing_feature->loaded = TRUE; + g_type_set_qdata (type, _gst_elementclass_factory, factory); + gst_object_unref (existing_feature); + return TRUE; + } + + factory = + GST_ELEMENT_FACTORY_CAST (g_object_new (GST_TYPE_ELEMENT_FACTORY, NULL)); + gst_plugin_feature_set_name (GST_PLUGIN_FEATURE_CAST (factory), name); GST_LOG_OBJECT (factory, "Created new elementfactory for type %s", g_type_name (type)); @@ -326,7 +329,7 @@ g_list_append (factory->staticpadtemplates, newt); } factory->numpadtemplates = klass->numpadtemplates; - klass->elementfactory = factory; + g_type_set_qdata (type, _gst_elementclass_factory, factory); /* special stuff for URI handling */ if (g_type_is_a (type, GST_TYPE_URI_HANDLER)) { @@ -357,15 +360,14 @@ g_free (interfaces); if (plugin && plugin->desc.name) { - GST_PLUGIN_FEATURE (factory)->plugin_name = plugin->desc.name; + GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = plugin->desc.name; } else { - GST_PLUGIN_FEATURE (factory)->plugin_name = "NULL"; + GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = "NULL"; } - gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE (factory), rank); - GST_PLUGIN_FEATURE (factory)->loaded = TRUE; + gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE_CAST (factory), rank); + GST_PLUGIN_FEATURE_CAST (factory)->loaded = TRUE; - gst_registry_add_feature (gst_registry_get_default (), - GST_PLUGIN_FEATURE (factory)); + gst_registry_add_feature (registry, GST_PLUGIN_FEATURE_CAST (factory)); return TRUE; @@ -435,16 +437,16 @@ /* fill in the pointer to the factory in the element class. The * class will not be unreffed currently. - * FIXME: This isn't safe and may leak a refcount on the factory if 2 threads - * create the first instance of an element at the same moment */ + * Be thread safe as there might be 2 threads creating the first instance of + * an element at the same moment + */ oclass = GST_ELEMENT_GET_CLASS (element); - if (G_UNLIKELY (oclass->elementfactory == NULL)) - oclass->elementfactory = factory; - else + if (!g_atomic_pointer_compare_and_exchange ( + (gpointer) & oclass->elementfactory, NULL, factory)) gst_object_unref (factory); if (name) - gst_object_set_name (GST_OBJECT (element), name); + gst_object_set_name (GST_OBJECT_CAST (element), name); GST_DEBUG ("created element \"%s\"", GST_PLUGIN_FEATURE_NAME (factory)); @@ -453,7 +455,8 @@ /* ERRORS */ load_failed: { - GST_WARNING_OBJECT (factory, "loading plugin returned NULL!"); + GST_WARNING_OBJECT (factory, + "loading plugin containing feature %s returned NULL!", name); return NULL; } no_type: @@ -503,10 +506,10 @@ GST_LOG_OBJECT (factory, "found factory %p", factory); element = gst_element_factory_create (factory, name); - gst_object_unref (factory); if (element == NULL) goto create_failed; + gst_object_unref (factory); return element; /* ERRORS */ @@ -518,6 +521,7 @@ create_failed: { GST_INFO_OBJECT (factory, "couldn't create instance!"); + gst_object_unref (factory); return NULL; } } @@ -709,7 +713,7 @@ * gst_element_factory_get_uri_type: * @factory: a #GstElementFactory * - * Gets the type of URIs the element supports or GST_URI_UNKNOWN if none. + * Gets the type of URIs the element supports or #GST_URI_UNKNOWN if none. * * Returns: type of URIs this element supports */