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 /* |
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 } |