bufferpool: Fix the buffer size reset code
[platform/upstream/gstreamer.git] / gst / gstregistrychunks.c
index 12e0f5a..6801a18 100644 (file)
@@ -20,8 +20,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 
 #ifdef HAVE_CONFIG_H
 #include <gst/gst_private.h>
 #include <gst/gstconfig.h>
 #include <gst/gstelement.h>
+#include <gst/gsttracerfactory.h>
 #include <gst/gsttypefind.h>
 #include <gst/gsttypefindfactory.h>
+#include <gst/gstdeviceproviderfactory.h>
+#include <gst/gstdynamictypefactory.h>
 #include <gst/gsturi.h>
 #include <gst/gstinfo.h>
 #include <gst/gstenumtypes.h>
@@ -60,7 +63,7 @@ _strnlen (const gchar * str, gint maxlen)
 #define unpack_element(inptr, outptr, element, endptr, error_label) G_STMT_START{ \
   if (inptr + sizeof(element) > endptr) { \
     GST_ERROR ("Failed reading element " G_STRINGIFY (element)  \
-        ". Have %d bytes need %" G_GSSIZE_FORMAT, \
+        ". Have %d bytes need %" G_GSIZE_FORMAT, \
         (int) (endptr - inptr), sizeof(element)); \
     goto error_label; \
   } \
@@ -84,10 +87,30 @@ _strnlen (const gchar * str, gint maxlen)
   inptr += _len + 1; \
 }G_STMT_END
 
+#define unpack_string_nocopy(inptr, outptr, endptr, error_label)  G_STMT_START{\
+  gint _len = _strnlen (inptr, (endptr-inptr)); \
+  if (_len == -1) \
+    goto error_label; \
+  outptr = (const gchar *)inptr; \
+  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))
 
+void
+_priv_gst_registry_chunk_free (GstRegistryChunk * chunk)
+{
+  if (!(chunk->flags & GST_REGISTRY_CHUNK_FLAG_CONST)) {
+    if ((chunk->flags & GST_REGISTRY_CHUNK_FLAG_MALLOC))
+      g_free (chunk->data);
+    else
+      g_slice_free1 (chunk->size, chunk->data);
+  }
+  g_slice_free (GstRegistryChunk, chunk);
+}
+
 /*
  * gst_registry_chunks_save_const_string:
  *
@@ -105,7 +128,7 @@ gst_registry_chunks_save_const_string (GList ** list, const gchar * str)
     str = "";
   }
 
-  chunk = g_malloc (sizeof (GstRegistryChunk));
+  chunk = g_slice_new (GstRegistryChunk);
   chunk->data = (gpointer) str;
   chunk->size = strlen ((gchar *) chunk->data) + 1;
   chunk->flags = GST_REGISTRY_CHUNK_FLAG_CONST;
@@ -126,10 +149,10 @@ gst_registry_chunks_save_string (GList ** list, gchar * str)
 {
   GstRegistryChunk *chunk;
 
-  chunk = g_malloc (sizeof (GstRegistryChunk));
+  chunk = g_slice_new (GstRegistryChunk);
   chunk->data = str;
   chunk->size = strlen ((gchar *) chunk->data) + 1;
-  chunk->flags = GST_REGISTRY_CHUNK_FLAG_NONE;
+  chunk->flags = GST_REGISTRY_CHUNK_FLAG_MALLOC;
   chunk->align = FALSE;
   *list = g_list_prepend (*list, chunk);
   return TRUE;
@@ -147,7 +170,7 @@ gst_registry_chunks_make_data (gpointer data, gulong size)
 {
   GstRegistryChunk *chunk;
 
-  chunk = g_malloc (sizeof (GstRegistryChunk));
+  chunk = g_slice_new (GstRegistryChunk);
   chunk->data = data;
   chunk->size = size;
   chunk->flags = GST_REGISTRY_CHUNK_FLAG_NONE;
@@ -170,7 +193,7 @@ gst_registry_chunks_save_pad_template (GList ** list,
   GstRegistryChunkPadTemplate *pt;
   GstRegistryChunk *chk;
 
-  pt = g_malloc0 (sizeof (GstRegistryChunkPadTemplate));
+  pt = g_slice_new (GstRegistryChunkPadTemplate);
   chk =
       gst_registry_chunks_make_data (pt, sizeof (GstRegistryChunkPadTemplate));
 
@@ -197,10 +220,11 @@ gst_registry_chunks_save_pad_template (GList ** list,
 static gboolean
 gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature)
 {
-  const gchar *type_name = g_type_name (G_OBJECT_TYPE (feature));
+  const gchar *type_name = G_OBJECT_TYPE_NAME (feature);
   GstRegistryChunkPluginFeature *pf = NULL;
   GstRegistryChunk *chk = NULL;
   GList *walk;
+  gsize pf_size = 0;
 
   if (!type_name) {
     GST_ERROR ("NULL feature type_name, aborting.");
@@ -211,10 +235,12 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature)
     GstRegistryChunkElementFactory *ef;
     GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
 
-    ef = g_malloc0 (sizeof (GstRegistryChunkElementFactory));
-    chk =
-        gst_registry_chunks_make_data (ef,
-        sizeof (GstRegistryChunkElementFactory));
+    /* Initialize with zeroes because of struct padding and
+     * valgrind complaining about copying uninitialized memory
+     */
+    ef = g_slice_new0 (GstRegistryChunkElementFactory);
+    pf_size = sizeof (GstRegistryChunkElementFactory);
+    chk = gst_registry_chunks_make_data (ef, pf_size);
     ef->npadtemplates = ef->ninterfaces = ef->nuriprotocols = 0;
     pf = (GstRegistryChunkPluginFeature *) ef;
 
@@ -223,8 +249,8 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature)
         walk = g_list_next (walk), ef->ninterfaces++) {
       gst_registry_chunks_save_const_string (list, (gchar *) walk->data);
     }
-    GST_DEBUG ("Feature %s: saved %d interfaces %d pad templates",
-        feature->name, ef->ninterfaces, ef->npadtemplates);
+    GST_DEBUG_OBJECT (feature, "saved %d interfaces %d pad templates",
+        ef->ninterfaces, ef->npadtemplates);
 
     /* save uritypes */
     if (GST_URI_TYPE_IS_VALID (factory->uri_type)) {
@@ -243,10 +269,10 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature)
           ef->nuriprotocols++;
         }
         *list = g_list_prepend (*list, subchk);
-        GST_DEBUG ("Saved %d UriTypes", ef->nuriprotocols);
+        GST_DEBUG_OBJECT (feature, "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);
+            " any protocols it can handle", GST_OBJECT_NAME (feature));
       }
     }
 
@@ -256,25 +282,25 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature)
       GstStaticPadTemplate *template = walk->data;
 
       if (!gst_registry_chunks_save_pad_template (list, template)) {
-        GST_ERROR ("Can't fill pad template, aborting.");
+        GST_ERROR_OBJECT (feature, "Can't fill pad template, aborting.");
         goto fail;
       }
     }
 
-    /* pack element factory strings */
-    gst_registry_chunks_save_const_string (list, factory->details.author);
-    gst_registry_chunks_save_const_string (list, factory->details.description);
-    gst_registry_chunks_save_const_string (list, factory->details.klass);
-    gst_registry_chunks_save_const_string (list, factory->details.longname);
+    /* pack element metadata strings */
+    gst_registry_chunks_save_string (list,
+        gst_structure_to_string (factory->metadata));
   } else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
     GstRegistryChunkTypeFindFactory *tff;
     GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature);
     gchar *str;
 
-    tff = g_malloc0 (sizeof (GstRegistryChunkTypeFindFactory));
-    chk =
-        gst_registry_chunks_make_data (tff,
-        sizeof (GstRegistryChunkTypeFindFactory));
+    /* Initialize with zeroes because of struct padding and
+     * valgrind complaining about copying uninitialized memory
+     */
+    tff = g_slice_new0 (GstRegistryChunkTypeFindFactory);
+    pf_size = sizeof (GstRegistryChunkTypeFindFactory);
+    chk = gst_registry_chunks_make_data (tff, pf_size);
     tff->nextensions = 0;
     pf = (GstRegistryChunkPluginFeature *) tff;
 
@@ -285,32 +311,54 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature)
             factory->extensions[tff->nextensions++]);
       }
     }
+    GST_DEBUG_OBJECT (feature, "saved %d extensions", tff->nextensions);
     /* save caps */
     if (factory->caps) {
-      /* we copy the caps here so we can simplify them before saving. This
-       * is a lot faster when loading them later on */
-      GstCaps *copy = gst_caps_copy (factory->caps);
+      GstCaps *fcaps = gst_caps_ref (factory->caps);
+      /* we simplify the caps before saving. This is a lot faster
+       * when loading them later on */
+      fcaps = gst_caps_simplify (fcaps);
+      str = gst_caps_to_string (fcaps);
+      gst_caps_unref (fcaps);
 
-      gst_caps_do_simplify (copy);
-      str = gst_caps_to_string (copy);
-      gst_caps_unref (copy);
       gst_registry_chunks_save_string (list, str);
     } else {
       gst_registry_chunks_save_const_string (list, "");
     }
-  } else if (GST_IS_INDEX_FACTORY (feature)) {
-    GstIndexFactory *factory = GST_INDEX_FACTORY (feature);
-
-    pf = g_malloc0 (sizeof (GstRegistryChunkPluginFeature));
+  } else if (GST_IS_DEVICE_PROVIDER_FACTORY (feature)) {
+    GstRegistryChunkDeviceProviderFactory *tff;
+    GstDeviceProviderFactory *factory = GST_DEVICE_PROVIDER_FACTORY (feature);
+
+    /* Initialize with zeroes because of struct padding and
+     * valgrind complaining about copying uninitialized memory
+     */
+    tff = g_slice_new0 (GstRegistryChunkDeviceProviderFactory);
     chk =
-        gst_registry_chunks_make_data (pf,
-        sizeof (GstRegistryChunkPluginFeature));
-    pf->rank = feature->rank;
+        gst_registry_chunks_make_data (tff,
+        sizeof (GstRegistryChunkDeviceProviderFactory));
+    pf = (GstRegistryChunkPluginFeature *) tff;
+
 
-    /* pack element factory strings */
-    gst_registry_chunks_save_const_string (list, factory->longdesc);
+    /* pack element metadata strings */
+    gst_registry_chunks_save_string (list,
+        gst_structure_to_string (factory->metadata));
+  } else if (GST_IS_TRACER_FACTORY (feature)) {
+    /* Initialize with zeroes because of struct padding and
+     * valgrind complaining about copying uninitialized memory
+     */
+    pf = g_slice_new0 (GstRegistryChunkPluginFeature);
+    pf_size = sizeof (GstRegistryChunkPluginFeature);
+    chk = gst_registry_chunks_make_data (pf, pf_size);
+  } else if (GST_IS_DYNAMIC_TYPE_FACTORY (feature)) {
+    GstRegistryChunkDynamicTypeFactory *tmp;
+
+    tmp = g_slice_new0 (GstRegistryChunkDynamicTypeFactory);
+    chk =
+        gst_registry_chunks_make_data (tmp,
+        sizeof (GstRegistryChunkDynamicTypeFactory));
+    pf = (GstRegistryChunkPluginFeature *) tmp;
   } else {
-    GST_WARNING ("unhandled feature type '%s'", type_name);
+    GST_WARNING_OBJECT (feature, "unhandled feature type '%s'", type_name);
   }
 
   if (pf) {
@@ -318,7 +366,7 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature)
     *list = g_list_prepend (*list, chk);
 
     /* pack plugin feature strings */
-    gst_registry_chunks_save_const_string (list, feature->name);
+    gst_registry_chunks_save_const_string (list, GST_OBJECT_NAME (feature));
     gst_registry_chunks_save_const_string (list, (gchar *) type_name);
 
     return TRUE;
@@ -326,8 +374,8 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature)
 
   /* Errors */
 fail:
-  g_free (chk);
-  g_free (pf);
+  g_slice_free (GstRegistryChunk, chk);
+  g_slice_free1 (pf_size, pf);
   return FALSE;
 }
 
@@ -338,7 +386,7 @@ gst_registry_chunks_save_plugin_dep (GList ** list, GstPluginDep * dep)
   GstRegistryChunk *chk;
   gchar **s;
 
-  ed = g_malloc0 (sizeof (GstRegistryChunkDep));
+  ed = g_slice_new (GstRegistryChunkDep);
   chk = gst_registry_chunks_make_data (ed, sizeof (GstRegistryChunkDep));
 
   ed->flags = dep->flags;
@@ -380,7 +428,7 @@ _priv_gst_registry_chunks_save_plugin (GList ** list, GstRegistry * registry,
   GList *plugin_features = NULL;
   GList *walk;
 
-  pe = g_malloc0 (sizeof (GstRegistryChunkPluginElement));
+  pe = g_slice_new (GstRegistryChunkPluginElement);
   chk =
       gst_registry_chunks_make_data (pe,
       sizeof (GstRegistryChunkPluginElement));
@@ -422,6 +470,8 @@ _priv_gst_registry_chunks_save_plugin (GList ** list, GstRegistry * registry,
   }
 
   /* pack plugin element strings */
+  gst_registry_chunks_save_const_string (list,
+      (plugin->desc.release_datetime) ? plugin->desc.release_datetime : "");
   gst_registry_chunks_save_const_string (list, plugin->desc.origin);
   gst_registry_chunks_save_const_string (list, plugin->desc.package);
   gst_registry_chunks_save_const_string (list, plugin->desc.source);
@@ -440,8 +490,8 @@ _priv_gst_registry_chunks_save_plugin (GList ** list, GstRegistry * registry,
   /* Errors */
 fail:
   gst_plugin_feature_list_free (plugin_features);
-  g_free (chk);
-  g_free (pe);
+  g_slice_free (GstRegistryChunk, chk);
+  g_slice_free (GstRegistryChunkPluginElement, pe);
   return FALSE;
 }
 
@@ -465,13 +515,14 @@ gst_registry_chunks_load_pad_template (GstElementFactory * factory, gchar ** in,
       *in);
   unpack_element (*in, pt, GstRegistryChunkPadTemplate, end, fail);
 
-  template = g_new0 (GstStaticPadTemplate, 1);
+  template = g_slice_new (GstStaticPadTemplate);
   template->presence = pt->presence;
-  template->direction = pt->direction;
+  template->direction = (GstPadDirection) pt->direction;
+  template->static_caps.caps = NULL;
 
   /* unpack pad template strings */
   unpack_const_string (*in, template->name_template, end, fail);
-  unpack_string (*in, template->static_caps.string, end, fail);
+  unpack_const_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);
@@ -479,7 +530,8 @@ gst_registry_chunks_load_pad_template (GstElementFactory * factory, gchar ** in,
   return TRUE;
 fail:
   GST_INFO ("Reading pad template failed");
-  g_free (template);
+  if (template)
+    g_slice_free (GstStaticPadTemplate, template);
   return FALSE;
 }
 
@@ -492,17 +544,21 @@ 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;
-  gchar *type_name = NULL, *str;
-  gchar *feature_name;
+  const gchar *const_str, *type_name;
+  const gchar *feature_name;
+  const gchar *plugin_name;
+  gchar *str;
   GType type;
   guint i;
 
+  plugin_name = plugin->desc.name;
+
   /* unpack plugin feature strings */
-  unpack_string (*in, type_name, end, fail);
+  unpack_string_nocopy (*in, type_name, end, fail);
 
   if (G_UNLIKELY (!type_name)) {
     GST_ERROR ("No feature type name");
@@ -510,7 +566,7 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
   }
 
   /* unpack more plugin feature strings */
-  unpack_string (*in, feature_name, end, fail);
+  unpack_string_nocopy (*in, feature_name, end, fail);
 
   GST_DEBUG ("Plugin '%s' feature '%s' typename : '%s'", plugin_name,
       feature_name, type_name);
@@ -518,18 +574,13 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
   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);
-    g_free (feature_name);
     return FALSE;
   }
-  if (G_UNLIKELY ((feature = g_object_newv (type, 0, NULL)) == NULL)) {
+  if (G_UNLIKELY ((feature = g_object_new (type, NULL)) == NULL)) {
     GST_ERROR ("Can't create feature from type");
-    g_free (type_name);
-    g_free (feature_name);
     return FALSE;
   }
-
-  feature->name = feature_name;
+  gst_plugin_feature_set_name (feature, feature_name);
 
   if (G_UNLIKELY (!GST_IS_PLUGIN_FEATURE (feature))) {
     GST_ERROR ("typename : '%s' is not a plugin feature", type_name);
@@ -540,6 +591,8 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
     GstRegistryChunkElementFactory *ef;
     guint n;
     GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (feature);
+    gchar *str;
+    const gchar *meta_data_str;
 
     align (*in);
     GST_LOG ("Reading/casting for GstRegistryChunkElementFactory at address %p",
@@ -548,13 +601,18 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
     pf = (GstRegistryChunkPluginFeature *) 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);
+    unpack_string_nocopy (*in, meta_data_str, end, fail);
+    if (meta_data_str && *meta_data_str) {
+      factory->metadata = gst_structure_from_string (meta_data_str, NULL);
+      if (!factory->metadata) {
+        GST_ERROR
+            ("Error when trying to deserialize structure for metadata '%s'",
+            meta_data_str);
+        goto fail;
+      }
+    }
     n = ef->npadtemplates;
-    GST_DEBUG ("Element factory : '%s' with npadtemplates=%d",
-        factory->details.longname, n);
+    GST_DEBUG ("Element factory : npadtemplates=%d", n);
 
     /* load pad templates */
     for (i = 0; i < n; i++) {
@@ -584,9 +642,8 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
     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);
+        unpack_string_nocopy (*in, const_str, end, fail);
+        __gst_element_factory_add_interface (factory, const_str);
       }
     }
   } else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
@@ -600,31 +657,62 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
     unpack_element (*in, tff, GstRegistryChunkTypeFindFactory, end, fail);
     pf = (GstRegistryChunkPluginFeature *) tff;
 
-    /* load caps */
-    unpack_string (*in, str, end, fail);
-    factory->caps = (str && *str) ? gst_caps_from_string (str) : NULL;
-    g_free (str);
+    /* load typefinder caps */
+    unpack_string_nocopy (*in, const_str, end, fail);
+    if (const_str != NULL && *const_str != '\0')
+      factory->caps = gst_caps_from_string (const_str);
+    else
+      factory->caps = NULL;
+
     /* 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 in reverse order to maintain the correct order */
+      for (i = tff->nextensions; i > 0; i--) {
         unpack_string (*in, str, end, fail);
-        factory->extensions[i] = str;
+        factory->extensions[i - 1] = str;
       }
     }
-  } else if (GST_IS_INDEX_FACTORY (feature)) {
-    GstIndexFactory *factory = GST_INDEX_FACTORY (feature);
+  } else if (GST_IS_DEVICE_PROVIDER_FACTORY (feature)) {
+    GstRegistryChunkDeviceProviderFactory *dmf;
+    GstDeviceProviderFactory *factory = GST_DEVICE_PROVIDER_FACTORY (feature);
+    const gchar *meta_data_str;
+
+    align (*in);
+    GST_DEBUG
+        ("Reading/casting for GstRegistryChunkPluginFeature at address %p",
+        *in);
+
+    unpack_element (*in, dmf, GstRegistryChunkDeviceProviderFactory, end, fail);
+
+    pf = (GstRegistryChunkPluginFeature *) dmf;
 
+    /* unpack element factory strings */
+    unpack_string_nocopy (*in, meta_data_str, end, fail);
+    if (meta_data_str && *meta_data_str) {
+      factory->metadata = gst_structure_from_string (meta_data_str, NULL);
+      if (!factory->metadata) {
+        GST_ERROR
+            ("Error when trying to deserialize structure for metadata '%s'",
+            meta_data_str);
+        goto fail;
+      }
+    }
+  } else if (GST_IS_TRACER_FACTORY (feature)) {
     align (*in);
     GST_DEBUG
         ("Reading/casting for GstRegistryChunkPluginFeature at address %p",
         *in);
     unpack_element (*in, pf, GstRegistryChunkPluginFeature, end, fail);
+  } else if (GST_IS_DYNAMIC_TYPE_FACTORY (feature)) {
+    GstRegistryChunkDynamicTypeFactory *tmp;
+
+    align (*in);
+    unpack_element (*in, tmp, GstRegistryChunkDynamicTypeFactory, end, fail);
 
-    /* unpack index factory strings */
-    unpack_string (*in, factory->longdesc, end, fail);
+    pf = (GstRegistryChunkPluginFeature *) tmp;
   } else {
     GST_WARNING ("unhandled factory type : %s", G_OBJECT_TYPE_NAME (feature));
     goto fail;
@@ -632,19 +720,20 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
 
   feature->rank = pf->rank;
 
-  /* should already be the interned string, but better make sure */
-  feature->plugin_name = g_intern_string (plugin_name);
+  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", GST_OBJECT_NAME (feature),
+      plugin, plugin_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);
@@ -670,6 +759,7 @@ gst_registry_chunks_load_plugin_dep_strv (gchar ** in, gchar * end, guint n)
   return arr;
 fail:
   GST_INFO ("Reading plugin dependency strings failed");
+  g_strfreev (arr);
   return NULL;
 }
 
@@ -685,12 +775,12 @@ gst_registry_chunks_load_plugin_dep (GstPlugin * plugin, gchar ** in,
   GST_LOG_OBJECT (plugin, "Unpacking GstRegistryChunkDep from %p", *in);
   unpack_element (*in, d, GstRegistryChunkDep, end, fail);
 
-  dep = g_malloc0 (sizeof (GstPluginDep));
+  dep = g_slice_new (GstPluginDep);
 
   dep->env_hash = d->env_hash;
   dep->stat_hash = d->stat_hash;
 
-  dep->flags = d->flags;
+  dep->flags = (GstPluginDependencyFlags) d->flags;
 
   dep->names = gst_registry_chunks_load_plugin_dep_strv (in, end, d->n_names);
   dep->paths = gst_registry_chunks_load_plugin_dep_strv (in, end, d->n_paths);
@@ -726,33 +816,37 @@ gboolean
 _priv_gst_registry_chunks_load_plugin (GstRegistry * registry, gchar ** in,
     gchar * end, GstPlugin ** out_plugin)
 {
+#ifndef GST_DISABLE_GST_DEBUG
+  gchar *start = *in;
+#endif
   GstRegistryChunkPluginElement *pe;
+  const gchar *cache_str = NULL;
   GstPlugin *plugin = NULL;
-  gchar *cache_str = NULL;
   guint i, n;
-  gchar *start = *in;
 
   align (*in);
   GST_LOG ("Reading/casting for GstRegistryChunkPluginElement at address %p",
       *in);
   unpack_element (*in, pe, GstRegistryChunkPluginElement, end, fail);
 
-  plugin = g_object_newv (GST_TYPE_PLUGIN, 0, NULL);
+  plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
 
   /* TODO: also set GST_PLUGIN_FLAG_CONST */
-  plugin->flags |= GST_PLUGIN_FLAG_CACHED;
+  GST_OBJECT_FLAG_SET (plugin, 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_const_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);
+  unpack_const_string (*in, plugin->desc.release_datetime, 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);
@@ -761,18 +855,20 @@ _priv_gst_registry_chunks_load_plugin (GstRegistry * registry, gchar ** in,
   GST_LOG ("  desc.source='%s'", plugin->desc.source);
   GST_LOG ("  desc.package='%s'", plugin->desc.package);
   GST_LOG ("  desc.origin='%s'", plugin->desc.origin);
+  GST_LOG ("  desc.datetime=%s", plugin->desc.release_datetime);
+
+  if (plugin->desc.release_datetime[0] == '\0')
+    plugin->desc.release_datetime = NULL;
 
   /* unpack cache data */
-  unpack_string (*in, cache_str, end, fail);
-  if (*cache_str) {
+  unpack_string_nocopy (*in, cache_str, end, fail);
+  if (cache_str != NULL && *cache_str != '\0')
     plugin->priv->cache_data = gst_structure_from_string (cache_str, NULL);
-  }
-  g_free (cache_str);
 
   /* If the license string is 'BLACKLIST', mark this as a blacklisted
    * plugin */
   if (strcmp (plugin->desc.license, "BLACKLIST") == 0)
-    plugin->flags |= GST_PLUGIN_FLAG_BLACKLISTED;
+    GST_OBJECT_FLAG_SET (plugin, GST_PLUGIN_FLAG_BLACKLISTED);
 
   plugin->basename = g_path_get_basename (plugin->filename);
 
@@ -785,7 +881,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);
@@ -813,3 +909,39 @@ fail:
   GST_INFO ("Reading plugin failed after %u bytes", (guint) (end - start));
   return FALSE;
 }
+
+void
+_priv_gst_registry_chunks_save_global_header (GList ** list,
+    GstRegistry * registry, guint32 filter_env_hash)
+{
+  GstRegistryChunkGlobalHeader *hdr;
+  GstRegistryChunk *chk;
+
+  hdr = g_slice_new (GstRegistryChunkGlobalHeader);
+  chk = gst_registry_chunks_make_data (hdr,
+      sizeof (GstRegistryChunkGlobalHeader));
+
+  hdr->filter_env_hash = filter_env_hash;
+
+  *list = g_list_prepend (*list, chk);
+
+  GST_LOG ("Saved global header (filter_env_hash=0x%08x)", filter_env_hash);
+}
+
+gboolean
+_priv_gst_registry_chunks_load_global_header (GstRegistry * registry,
+    gchar ** in, gchar * end, guint32 * filter_env_hash)
+{
+  GstRegistryChunkGlobalHeader *hdr;
+
+  align (*in);
+  GST_LOG ("Reading/casting for GstRegistryChunkGlobalHeader at %p", *in);
+  unpack_element (*in, hdr, GstRegistryChunkGlobalHeader, end, fail);
+  *filter_env_hash = hdr->filter_env_hash;
+  return TRUE;
+
+  /* Errors */
+fail:
+  GST_WARNING ("Reading global header failed");
+  return FALSE;
+}