gstreamer_core/gst/gstelementfactory.c
branchRCL_3
changeset 7 567bb019e3e3
parent 0 0e761a78d257
child 8 7e817e7e631c
--- 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 @@
  * <title>Using an element factory</title>
  * <programlisting language="c">
  *   #include &lt;gst/gst.h&gt;
+ *   
  *   GstElement *src;
  *   GstElementFactory *srcfactory;
- *   gst_init(&amp;argc,&amp;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 (&amp;argc, &amp;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);
  *   ...
  * </programlisting>
  * </example>
@@ -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
  */