diff options
author | Jan Schmidt <thaytan@noraisin.net> | 2009-03-14 23:07:40 +0000 |
---|---|---|
committer | Jan Schmidt <thaytan@noraisin.net> | 2009-10-06 19:51:42 +0100 |
commit | 51675e0c2a1bcf0263e45a74ab0da081469b3236 (patch) | |
tree | db9ad1db6d6ef438c4bb2f5875c6be2b8ea26779 /gst/gstregistrybinary.c | |
parent | 1f4e47703348686bb2bf2b8c314eeff0e9066ff9 (diff) |
registry: Add registry helper phase 1
Phase 1 of adding the registry scan helper
Diffstat (limited to 'gst/gstregistrybinary.c')
-rw-r--r-- | gst/gstregistrybinary.c | 854 |
1 files changed, 69 insertions, 785 deletions
diff --git a/gst/gstregistrybinary.c b/gst/gstregistrybinary.c index 661685ea88..576ab0221f 100644 --- a/gst/gstregistrybinary.c +++ b/gst/gstregistrybinary.c @@ -61,6 +61,7 @@ #include <gst/gstenumtypes.h> #include <gst/gstpadtemplate.h> +#include <gst/gstregistrychunks.h> #include <gst/gstregistrybinary.h> #include <glib/gstdio.h> /* for g_stat(), g_mapped_file(), ... */ @@ -70,25 +71,7 @@ #define GST_CAT_DEFAULT GST_CAT_REGISTRY -/* count string length, but return -1 if we hit the eof */ -static gint -_strnlen (const gchar * str, gint maxlen) -{ - gint len = 0; - - if (G_UNLIKELY (len == maxlen)) - return -1; - - while (*str++ != '\0') { - len++; - if (G_UNLIKELY (len == maxlen)) - return -1; - } - return len; -} - /* reading macros */ - #define unpack_element(inptr, outptr, element, endptr, error_label) G_STMT_START{ \ if (inptr + sizeof(element) >= endptr) \ goto error_label; \ @@ -96,22 +79,6 @@ _strnlen (const gchar * str, gint maxlen) inptr += sizeof (element); \ }G_STMT_END -#define unpack_const_string(inptr, outptr, endptr, error_label) G_STMT_START{\ - gint _len = _strnlen (inptr, (endptr-inptr)); \ - if (_len == -1) \ - goto error_label; \ - outptr = g_intern_string ((const gchar *)inptr); \ - inptr += _len + 1; \ -}G_STMT_END - -#define unpack_string(inptr, outptr, endptr, error_label) G_STMT_START{\ - gint _len = _strnlen (inptr, (endptr-inptr)); \ - if (_len == -1) \ - goto error_label; \ - outptr = g_memdup ((gconstpointer)inptr, _len + 1); \ - inptr += _len + 1; \ -}G_STMT_END - #define ALIGNMENT (sizeof (void *)) #define alignment(_address) (gsize)_address%ALIGNMENT #define align(_ptr) _ptr += (( alignment(_ptr) == 0) ? 0 : ALIGNMENT-alignment(_ptr)) @@ -140,9 +107,8 @@ gst_registry_binary_cache_init (GstRegistry * registry, const char *location) } static int -gst_registry_binary_cache_write (GstRegistry * registry, - BinaryRegistryCache * cache, unsigned long offset, - const void *data, int length) +gst_registry_binary_cache_write (BinaryRegistryCache * cache, + unsigned long offset, const void *data, int length) { cache->len = MAX (offset + length, cache->len); cache->mem = g_realloc (cache->mem, cache->len); @@ -153,8 +119,7 @@ gst_registry_binary_cache_write (GstRegistry * registry, } static gboolean -gst_registry_binary_cache_finish (GstRegistry * registry, - BinaryRegistryCache * cache, gboolean success) +gst_registry_binary_cache_finish (BinaryRegistryCache * cache, gboolean success) { gboolean ret = TRUE; GError *error = NULL; @@ -171,9 +136,21 @@ gst_registry_binary_cache_finish (GstRegistry * registry, if (!g_file_set_contents (cache->location, (const gchar *) cache->mem, cache->len, &error)) { - GST_ERROR ("Failed to write to cache file: %s", error->message); + /* Probably the directory didn't exist; create it */ + gchar *dir; + dir = g_path_get_dirname (cache->location); + g_mkdir_with_parents (dir, 0777); + g_free (dir); + g_error_free (error); - ret = FALSE; + error = NULL; + + if (!g_file_set_contents (cache->location, (const gchar *) cache->mem, + cache->len, &error)) { + GST_ERROR ("Failed to write to cache file: %s", error->message); + g_error_free (error); + ret = FALSE; + } } } @@ -188,6 +165,7 @@ typedef struct BinaryRegistryCache const char *location; char *tmp_location; unsigned long currentoffset; + int cache_fd; } BinaryRegistryCache; static BinaryRegistryCache * @@ -197,8 +175,8 @@ gst_registry_binary_cache_init (GstRegistry * registry, const char *location) cache->location = location; cache->tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL); - registry->cache_file = g_mkstemp (cache->tmp_location); - if (registry->cache_file == -1) { + cache->cache_fd = g_mkstemp (cache->tmp_location); + if (cache->cache_fd == -1) { gchar *dir; /* oops, I bet the directory doesn't exist */ @@ -209,9 +187,9 @@ gst_registry_binary_cache_init (GstRegistry * registry, const char *location) /* the previous g_mkstemp call overwrote the XXXXXX placeholder ... */ g_free (cache->tmp_location); cache->tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL); - registry->cache_file = g_mkstemp (cache->tmp_location); + cache->cache_fd = g_mkstemp (cache->tmp_location); - if (registry->cache_file == -1) { + if (cache->cache_fd == -1) { GST_DEBUG ("g_mkstemp() failed: %s", g_strerror (errno)); g_free (cache->tmp_location); g_free (cache); @@ -223,20 +201,19 @@ gst_registry_binary_cache_init (GstRegistry * registry, const char *location) } static int -gst_registry_binary_cache_write (GstRegistry * registry, - BinaryRegistryCache * cache, unsigned long offset, - const void *data, int length) +gst_registry_binary_cache_write (BinaryRegistryCache * cache, + unsigned long offset, const void *data, int length) { long written; if (offset != cache->currentoffset) { - if (lseek (registry->cache_file, offset, SEEK_SET) != 0) { + if (lseek (cache->cache_fd, offset, SEEK_SET) != 0) { GST_ERROR ("Seeking to new offset failed"); return FALSE; } cache->currentoffset = offset; } - written = write (registry->cache_file, data, length); + written = write (cache->cache_fd, data, length); if (written != length) { GST_ERROR ("Failed to write to cache file"); } @@ -246,20 +223,21 @@ gst_registry_binary_cache_write (GstRegistry * registry, } static gboolean -gst_registry_binary_cache_finish (GstRegistry * registry, - BinaryRegistryCache * cache, gboolean success) +gst_registry_binary_cache_finish (BinaryRegistryCache * cache, gboolean success) { /* only fsync if we're actually going to use and rename the file below */ - if (success && fsync (registry->cache_file) < 0) + if (success && fsync (cache->cache_fd) < 0) goto fsync_failed; - if (close (registry->cache_file) < 0) + if (close (cache->cache_fd) < 0) goto close_failed; if (success) { /* Only do the rename if we wrote the entire file successfully */ - if (g_rename (cache->tmp_location, cache->location) < 0) + if (g_rename (cache->tmp_location, cache->location) < 0) { + GST_ERROR ("g_rename() failed: %s", g_strerror (errno)); goto rename_failed; + } } g_free (cache->tmp_location); @@ -301,17 +279,16 @@ rename_failed: * Returns: %TRUE for success */ inline static gboolean -gst_registry_binary_write_chunk (GstRegistry * registry, - BinaryRegistryCache * cache, const void *mem, - const gssize size, unsigned long *file_position, gboolean align) +gst_registry_binary_write_chunk (BinaryRegistryCache * cache, + GstRegistryChunk * chunk, unsigned long *file_position) { gchar padder[ALIGNMENT] = { 0, }; int padsize = 0; /* Padding to insert the struct that requiere word alignment */ - if ((align) && (alignment (*file_position) != 0)) { + if ((chunk->align) && (alignment (*file_position) != 0)) { padsize = ALIGNMENT - alignment (*file_position); - if (gst_registry_binary_cache_write (registry, cache, *file_position, + if (gst_registry_binary_cache_write (cache, *file_position, padder, padsize) != padsize) { GST_ERROR ("Failed to write binary registry padder"); return FALSE; @@ -319,13 +296,13 @@ gst_registry_binary_write_chunk (GstRegistry * registry, *file_position += padsize; } - if (gst_registry_binary_cache_write (registry, cache, *file_position, - mem, size) != size) { + if (gst_registry_binary_cache_write (cache, *file_position, + chunk->data, chunk->size) != chunk->size) { GST_ERROR ("Failed to write binary registry element"); return FALSE; } - *file_position += size; + *file_position += chunk->size; return TRUE; } @@ -353,359 +330,6 @@ gst_registry_binary_initialize_magic (GstBinaryRegistryMagic * m) return TRUE; } - -/* - * gst_registry_binary_save_const_string: - * - * Store a const string in a binary chunk. - * - * Returns: %TRUE for success - */ -inline static gboolean -gst_registry_binary_save_const_string (GList ** list, const gchar * str) -{ - GstBinaryChunk *chunk; - - if (G_UNLIKELY (str == NULL)) { - GST_ERROR ("unexpected NULL string in plugin or plugin feature data"); - str = ""; - } - - chunk = g_malloc (sizeof (GstBinaryChunk)); - chunk->data = (gpointer) str; - chunk->size = strlen ((gchar *) chunk->data) + 1; - chunk->flags = GST_BINARY_REGISTRY_FLAG_CONST; - chunk->align = FALSE; - *list = g_list_prepend (*list, chunk); - return TRUE; -} - -/* - * gst_registry_binary_save_string: - * - * Store a string in a binary chunk. - * - * Returns: %TRUE for success - */ -inline static gboolean -gst_registry_binary_save_string (GList ** list, gchar * str) -{ - GstBinaryChunk *chunk; - - chunk = g_malloc (sizeof (GstBinaryChunk)); - chunk->data = str; - chunk->size = strlen ((gchar *) chunk->data) + 1; - chunk->flags = GST_BINARY_REGISTRY_FLAG_NONE; - chunk->align = FALSE; - *list = g_list_prepend (*list, chunk); - return TRUE; -} - - -/* - * gst_registry_binary_save_data: - * - * Store some data in a binary chunk. - * - * Returns: the initialized chunk - */ -inline static GstBinaryChunk * -gst_registry_binary_make_data (gpointer data, gulong size) -{ - GstBinaryChunk *chunk; - - chunk = g_malloc (sizeof (GstBinaryChunk)); - chunk->data = data; - chunk->size = size; - chunk->flags = GST_BINARY_REGISTRY_FLAG_NONE; - chunk->align = TRUE; - return chunk; -} - - -/* - * gst_registry_binary_save_pad_template: - * - * Store pad_templates in binary chunks. - * - * Returns: %TRUE for success - */ -static gboolean -gst_registry_binary_save_pad_template (GList ** list, - GstStaticPadTemplate * template) -{ - GstBinaryPadTemplate *pt; - GstBinaryChunk *chk; - - pt = g_malloc0 (sizeof (GstBinaryPadTemplate)); - chk = gst_registry_binary_make_data (pt, sizeof (GstBinaryPadTemplate)); - - pt->presence = template->presence; - pt->direction = template->direction; - - /* pack pad template strings */ - gst_registry_binary_save_const_string (list, - (gchar *) (template->static_caps.string)); - gst_registry_binary_save_const_string (list, template->name_template); - - *list = g_list_prepend (*list, chk); - - return TRUE; -} - - -/* - * gst_registry_binary_save_feature: - * - * Store features in binary chunks. - * - * Returns: %TRUE for success - */ -static gboolean -gst_registry_binary_save_feature (GList ** list, GstPluginFeature * feature) -{ - const gchar *type_name = g_type_name (G_OBJECT_TYPE (feature)); - GstBinaryPluginFeature *pf = NULL; - GstBinaryChunk *chk = NULL; - GList *walk; - - if (!type_name) { - GST_ERROR ("NULL feature type_name, aborting."); - return FALSE; - } - - if (GST_IS_ELEMENT_FACTORY (feature)) { - GstBinaryElementFactory *ef; - GstElementFactory *factory = GST_ELEMENT_FACTORY (feature); - - ef = g_malloc0 (sizeof (GstBinaryElementFactory)); - chk = gst_registry_binary_make_data (ef, sizeof (GstBinaryElementFactory)); - ef->npadtemplates = ef->ninterfaces = ef->nuriprotocols = 0; - pf = (GstBinaryPluginFeature *) ef; - - /* save interfaces */ - for (walk = factory->interfaces; walk; - walk = g_list_next (walk), ef->ninterfaces++) { - gst_registry_binary_save_const_string (list, (gchar *) walk->data); - } - GST_DEBUG ("Saved %d Interfaces", ef->ninterfaces); - /* save uritypes */ - if (GST_URI_TYPE_IS_VALID (factory->uri_type)) { - if (factory->uri_protocols && *factory->uri_protocols) { - GstBinaryChunk *subchk; - gchar **protocol; - - subchk = - gst_registry_binary_make_data (&factory->uri_type, - sizeof (factory->uri_type)); - subchk->flags = GST_BINARY_REGISTRY_FLAG_CONST; - - protocol = factory->uri_protocols; - while (*protocol) { - gst_registry_binary_save_const_string (list, *protocol++); - ef->nuriprotocols++; - } - *list = g_list_prepend (*list, subchk); - GST_DEBUG ("Saved %d UriTypes", ef->nuriprotocols); - } else { - g_warning ("GStreamer feature '%s' is URI handler but does not provide" - " any protocols it can handle", feature->name); - } - } - - /* save pad-templates */ - for (walk = factory->staticpadtemplates; walk; - walk = g_list_next (walk), ef->npadtemplates++) { - GstStaticPadTemplate *template = walk->data; - - if (!gst_registry_binary_save_pad_template (list, template)) { - GST_ERROR ("Can't fill pad template, aborting."); - goto fail; - } - } - - /* pack element factory strings */ - gst_registry_binary_save_const_string (list, factory->details.author); - gst_registry_binary_save_const_string (list, factory->details.description); - gst_registry_binary_save_const_string (list, factory->details.klass); - gst_registry_binary_save_const_string (list, factory->details.longname); - } else if (GST_IS_TYPE_FIND_FACTORY (feature)) { - GstBinaryTypeFindFactory *tff; - GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature); - - tff = g_malloc0 (sizeof (GstBinaryTypeFindFactory)); - chk = - gst_registry_binary_make_data (tff, sizeof (GstBinaryTypeFindFactory)); - tff->nextensions = 0; - pf = (GstBinaryPluginFeature *) tff; - - /* save extensions */ - if (factory->extensions) { - while (factory->extensions[tff->nextensions]) { - gst_registry_binary_save_const_string (list, - factory->extensions[tff->nextensions++]); - } - } - /* save caps */ - if (factory->caps) { - GstCaps *copy = gst_caps_copy (factory->caps); - gchar *str; - - /* we copy the caps here so we can simplify them - * before saving. This is a lot faster when loading - * them later on */ - gst_caps_do_simplify (copy); - str = gst_caps_to_string (copy); - gst_caps_unref (copy); - gst_registry_binary_save_string (list, str); - } else { - gst_registry_binary_save_const_string (list, ""); - } - - } else if (GST_IS_INDEX_FACTORY (feature)) { - GstIndexFactory *factory = GST_INDEX_FACTORY (feature); - - pf = g_malloc0 (sizeof (GstBinaryPluginFeature)); - chk = gst_registry_binary_make_data (pf, sizeof (GstBinaryPluginFeature)); - pf->rank = feature->rank; - - /* pack element factory strings */ - gst_registry_binary_save_const_string (list, factory->longdesc); - } else { - GST_WARNING ("unhandled feature type '%s'", type_name); - } - - if (pf) { - pf->rank = feature->rank; - *list = g_list_prepend (*list, chk); - - /* pack plugin feature strings */ - gst_registry_binary_save_const_string (list, feature->name); - gst_registry_binary_save_const_string (list, (gchar *) type_name); - - return TRUE; - } - - /* Errors */ -fail: - g_free (chk); - g_free (pf); - return FALSE; -} - -static gboolean -gst_registry_binary_save_plugin_dep (GList ** list, GstPluginDep * dep) -{ - GstBinaryDep *ed; - GstBinaryChunk *chk; - gchar **s; - - ed = g_new0 (GstBinaryDep, 1); - chk = gst_registry_binary_make_data (ed, sizeof (GstBinaryDep)); - - ed->flags = dep->flags; - ed->n_env_vars = 0; - ed->n_paths = 0; - ed->n_names = 0; - - ed->env_hash = dep->env_hash; - ed->stat_hash = dep->stat_hash; - - for (s = dep->env_vars; s != NULL && *s != NULL; ++s, ++ed->n_env_vars) - gst_registry_binary_save_string (list, g_strdup (*s)); - - for (s = dep->paths; s != NULL && *s != NULL; ++s, ++ed->n_paths) - gst_registry_binary_save_string (list, g_strdup (*s)); - - for (s = dep->names; s != NULL && *s != NULL; ++s, ++ed->n_names) - gst_registry_binary_save_string (list, g_strdup (*s)); - - *list = g_list_prepend (*list, chk); - - GST_LOG ("Saved external plugin dependency"); - return TRUE; -} - -/* - * gst_registry_binary_save_plugin: - * - * Adapt a GstPlugin to our GstBinaryPluginElement structure, and write it to - * the registry file. - */ -static gboolean -gst_registry_binary_save_plugin (GList ** list, GstRegistry * registry, - GstPlugin * plugin) -{ - GstBinaryPluginElement *pe; - GstBinaryChunk *chk; - GList *plugin_features = NULL; - GList *walk; - - pe = g_malloc0 (sizeof (GstBinaryPluginElement)); - chk = gst_registry_binary_make_data (pe, sizeof (GstBinaryPluginElement)); - - pe->file_size = plugin->file_size; - pe->file_mtime = plugin->file_mtime; - pe->n_deps = 0; - pe->nfeatures = 0; - - /* pack external deps */ - for (walk = plugin->priv->deps; walk != NULL; walk = walk->next) { - if (!gst_registry_binary_save_plugin_dep (list, walk->data)) { - GST_ERROR ("Could not save external plugin dependency, aborting."); - goto fail; - } - ++pe->n_deps; - } - - /* pack plugin features */ - plugin_features = - gst_registry_get_feature_list_by_plugin (registry, plugin->desc.name); - for (walk = plugin_features; walk; walk = g_list_next (walk), pe->nfeatures++) { - GstPluginFeature *feature = GST_PLUGIN_FEATURE (walk->data); - - if (!gst_registry_binary_save_feature (list, feature)) { - GST_ERROR ("Can't fill plugin feature, aborting."); - goto fail; - } - } - GST_DEBUG ("Save plugin '%s' with %d feature(s)", plugin->desc.name, - pe->nfeatures); - - gst_plugin_feature_list_free (plugin_features); - - /* pack cache data */ - if (plugin->priv->cache_data) { - gchar *cache_str = gst_structure_to_string (plugin->priv->cache_data); - gst_registry_binary_save_string (list, cache_str); - } else { - gst_registry_binary_save_const_string (list, ""); - } - - /* pack plugin element strings */ - gst_registry_binary_save_const_string (list, plugin->desc.origin); - gst_registry_binary_save_const_string (list, plugin->desc.package); - gst_registry_binary_save_const_string (list, plugin->desc.source); - gst_registry_binary_save_const_string (list, plugin->desc.license); - gst_registry_binary_save_const_string (list, plugin->desc.version); - gst_registry_binary_save_const_string (list, plugin->filename); - gst_registry_binary_save_const_string (list, plugin->desc.description); - gst_registry_binary_save_const_string (list, plugin->desc.name); - - *list = g_list_prepend (*list, chk); - - GST_DEBUG ("Found %d features in plugin \"%s\"", pe->nfeatures, - plugin->desc.name); - return TRUE; - - /* Errors */ -fail: - gst_plugin_feature_list_free (plugin_features); - g_free (chk); - g_free (pe); - return FALSE; -} - /** * gst_registry_binary_write_cache: * @registry: a #GstRegistry @@ -747,7 +371,7 @@ gst_registry_binary_write_cache (GstRegistry * registry, const char *location) continue; } - if (!gst_registry_binary_save_plugin (&to_write, registry, plugin)) { + if (!_priv_gst_registry_chunks_save_plugin (&to_write, registry, plugin)) { GST_ERROR ("Can't write binary plugin information for \"%s\"", plugin->filename); } @@ -760,7 +384,7 @@ gst_registry_binary_write_cache (GstRegistry * registry, const char *location) goto fail_free_list; /* write magic */ - if (gst_registry_binary_cache_write (registry, cache, file_position, + if (gst_registry_binary_cache_write (cache, file_position, &magic, sizeof (GstBinaryRegistryMagic)) != sizeof (GstBinaryRegistryMagic)) { GST_ERROR ("Failed to write binary registry magic"); @@ -770,20 +394,20 @@ gst_registry_binary_write_cache (GstRegistry * registry, const char *location) /* write out data chunks */ for (walk = to_write; walk; walk = g_list_next (walk)) { - GstBinaryChunk *cur = walk->data; + GstRegistryChunk *cur = walk->data; + gboolean res; - if (!gst_registry_binary_write_chunk (registry, cache, cur->data, cur->size, - &file_position, cur->align)) { - goto fail_free_list; - } - if (!(cur->flags & GST_BINARY_REGISTRY_FLAG_CONST)) + res = gst_registry_binary_write_chunk (cache, cur, &file_position); + if (!(cur->flags & GST_REGISTRY_CHUNK_FLAG_CONST)) g_free (cur->data); g_free (cur); walk->data = NULL; + if (!res) + goto fail_free_list; } g_list_free (to_write); - if (!gst_registry_binary_cache_finish (registry, cache, TRUE)) + if (!gst_registry_binary_cache_finish (cache, TRUE)) return FALSE; return TRUE; @@ -792,10 +416,10 @@ gst_registry_binary_write_cache (GstRegistry * registry, const char *location) fail_free_list: { for (walk = to_write; walk; walk = g_list_next (walk)) { - GstBinaryChunk *cur = walk->data; + GstRegistryChunk *cur = walk->data; if (cur) { - if (!(cur->flags & GST_BINARY_REGISTRY_FLAG_CONST)) + if (!(cur->flags & GST_REGISTRY_CHUNK_FLAG_CONST)) g_free (cur->data); g_free (cur); } @@ -803,7 +427,7 @@ fail_free_list: g_list_free (to_write); if (cache) - (void) gst_registry_binary_cache_finish (registry, cache, FALSE); + (void) gst_registry_binary_cache_finish (cache, FALSE); /* fall through */ } fail: @@ -857,354 +481,6 @@ fail: return -1; } - -/* - * gst_registry_binary_load_pad_template: - * - * Make a new GstStaticPadTemplate from current GstBinaryPadTemplate structure - * - * Returns: new GstStaticPadTemplate - */ -static gboolean -gst_registry_binary_load_pad_template (GstElementFactory * factory, gchar ** in, - gchar * end) -{ - GstBinaryPadTemplate *pt; - GstStaticPadTemplate *template = NULL; - - align (*in); - GST_DEBUG ("Reading/casting for GstBinaryPadTemplate at address %p", *in); - unpack_element (*in, pt, GstBinaryPadTemplate, end, fail); - - template = g_new0 (GstStaticPadTemplate, 1); - template->presence = pt->presence; - template->direction = pt->direction; - - /* unpack pad template strings */ - unpack_const_string (*in, template->name_template, end, fail); - unpack_string (*in, template->static_caps.string, end, fail); - - __gst_element_factory_add_static_pad_template (factory, template); - GST_DEBUG ("Added pad_template %s", template->name_template); - - return TRUE; - -fail: - GST_INFO ("Reading pad template failed"); - g_free (template); - return FALSE; -} - - -/* - * gst_registry_binary_load_feature: - * - * Make a new GstPluginFeature from current binary plugin feature structure - * - * Returns: new GstPluginFeature - */ -static gboolean -gst_registry_binary_load_feature (GstRegistry * registry, gchar ** in, - gchar * end, const gchar * plugin_name) -{ - GstBinaryPluginFeature *pf = NULL; - GstPluginFeature *feature = NULL; - gchar *type_name = NULL, *str; - GType type; - guint i; - - /* unpack plugin feature strings */ - unpack_string (*in, type_name, end, fail); - - if (G_UNLIKELY (!type_name)) { - GST_ERROR ("No feature type name"); - return FALSE; - } - - GST_DEBUG ("Plugin '%s' feature typename : '%s'", plugin_name, type_name); - - if (G_UNLIKELY (!(type = g_type_from_name (type_name)))) { - GST_ERROR ("Unknown type from typename '%s' for plugin '%s'", type_name, - plugin_name); - g_free (type_name); - return FALSE; - } - if (G_UNLIKELY ((feature = g_object_new (type, NULL)) == NULL)) { - GST_ERROR ("Can't create feature from type"); - g_free (type_name); - return FALSE; - } - - if (G_UNLIKELY (!GST_IS_PLUGIN_FEATURE (feature))) { - GST_ERROR ("typename : '%s' is not a plugin feature", type_name); - goto fail; - } - - /* unpack more plugin feature strings */ - unpack_string (*in, feature->name, end, fail); - - if (GST_IS_ELEMENT_FACTORY (feature)) { - GstBinaryElementFactory *ef; - guint n; - GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (feature); - - align (*in); - GST_LOG ("Reading/casting for GstBinaryElementFactory at address %p", *in); - unpack_element (*in, ef, GstBinaryElementFactory, end, fail); - pf = (GstBinaryPluginFeature *) ef; - - /* unpack element factory strings */ - unpack_string (*in, factory->details.longname, end, fail); - unpack_string (*in, factory->details.klass, end, fail); - unpack_string (*in, factory->details.description, end, fail); - unpack_string (*in, factory->details.author, end, fail); - n = ef->npadtemplates; - GST_DEBUG ("Element factory : '%s' with npadtemplates=%d", - factory->details.longname, n); - - /* load pad templates */ - for (i = 0; i < n; i++) { - if (G_UNLIKELY (!gst_registry_binary_load_pad_template (factory, in, - end))) { - GST_ERROR ("Error while loading binary pad template"); - goto fail; - } - } - - /* load uritypes */ - if (G_UNLIKELY ((n = ef->nuriprotocols))) { - GST_DEBUG ("Reading %d UriTypes at address %p", n, *in); - - align (*in); - factory->uri_type = *((guint *) * in); - *in += sizeof (factory->uri_type); - /*unpack_element(*in, &factory->uri_type, factory->uri_type, end, fail); */ - - factory->uri_protocols = g_new0 (gchar *, n + 1); - for (i = 0; i < n; i++) { - unpack_string (*in, str, end, fail); - factory->uri_protocols[i] = str; - } - } - - /* load interfaces */ - if (G_UNLIKELY ((n = ef->ninterfaces))) { - GST_DEBUG ("Reading %d Interfaces at address %p", n, *in); - for (i = 0; i < n; i++) { - unpack_string (*in, str, end, fail); - __gst_element_factory_add_interface (factory, str); - g_free (str); - } - } - } else if (GST_IS_TYPE_FIND_FACTORY (feature)) { - GstBinaryTypeFindFactory *tff; - GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature); - - align (*in); - GST_DEBUG ("Reading/casting for GstBinaryPluginFeature at address %p", *in); - unpack_element (*in, tff, GstBinaryTypeFindFactory, end, fail); - pf = (GstBinaryPluginFeature *) tff; - - /* load caps */ - unpack_string (*in, str, end, fail); - factory->caps = (str && *str) ? gst_caps_from_string (str) : NULL; - g_free (str); - /* load extensions */ - if (tff->nextensions) { - GST_DEBUG ("Reading %d Typefind extensions at address %p", - tff->nextensions, *in); - factory->extensions = g_new0 (gchar *, tff->nextensions + 1); - for (i = 0; i < tff->nextensions; i++) { - unpack_string (*in, str, end, fail); - factory->extensions[i] = str; - } - } - } else if (GST_IS_INDEX_FACTORY (feature)) { - GstIndexFactory *factory = GST_INDEX_FACTORY (feature); - - align (*in); - GST_DEBUG ("Reading/casting for GstBinaryPluginFeature at address %p", *in); - unpack_element (*in, pf, GstBinaryPluginFeature, end, fail); - - /* unpack index factory strings */ - unpack_string (*in, factory->longdesc, end, fail); - } else { - GST_WARNING ("unhandled factory type : %s", G_OBJECT_TYPE_NAME (feature)); - goto fail; - } - - feature->rank = pf->rank; - - /* should already be the interned string, but better make sure */ - feature->plugin_name = g_intern_string (plugin_name); - - gst_registry_add_feature (registry, feature); - GST_DEBUG ("Added feature %s", feature->name); - - g_free (type_name); - return TRUE; - - /* Errors */ -fail: - GST_INFO ("Reading plugin feature failed"); - g_free (type_name); - if (feature) { - if (GST_IS_OBJECT (feature)) - gst_object_unref (feature); - else - g_object_unref (feature); - } - return FALSE; -} - -static gchar ** -gst_registry_binary_load_plugin_dep_strv (gchar ** in, gchar * end, guint n) -{ - gchar **arr; - - if (n == 0) - return NULL; - - arr = g_new0 (gchar *, n + 1); - while (n > 0) { - unpack_string (*in, arr[n - 1], end, fail); - --n; - } - return arr; -fail: - GST_INFO ("Reading plugin dependency strings failed"); - return NULL; -} - -static gboolean -gst_registry_binary_load_plugin_dep (GstPlugin * plugin, gchar ** in, - gchar * end) -{ - GstPluginDep *dep; - GstBinaryDep *d; - gchar **s; - - align (*in); - GST_LOG_OBJECT (plugin, "Unpacking GstBinaryDep from %p", *in); - unpack_element (*in, d, GstBinaryDep, end, fail); - - dep = g_new0 (GstPluginDep, 1); - - dep->env_hash = d->env_hash; - dep->stat_hash = d->stat_hash; - - dep->flags = d->flags; - - dep->names = gst_registry_binary_load_plugin_dep_strv (in, end, d->n_names); - dep->paths = gst_registry_binary_load_plugin_dep_strv (in, end, d->n_paths); - dep->env_vars = - gst_registry_binary_load_plugin_dep_strv (in, end, d->n_env_vars); - - plugin->priv->deps = g_list_append (plugin->priv->deps, dep); - - GST_DEBUG_OBJECT (plugin, "Loaded external plugin dependency from registry: " - "env_hash: %08x, stat_hash: %08x", dep->env_hash, dep->stat_hash); - for (s = dep->env_vars; s != NULL && *s != NULL; ++s) - GST_LOG_OBJECT (plugin, " evar: %s", *s); - for (s = dep->paths; s != NULL && *s != NULL; ++s) - GST_LOG_OBJECT (plugin, " path: %s", *s); - for (s = dep->names; s != NULL && *s != NULL; ++s) - GST_LOG_OBJECT (plugin, " name: %s", *s); - - return TRUE; -fail: - GST_INFO ("Reading plugin dependency failed"); - return FALSE; -} - -/* - * gst_registry_binary_load_plugin: - * - * Make a new GstPlugin from current GstBinaryPluginElement structure - * and save it to the GstRegistry. Return an offset to the next - * GstBinaryPluginElement structure. - */ -static gboolean -gst_registry_binary_load_plugin (GstRegistry * registry, gchar ** in, - gchar * end) -{ - GstBinaryPluginElement *pe; - GstPlugin *plugin = NULL; - gchar *cache_str = NULL; - guint i, n; - - align (*in); - GST_LOG ("Reading/casting for GstBinaryPluginElement at address %p", *in); - unpack_element (*in, pe, GstBinaryPluginElement, end, fail); - - plugin = g_object_new (GST_TYPE_PLUGIN, NULL); - - /* TODO: also set GST_PLUGIN_FLAG_CONST */ - plugin->flags |= GST_PLUGIN_FLAG_CACHED; - plugin->file_mtime = pe->file_mtime; - plugin->file_size = pe->file_size; - - /* unpack plugin element strings */ - unpack_const_string (*in, plugin->desc.name, end, fail); - unpack_string (*in, plugin->desc.description, end, fail); - unpack_string (*in, plugin->filename, end, fail); - unpack_const_string (*in, plugin->desc.version, end, fail); - unpack_const_string (*in, plugin->desc.license, end, fail); - unpack_const_string (*in, plugin->desc.source, end, fail); - unpack_const_string (*in, plugin->desc.package, end, fail); - unpack_const_string (*in, plugin->desc.origin, end, fail); - GST_LOG ("read strings for name='%s'", plugin->desc.name); - GST_LOG (" desc.description='%s'", plugin->desc.description); - GST_LOG (" filename='%s'", plugin->filename); - GST_LOG (" desc.version='%s'", plugin->desc.version); - GST_LOG (" desc.license='%s'", plugin->desc.license); - GST_LOG (" desc.source='%s'", plugin->desc.source); - GST_LOG (" desc.package='%s'", plugin->desc.package); - GST_LOG (" desc.origin='%s'", plugin->desc.origin); - - /* unpack cache data */ - unpack_string (*in, cache_str, end, fail); - if (*cache_str) { - plugin->priv->cache_data = gst_structure_from_string (cache_str, NULL); - } - g_free (cache_str); - - plugin->basename = g_path_get_basename (plugin->filename); - - /* Takes ownership of plugin */ - gst_registry_add_plugin (registry, plugin); - n = pe->nfeatures; - GST_DEBUG ("Added plugin '%s' plugin with %d features from binary registry", - plugin->desc.name, n); - - /* Load plugin features */ - for (i = 0; i < n; i++) { - if (G_UNLIKELY (!gst_registry_binary_load_feature (registry, in, end, - plugin->desc.name))) { - GST_ERROR ("Error while loading binary feature"); - gst_registry_remove_plugin (registry, plugin); - goto fail; - } - } - - /* Load external plugin dependencies */ - for (i = 0; i < pe->n_deps; ++i) { - if (G_UNLIKELY (!gst_registry_binary_load_plugin_dep (plugin, in, end))) { - GST_ERROR_OBJECT (plugin, "Could not read external plugin dependency"); - gst_registry_remove_plugin (registry, plugin); - goto fail; - } - } - - return TRUE; - - /* Errors */ -fail: - GST_INFO ("Reading plugin failed"); - return FALSE; -} - - /** * gst_registry_binary_read_cache: * @registry: a #GstRegistry @@ -1243,6 +519,14 @@ gst_registry_binary_read_cache (GstRegistry * registry, const char *location) GST_INFO ("Unable to mmap file %s : %s", location, err->message); g_error_free (err); err = NULL; + } + + if (contents == NULL) { + /* Error mmap-ing the cache, try a plain memory read */ + if (mapped) { + g_mapped_file_free (mapped); + mapped = NULL; + } g_file_get_contents (location, &contents, &size, &err); if (err != NULL) { @@ -1258,8 +542,6 @@ gst_registry_binary_read_cache (GstRegistry * registry, const char *location) GST_ERROR ("Can't load file %s : %s", location, g_strerror (errno)); goto Error; } - /* check length for header */ - size = g_mapped_file_get_length (mapped); } /* in is a cursor pointer, we initialize it with the begin of registry and is updated on each read */ @@ -1282,20 +564,20 @@ gst_registry_binary_read_cache (GstRegistry * registry, const char *location) } /* check if there are plugins in the file */ - if (G_UNLIKELY (!(((gsize) in + sizeof (GstBinaryPluginElement)) < + if (G_UNLIKELY (!(((gsize) in + sizeof (GstRegistryChunkPluginElement)) < (gsize) contents + size))) { GST_INFO ("No binary plugins structure to read"); /* empty file, this is not an error */ } else { gchar *end = contents + size; - /* read as long as we still have space for a GstBinaryPluginElement */ + /* read as long as we still have space for a GstRegistryChunkPluginElement */ for (; - ((gsize) in + sizeof (GstBinaryPluginElement)) < + ((gsize) in + sizeof (GstRegistryChunkPluginElement)) < (gsize) contents + size;) { GST_DEBUG ("reading binary registry %" G_GSIZE_FORMAT "(%x)/%" G_GSIZE_FORMAT, (gsize) in - (gsize) contents, (guint) ((gsize) in - (gsize) contents), size); - if (!gst_registry_binary_load_plugin (registry, &in, end)) { + if (!_priv_gst_registry_chunks_load_plugin (registry, &in, end, NULL)) { GST_ERROR ("Problem while reading binary registry %s", location); goto Error; } @@ -1313,6 +595,9 @@ gst_registry_binary_read_cache (GstRegistry * registry, const char *location) /* TODO: once we re-use the pointers to registry contents, return here */ Error: + if (err) + g_error_free (err); + #ifndef GST_DISABLE_GST_DEBUG g_timer_destroy (timer); #endif @@ -1324,9 +609,8 @@ Error: return res; } - -/* FIXME 0.11: these are here for backwards compatibility */ - +/* FIXME 0.11: these symbols are here for backwards compatibility and should + * be removed or made private */ gboolean gst_registry_xml_read_cache (GstRegistry * registry, const char *location) { |