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