gstreamer_core/gst/gstregistrybinary.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
     1 /* GStreamer
     1 /* GStreamer
     2  * Copyright (C) 2006 Josep Torra <josep@fluendo.com>
     2  * Copyright (C) 2006 Josep Torra <josep@fluendo.com>
     3  *               2006 Mathieu Garcia <matthieu@fluendo.com>
     3  *               2006 Mathieu Garcia <matthieu@fluendo.com>
     4  *               2006,2007 Stefan Kost <ensonic@users.sf.net>
     4  *               2006,2007 Stefan Kost <ensonic@users.sf.net>
     5  *               2008 Sebastian Dröge <slomo@circular-chaos.org>
       
     6  *
     5  *
     7  * gstregistrybinary.c: GstRegistryBinary object, support routines
     6  * gstregistrybinary.c: GstRegistryBinary object, support routines
     8  *
     7  *
     9  * This library is free software; you can redistribute it and/or
     8  * This library is free software; you can redistribute it and/or
    10  * modify it under the terms of the GNU Library General Public
     9  * modify it under the terms of the GNU Library General Public
    21  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    22  * Boston, MA 02111-1307, USA.
    21  * Boston, MA 02111-1307, USA.
    23  */
    22  */
    24 
    23 
    25 /* FIXME:
    24 /* FIXME:
       
    25  * - Add random key to libgstreamer during build and only accept registry,
       
    26  *   if key matches (or is the version check enough)
    26  * - keep registry binary blob and reference strings
    27  * - keep registry binary blob and reference strings
    27  *   - don't free/
    28  *   - don't free/unmmap contents when leaving gst_registry_binary_read_cache()
    28 #ifdef __SYMBIAN32__
       
    29 EXPORT_C
       
    30 #endif
       
    31 unmmap contents when leaving gst_registry_binary_read_cache()
       
    32  *     - free at gst_deinit() / _priv_gst_registry_cleanup() ?
    29  *     - free at gst_deinit() / _priv_gst_registry_cleanup() ?
    33  *   - GstPlugin:
    30  *   - GstPlugin:
    34  *     - GST_PLUGIN_FLAG_CONST
    31  *     - GST_PLUGIN_FLAG_CONST
    35  *   - GstPluginFeature, GstIndexFactory, GstElementFactory
    32  *   -GstPluginFeature, GstIndexFactory, GstElementFactory
    36  *     - needs Flags (GST_PLUGIN_FEATURE_FLAG_CONST)
    33  *     - needs Flags (GST_PLUGIN_FEATURE_FLAG_CONST)
    37  *     - can we turn loaded into flag?
    34  *     - can we turn loaded into flag?
    38  * - why do we collect a list of binary chunks and not write immediately
    35  * - why do we collect a list of binary chunks and not write immediately
    39  *   - because we need to process subchunks, before we can set e.g. nr_of_items
    36  *   - because we need to process subchunks, before we can set e.g. nr_of_items
    40  *     in parent chunk
    37  *     in parent chunk
       
    38  * - need more robustness
       
    39  *   - don't parse beyond mem-block size
       
    40  *   - include md5-sum ?
    41  */
    41  */
    42 
    42 
    43 #ifdef HAVE_CONFIG_H
    43 #ifdef HAVE_CONFIG_H
    44 #  include "config.h"
    44 #  include "config.h"
    45 #endif
    45 #endif
    72 #include "glib-compat-private.h"
    72 #include "glib-compat-private.h"
    73 
    73 
    74 
    74 
    75 #define GST_CAT_DEFAULT GST_CAT_REGISTRY
    75 #define GST_CAT_DEFAULT GST_CAT_REGISTRY
    76 
    76 
    77 /* count string length, but return -1 if we hit the eof */
    77 /* macros */
    78 static gint
    78 
    79 _strnlen (const gchar * str, gint maxlen)
    79 #define unpack_element(_inptr, _outptr, _element)  \
    80 {
    80   _outptr = (_element *)_inptr; \
    81   gint len = 0;
    81   _inptr += sizeof (_element)
    82 
    82 
    83   if (G_UNLIKELY (len == maxlen))
    83 #define unpack_const_string(_inptr, _outptr) \
    84     return -1;
    84   _outptr = g_intern_string ((const gchar *)_inptr); \
    85 
    85   _inptr += strlen(_outptr) + 1
    86   while (*str++ != '\0') {
    86 
    87     len++;
    87 #define unpack_string(_inptr, _outptr)  \
    88     if (G_UNLIKELY (len == maxlen))
    88   _outptr = g_strdup ((gchar *)_inptr); \
    89       return -1;
    89   _inptr += strlen(_outptr) + 1
    90   }
    90 
    91   return len;
    91 #if !GST_HAVE_UNALIGNED_ACCESS
    92 }
    92 #  define alignment32(_address)  (gsize)_address%4
    93 
    93 #  define align32(_ptr)          _ptr += (( alignment32(_ptr) == 0) ? 0 : 4-alignment32(_ptr))
    94 /* reading macros */
    94 #else
    95 
    95 #  define alignment32(_address)  0
    96 #define unpack_element(inptr, outptr, element, endptr, error_label) G_STMT_START{ \
    96 #  define align32(_ptr)          do {} while(0)
    97   if (inptr + sizeof(element) >= endptr) \
    97 #endif
    98     goto error_label; \
    98 
    99   outptr = (element *) inptr; \
       
   100   inptr += sizeof (element); \
       
   101 }G_STMT_END
       
   102 
       
   103 #define unpack_const_string(inptr, outptr, endptr, error_label) G_STMT_START{\
       
   104   gint _len = _strnlen (inptr, (endptr-inptr)); \
       
   105   if (_len == -1) \
       
   106     goto error_label; \
       
   107   outptr = g_intern_string ((const gchar *)inptr); \
       
   108   inptr += _len + 1; \
       
   109 }G_STMT_END
       
   110 
       
   111 #define unpack_string(inptr, outptr, endptr, error_label)  G_STMT_START{\
       
   112   gint _len = _strnlen (inptr, (endptr-inptr)); \
       
   113   if (_len == -1) \
       
   114     goto error_label; \
       
   115   outptr = g_memdup ((gconstpointer)inptr, _len + 1); \
       
   116   inptr += _len + 1; \
       
   117 }G_STMT_END
       
   118 
       
   119 #define ALIGNMENT            (sizeof (void *))
       
   120 #define alignment(_address)  (gsize)_address%ALIGNMENT
       
   121 #define align(_ptr)          _ptr += (( alignment(_ptr) == 0) ? 0 : ALIGNMENT-alignment(_ptr))
       
   122 
    99 
   123 /* Registry saving */
   100 /* Registry saving */
   124 
   101 
   125 #ifdef G_OS_WIN32
   102 /*
   126 /* On win32, we can't use g_mkstmp(), because of cross-DLL file I/O problems.
   103  * gst_registry_binary_write:
   127  * So, we just create the entire binary registry in memory, then write it out
       
   128  * with g_file_set_contents(), which creates a temporary file internally
       
   129  */
       
   130 
       
   131 typedef struct BinaryRegistryCache
       
   132 {
       
   133   const char *location;
       
   134   guint8 *mem;
       
   135   gssize len;
       
   136 } BinaryRegistryCache;
       
   137 
       
   138 static BinaryRegistryCache *
       
   139 gst_registry_binary_cache_init (GstRegistry * registry, const char *location)
       
   140 {
       
   141   BinaryRegistryCache *cache = g_new0 (BinaryRegistryCache, 1);
       
   142   cache->location = location;
       
   143   return cache;
       
   144 }
       
   145 
       
   146 static int
       
   147 gst_registry_binary_cache_write (GstRegistry * registry,
       
   148     BinaryRegistryCache * cache, unsigned long offset,
       
   149     const void *data, int length)
       
   150 {
       
   151   cache->len = MAX (offset + length, cache->len);
       
   152   cache->mem = g_realloc (cache->mem, cache->len);
       
   153 
       
   154   memcpy (cache->mem + offset, data, length);
       
   155 
       
   156   return length;
       
   157 }
       
   158 
       
   159 static gboolean
       
   160 gst_registry_binary_cache_finish (GstRegistry * registry,
       
   161     BinaryRegistryCache * cache, gboolean success)
       
   162 {
       
   163   gboolean ret = TRUE;
       
   164   GError *error = NULL;
       
   165   if (!g_file_set_contents (cache->location, (const gchar *) cache->mem,
       
   166           cache->len, &error)) {
       
   167     /* Probably the directory didn't exist; create it */
       
   168     gchar *dir;
       
   169     dir = g_path_get_dirname (cache->location);
       
   170     g_mkdir_with_parents (dir, 0777);
       
   171     g_free (dir);
       
   172 
       
   173     g_error_free (error);
       
   174     error = NULL;
       
   175 
       
   176     if (!g_file_set_contents (cache->location, (const gchar *) cache->mem,
       
   177             cache->len, &error)) {
       
   178       GST_ERROR ("Failed to write to cache file: %s", error->message);
       
   179       g_error_free (error);
       
   180       ret = FALSE;
       
   181     }
       
   182   }
       
   183 
       
   184   g_free (cache->mem);
       
   185   g_free (cache);
       
   186   return ret;
       
   187 }
       
   188 
       
   189 #else
       
   190 typedef struct BinaryRegistryCache
       
   191 {
       
   192   const char *location;
       
   193   char *tmp_location;
       
   194   unsigned long currentoffset;
       
   195 } BinaryRegistryCache;
       
   196 
       
   197 static BinaryRegistryCache *
       
   198 gst_registry_binary_cache_init (GstRegistry * registry, const char *location)
       
   199 {
       
   200   BinaryRegistryCache *cache = g_new0 (BinaryRegistryCache, 1);
       
   201 
       
   202   cache->location = location;
       
   203   cache->tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL);
       
   204   registry->cache_file = g_mkstemp (cache->tmp_location);
       
   205   if (registry->cache_file == -1) {
       
   206     gchar *dir;
       
   207 
       
   208     /* oops, I bet the directory doesn't exist */
       
   209     dir = g_path_get_dirname (location);
       
   210     g_mkdir_with_parents (dir, 0777);
       
   211     g_free (dir);
       
   212 
       
   213     /* the previous g_mkstemp call overwrote the XXXXXX placeholder ... */
       
   214     g_free (cache->tmp_location);
       
   215     cache->tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL);
       
   216     registry->cache_file = g_mkstemp (cache->tmp_location);
       
   217 
       
   218     if (registry->cache_file == -1) {
       
   219       GST_DEBUG ("g_mkstemp() failed: %s", g_strerror (errno));
       
   220       g_free (cache->tmp_location);
       
   221       g_free (cache);
       
   222       return NULL;
       
   223     }
       
   224   }
       
   225 
       
   226   return cache;
       
   227 }
       
   228 
       
   229 static int
       
   230 gst_registry_binary_cache_write (GstRegistry * registry,
       
   231     BinaryRegistryCache * cache, unsigned long offset,
       
   232     const void *data, int length)
       
   233 {
       
   234   long written;
       
   235   if (offset != cache->currentoffset) {
       
   236     if (lseek (registry->cache_file, offset, SEEK_SET) != 0) {
       
   237       GST_ERROR ("Seeking to new offset failed");
       
   238       return FALSE;
       
   239     }
       
   240     cache->currentoffset = offset;
       
   241   }
       
   242 
       
   243   written = write (registry->cache_file, data, length);
       
   244   if (written != length) {
       
   245     GST_ERROR ("Failed to write to cache file");
       
   246   }
       
   247   cache->currentoffset += written;
       
   248 
       
   249   return written;
       
   250 }
       
   251 
       
   252 static gboolean
       
   253 gst_registry_binary_cache_finish (GstRegistry * registry,
       
   254     BinaryRegistryCache * cache, gboolean success)
       
   255 {
       
   256   /* only fsync if we're actually going to use and rename the file below */
       
   257   if (success && fsync (registry->cache_file) < 0)
       
   258     goto fsync_failed;
       
   259 
       
   260   if (close (registry->cache_file) < 0)
       
   261     goto close_failed;
       
   262 
       
   263   if (success) {
       
   264     /* Only do the rename if we wrote the entire file successfully */
       
   265     if (g_rename (cache->tmp_location, cache->location) < 0)
       
   266       goto rename_failed;
       
   267   }
       
   268 
       
   269   g_free (cache->tmp_location);
       
   270   g_free (cache);
       
   271   GST_INFO ("Wrote binary registry cache");
       
   272   return TRUE;
       
   273 
       
   274 /* ERRORS */
       
   275 fail_after_close:
       
   276   {
       
   277     g_unlink (cache->tmp_location);
       
   278     g_free (cache->tmp_location);
       
   279     g_free (cache);
       
   280     return FALSE;
       
   281   }
       
   282 fsync_failed:
       
   283   {
       
   284     GST_ERROR ("fsync() failed: %s", g_strerror (errno));
       
   285     goto fail_after_close;
       
   286   }
       
   287 close_failed:
       
   288   {
       
   289     GST_ERROR ("close() failed: %s", g_strerror (errno));
       
   290     goto fail_after_close;
       
   291   }
       
   292 rename_failed:
       
   293   {
       
   294     GST_ERROR ("g_rename() failed: %s", g_strerror (errno));
       
   295     goto fail_after_close;
       
   296   }
       
   297 }
       
   298 #endif
       
   299 
       
   300 /*
       
   301  * gst_registry_binary_write_chunk:
       
   302  *
   104  *
   303  * Write from a memory location to the registry cache file
   105  * Write from a memory location to the registry cache file
   304  *
   106  *
   305  * Returns: %TRUE for success
   107  * Returns: %TRUE for success
   306  */
   108  */
   307 inline static gboolean
   109 inline static gboolean
   308 gst_registry_binary_write_chunk (GstRegistry * registry,
   110 gst_registry_binary_write (GstRegistry * registry, const void *mem,
   309     BinaryRegistryCache * cache, const void *mem,
       
   310     const gssize size, unsigned long *file_position, gboolean align)
   111     const gssize size, unsigned long *file_position, gboolean align)
   311 {
   112 {
   312   gchar padder[ALIGNMENT] = { 0, };
   113 #if !GST_HAVE_UNALIGNED_ACCESS
       
   114   gchar padder[] = { 0, 0, 0, 0 };
   313   int padsize = 0;
   115   int padsize = 0;
   314 
   116 
   315   /* Padding to insert the struct that requiere word alignment */
   117   /* Padding to insert the struct that requiere word alignment */
   316   if ((align) && (alignment (*file_position) != 0)) {
   118   if ((align) && (alignment32 (*file_position) != 0)) {
   317     padsize = ALIGNMENT - alignment (*file_position);
   119     padsize = 4 - alignment32 (*file_position);
   318     if (gst_registry_binary_cache_write (registry, cache, *file_position,
   120     if (write (registry->cache_file, padder, padsize) != padsize) {
   319             padder, padsize) != padsize) {
       
   320       GST_ERROR ("Failed to write binary registry padder");
   121       GST_ERROR ("Failed to write binary registry padder");
   321       return FALSE;
   122       return FALSE;
   322     }
   123     }
   323     *file_position += padsize;
   124     *file_position = *file_position + padsize;
   324   }
   125   }
   325 
   126 #endif
   326   if (gst_registry_binary_cache_write (registry, cache, *file_position,
   127 
   327           mem, size) != size) {
   128   if (write (registry->cache_file, mem, size) != size) {
   328     GST_ERROR ("Failed to write binary registry element");
   129     GST_ERROR ("Failed to write binary registry element");
   329     return FALSE;
   130     return FALSE;
   330   }
   131   }
   331 
   132   *file_position = *file_position + size;
   332   *file_position += size;
       
   333 
       
   334   return TRUE;
   133   return TRUE;
   335 }
   134 }
   336 
   135 
   337 
   136 
   338 /*
   137 /*
   342  * gstreamer major/minor version
   141  * gstreamer major/minor version
   343  */
   142  */
   344 inline static gboolean
   143 inline static gboolean
   345 gst_registry_binary_initialize_magic (GstBinaryRegistryMagic * m)
   144 gst_registry_binary_initialize_magic (GstBinaryRegistryMagic * m)
   346 {
   145 {
   347   memset (m, 0, sizeof (GstBinaryRegistryMagic));
       
   348 
       
   349   if (!strncpy (m->magic, GST_MAGIC_BINARY_REGISTRY_STR,
   146   if (!strncpy (m->magic, GST_MAGIC_BINARY_REGISTRY_STR,
   350           GST_MAGIC_BINARY_REGISTRY_LEN)
   147           GST_MAGIC_BINARY_REGISTRY_LEN)
   351       || !strncpy (m->version, GST_MAGIC_BINARY_VERSION_STR,
   148       || !strncpy (m->version, GST_MAJORMINOR, GST_MAGIC_BINARY_VERSION_LEN)) {
   352           GST_MAGIC_BINARY_VERSION_LEN)) {
       
   353     GST_ERROR ("Failed to write magic to the registry magic structure");
   149     GST_ERROR ("Failed to write magic to the registry magic structure");
   354     return FALSE;
   150     return FALSE;
   355   }
   151   }
   356 
       
   357   return TRUE;
   152   return TRUE;
   358 }
   153 }
   359 
   154 
   360 
   155 
   361 /*
   156 /*
   367  */
   162  */
   368 inline static gboolean
   163 inline static gboolean
   369 gst_registry_binary_save_const_string (GList ** list, const gchar * str)
   164 gst_registry_binary_save_const_string (GList ** list, const gchar * str)
   370 {
   165 {
   371   GstBinaryChunk *chunk;
   166   GstBinaryChunk *chunk;
   372 
       
   373   if (G_UNLIKELY (str == NULL)) {
       
   374     GST_ERROR ("unexpected NULL string in plugin or plugin feature data");
       
   375     str = "";
       
   376   }
       
   377 
   167 
   378   chunk = g_malloc (sizeof (GstBinaryChunk));
   168   chunk = g_malloc (sizeof (GstBinaryChunk));
   379   chunk->data = (gpointer) str;
   169   chunk->data = (gpointer) str;
   380   chunk->size = strlen ((gchar *) chunk->data) + 1;
   170   chunk->size = strlen ((gchar *) chunk->data) + 1;
   381   chunk->flags = GST_BINARY_REGISTRY_FLAG_CONST;
   171   chunk->flags = GST_BINARY_REGISTRY_FLAG_CONST;
   439     GstStaticPadTemplate * template)
   229     GstStaticPadTemplate * template)
   440 {
   230 {
   441   GstBinaryPadTemplate *pt;
   231   GstBinaryPadTemplate *pt;
   442   GstBinaryChunk *chk;
   232   GstBinaryChunk *chk;
   443 
   233 
   444   pt = g_malloc0 (sizeof (GstBinaryPadTemplate));
   234   pt = g_malloc (sizeof (GstBinaryPadTemplate));
   445   chk = gst_registry_binary_make_data (pt, sizeof (GstBinaryPadTemplate));
   235   chk = gst_registry_binary_make_data (pt, sizeof (GstBinaryPadTemplate));
   446 
   236 
   447   pt->presence = template->presence;
   237   pt->presence = template->presence;
   448   pt->direction = template->direction;
   238   pt->direction = template->direction;
   449 
   239 
   480 
   270 
   481   if (GST_IS_ELEMENT_FACTORY (feature)) {
   271   if (GST_IS_ELEMENT_FACTORY (feature)) {
   482     GstBinaryElementFactory *ef;
   272     GstBinaryElementFactory *ef;
   483     GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
   273     GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
   484 
   274 
   485     ef = g_malloc0 (sizeof (GstBinaryElementFactory));
   275     ef = g_malloc (sizeof (GstBinaryElementFactory));
   486     chk = gst_registry_binary_make_data (ef, sizeof (GstBinaryElementFactory));
   276     chk = gst_registry_binary_make_data (ef, sizeof (GstBinaryElementFactory));
   487     ef->npadtemplates = ef->ninterfaces = ef->nuriprotocols = 0;
   277     ef->npadtemplates = ef->ninterfaces = ef->nuriprotocols = 0;
   488     pf = (GstBinaryPluginFeature *) ef;
   278     pf = (GstBinaryPluginFeature *) ef;
   489 
   279 
   490     /* save interfaces */
   280     /* save interfaces */
   493       gst_registry_binary_save_const_string (list, (gchar *) walk->data);
   283       gst_registry_binary_save_const_string (list, (gchar *) walk->data);
   494     }
   284     }
   495     GST_DEBUG ("Saved %d Interfaces", ef->ninterfaces);
   285     GST_DEBUG ("Saved %d Interfaces", ef->ninterfaces);
   496     /* save uritypes */
   286     /* save uritypes */
   497     if (GST_URI_TYPE_IS_VALID (factory->uri_type)) {
   287     if (GST_URI_TYPE_IS_VALID (factory->uri_type)) {
   498       if (factory->uri_protocols && *factory->uri_protocols) {
   288       if (factory->uri_protocols) {
   499         GstBinaryChunk *subchk;
   289         GstBinaryChunk *subchk;
   500         gchar **protocol;
   290         gchar **protocol;
   501 
   291 
   502         subchk =
   292         subchk =
   503             gst_registry_binary_make_data (&factory->uri_type,
   293             gst_registry_binary_make_data (&factory->uri_type,
   534     gst_registry_binary_save_const_string (list, factory->details.klass);
   324     gst_registry_binary_save_const_string (list, factory->details.klass);
   535     gst_registry_binary_save_const_string (list, factory->details.longname);
   325     gst_registry_binary_save_const_string (list, factory->details.longname);
   536   } else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
   326   } else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
   537     GstBinaryTypeFindFactory *tff;
   327     GstBinaryTypeFindFactory *tff;
   538     GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature);
   328     GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature);
   539 
   329     gchar *str;
   540     tff = g_malloc0 (sizeof (GstBinaryTypeFindFactory));
   330 
       
   331     /* we copy the caps here so we can simplify them before saving. This is a lot
       
   332      * faster when loading them later on */
       
   333     GstCaps *copy = gst_caps_copy (factory->caps);
       
   334 
       
   335     tff = g_malloc (sizeof (GstBinaryTypeFindFactory));
   541     chk =
   336     chk =
   542         gst_registry_binary_make_data (tff, sizeof (GstBinaryTypeFindFactory));
   337         gst_registry_binary_make_data (tff, sizeof (GstBinaryTypeFindFactory));
   543     tff->nextensions = 0;
   338     tff->nextensions = 0;
   544     pf = (GstBinaryPluginFeature *) tff;
   339     pf = (GstBinaryPluginFeature *) tff;
   545 
   340 
   549         gst_registry_binary_save_const_string (list,
   344         gst_registry_binary_save_const_string (list,
   550             factory->extensions[tff->nextensions++]);
   345             factory->extensions[tff->nextensions++]);
   551       }
   346       }
   552     }
   347     }
   553     /* save caps */
   348     /* save caps */
   554     if (factory->caps) {
   349     gst_caps_do_simplify (copy);
   555       GstCaps *copy = gst_caps_copy (factory->caps);
   350     str = gst_caps_to_string (copy);
   556       gchar *str;
   351     gst_caps_unref (copy);
   557 
   352     gst_registry_binary_save_string (list, str);
   558       /* we copy the caps here so we can simplify them
   353   }
   559        * before saving. This is a lot faster when loading
   354 #ifndef GST_DISABLE_INDEX
   560        * them later on */
   355   else if (GST_IS_INDEX_FACTORY (feature)) {
   561       gst_caps_do_simplify (copy);
       
   562       str = gst_caps_to_string (copy);
       
   563       gst_caps_unref (copy);
       
   564       gst_registry_binary_save_string (list, str);
       
   565     } else {
       
   566       gst_registry_binary_save_const_string (list, "");
       
   567     }
       
   568 
       
   569   } else if (GST_IS_INDEX_FACTORY (feature)) {
       
   570     GstIndexFactory *factory = GST_INDEX_FACTORY (feature);
   356     GstIndexFactory *factory = GST_INDEX_FACTORY (feature);
   571 
   357 
   572     pf = g_malloc0 (sizeof (GstBinaryPluginFeature));
   358     pf = g_malloc (sizeof (GstBinaryPluginFeature));
   573     chk = gst_registry_binary_make_data (pf, sizeof (GstBinaryPluginFeature));
   359     chk = gst_registry_binary_make_data (pf, sizeof (GstBinaryPluginFeature));
   574     pf->rank = feature->rank;
   360     pf->rank = feature->rank;
   575 
   361 
   576     /* pack element factory strings */
   362     /* pack element factory strings */
   577     gst_registry_binary_save_const_string (list, factory->longdesc);
   363     gst_registry_binary_save_const_string (list, factory->longdesc);
   578   } else {
   364   }
       
   365 #endif
       
   366   else {
   579     GST_WARNING ("unhandled feature type '%s'", type_name);
   367     GST_WARNING ("unhandled feature type '%s'", type_name);
   580   }
   368   }
   581 
   369 
   582   if (pf) {
   370   if (pf) {
   583     pf->rank = feature->rank;
   371     pf->rank = feature->rank;
   595   g_free (chk);
   383   g_free (chk);
   596   g_free (pf);
   384   g_free (pf);
   597   return FALSE;
   385   return FALSE;
   598 }
   386 }
   599 
   387 
   600 static gboolean
       
   601 gst_registry_binary_save_plugin_dep (GList ** list, GstPluginDep * dep)
       
   602 {
       
   603   GstBinaryDep *ed;
       
   604   GstBinaryChunk *chk;
       
   605   gchar **s;
       
   606 
       
   607   ed = g_new0 (GstBinaryDep, 1);
       
   608   chk = gst_registry_binary_make_data (ed, sizeof (GstBinaryDep));
       
   609 
       
   610   ed->flags = dep->flags;
       
   611   ed->n_env_vars = 0;
       
   612   ed->n_paths = 0;
       
   613   ed->n_names = 0;
       
   614 
       
   615   ed->env_hash = dep->env_hash;
       
   616   ed->stat_hash = dep->stat_hash;
       
   617 
       
   618   for (s = dep->env_vars; s != NULL && *s != NULL; ++s, ++ed->n_env_vars)
       
   619     gst_registry_binary_save_string (list, g_strdup (*s));
       
   620 
       
   621   for (s = dep->paths; s != NULL && *s != NULL; ++s, ++ed->n_paths)
       
   622     gst_registry_binary_save_string (list, g_strdup (*s));
       
   623 
       
   624   for (s = dep->names; s != NULL && *s != NULL; ++s, ++ed->n_names)
       
   625     gst_registry_binary_save_string (list, g_strdup (*s));
       
   626 
       
   627   *list = g_list_prepend (*list, chk);
       
   628 
       
   629   GST_LOG ("Saved external plugin dependency");
       
   630   return TRUE;
       
   631 }
       
   632 
   388 
   633 /*
   389 /*
   634  * gst_registry_binary_save_plugin:
   390  * gst_registry_binary_save_plugin:
   635  *
   391  *
   636  * Adapt a GstPlugin to our GstBinaryPluginElement structure, and write it to
   392  * Adapt a GstPlugin to our GstBinaryPluginElement structure, and write it to
   643   GstBinaryPluginElement *pe;
   399   GstBinaryPluginElement *pe;
   644   GstBinaryChunk *chk;
   400   GstBinaryChunk *chk;
   645   GList *plugin_features = NULL;
   401   GList *plugin_features = NULL;
   646   GList *walk;
   402   GList *walk;
   647 
   403 
   648   pe = g_malloc0 (sizeof (GstBinaryPluginElement));
   404   pe = g_malloc (sizeof (GstBinaryPluginElement));
   649   chk = gst_registry_binary_make_data (pe, sizeof (GstBinaryPluginElement));
   405   chk = gst_registry_binary_make_data (pe, sizeof (GstBinaryPluginElement));
   650 
   406 
   651   pe->file_size = plugin->file_size;
   407   pe->file_size = plugin->file_size;
   652   pe->file_mtime = plugin->file_mtime;
   408   pe->file_mtime = plugin->file_mtime;
   653   pe->n_deps = 0;
       
   654   pe->nfeatures = 0;
   409   pe->nfeatures = 0;
   655 
       
   656   /* pack external deps */
       
   657   for (walk = plugin->priv->deps; walk != NULL; walk = walk->next) {
       
   658     if (!gst_registry_binary_save_plugin_dep (list, walk->data)) {
       
   659       GST_ERROR ("Could not save external plugin dependency, aborting.");
       
   660       goto fail;
       
   661     }
       
   662     ++pe->n_deps;
       
   663   }
       
   664 
   410 
   665   /* pack plugin features */
   411   /* pack plugin features */
   666   plugin_features =
   412   plugin_features =
   667       gst_registry_get_feature_list_by_plugin (registry, plugin->desc.name);
   413       gst_registry_get_feature_list_by_plugin (registry, plugin->desc.name);
   668   for (walk = plugin_features; walk; walk = g_list_next (walk), pe->nfeatures++) {
   414   for (walk = plugin_features; walk; walk = g_list_next (walk), pe->nfeatures++) {
   671     if (!gst_registry_binary_save_feature (list, feature)) {
   417     if (!gst_registry_binary_save_feature (list, feature)) {
   672       GST_ERROR ("Can't fill plugin feature, aborting.");
   418       GST_ERROR ("Can't fill plugin feature, aborting.");
   673       goto fail;
   419       goto fail;
   674     }
   420     }
   675   }
   421   }
   676   GST_DEBUG ("Save plugin '%s' with %d feature(s)", plugin->desc.name,
   422   GST_DEBUG ("Save plugin '%s' with %d features", plugin->desc.name,
   677       pe->nfeatures);
   423       pe->nfeatures);
   678 
   424 
   679   gst_plugin_feature_list_free (plugin_features);
   425   gst_plugin_feature_list_free (plugin_features);
   680 
       
   681   /* pack cache data */
       
   682   if (plugin->priv->cache_data) {
       
   683     gchar *cache_str = gst_structure_to_string (plugin->priv->cache_data);
       
   684     gst_registry_binary_save_string (list, cache_str);
       
   685   } else {
       
   686     gst_registry_binary_save_const_string (list, "");
       
   687   }
       
   688 
   426 
   689   /* pack plugin element strings */
   427   /* pack plugin element strings */
   690   gst_registry_binary_save_const_string (list, plugin->desc.origin);
   428   gst_registry_binary_save_const_string (list, plugin->desc.origin);
   691   gst_registry_binary_save_const_string (list, plugin->desc.package);
   429   gst_registry_binary_save_const_string (list, plugin->desc.package);
   692   gst_registry_binary_save_const_string (list, plugin->desc.source);
   430   gst_registry_binary_save_const_string (list, plugin->desc.source);
   708   g_free (chk);
   446   g_free (chk);
   709   g_free (pe);
   447   g_free (pe);
   710   return FALSE;
   448   return FALSE;
   711 }
   449 }
   712 
   450 
       
   451 
   713 /**
   452 /**
   714  * gst_registry_binary_write_cache:
   453  * gst_registry_binary_write_cache:
   715  * @registry: a #GstRegistry
   454  * @registry: a #GstRegistry
   716  * @location: a filename
   455  * @location: a filename
   717  *
   456  *
   725 
   464 
   726 gboolean
   465 gboolean
   727 gst_registry_binary_write_cache (GstRegistry * registry, const char *location)
   466 gst_registry_binary_write_cache (GstRegistry * registry, const char *location)
   728 {
   467 {
   729   GList *walk;
   468   GList *walk;
   730   GstBinaryRegistryMagic magic;
   469   gchar *tmp_location;
       
   470   GstBinaryRegistryMagic *magic;
       
   471   GstBinaryChunk *magic_chunk;
   731   GList *to_write = NULL;
   472   GList *to_write = NULL;
   732   unsigned long file_position = 0;
   473   unsigned long file_position = 0;
   733   BinaryRegistryCache *cache;
       
   734 
   474 
   735   GST_INFO ("Building binary registry cache image");
   475   GST_INFO ("Building binary registry cache image");
   736 
   476 
   737   g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
   477   g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
   738 
   478   tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL);
   739   if (!gst_registry_binary_initialize_magic (&magic))
   479   registry->cache_file = g_mkstemp (tmp_location);
       
   480   if (registry->cache_file == -1) {
       
   481     gchar *dir;
       
   482 
       
   483     /* oops, I bet the directory doesn't exist */
       
   484     dir = g_path_get_dirname (location);
       
   485     g_mkdir_with_parents (dir, 0777);
       
   486     g_free (dir);
       
   487 
       
   488     /* the previous g_mkstemp call overwrote the XXXXXX placeholder ... */
       
   489     g_free (tmp_location);
       
   490     tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL);
       
   491     registry->cache_file = g_mkstemp (tmp_location);
       
   492 
       
   493     if (registry->cache_file == -1) {
       
   494       GST_DEBUG ("g_mkstemp() failed: %s", g_strerror (errno));
       
   495       g_free (tmp_location);
       
   496       return FALSE;
       
   497     }
       
   498   }
       
   499 
       
   500   magic = g_malloc (sizeof (GstBinaryRegistryMagic));
       
   501   if (!gst_registry_binary_initialize_magic (magic))
   740     goto fail;
   502     goto fail;
       
   503 
       
   504   magic_chunk = g_malloc (sizeof (GstBinaryChunk));
       
   505   magic_chunk->data = magic;
       
   506   magic_chunk->size = sizeof (GstBinaryRegistryMagic);
       
   507   magic_chunk->flags = GST_BINARY_REGISTRY_FLAG_NONE;
       
   508   magic_chunk->align = TRUE;
   741 
   509 
   742   /* iterate trough the list of plugins and fit them into binary structures */
   510   /* iterate trough the list of plugins and fit them into binary structures */
   743   for (walk = registry->plugins; walk; walk = g_list_next (walk)) {
   511   for (walk = registry->plugins; walk; walk = g_list_next (walk)) {
   744     GstPlugin *plugin = GST_PLUGIN (walk->data);
   512     GstPlugin *plugin = GST_PLUGIN (walk->data);
   745 
   513 
   746     if (!plugin->filename)
   514     if (!plugin->filename)
   747       continue;
   515       continue;
   748 
   516 
   749     if (plugin->flags & GST_PLUGIN_FLAG_CACHED) {
   517     if (plugin->flags & GST_PLUGIN_FLAG_CACHED) {
       
   518       int ret;
   750       struct stat statbuf;
   519       struct stat statbuf;
   751 
   520 
   752       if (g_stat (plugin->filename, &statbuf) < 0 ||
   521       ret = g_stat (plugin->filename, &statbuf);
       
   522       if ((ret = g_stat (plugin->filename, &statbuf)) < 0 ||
   753           plugin->file_mtime != statbuf.st_mtime ||
   523           plugin->file_mtime != statbuf.st_mtime ||
   754           plugin->file_size != statbuf.st_size)
   524           plugin->file_size != statbuf.st_size)
   755         continue;
   525         continue;
   756     }
   526     }
   757 
   527 
   758     if (!gst_registry_binary_save_plugin (&to_write, registry, plugin)) {
   528     if (!gst_registry_binary_save_plugin (&to_write, registry, plugin)) {
   759       GST_ERROR ("Can't write binary plugin information for \"%s\"",
   529       GST_ERROR ("Can't write binary plugin information for \"%s\"",
   760           plugin->filename);
   530           plugin->filename);
   761     }
   531     }
   762   }
   532   }
       
   533   to_write = g_list_prepend (to_write, magic_chunk);
   763 
   534 
   764   GST_INFO ("Writing binary registry cache");
   535   GST_INFO ("Writing binary registry cache");
   765 
       
   766   cache = gst_registry_binary_cache_init (registry, location);
       
   767   if (!cache)
       
   768     goto fail_free_list;
       
   769 
       
   770   /* write magic */
       
   771   if (gst_registry_binary_cache_write (registry, cache, file_position,
       
   772           &magic, sizeof (GstBinaryRegistryMagic)) !=
       
   773       sizeof (GstBinaryRegistryMagic)) {
       
   774     GST_ERROR ("Failed to write binary registry magic");
       
   775     goto fail_free_list;
       
   776   }
       
   777   file_position += sizeof (GstBinaryRegistryMagic);
       
   778 
   536 
   779   /* write out data chunks */
   537   /* write out data chunks */
   780   for (walk = to_write; walk; walk = g_list_next (walk)) {
   538   for (walk = to_write; walk; walk = g_list_next (walk)) {
   781     GstBinaryChunk *cur = walk->data;
   539     GstBinaryChunk *cur = walk->data;
   782 
   540 
   783     if (!gst_registry_binary_write_chunk (registry, cache, cur->data, cur->size,
   541     if (!gst_registry_binary_write (registry, cur->data, cur->size,
   784             &file_position, cur->align)) {
   542             &file_position, cur->align)) {
   785       goto fail_free_list;
   543       if (!(cur->flags & GST_BINARY_REGISTRY_FLAG_CONST))
       
   544         g_free (cur->data);
       
   545       g_free (cur);
       
   546       g_list_free (to_write);
       
   547       goto fail;
   786     }
   548     }
   787     if (!(cur->flags & GST_BINARY_REGISTRY_FLAG_CONST))
   549     if (!(cur->flags & GST_BINARY_REGISTRY_FLAG_CONST))
   788       g_free (cur->data);
   550       g_free (cur->data);
   789     g_free (cur);
   551     g_free (cur);
   790     walk->data = NULL;
       
   791   }
   552   }
   792   g_list_free (to_write);
   553   g_list_free (to_write);
   793 
   554 
   794   if (!gst_registry_binary_cache_finish (registry, cache, TRUE))
   555   if (close (registry->cache_file) < 0)
   795     return FALSE;
   556     goto close_failed;
   796 
   557 
       
   558   if (g_file_test (tmp_location, G_FILE_TEST_EXISTS)) {
       
   559 #ifdef WIN32
       
   560     g_remove (location);
       
   561 #endif
       
   562     if (g_rename (tmp_location, location) < 0)
       
   563       goto rename_failed;
       
   564   } else {
       
   565     /* FIXME: shouldn't we return FALSE here? */
       
   566   }
       
   567 
       
   568   g_free (tmp_location);
       
   569   GST_INFO ("Wrote binary registry cache");
   797   return TRUE;
   570   return TRUE;
   798 
   571 
   799   /* Errors */
   572   /* Errors */
   800 fail_free_list:
       
   801   {
       
   802     for (walk = to_write; walk; walk = g_list_next (walk)) {
       
   803       GstBinaryChunk *cur = walk->data;
       
   804 
       
   805       if (!(cur->flags & GST_BINARY_REGISTRY_FLAG_CONST))
       
   806         g_free (cur->data);
       
   807       g_free (cur);
       
   808     }
       
   809     g_list_free (to_write);
       
   810 
       
   811     if (cache)
       
   812       (void) gst_registry_binary_cache_finish (registry, cache, FALSE);
       
   813     /* fall through */
       
   814   }
       
   815 fail:
   573 fail:
   816   {
   574   {
   817     return FALSE;
   575     (void) close (registry->cache_file);
       
   576     /* fall through */
       
   577   }
       
   578 fail_after_close:
       
   579   {
       
   580     g_remove (tmp_location);
       
   581     g_free (tmp_location);
       
   582     return FALSE;
       
   583   }
       
   584 close_failed:
       
   585   {
       
   586     GST_ERROR ("close() failed: %s", g_strerror (errno));
       
   587     goto fail_after_close;
       
   588   }
       
   589 rename_failed:
       
   590   {
       
   591     GST_ERROR ("g_rename() failed: %s", g_strerror (errno));
       
   592     goto fail_after_close;
   818   }
   593   }
   819 }
   594 }
   820 
   595 
   821 
   596 
   822 /* Registry loading */
   597 /* Registry loading */
   823 
   598 
   824 /*
   599 /*
   825  * gst_registry_binary_check_magic:
   600  * gst_registry_binary_check_magic:
   826  *
   601  *
   827  * Check GstBinaryRegistryMagic validity.
   602  * Check GstBinaryRegistryMagic validity.
   828  * Return < 0 if something is wrong, -2 means
   603  * Return FALSE if something is wrong
   829  * that just the version of the registry is out of
   604  */
   830  * date, -1 is a general failure.
   605 static gboolean
   831  */
   606 gst_registry_binary_check_magic (gchar ** in)
   832 static gint
       
   833 gst_registry_binary_check_magic (gchar ** in, gsize size)
       
   834 {
   607 {
   835   GstBinaryRegistryMagic *m;
   608   GstBinaryRegistryMagic *m;
   836 
   609 
   837   align (*in);
   610   align32 (*in);
   838   GST_DEBUG ("Reading/casting for GstBinaryRegistryMagic at address %p", *in);
   611   GST_DEBUG ("Reading/casting for GstBinaryRegistryMagic at address %p", *in);
   839   unpack_element (*in, m, GstBinaryRegistryMagic, (*in + size), fail);
   612   unpack_element (*in, m, GstBinaryRegistryMagic);
   840 
   613 
       
   614   if (m == NULL || m->magic == NULL || m->version == NULL) {
       
   615     GST_WARNING ("Binary registry magic structure is broken");
       
   616     return FALSE;
       
   617   }
   841   if (strncmp (m->magic, GST_MAGIC_BINARY_REGISTRY_STR,
   618   if (strncmp (m->magic, GST_MAGIC_BINARY_REGISTRY_STR,
   842           GST_MAGIC_BINARY_REGISTRY_LEN) != 0) {
   619           GST_MAGIC_BINARY_REGISTRY_LEN) != 0) {
   843     GST_WARNING
   620     GST_WARNING
   844         ("Binary registry magic is different : %02x%02x%02x%02x != %02x%02x%02x%02x",
   621         ("Binary registry magic is different : %02x%02x%02x%02x != %02x%02x%02x%02x",
   845         GST_MAGIC_BINARY_REGISTRY_STR[0] & 0xff,
   622         GST_MAGIC_BINARY_REGISTRY_STR[0] & 0xff,
   846         GST_MAGIC_BINARY_REGISTRY_STR[1] & 0xff,
   623         GST_MAGIC_BINARY_REGISTRY_STR[1] & 0xff,
   847         GST_MAGIC_BINARY_REGISTRY_STR[2] & 0xff,
   624         GST_MAGIC_BINARY_REGISTRY_STR[2] & 0xff,
   848         GST_MAGIC_BINARY_REGISTRY_STR[3] & 0xff, m->magic[0] & 0xff,
   625         GST_MAGIC_BINARY_REGISTRY_STR[3] & 0xff, m->magic[0] & 0xff,
   849         m->magic[1] & 0xff, m->magic[2] & 0xff, m->magic[3] & 0xff);
   626         m->magic[1] & 0xff, m->magic[2] & 0xff, m->magic[3] & 0xff);
   850     return -1;
   627     return FALSE;
   851   }
   628   }
   852   if (strncmp (m->version, GST_MAGIC_BINARY_VERSION_STR,
   629   if (strncmp (m->version, GST_MAJORMINOR, GST_MAGIC_BINARY_VERSION_LEN)) {
   853           GST_MAGIC_BINARY_VERSION_LEN)) {
       
   854     GST_WARNING ("Binary registry magic version is different : %s != %s",
   630     GST_WARNING ("Binary registry magic version is different : %s != %s",
   855         GST_MAGIC_BINARY_VERSION_STR, m->version);
   631         GST_MAJORMINOR, m->version);
   856     return -2;
   632     return FALSE;
   857   }
   633   }
   858 
   634   return TRUE;
   859   return 0;
       
   860 
       
   861 fail:
       
   862   GST_WARNING ("Not enough data for binary registry magic structure");
       
   863   return -1;
       
   864 }
   635 }
   865 
   636 
   866 
   637 
   867 /*
   638 /*
   868  * gst_registry_binary_load_pad_template:
   639  * gst_registry_binary_load_pad_template:
   870  * Make a new GstStaticPadTemplate from current GstBinaryPadTemplate structure
   641  * Make a new GstStaticPadTemplate from current GstBinaryPadTemplate structure
   871  *
   642  *
   872  * Returns: new GstStaticPadTemplate
   643  * Returns: new GstStaticPadTemplate
   873  */
   644  */
   874 static gboolean
   645 static gboolean
   875 gst_registry_binary_load_pad_template (GstElementFactory * factory, gchar ** in,
   646 gst_registry_binary_load_pad_template (GstElementFactory * factory, gchar ** in)
   876     gchar * end)
       
   877 {
   647 {
   878   GstBinaryPadTemplate *pt;
   648   GstBinaryPadTemplate *pt;
   879   GstStaticPadTemplate *template = NULL;
   649   GstStaticPadTemplate *template;
   880 
   650 
   881   align (*in);
   651   align32 (*in);
   882   GST_DEBUG ("Reading/casting for GstBinaryPadTemplate at address %p", *in);
   652   GST_DEBUG ("Reading/casting for GstBinaryPadTemplate at address %p", *in);
   883   unpack_element (*in, pt, GstBinaryPadTemplate, end, fail);
   653   unpack_element (*in, pt, GstBinaryPadTemplate);
   884 
   654 
   885   template = g_new0 (GstStaticPadTemplate, 1);
   655   template = g_new0 (GstStaticPadTemplate, 1);
   886   template->presence = pt->presence;
   656   template->presence = pt->presence;
   887   template->direction = pt->direction;
   657   template->direction = pt->direction;
   888 
   658 
   889   /* unpack pad template strings */
   659   /* unpack pad template strings */
   890   unpack_const_string (*in, template->name_template, end, fail);
   660   unpack_const_string (*in, template->name_template);
   891   unpack_string (*in, template->static_caps.string, end, fail);
   661   unpack_string (*in, template->static_caps.string);
   892 
   662 
   893   __gst_element_factory_add_static_pad_template (factory, template);
   663   __gst_element_factory_add_static_pad_template (factory, template);
   894   GST_DEBUG ("Added pad_template %s", template->name_template);
   664   GST_DEBUG ("Added pad_template %s", template->name_template);
   895 
   665 
   896   return TRUE;
   666   return TRUE;
   897 
       
   898 fail:
       
   899   GST_INFO ("Reading pad template failed");
       
   900   g_free (template);
       
   901   return FALSE;
       
   902 }
   667 }
   903 
   668 
   904 
   669 
   905 /*
   670 /*
   906  * gst_registry_binary_load_feature:
   671  * gst_registry_binary_load_feature:
   909  *
   674  *
   910  * Returns: new GstPluginFeature
   675  * Returns: new GstPluginFeature
   911  */
   676  */
   912 static gboolean
   677 static gboolean
   913 gst_registry_binary_load_feature (GstRegistry * registry, gchar ** in,
   678 gst_registry_binary_load_feature (GstRegistry * registry, gchar ** in,
   914     gchar * end, const gchar * plugin_name)
   679     const gchar * plugin_name)
   915 {
   680 {
   916   GstBinaryPluginFeature *pf = NULL;
   681   GstBinaryPluginFeature *pf = NULL;
   917   GstPluginFeature *feature = NULL;
   682   GstPluginFeature *feature;
   918   gchar *type_name = NULL, *str;
   683   gchar *type_name = NULL, *str;
   919   GType type;
   684   GType type;
   920   guint i;
   685   guint i;
   921 
   686 
   922   /* unpack plugin feature strings */
   687   /* unpack plugin feature strings */
   923   unpack_string (*in, type_name, end, fail);
   688   unpack_string (*in, type_name);
   924 
   689 
   925   if (G_UNLIKELY (!type_name)) {
   690   if (!type_name || !*(type_name))
   926     GST_ERROR ("No feature type name");
   691     return FALSE;
   927     return FALSE;
       
   928   }
       
   929 
   692 
   930   GST_DEBUG ("Plugin '%s' feature typename : '%s'", plugin_name, type_name);
   693   GST_DEBUG ("Plugin '%s' feature typename : '%s'", plugin_name, type_name);
   931 
   694 
   932   if (G_UNLIKELY (!(type = g_type_from_name (type_name)))) {
   695   if (!(type = g_type_from_name (type_name))) {
   933     GST_ERROR ("Unknown type from typename '%s' for plugin '%s'", type_name,
   696     GST_ERROR ("Unknown type from typename '%s' for plugin '%s'", type_name,
   934         plugin_name);
   697         plugin_name);
   935     g_free (type_name);
   698     return FALSE;
   936     return FALSE;
   699   }
   937   }
   700   if ((feature = g_object_new (type, NULL)) == NULL) {
   938   if (G_UNLIKELY ((feature = g_object_new (type, NULL)) == NULL)) {
       
   939     GST_ERROR ("Can't create feature from type");
   701     GST_ERROR ("Can't create feature from type");
   940     g_free (type_name);
   702     return FALSE;
   941     return FALSE;
   703   }
   942   }
   704 
   943 
   705   if (!GST_IS_PLUGIN_FEATURE (feature)) {
   944   if (G_UNLIKELY (!GST_IS_PLUGIN_FEATURE (feature))) {
   706     GST_ERROR ("typename : '%s' is not a plgin feature", type_name);
   945     GST_ERROR ("typename : '%s' is not a plugin feature", type_name);
       
   946     goto fail;
   707     goto fail;
   947   }
   708   }
   948 
   709 
   949   /* unpack more plugin feature strings */
   710   /* unpack more plugin feature strings */
   950   unpack_string (*in, feature->name, end, fail);
   711   unpack_string (*in, feature->name);
   951 
   712 
   952   if (GST_IS_ELEMENT_FACTORY (feature)) {
   713   if (GST_IS_ELEMENT_FACTORY (feature)) {
   953     GstBinaryElementFactory *ef;
   714     GstBinaryElementFactory *ef;
   954     guint n;
   715     GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
   955     GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (feature);
   716 
   956 
   717     align32 (*in);
   957     align (*in);
       
   958     GST_LOG ("Reading/casting for GstBinaryElementFactory at address %p", *in);
   718     GST_LOG ("Reading/casting for GstBinaryElementFactory at address %p", *in);
   959     unpack_element (*in, ef, GstBinaryElementFactory, end, fail);
   719     unpack_element (*in, ef, GstBinaryElementFactory);
   960     pf = (GstBinaryPluginFeature *) ef;
   720     pf = (GstBinaryPluginFeature *) ef;
   961 
   721 
   962     /* unpack element factory strings */
   722     /* unpack element factory strings */
   963     unpack_string (*in, factory->details.longname, end, fail);
   723     unpack_string (*in, factory->details.longname);
   964     unpack_string (*in, factory->details.klass, end, fail);
   724     unpack_string (*in, factory->details.klass);
   965     unpack_string (*in, factory->details.description, end, fail);
   725     unpack_string (*in, factory->details.description);
   966     unpack_string (*in, factory->details.author, end, fail);
   726     unpack_string (*in, factory->details.author);
   967     n = ef->npadtemplates;
       
   968     GST_DEBUG ("Element factory : '%s' with npadtemplates=%d",
   727     GST_DEBUG ("Element factory : '%s' with npadtemplates=%d",
   969         factory->details.longname, n);
   728         factory->details.longname, ef->npadtemplates);
   970 
   729 
   971     /* load pad templates */
   730     /* load pad templates */
   972     for (i = 0; i < n; i++) {
   731     for (i = 0; i < ef->npadtemplates; i++) {
   973       if (G_UNLIKELY (!gst_registry_binary_load_pad_template (factory, in,
   732       if (!gst_registry_binary_load_pad_template (factory, in)) {
   974                   end))) {
       
   975         GST_ERROR ("Error while loading binary pad template");
   733         GST_ERROR ("Error while loading binary pad template");
   976         goto fail;
   734         goto fail;
   977       }
   735       }
   978     }
   736     }
   979 
   737 
   980     /* load uritypes */
   738     /* load uritypes */
   981     if (G_UNLIKELY ((n = ef->nuriprotocols))) {
   739     if (ef->nuriprotocols) {
   982       GST_DEBUG ("Reading %d UriTypes at address %p", n, *in);
   740       GST_DEBUG ("Reading %d UriTypes at address %p", ef->nuriprotocols, *in);
   983 
   741 
   984       align (*in);
   742       align32 (*in);
   985       factory->uri_type = *((guint *) * in);
   743       factory->uri_type = *((guint *) * in);
   986       *in += sizeof (factory->uri_type);
   744       *in += sizeof (factory->uri_type);
   987       /*unpack_element(*in, &factory->uri_type, factory->uri_type, end, fail); */
   745       //unpack_element(*in, &factory->uri_type, factory->uri_type);
   988 
   746 
   989       factory->uri_protocols = g_new0 (gchar *, n + 1);
   747       factory->uri_protocols = g_new0 (gchar *, ef->nuriprotocols + 1);
   990       for (i = 0; i < n; i++) {
   748       for (i = 0; i < ef->nuriprotocols; i++) {
   991         unpack_string (*in, str, end, fail);
   749         unpack_string (*in, str);
   992         factory->uri_protocols[i] = str;
   750         factory->uri_protocols[i] = str;
   993       }
   751       }
   994     }
   752     }
   995 
       
   996     /* load interfaces */
   753     /* load interfaces */
   997     if (G_UNLIKELY ((n = ef->ninterfaces))) {
   754     GST_DEBUG ("Reading %d Interfaces at address %p", ef->ninterfaces, *in);
   998       GST_DEBUG ("Reading %d Interfaces at address %p", n, *in);
   755     for (i = 0; i < ef->ninterfaces; i++) {
   999       for (i = 0; i < n; i++) {
   756       unpack_string (*in, str);
  1000         unpack_string (*in, str, end, fail);
   757       __gst_element_factory_add_interface (factory, str);
  1001         __gst_element_factory_add_interface (factory, str);
   758       g_free (str);
  1002         g_free (str);
       
  1003       }
       
  1004     }
   759     }
  1005   } else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
   760   } else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
  1006     GstBinaryTypeFindFactory *tff;
   761     GstBinaryTypeFindFactory *tff;
  1007     GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature);
   762     GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature);
  1008 
   763 
  1009     align (*in);
   764     align32 (*in);
  1010     GST_DEBUG ("Reading/casting for GstBinaryPluginFeature at address %p", *in);
   765     GST_DEBUG ("Reading/casting for GstBinaryPluginFeature at address %p", *in);
  1011     unpack_element (*in, tff, GstBinaryTypeFindFactory, end, fail);
   766     unpack_element (*in, tff, GstBinaryTypeFindFactory);
  1012     pf = (GstBinaryPluginFeature *) tff;
   767     pf = (GstBinaryPluginFeature *) tff;
  1013 
   768 
  1014     /* load caps */
   769     /* load caps */
  1015     unpack_string (*in, str, end, fail);
   770     unpack_string (*in, str);
  1016     factory->caps = (str && *str) ? gst_caps_from_string (str) : NULL;
   771     factory->caps = gst_caps_from_string (str);
  1017     g_free (str);
   772     g_free (str);
  1018     /* load extensions */
   773     /* load extensions */
  1019     if (tff->nextensions) {
   774     if (tff->nextensions) {
  1020       GST_DEBUG ("Reading %d Typefind extensions at address %p",
   775       GST_DEBUG ("Reading %d Typefind extensions at address %p",
  1021           tff->nextensions, *in);
   776           tff->nextensions, *in);
  1022       factory->extensions = g_new0 (gchar *, tff->nextensions + 1);
   777       factory->extensions = g_new0 (gchar *, tff->nextensions + 1);
  1023       for (i = 0; i < tff->nextensions; i++) {
   778       for (i = 0; i < tff->nextensions; i++) {
  1024         unpack_string (*in, str, end, fail);
   779         unpack_string (*in, str);
  1025         factory->extensions[i] = str;
   780         factory->extensions[i] = str;
  1026       }
   781       }
  1027     }
   782     }
  1028   } else if (GST_IS_INDEX_FACTORY (feature)) {
   783   }
       
   784 #ifndef GST_DISABLE_INDEX
       
   785   else if (GST_IS_INDEX_FACTORY (feature)) {
  1029     GstIndexFactory *factory = GST_INDEX_FACTORY (feature);
   786     GstIndexFactory *factory = GST_INDEX_FACTORY (feature);
  1030 
   787 
  1031     align (*in);
   788     align32 (*in);
  1032     GST_DEBUG ("Reading/casting for GstBinaryPluginFeature at address %p", *in);
   789     GST_DEBUG ("Reading/casting for GstBinaryPluginFeature at address %p", *in);
  1033     unpack_element (*in, pf, GstBinaryPluginFeature, end, fail);
   790     unpack_element (*in, pf, GstBinaryPluginFeature);
  1034 
   791 
  1035     /* unpack index factory strings */
   792     /* unpack index factory strings */
  1036     unpack_string (*in, factory->longdesc, end, fail);
   793     unpack_string (*in, factory->longdesc);
  1037   } else {
   794   }
  1038     GST_WARNING ("unhandled factory type : %s", G_OBJECT_TYPE_NAME (feature));
   795 #endif
  1039     goto fail;
       
  1040   }
       
  1041 
   796 
  1042   feature->rank = pf->rank;
   797   feature->rank = pf->rank;
  1043 
   798 
  1044   /* should already be the interned string, but better make sure */
   799   /* should already be the interned string, but better make sure */
  1045   feature->plugin_name = g_intern_string (plugin_name);
   800   feature->plugin_name = g_intern_string (plugin_name);
  1050   g_free (type_name);
   805   g_free (type_name);
  1051   return TRUE;
   806   return TRUE;
  1052 
   807 
  1053   /* Errors */
   808   /* Errors */
  1054 fail:
   809 fail:
  1055   GST_INFO ("Reading plugin feature failed");
       
  1056   g_free (type_name);
   810   g_free (type_name);
  1057   if (feature) {
   811   if (GST_IS_OBJECT (feature))
  1058     if (GST_IS_OBJECT (feature))
   812     gst_object_unref (feature);
  1059       gst_object_unref (feature);
   813   else
  1060     else
   814     g_object_unref (feature);
  1061       g_object_unref (feature);
       
  1062   }
       
  1063   return FALSE;
   815   return FALSE;
  1064 }
   816 }
  1065 
   817 
  1066 static gchar **
       
  1067 gst_registry_binary_load_plugin_dep_strv (gchar ** in, gchar * end, guint n)
       
  1068 {
       
  1069   gchar **arr;
       
  1070 
       
  1071   if (n == 0)
       
  1072     return NULL;
       
  1073 
       
  1074   arr = g_new0 (gchar *, n + 1);
       
  1075   while (n > 0) {
       
  1076     unpack_string (*in, arr[n - 1], end, fail);
       
  1077     --n;
       
  1078   }
       
  1079   return arr;
       
  1080 fail:
       
  1081   GST_INFO ("Reading plugin dependency strings failed");
       
  1082   return NULL;
       
  1083 }
       
  1084 
       
  1085 static gboolean
       
  1086 gst_registry_binary_load_plugin_dep (GstPlugin * plugin, gchar ** in,
       
  1087     gchar * end)
       
  1088 {
       
  1089   GstPluginDep *dep;
       
  1090   GstBinaryDep *d;
       
  1091   gchar **s;
       
  1092 
       
  1093   align (*in);
       
  1094   GST_LOG_OBJECT (plugin, "Unpacking GstBinaryDep from %p", *in);
       
  1095   unpack_element (*in, d, GstBinaryDep, end, fail);
       
  1096 
       
  1097   dep = g_new0 (GstPluginDep, 1);
       
  1098 
       
  1099   dep->env_hash = d->env_hash;
       
  1100   dep->stat_hash = d->stat_hash;
       
  1101 
       
  1102   dep->flags = d->flags;
       
  1103 
       
  1104   dep->names = gst_registry_binary_load_plugin_dep_strv (in, end, d->n_names);
       
  1105   dep->paths = gst_registry_binary_load_plugin_dep_strv (in, end, d->n_paths);
       
  1106   dep->env_vars =
       
  1107       gst_registry_binary_load_plugin_dep_strv (in, end, d->n_env_vars);
       
  1108 
       
  1109   plugin->priv->deps = g_list_append (plugin->priv->deps, dep);
       
  1110 
       
  1111   GST_DEBUG_OBJECT (plugin, "Loaded external plugin dependency from registry: "
       
  1112       "env_hash: %08x, stat_hash: %08x", dep->env_hash, dep->stat_hash);
       
  1113   for (s = dep->env_vars; s != NULL && *s != NULL; ++s)
       
  1114     GST_LOG_OBJECT (plugin, " evar: %s", *s);
       
  1115   for (s = dep->paths; s != NULL && *s != NULL; ++s)
       
  1116     GST_LOG_OBJECT (plugin, " path: %s", *s);
       
  1117   for (s = dep->names; s != NULL && *s != NULL; ++s)
       
  1118     GST_LOG_OBJECT (plugin, " name: %s", *s);
       
  1119 
       
  1120   return TRUE;
       
  1121 fail:
       
  1122   GST_INFO ("Reading plugin dependency failed");
       
  1123   return FALSE;
       
  1124 }
       
  1125 
   818 
  1126 /*
   819 /*
  1127  * gst_registry_binary_load_plugin:
   820  * gst_registry_binary_load_plugin:
  1128  *
   821  *
  1129  * Make a new GstPlugin from current GstBinaryPluginElement structure
   822  * Make a new GstPlugin from current GstBinaryPluginElement structure
  1130  * and save it to the GstRegistry. Return an offset to the next
   823  * and save it to the GstRegistry. Return an offset to the next
  1131  * GstBinaryPluginElement structure.
   824  * GstBinaryPluginElement structure.
  1132  */
   825  */
  1133 static gboolean
   826 static gboolean
  1134 gst_registry_binary_load_plugin (GstRegistry * registry, gchar ** in,
   827 gst_registry_binary_load_plugin (GstRegistry * registry, gchar ** in)
  1135     gchar * end)
       
  1136 {
   828 {
  1137   GstBinaryPluginElement *pe;
   829   GstBinaryPluginElement *pe;
  1138   GstPlugin *plugin = NULL;
   830   GstPlugin *plugin = NULL;
  1139   gchar *cache_str = NULL;
   831   guint i;
  1140   guint i, n;
   832 
  1141 
   833   align32 (*in);
  1142   align (*in);
       
  1143   GST_LOG ("Reading/casting for GstBinaryPluginElement at address %p", *in);
   834   GST_LOG ("Reading/casting for GstBinaryPluginElement at address %p", *in);
  1144   unpack_element (*in, pe, GstBinaryPluginElement, end, fail);
   835   unpack_element (*in, pe, GstBinaryPluginElement);
       
   836 
       
   837   if (pe->nfeatures < 0) {
       
   838     GST_ERROR ("The number of feature structure is not valid !");
       
   839     return FALSE;
       
   840   }
       
   841 
       
   842   if (pe->file_mtime < 0 || pe->file_size < 0) {
       
   843     GST_ERROR ("Plugin time or file size is not valid !");
       
   844     return FALSE;
       
   845   }
  1145 
   846 
  1146   plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
   847   plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
  1147 
   848 
  1148   /* TODO: also set GST_PLUGIN_FLAG_CONST */
   849   /* TODO: also set GST_PLUGIN_FLAG_CONST */
  1149   plugin->flags |= GST_PLUGIN_FLAG_CACHED;
   850   plugin->flags |= GST_PLUGIN_FLAG_CACHED;
  1150   plugin->file_mtime = pe->file_mtime;
   851   plugin->file_mtime = pe->file_mtime;
  1151   plugin->file_size = pe->file_size;
   852   plugin->file_size = pe->file_size;
  1152 
   853 
  1153   /* unpack plugin element strings */
   854   /* unpack plugin element strings */
  1154   unpack_const_string (*in, plugin->desc.name, end, fail);
   855   unpack_const_string (*in, plugin->desc.name);
  1155   unpack_string (*in, plugin->desc.description, end, fail);
   856   unpack_string (*in, plugin->desc.description);
  1156   unpack_string (*in, plugin->filename, end, fail);
   857   unpack_string (*in, plugin->filename);
  1157   unpack_const_string (*in, plugin->desc.version, end, fail);
   858   unpack_const_string (*in, plugin->desc.version);
  1158   unpack_const_string (*in, plugin->desc.license, end, fail);
   859   unpack_const_string (*in, plugin->desc.license);
  1159   unpack_const_string (*in, plugin->desc.source, end, fail);
   860   unpack_const_string (*in, plugin->desc.source);
  1160   unpack_const_string (*in, plugin->desc.package, end, fail);
   861   unpack_const_string (*in, plugin->desc.package);
  1161   unpack_const_string (*in, plugin->desc.origin, end, fail);
   862   unpack_const_string (*in, plugin->desc.origin);
  1162   GST_LOG ("read strings for name='%s'", plugin->desc.name);
   863   GST_LOG ("read strings for '%s'", plugin->desc.name);
  1163   GST_LOG ("  desc.description='%s'", plugin->desc.description);
       
  1164   GST_LOG ("  filename='%s'", plugin->filename);
       
  1165   GST_LOG ("  desc.version='%s'", plugin->desc.version);
       
  1166   GST_LOG ("  desc.license='%s'", plugin->desc.license);
       
  1167   GST_LOG ("  desc.source='%s'", plugin->desc.source);
       
  1168   GST_LOG ("  desc.package='%s'", plugin->desc.package);
       
  1169   GST_LOG ("  desc.origin='%s'", plugin->desc.origin);
       
  1170 
       
  1171   /* unpack cache data */
       
  1172   unpack_string (*in, cache_str, end, fail);
       
  1173   if (*cache_str) {
       
  1174     plugin->priv->cache_data = gst_structure_from_string (cache_str, NULL);
       
  1175   }
       
  1176   g_free (cache_str);
       
  1177 
   864 
  1178   plugin->basename = g_path_get_basename (plugin->filename);
   865   plugin->basename = g_path_get_basename (plugin->filename);
  1179 
       
  1180   /* Takes ownership of plugin */
       
  1181   gst_registry_add_plugin (registry, plugin);
   866   gst_registry_add_plugin (registry, plugin);
  1182   n = pe->nfeatures;
   867   GST_INFO ("Added plugin '%s' plugin with %d features from binary registry",
  1183   GST_DEBUG ("Added plugin '%s' plugin with %d features from binary registry",
   868       plugin->desc.name, pe->nfeatures);
  1184       plugin->desc.name, n);
   869   for (i = 0; i < pe->nfeatures; i++) {
  1185 
   870     if (!gst_registry_binary_load_feature (registry, in, plugin->desc.name)) {
  1186   /* Load plugin features */
       
  1187   for (i = 0; i < n; i++) {
       
  1188     if (G_UNLIKELY (!gst_registry_binary_load_feature (registry, in, end,
       
  1189                 plugin->desc.name))) {
       
  1190       GST_ERROR ("Error while loading binary feature");
   871       GST_ERROR ("Error while loading binary feature");
  1191       gst_registry_remove_plugin (registry, plugin);
       
  1192       goto fail;
       
  1193     }
       
  1194   }
       
  1195 
       
  1196   /* Load external plugin dependencies */
       
  1197   for (i = 0; i < pe->n_deps; ++i) {
       
  1198     if (G_UNLIKELY (!gst_registry_binary_load_plugin_dep (plugin, in, end))) {
       
  1199       GST_ERROR_OBJECT (plugin, "Could not read external plugin dependency");
       
  1200       gst_registry_remove_plugin (registry, plugin);
       
  1201       goto fail;
   872       goto fail;
  1202     }
   873     }
  1203   }
   874   }
  1204 
   875 
  1205   return TRUE;
   876   return TRUE;
  1206 
   877 
  1207   /* Errors */
   878   /* Errors */
  1208 fail:
   879 fail:
  1209   GST_INFO ("Reading plugin failed");
   880   gst_object_unref (plugin);
  1210   return FALSE;
   881   return FALSE;
  1211 }
   882 }
  1212 
   883 
  1213 
   884 
  1214 /**
   885 /**
  1221  * Returns: %TRUE on success.
   892  * Returns: %TRUE on success.
  1222  */
   893  */
  1223 #ifdef __SYMBIAN32__
   894 #ifdef __SYMBIAN32__
  1224 EXPORT_C
   895 EXPORT_C
  1225 #endif
   896 #endif
       
   897 
  1226 gboolean
   898 gboolean
  1227 gst_registry_binary_read_cache (GstRegistry * registry, const char *location)
   899 gst_registry_binary_read_cache (GstRegistry * registry, const char *location)
  1228 {
   900 {
  1229   GMappedFile *mapped = NULL;
   901   GMappedFile *mapped = NULL;
       
   902   GTimer *timer = NULL;
  1230   gchar *contents = NULL;
   903   gchar *contents = NULL;
  1231   gchar *in = NULL;
   904   gchar *in = NULL;
       
   905   gdouble seconds;
  1232   gsize size;
   906   gsize size;
  1233   GError *err = NULL;
   907   GError *err = NULL;
  1234   gboolean res = FALSE;
   908   gboolean res = FALSE;
  1235   gint check_magic_result;
       
  1236 #ifndef GST_DISABLE_GST_DEBUG
       
  1237   GTimer *timer = NULL;
       
  1238   gdouble seconds;
       
  1239 #endif
       
  1240 
   909 
  1241   /* make sure these types exist */
   910   /* make sure these types exist */
  1242   GST_TYPE_ELEMENT_FACTORY;
   911   GST_TYPE_ELEMENT_FACTORY;
  1243   GST_TYPE_TYPE_FIND_FACTORY;
   912   GST_TYPE_TYPE_FIND_FACTORY;
       
   913 #ifndef GST_DISABLE_INDEX
  1244   GST_TYPE_INDEX_FACTORY;
   914   GST_TYPE_INDEX_FACTORY;
  1245 
   915 #endif
  1246 #ifndef GST_DISABLE_GST_DEBUG
   916 
  1247   timer = g_timer_new ();
   917   timer = g_timer_new ();
  1248 #endif
       
  1249 
   918 
  1250   mapped = g_mapped_file_new (location, FALSE, &err);
   919   mapped = g_mapped_file_new (location, FALSE, &err);
  1251   if (G_UNLIKELY (err != NULL)) {
   920   if (err != NULL) {
  1252     GST_INFO ("Unable to mmap file %s : %s", location, err->message);
   921     GST_INFO ("Unable to mmap file %s : %s", location, err->message);
  1253     g_error_free (err);
   922     g_error_free (err);
  1254     err = NULL;
   923     err = NULL;
  1255 
   924 
  1256     g_file_get_contents (location, &contents, &size, &err);
   925     g_file_get_contents (location, &contents, &size, &err);
  1257     if (err != NULL) {
   926     if (err != NULL) {
  1258       GST_INFO ("Unable to read file %s : %s", location, err->message);
   927       GST_INFO ("Unable to read file %s : %s", location, err->message);
  1259 #ifndef GST_DISABLE_GST_DEBUG
       
  1260       g_timer_destroy (timer);
   928       g_timer_destroy (timer);
  1261 #endif
       
  1262       g_error_free (err);
   929       g_error_free (err);
  1263       return FALSE;
   930       return FALSE;
  1264     }
   931     }
  1265   } else {
   932   } else {
  1266     if (G_UNLIKELY ((contents = g_mapped_file_get_contents (mapped)) == NULL)) {
   933     if ((contents = g_mapped_file_get_contents (mapped)) == NULL) {
  1267       GST_ERROR ("Can't load file %s : %s", location, g_strerror (errno));
   934       GST_ERROR ("Can't load file %s : %s", location, g_strerror (errno));
  1268       goto Error;
   935       goto Error;
  1269     }
   936     }
  1270     /* check length for header */
   937     /* check length for header */
  1271     size = g_mapped_file_get_length (mapped);
   938     size = g_mapped_file_get_length (mapped);
  1272   }
   939   }
  1273 
       
  1274   /* in is a cursor pointer, we initialize it with the begin of registry and is updated on each read */
   940   /* in is a cursor pointer, we initialize it with the begin of registry and is updated on each read */
  1275   in = contents;
   941   in = contents;
  1276   GST_DEBUG ("File data at address %p", in);
   942   GST_DEBUG ("File data at address %p", in);
  1277   if (G_UNLIKELY (size < sizeof (GstBinaryRegistryMagic))) {
   943   if (size < sizeof (GstBinaryRegistryMagic)) {
  1278     GST_ERROR ("No or broken registry header");
   944     GST_ERROR ("No or broken registry header");
  1279     goto Error;
   945     goto Error;
  1280   }
   946   }
  1281 
       
  1282   /* check if header is valid */
   947   /* check if header is valid */
  1283   if (G_UNLIKELY ((check_magic_result =
   948   if (!gst_registry_binary_check_magic (&in)) {
  1284               gst_registry_binary_check_magic (&in, size)) < 0)) {
   949     GST_ERROR
  1285 
   950         ("Binary registry type not recognized (invalid magic) for file at %s",
  1286     if (check_magic_result == -1)
   951         location);
  1287       GST_ERROR
       
  1288           ("Binary registry type not recognized (invalid magic) for file at %s",
       
  1289           location);
       
  1290     goto Error;
   952     goto Error;
  1291   }
   953   }
  1292 
   954 
  1293   /* check if there are plugins in the file */
   955   /* check if there are plugins in the file */
  1294   if (G_UNLIKELY (!(((gsize) in + sizeof (GstBinaryPluginElement)) <
   956 
  1295               (gsize) contents + size))) {
   957   if (!(((gsize) in + sizeof (GstBinaryPluginElement)) <
       
   958           (gsize) contents + size)) {
  1296     GST_INFO ("No binary plugins structure to read");
   959     GST_INFO ("No binary plugins structure to read");
  1297     /* empty file, this is not an error */
   960     /* empty file, this is not an error */
  1298   } else {
   961   } else {
  1299     gchar *end = contents + size;
       
  1300     /* read as long as we still have space for a GstBinaryPluginElement */
       
  1301     for (;
   962     for (;
  1302         ((gsize) in + sizeof (GstBinaryPluginElement)) <
   963         ((gsize) in + sizeof (GstBinaryPluginElement)) <
  1303         (gsize) contents + size;) {
   964         (gsize) contents + size;) {
  1304       GST_DEBUG ("reading binary registry %" G_GSIZE_FORMAT "(%x)/%"
   965       GST_DEBUG ("reading binary registry %" G_GSIZE_FORMAT "(%x)/%"
  1305           G_GSIZE_FORMAT, (gsize) in - (gsize) contents,
   966           G_GSIZE_FORMAT, (gsize) in - (gsize) contents,
  1306           (guint) ((gsize) in - (gsize) contents), size);
   967           (guint) ((gsize) in - (gsize) contents), size);
  1307       if (!gst_registry_binary_load_plugin (registry, &in, end)) {
   968       if (!gst_registry_binary_load_plugin (registry, &in)) {
  1308         GST_ERROR ("Problem while reading binary registry %s", location);
   969         GST_ERROR ("Problem while reading binary registry");
  1309         goto Error;
   970         goto Error;
  1310       }
   971       }
  1311     }
   972     }
  1312   }
   973   }
  1313 
   974 
  1314 #ifndef GST_DISABLE_GST_DEBUG
       
  1315   g_timer_stop (timer);
   975   g_timer_stop (timer);
  1316   seconds = g_timer_elapsed (timer, NULL);
   976   seconds = g_timer_elapsed (timer, NULL);
  1317 #endif
       
  1318 
   977 
  1319   GST_INFO ("loaded %s in %lf seconds", location, seconds);
   978   GST_INFO ("loaded %s in %lf seconds", location, seconds);
  1320 
   979 
  1321   res = TRUE;
   980   res = TRUE;
  1322   /* TODO: once we re-use the pointers to registry contents, return here */
   981   /* TODO: once we re-use the pointers to registry contents return here */
  1323 
   982 
  1324 Error:
   983 Error:
  1325 #ifndef GST_DISABLE_GST_DEBUG
       
  1326   g_timer_destroy (timer);
   984   g_timer_destroy (timer);
  1327 #endif
       
  1328   if (mapped) {
   985   if (mapped) {
  1329     g_mapped_file_free (mapped);
   986     g_mapped_file_free (mapped);
  1330   } else {
   987   } else {
  1331     g_free (contents);
   988     g_free (contents);
  1332   }
   989   }