2 * Copyright (C) 2006 Josep Torra <josep@fluendo.com>
3 * 2006 Mathieu Garcia <matthieu@fluendo.com>
4 * 2006,2007 Stefan Kost <ensonic@users.sf.net>
5 * 2008 Sebastian Dröge <slomo@circular-chaos.org>
6 * 2008 Jan Schmidt <jan.schmidt@sun.com>
8 * gstregistrychunks.c: GstRegistryChunk helper for serialising/deserialising
9 * plugin entries and features.
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Library General Public License for more details.
21 * You should have received a copy of the GNU Library General Public
22 * License along with this library; if not, write to the
23 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
24 * Boston, MA 02110-1301, USA.
31 #include <gst/gst_private.h>
32 #include <gst/gstconfig.h>
33 #include <gst/gstelement.h>
34 #include <gst/gsttracerfactory.h>
35 #include <gst/gsttypefind.h>
36 #include <gst/gsttypefindfactory.h>
37 #include <gst/gstdeviceproviderfactory.h>
38 #include <gst/gstdynamictypefactory.h>
39 #include <gst/gsturi.h>
40 #include <gst/gstinfo.h>
41 #include <gst/gstenumtypes.h>
42 #include <gst/gstpadtemplate.h>
43 #include "glib-compat-private.h"
45 #include <gst/gstregistrychunks.h>
47 #define GST_CAT_DEFAULT GST_CAT_REGISTRY
49 /* count string length, but return -1 if we hit the eof */
52 _strnlen (const gchar * str, gint maxlen)
54 gint len = strnlen (str, maxlen);
56 if (G_UNLIKELY (len == maxlen))
62 _strnlen (const gchar * str, gint maxlen)
66 while (G_LIKELY (len < maxlen)) {
67 if (G_UNLIKELY (str[len] == '\0'))
76 #define unpack_element(inptr, outptr, element, endptr, error_label) G_STMT_START{ \
77 if (inptr + sizeof(element) > endptr) { \
78 GST_ERROR ("Failed reading element " G_STRINGIFY (element) \
79 ". Have %d bytes need %" G_GSIZE_FORMAT, \
80 (int) (endptr - inptr), sizeof(element)); \
83 outptr = (element *) inptr; \
84 inptr += sizeof (element); \
87 #define unpack_const_string(inptr, outptr, endptr, error_label) G_STMT_START{\
88 gint _len = _strnlen (inptr, (endptr-inptr)); \
91 outptr = g_intern_string ((const gchar *)inptr); \
95 #define unpack_string(inptr, outptr, endptr, error_label) G_STMT_START{\
96 gint _len = _strnlen (inptr, (endptr-inptr)); \
99 outptr = g_memdup2 ((gconstpointer)inptr, _len + 1); \
103 #define unpack_string_nocopy(inptr, outptr, endptr, error_label) G_STMT_START{\
104 gint _len = _strnlen (inptr, (endptr-inptr)); \
107 outptr = (const gchar *)inptr; \
111 #define ALIGNMENT (sizeof (void *))
112 #define alignment(_address) (gsize)_address%ALIGNMENT
113 #define align(_ptr) _ptr += (( alignment(_ptr) == 0) ? 0 : ALIGNMENT-alignment(_ptr))
116 _priv_gst_registry_chunk_free (GstRegistryChunk * chunk)
118 if (!(chunk->flags & GST_REGISTRY_CHUNK_FLAG_CONST)) {
119 if ((chunk->flags & GST_REGISTRY_CHUNK_FLAG_MALLOC))
120 g_free (chunk->data);
122 g_slice_free1 (chunk->size, chunk->data);
124 g_slice_free (GstRegistryChunk, chunk);
128 * gst_registry_chunks_save_const_string:
130 * Store a const string in a binary chunk.
132 * Returns: %TRUE for success
134 inline static gboolean
135 gst_registry_chunks_save_const_string (GList ** list, const gchar * str)
137 GstRegistryChunk *chunk;
139 if (G_UNLIKELY (str == NULL)) {
140 GST_ERROR ("unexpected NULL string in plugin or plugin feature data");
144 chunk = g_slice_new (GstRegistryChunk);
145 chunk->data = (gpointer) str;
146 chunk->size = strlen ((gchar *) chunk->data) + 1;
147 chunk->flags = GST_REGISTRY_CHUNK_FLAG_CONST;
148 chunk->align = FALSE;
149 *list = g_list_prepend (*list, chunk);
154 * gst_registry_chunks_save_string:
156 * Store a string in a binary chunk.
158 * Returns: %TRUE for success
160 inline static gboolean
161 gst_registry_chunks_save_string (GList ** list, gchar * str)
163 GstRegistryChunk *chunk;
165 chunk = g_slice_new (GstRegistryChunk);
167 chunk->size = strlen ((gchar *) chunk->data) + 1;
168 chunk->flags = GST_REGISTRY_CHUNK_FLAG_MALLOC;
169 chunk->align = FALSE;
170 *list = g_list_prepend (*list, chunk);
175 * gst_registry_chunks_save_data:
177 * Store some data in a binary chunk.
179 * Returns: the initialized chunk
181 inline static GstRegistryChunk *
182 gst_registry_chunks_make_data (gpointer data, gulong size)
184 GstRegistryChunk *chunk;
186 chunk = g_slice_new (GstRegistryChunk);
189 chunk->flags = GST_REGISTRY_CHUNK_FLAG_NONE;
196 * gst_registry_chunks_save_pad_template:
198 * Store pad_templates in binary chunks.
200 * Returns: %TRUE for success
203 gst_registry_chunks_save_pad_template (GList ** list,
204 GstStaticPadTemplate * template)
206 GstRegistryChunkPadTemplate *pt;
207 GstRegistryChunk *chk;
209 pt = g_slice_new (GstRegistryChunkPadTemplate);
211 gst_registry_chunks_make_data (pt, sizeof (GstRegistryChunkPadTemplate));
213 pt->presence = template->presence;
214 pt->direction = template->direction;
216 /* pack pad template strings */
217 gst_registry_chunks_save_const_string (list,
218 (gchar *) (template->static_caps.string));
219 gst_registry_chunks_save_const_string (list, template->name_template);
221 *list = g_list_prepend (*list, chk);
227 * gst_registry_chunks_save_feature:
229 * Store features in binary chunks.
231 * Returns: %TRUE for success
234 gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature)
236 const gchar *type_name = G_OBJECT_TYPE_NAME (feature);
237 GstRegistryChunkPluginFeature *pf = NULL;
238 GstRegistryChunk *chk = NULL;
243 GST_ERROR ("NULL feature type_name, aborting.");
247 if (GST_IS_ELEMENT_FACTORY (feature)) {
248 GstRegistryChunkElementFactory *ef;
249 GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
251 /* Initialize with zeroes because of struct padding and
252 * valgrind complaining about copying uninitialized memory
254 ef = g_slice_new0 (GstRegistryChunkElementFactory);
255 pf_size = sizeof (GstRegistryChunkElementFactory);
256 chk = gst_registry_chunks_make_data (ef, pf_size);
257 ef->npadtemplates = ef->ninterfaces = ef->nuriprotocols = 0;
258 pf = (GstRegistryChunkPluginFeature *) ef;
260 /* save interfaces */
261 for (walk = factory->interfaces; walk;
262 walk = g_list_next (walk), ef->ninterfaces++) {
263 gst_registry_chunks_save_const_string (list, (gchar *) walk->data);
265 GST_DEBUG_OBJECT (feature, "saved %d interfaces %d pad templates",
266 ef->ninterfaces, ef->npadtemplates);
269 if (GST_URI_TYPE_IS_VALID (factory->uri_type)) {
270 if (factory->uri_protocols && *factory->uri_protocols) {
271 GstRegistryChunk *subchk;
275 gst_registry_chunks_make_data (&factory->uri_type,
276 sizeof (factory->uri_type));
277 subchk->flags = GST_REGISTRY_CHUNK_FLAG_CONST;
279 protocol = factory->uri_protocols;
281 gst_registry_chunks_save_const_string (list, *protocol++);
284 *list = g_list_prepend (*list, subchk);
285 GST_DEBUG_OBJECT (feature, "Saved %d UriTypes", ef->nuriprotocols);
287 g_warning ("GStreamer feature '%s' is URI handler but does not provide"
288 " any protocols it can handle", GST_OBJECT_NAME (feature));
292 /* save pad-templates */
293 for (walk = factory->staticpadtemplates; walk;
294 walk = g_list_next (walk), ef->npadtemplates++) {
295 GstStaticPadTemplate *template = walk->data;
297 if (!gst_registry_chunks_save_pad_template (list, template)) {
298 GST_ERROR_OBJECT (feature, "Can't fill pad template, aborting.");
303 /* pack element metadata strings */
304 gst_registry_chunks_save_string (list,
305 gst_structure_to_string (factory->metadata));
306 } else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
307 GstRegistryChunkTypeFindFactory *tff;
308 GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature);
311 /* Initialize with zeroes because of struct padding and
312 * valgrind complaining about copying uninitialized memory
314 tff = g_slice_new0 (GstRegistryChunkTypeFindFactory);
315 pf_size = sizeof (GstRegistryChunkTypeFindFactory);
316 chk = gst_registry_chunks_make_data (tff, pf_size);
317 tff->nextensions = 0;
318 pf = (GstRegistryChunkPluginFeature *) tff;
320 /* save extensions */
321 if (factory->extensions) {
322 while (factory->extensions[tff->nextensions]) {
323 gst_registry_chunks_save_const_string (list,
324 factory->extensions[tff->nextensions++]);
327 GST_DEBUG_OBJECT (feature, "saved %d extensions", tff->nextensions);
330 GstCaps *fcaps = gst_caps_ref (factory->caps);
331 /* we simplify the caps before saving. This is a lot faster
332 * when loading them later on */
333 fcaps = gst_caps_simplify (fcaps);
334 str = gst_caps_to_string (fcaps);
335 gst_caps_unref (fcaps);
337 gst_registry_chunks_save_string (list, str);
339 gst_registry_chunks_save_const_string (list, "");
341 } else if (GST_IS_DEVICE_PROVIDER_FACTORY (feature)) {
342 GstRegistryChunkDeviceProviderFactory *tff;
343 GstDeviceProviderFactory *factory = GST_DEVICE_PROVIDER_FACTORY (feature);
345 /* Initialize with zeroes because of struct padding and
346 * valgrind complaining about copying uninitialized memory
348 tff = g_slice_new0 (GstRegistryChunkDeviceProviderFactory);
350 gst_registry_chunks_make_data (tff,
351 sizeof (GstRegistryChunkDeviceProviderFactory));
352 pf = (GstRegistryChunkPluginFeature *) tff;
355 /* pack element metadata strings */
356 gst_registry_chunks_save_string (list,
357 gst_structure_to_string (factory->metadata));
358 } else if (GST_IS_TRACER_FACTORY (feature)) {
359 /* Initialize with zeroes because of struct padding and
360 * valgrind complaining about copying uninitialized memory
362 pf = g_slice_new0 (GstRegistryChunkPluginFeature);
363 pf_size = sizeof (GstRegistryChunkPluginFeature);
364 chk = gst_registry_chunks_make_data (pf, pf_size);
365 } else if (GST_IS_DYNAMIC_TYPE_FACTORY (feature)) {
366 GstRegistryChunkDynamicTypeFactory *tmp;
368 tmp = g_slice_new0 (GstRegistryChunkDynamicTypeFactory);
370 gst_registry_chunks_make_data (tmp,
371 sizeof (GstRegistryChunkDynamicTypeFactory));
372 pf = (GstRegistryChunkPluginFeature *) tmp;
374 GST_WARNING_OBJECT (feature, "unhandled feature type '%s'", type_name);
378 pf->rank = feature->rank;
379 *list = g_list_prepend (*list, chk);
381 /* pack plugin feature strings */
382 gst_registry_chunks_save_const_string (list, GST_OBJECT_NAME (feature));
383 gst_registry_chunks_save_const_string (list, (gchar *) type_name);
390 g_slice_free (GstRegistryChunk, chk);
391 g_slice_free1 (pf_size, pf);
396 gst_registry_chunks_save_plugin_dep (GList ** list, GstPluginDep * dep)
398 GstRegistryChunkDep *ed;
399 GstRegistryChunk *chk;
402 ed = g_slice_new (GstRegistryChunkDep);
403 chk = gst_registry_chunks_make_data (ed, sizeof (GstRegistryChunkDep));
405 ed->flags = dep->flags;
410 ed->env_hash = dep->env_hash;
411 ed->stat_hash = dep->stat_hash;
413 for (s = dep->env_vars; s != NULL && *s != NULL; ++s, ++ed->n_env_vars)
414 gst_registry_chunks_save_string (list, g_strdup (*s));
416 for (s = dep->paths; s != NULL && *s != NULL; ++s, ++ed->n_paths)
417 gst_registry_chunks_save_string (list, g_strdup (*s));
419 for (s = dep->names; s != NULL && *s != NULL; ++s, ++ed->n_names)
420 gst_registry_chunks_save_string (list, g_strdup (*s));
422 *list = g_list_prepend (*list, chk);
424 GST_LOG ("Saved external plugin dependency");
429 * _priv_gst_registry_chunks_save_plugin:
431 * Adapt a GstPlugin to our GstRegistryChunkPluginElement structure, and
432 * prepend it as a GstRegistryChunk in the provided list.
436 _priv_gst_registry_chunks_save_plugin (GList ** list, GstRegistry * registry,
439 GstRegistryChunkPluginElement *pe;
440 GstRegistryChunk *chk;
441 GList *plugin_features = NULL;
444 pe = g_slice_new (GstRegistryChunkPluginElement);
446 gst_registry_chunks_make_data (pe,
447 sizeof (GstRegistryChunkPluginElement));
449 pe->file_size = plugin->file_size;
450 pe->file_mtime = plugin->file_mtime;
454 /* pack external deps */
455 for (walk = plugin->priv->deps; walk != NULL; walk = walk->next) {
456 if (!gst_registry_chunks_save_plugin_dep (list, walk->data)) {
457 GST_ERROR ("Could not save external plugin dependency, aborting.");
463 /* pack plugin features */
464 plugin_features = _priv_plugin_get_features (registry, plugin);
465 for (walk = plugin_features; walk; walk = g_list_next (walk), pe->nfeatures++) {
466 GstPluginFeature *feature = GST_PLUGIN_FEATURE (walk->data);
468 if (!gst_registry_chunks_save_feature (list, feature)) {
469 GST_ERROR ("Can't fill plugin feature, aborting.");
474 gst_plugin_feature_list_free (plugin_features);
476 /* pack cache data */
477 if (plugin->priv->cache_data) {
478 gchar *cache_str = gst_structure_to_string (plugin->priv->cache_data);
479 gst_registry_chunks_save_string (list, cache_str);
481 gst_registry_chunks_save_const_string (list, "");
484 /* pack plugin element strings */
485 gst_registry_chunks_save_const_string (list,
486 (plugin->desc.release_datetime) ? plugin->desc.release_datetime : "");
487 gst_registry_chunks_save_const_string (list, plugin->desc.origin);
488 gst_registry_chunks_save_const_string (list, plugin->desc.package);
489 gst_registry_chunks_save_const_string (list, plugin->desc.source);
490 gst_registry_chunks_save_const_string (list, plugin->desc.license);
491 gst_registry_chunks_save_const_string (list, plugin->desc.version);
492 gst_registry_chunks_save_const_string (list, plugin->filename);
493 gst_registry_chunks_save_const_string (list, plugin->desc.description);
494 gst_registry_chunks_save_const_string (list, plugin->desc.name);
496 *list = g_list_prepend (*list, chk);
498 GST_DEBUG ("Found %d features in plugin %p (%s)", pe->nfeatures,
499 plugin, plugin->desc.name);
504 gst_plugin_feature_list_free (plugin_features);
505 g_slice_free (GstRegistryChunk, chk);
506 g_slice_free (GstRegistryChunkPluginElement, pe);
511 * gst_registry_chunks_load_pad_template:
513 * Make a new GstStaticPadTemplate from current GstRegistryChunkPadTemplate
516 * Returns: new GstStaticPadTemplate
519 gst_registry_chunks_load_pad_template (GstElementFactory * factory, gchar ** in,
522 GstRegistryChunkPadTemplate *pt;
523 GstStaticPadTemplate *template = NULL;
526 GST_DEBUG ("Reading/casting for GstRegistryChunkPadTemplate at address %p",
528 unpack_element (*in, pt, GstRegistryChunkPadTemplate, end, fail);
530 template = g_slice_new (GstStaticPadTemplate);
531 template->presence = pt->presence;
532 template->direction = (GstPadDirection) pt->direction;
533 template->static_caps.caps = NULL;
535 /* unpack pad template strings */
536 unpack_const_string (*in, template->name_template, end, fail);
537 unpack_const_string (*in, template->static_caps.string, end, fail);
539 __gst_element_factory_add_static_pad_template (factory, template);
540 GST_DEBUG ("Added pad_template %s", template->name_template);
544 GST_INFO ("Reading pad template failed");
546 g_slice_free (GstStaticPadTemplate, template);
551 * gst_registry_chunks_load_feature:
553 * Make a new GstPluginFeature from current binary plugin feature structure
555 * Returns: new GstPluginFeature
558 gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
559 gchar * end, GstPlugin * plugin)
561 GstRegistryChunkPluginFeature *pf = NULL;
562 GstPluginFeature *feature = NULL;
563 const gchar *const_str, *type_name;
564 const gchar *feature_name;
565 const gchar *plugin_name;
570 plugin_name = plugin->desc.name;
572 /* unpack plugin feature strings */
573 unpack_string_nocopy (*in, type_name, end, fail);
575 if (G_UNLIKELY (!type_name)) {
576 GST_ERROR ("No feature type name");
580 /* unpack more plugin feature strings */
581 unpack_string_nocopy (*in, feature_name, end, fail);
583 GST_DEBUG ("Plugin '%s' feature '%s' typename : '%s'", plugin_name,
584 feature_name, type_name);
586 if (G_UNLIKELY (!(type = g_type_from_name (type_name)))) {
587 GST_ERROR ("Unknown type from typename '%s' for plugin '%s'", type_name,
591 if (G_UNLIKELY ((feature =
592 g_object_new (type, "name", feature_name, NULL)) == NULL)) {
593 GST_ERROR ("Can't create feature from type");
597 if (G_UNLIKELY (!GST_IS_PLUGIN_FEATURE (feature))) {
598 GST_ERROR ("typename : '%s' is not a plugin feature", type_name);
602 if (GST_IS_ELEMENT_FACTORY (feature)) {
603 GstRegistryChunkElementFactory *ef;
605 GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (feature);
607 const gchar *meta_data_str;
610 GST_LOG ("Reading/casting for GstRegistryChunkElementFactory at address %p",
612 unpack_element (*in, ef, GstRegistryChunkElementFactory, end, fail);
613 pf = (GstRegistryChunkPluginFeature *) ef;
615 /* unpack element factory strings */
616 unpack_string_nocopy (*in, meta_data_str, end, fail);
617 if (meta_data_str && *meta_data_str) {
618 factory->metadata = gst_structure_from_string (meta_data_str, NULL);
619 if (!factory->metadata) {
621 ("Error when trying to deserialize structure for metadata '%s'",
626 n = ef->npadtemplates;
627 GST_DEBUG ("Element factory : npadtemplates=%d", n);
629 /* load pad templates */
630 for (i = 0; i < n; i++) {
631 if (G_UNLIKELY (!gst_registry_chunks_load_pad_template (factory, in,
633 GST_ERROR ("Error while loading binary pad template");
639 if (G_UNLIKELY ((n = ef->nuriprotocols))) {
640 GST_DEBUG ("Reading %d UriTypes at address %p", n, *in);
643 factory->uri_type = *((guint *) * in);
644 *in += sizeof (factory->uri_type);
645 /*unpack_element(*in, &factory->uri_type, factory->uri_type, end, fail); */
647 factory->uri_protocols = g_new0 (gchar *, n + 1);
648 for (i = 0; i < n; i++) {
649 unpack_string (*in, str, end, fail);
650 factory->uri_protocols[i] = str;
653 /* load interfaces */
654 if (G_UNLIKELY ((n = ef->ninterfaces))) {
655 GST_DEBUG ("Reading %d Interfaces at address %p", n, *in);
656 for (i = 0; i < n; i++) {
657 unpack_string_nocopy (*in, const_str, end, fail);
658 __gst_element_factory_add_interface (factory, const_str);
661 } else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
662 GstRegistryChunkTypeFindFactory *tff;
663 GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature);
667 ("Reading/casting for GstRegistryChunkPluginFeature at address %p",
669 unpack_element (*in, tff, GstRegistryChunkTypeFindFactory, end, fail);
670 pf = (GstRegistryChunkPluginFeature *) tff;
672 /* load typefinder caps */
673 unpack_string_nocopy (*in, const_str, end, fail);
674 if (const_str != NULL && *const_str != '\0')
675 factory->caps = gst_caps_from_string (const_str);
677 factory->caps = NULL;
679 /* load extensions */
680 if (tff->nextensions) {
681 GST_DEBUG ("Reading %d Typefind extensions at address %p",
682 tff->nextensions, *in);
683 factory->extensions = g_new0 (gchar *, tff->nextensions + 1);
684 /* unpack in reverse order to maintain the correct order */
685 for (i = tff->nextensions; i > 0; i--) {
686 unpack_string (*in, str, end, fail);
687 factory->extensions[i - 1] = str;
690 } else if (GST_IS_DEVICE_PROVIDER_FACTORY (feature)) {
691 GstRegistryChunkDeviceProviderFactory *dmf;
692 GstDeviceProviderFactory *factory = GST_DEVICE_PROVIDER_FACTORY (feature);
693 const gchar *meta_data_str;
697 ("Reading/casting for GstRegistryChunkPluginFeature at address %p",
700 unpack_element (*in, dmf, GstRegistryChunkDeviceProviderFactory, end, fail);
702 pf = (GstRegistryChunkPluginFeature *) dmf;
704 /* unpack element factory strings */
705 unpack_string_nocopy (*in, meta_data_str, end, fail);
706 if (meta_data_str && *meta_data_str) {
707 factory->metadata = gst_structure_from_string (meta_data_str, NULL);
708 if (!factory->metadata) {
710 ("Error when trying to deserialize structure for metadata '%s'",
715 } else if (GST_IS_TRACER_FACTORY (feature)) {
718 ("Reading/casting for GstRegistryChunkPluginFeature at address %p",
720 unpack_element (*in, pf, GstRegistryChunkPluginFeature, end, fail);
721 } else if (GST_IS_DYNAMIC_TYPE_FACTORY (feature)) {
722 GstRegistryChunkDynamicTypeFactory *tmp;
725 unpack_element (*in, tmp, GstRegistryChunkDynamicTypeFactory, end, fail);
727 pf = (GstRegistryChunkPluginFeature *) tmp;
729 GST_WARNING ("unhandled factory type : %s", G_OBJECT_TYPE_NAME (feature));
733 feature->rank = pf->rank;
735 feature->plugin_name = plugin_name;
736 feature->plugin = plugin;
737 g_object_add_weak_pointer ((GObject *) plugin,
738 (gpointer *) & feature->plugin);
740 gst_registry_add_feature (registry, feature);
741 GST_DEBUG ("Added feature %s, plugin %p %s", GST_OBJECT_NAME (feature),
742 plugin, plugin_name);
748 GST_INFO ("Reading plugin feature failed");
750 gst_object_unref (feature);
756 gst_registry_chunks_load_plugin_dep_strv (gchar ** in, gchar * end, guint n)
763 arr = g_new0 (gchar *, n + 1);
765 unpack_string (*in, arr[n - 1], end, fail);
770 GST_INFO ("Reading plugin dependency strings failed");
776 gst_registry_chunks_load_plugin_dep (GstPlugin * plugin, gchar ** in,
780 GstRegistryChunkDep *d;
784 GST_LOG_OBJECT (plugin, "Unpacking GstRegistryChunkDep from %p", *in);
785 unpack_element (*in, d, GstRegistryChunkDep, end, fail);
787 dep = g_slice_new (GstPluginDep);
789 dep->env_hash = d->env_hash;
790 dep->stat_hash = d->stat_hash;
792 dep->flags = (GstPluginDependencyFlags) d->flags;
794 dep->names = gst_registry_chunks_load_plugin_dep_strv (in, end, d->n_names);
795 dep->paths = gst_registry_chunks_load_plugin_dep_strv (in, end, d->n_paths);
797 gst_registry_chunks_load_plugin_dep_strv (in, end, d->n_env_vars);
799 plugin->priv->deps = g_list_append (plugin->priv->deps, dep);
801 GST_DEBUG_OBJECT (plugin, "Loaded external plugin dependency from registry: "
802 "env_hash: %08x, stat_hash: %08x", dep->env_hash, dep->stat_hash);
803 for (s = dep->env_vars; s != NULL && *s != NULL; ++s)
804 GST_LOG_OBJECT (plugin, " evar: %s", *s);
805 for (s = dep->paths; s != NULL && *s != NULL; ++s)
806 GST_LOG_OBJECT (plugin, " path: %s", *s);
807 for (s = dep->names; s != NULL && *s != NULL; ++s)
808 GST_LOG_OBJECT (plugin, " name: %s", *s);
812 GST_INFO ("Reading plugin dependency failed");
818 * _priv_gst_registry_chunks_load_plugin:
820 * Make a new GstPlugin from current GstRegistryChunkPluginElement structure
821 * and add it to the GstRegistry. Return an offset to the next
822 * GstRegistryChunkPluginElement structure.
825 _priv_gst_registry_chunks_load_plugin (GstRegistry * registry, gchar ** in,
826 gchar * end, GstPlugin ** out_plugin)
828 #ifndef GST_DISABLE_GST_DEBUG
831 GstRegistryChunkPluginElement *pe;
832 const gchar *cache_str = NULL;
833 GstPlugin *plugin = NULL;
837 GST_LOG ("Reading/casting for GstRegistryChunkPluginElement at address %p",
839 unpack_element (*in, pe, GstRegistryChunkPluginElement, end, fail);
841 plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
843 /* TODO: also set GST_PLUGIN_FLAG_CONST */
844 GST_OBJECT_FLAG_SET (plugin, GST_PLUGIN_FLAG_CACHED);
845 plugin->file_mtime = pe->file_mtime;
846 plugin->file_size = pe->file_size;
848 /* unpack plugin element strings */
849 unpack_const_string (*in, plugin->desc.name, end, fail);
850 unpack_const_string (*in, plugin->desc.description, end, fail);
851 unpack_string (*in, plugin->filename, end, fail);
852 unpack_const_string (*in, plugin->desc.version, end, fail);
853 unpack_const_string (*in, plugin->desc.license, end, fail);
854 unpack_const_string (*in, plugin->desc.source, end, fail);
855 unpack_const_string (*in, plugin->desc.package, end, fail);
856 unpack_const_string (*in, plugin->desc.origin, end, fail);
857 unpack_const_string (*in, plugin->desc.release_datetime, end, fail);
859 GST_LOG ("read strings for name='%s'", plugin->desc.name);
860 GST_LOG (" desc.description='%s'", plugin->desc.description);
861 GST_LOG (" filename='%s'", plugin->filename);
862 GST_LOG (" desc.version='%s'", plugin->desc.version);
863 GST_LOG (" desc.license='%s'", plugin->desc.license);
864 GST_LOG (" desc.source='%s'", plugin->desc.source);
865 GST_LOG (" desc.package='%s'", plugin->desc.package);
866 GST_LOG (" desc.origin='%s'", plugin->desc.origin);
867 GST_LOG (" desc.datetime=%s", plugin->desc.release_datetime);
869 if (plugin->desc.release_datetime[0] == '\0')
870 plugin->desc.release_datetime = NULL;
872 /* unpack cache data */
873 unpack_string_nocopy (*in, cache_str, end, fail);
874 if (cache_str != NULL && *cache_str != '\0')
875 plugin->priv->cache_data = gst_structure_from_string (cache_str, NULL);
877 /* If the license string is 'BLACKLIST', mark this as a blacklisted
879 if (strcmp (plugin->desc.license, "BLACKLIST") == 0)
880 GST_OBJECT_FLAG_SET (plugin, GST_PLUGIN_FLAG_BLACKLISTED);
882 plugin->basename = g_path_get_basename (plugin->filename);
884 /* Takes ownership of plugin */
885 gst_registry_add_plugin (registry, plugin);
887 GST_DEBUG ("Added plugin '%s' plugin with %d features from binary registry",
888 plugin->desc.name, n);
890 /* Load plugin features */
891 for (i = 0; i < n; i++) {
892 if (G_UNLIKELY (!gst_registry_chunks_load_feature (registry, in, end,
894 GST_ERROR ("Error while loading binary feature for plugin '%s'",
895 GST_STR_NULL (plugin->desc.name));
896 gst_registry_remove_plugin (registry, plugin);
901 /* Load external plugin dependencies */
902 for (i = 0; i < pe->n_deps; ++i) {
903 if (G_UNLIKELY (!gst_registry_chunks_load_plugin_dep (plugin, in, end))) {
904 GST_ERROR_OBJECT (plugin, "Could not read external plugin dependency "
905 "for plugin '%s'", GST_STR_NULL (plugin->desc.name));
906 gst_registry_remove_plugin (registry, plugin);
912 *out_plugin = plugin;
918 GST_INFO ("Reading plugin failed after %u bytes", (guint) (end - start));
923 _priv_gst_registry_chunks_save_global_header (GList ** list,
924 GstRegistry * registry, guint32 filter_env_hash)
926 GstRegistryChunkGlobalHeader *hdr;
927 GstRegistryChunk *chk;
929 hdr = g_slice_new (GstRegistryChunkGlobalHeader);
930 chk = gst_registry_chunks_make_data (hdr,
931 sizeof (GstRegistryChunkGlobalHeader));
933 hdr->filter_env_hash = filter_env_hash;
935 *list = g_list_prepend (*list, chk);
937 GST_LOG ("Saved global header (filter_env_hash=0x%08x)", filter_env_hash);
941 _priv_gst_registry_chunks_load_global_header (GstRegistry * registry,
942 gchar ** in, gchar * end, guint32 * filter_env_hash)
944 GstRegistryChunkGlobalHeader *hdr;
947 GST_LOG ("Reading/casting for GstRegistryChunkGlobalHeader at %p", *in);
948 unpack_element (*in, hdr, GstRegistryChunkGlobalHeader, end, fail);
949 *filter_env_hash = hdr->filter_env_hash;
954 GST_WARNING ("Reading global header failed");