static GstObjectClass *parent_class = NULL;
static guint gst_element_signals[LAST_SIGNAL] = { 0 };
+/* this is used in gstelementfactory.c:gst_element_register() */
+GQuark _gst_elementclass_factory = 0;
+
GType
gst_element_get_type (void)
{
_type = g_type_register_static (GST_TYPE_OBJECT, "GstElement",
&element_info, G_TYPE_FLAG_ABSTRACT);
+
+ _gst_elementclass_factory =
+ g_quark_from_static_string ("GST_ELEMENTCLASS_FACTORY");
g_once_init_leave (&gst_element_type, _type);
}
return gst_element_type;
*/
memset (&element_class->details, 0, sizeof (GstElementDetails));
element_class->padtemplates = NULL;
+
+ /* set the factory, see gst_element_register() */
+ element_class->elementfactory =
+ g_type_get_qdata (G_TYPE_FROM_CLASS (element_class),
+ _gst_elementclass_factory);
+ GST_DEBUG ("type %s : factory %p", G_OBJECT_CLASS_NAME (element_class),
+ element_class->elementfactory);
}
static void
/* static guint gst_element_factory_signals[LAST_SIGNAL] = { 0 }; */
+/* this is defined in gstelement.c */
+extern GQuark _gst_elementclass_factory;
+
#define _do_init \
{ \
GST_DEBUG_CATEGORY_INIT (element_factory_debug, "GST_ELEMENT_FACTORY", \
__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) {
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;
g_return_val_if_fail (name != NULL, FALSE);
g_return_val_if_fail (g_type_is_a (type, GST_TYPE_ELEMENT), FALSE);
+ 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);
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)) {
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_CAST (factory));
+ gst_registry_add_feature (registry, GST_PLUGIN_FEATURE_CAST (factory));
return TRUE;
/* 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)
/* 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:
gpointer ptr;
struct stat file_status;
GstRegistry *registry;
+ gboolean new_plugin = TRUE;
g_return_val_if_fail (filename != NULL, NULL);
plugin = gst_registry_lookup (registry, filename);
if (plugin) {
if (plugin->module) {
+ /* already loaded */
g_static_mutex_unlock (&gst_plugin_loading_mutex);
return plugin;
} else {
- gst_object_unref (plugin);
- plugin = NULL;
+ /* load plugin and update fields */
+ new_plugin = FALSE;
}
}
goto return_error;
}
- plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
-
+ if (new_plugin) {
+ plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
+ plugin->file_mtime = file_status.st_mtime;
+ plugin->file_size = file_status.st_size;
+ }
plugin->module = module;
plugin->filename = g_strdup (filename);
plugin->basename = g_path_get_basename (filename);
- plugin->file_mtime = file_status.st_mtime;
- plugin->file_size = file_status.st_size;
ret = g_module_symbol (module, "gst_plugin_desc", &ptr);
if (!ret) {
}
plugin->orig_desc = (GstPluginDesc *) ptr;
- /* check plugin description: complain about bad values but accept them, to
- * maintain backwards compatibility (FIXME: 0.11) */
- CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, name, filename);
- CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, description, filename);
- CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, version, filename);
- CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, license, filename);
- CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, source, filename);
- CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, package, filename);
- CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, origin, filename);
+ if (new_plugin) {
+ /* check plugin description: complain about bad values but accept them, to
+ * maintain backwards compatibility (FIXME: 0.11) */
+ CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, name, filename);
+ CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, description, filename);
+ CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, version, filename);
+ CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, license, filename);
+ CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, source, filename);
+ CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, package, filename);
+ CHECK_PLUGIN_DESC_FIELD (plugin->orig_desc, origin, filename);
+ }
GST_LOG ("Plugin %p for file \"%s\" prepared, calling entry function...",
plugin, filename);
_gst_plugin_fault_handler_filename = NULL;
GST_INFO ("plugin \"%s\" loaded", plugin->filename);
- gst_object_ref (plugin);
- gst_default_registry_add_plugin (plugin);
+ if (new_plugin) {
+ gst_object_ref (plugin);
+ gst_default_registry_add_plugin (plugin);
+ }
g_static_mutex_unlock (&gst_plugin_loading_mutex);
return plugin;
_gst_debug_nameof_funcptr
_gst_debug_register_funcptr
_gst_element_error_printf
+ _gst_elementclass_factory DATA
_gst_plugin_register_static
_gst_trace_add_entry
_gst_trace_on DATA