diff options
Diffstat (limited to 'meta/packages/gstreamer/gstreamer/gstregistrybinary.c')
-rw-r--r-- | meta/packages/gstreamer/gstreamer/gstregistrybinary.c | 487 |
1 files changed, 487 insertions, 0 deletions
diff --git a/meta/packages/gstreamer/gstreamer/gstregistrybinary.c b/meta/packages/gstreamer/gstreamer/gstregistrybinary.c new file mode 100644 index 0000000000..c1f3e71af6 --- /dev/null +++ b/meta/packages/gstreamer/gstreamer/gstregistrybinary.c | |||
@@ -0,0 +1,487 @@ | |||
1 | /* GStreamer | ||
2 | * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> | ||
3 | * 2000 Wim Taymans <wtay@chello.be> | ||
4 | * 2005 David A. Schleef <ds@schleef.org> | ||
5 | * | ||
6 | * gstregistryxml.c: GstRegistry object, support routines | ||
7 | * | ||
8 | * This library is free software; you can redistribute it and/or | ||
9 | * modify it ulnder the terms of the GNU Library General Public | ||
10 | * License as published by the Free Software Foundation; either | ||
11 | * version 2 of the License, or (at your option) any later version. | ||
12 | * | ||
13 | * This library is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Library General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Library General Public | ||
19 | * License along with this library; if not, write to the | ||
20 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
21 | * Boston, MA 02111-1307, USA. | ||
22 | */ | ||
23 | |||
24 | |||
25 | #include <gst/gstregistrybinary.h> | ||
26 | |||
27 | /* | ||
28 | ** Simple handy function to write a memory location to the registry cache file | ||
29 | */ | ||
30 | inline static gboolean | ||
31 | gst_registry_binary_write(GstRegistry *registry, const void *mem, const ssize_t size) | ||
32 | { | ||
33 | if (write(registry->cache_file, mem, size) != size) | ||
34 | { | ||
35 | GST_ERROR("Failed to write binary registry element: ptr=%p size=%u error=%s\n", | ||
36 | mem, size, strerror(errno)); | ||
37 | return FALSE; | ||
38 | } | ||
39 | return TRUE; | ||
40 | } | ||
41 | |||
42 | /* | ||
43 | ** Save features GstBinary style | ||
44 | */ | ||
45 | static gboolean | ||
46 | gst_registry_binary_fill_feature(GList **list, GstPluginFeature *orig, GstBinaryPluginFeature *dest, const char *name) | ||
47 | { | ||
48 | GstBinaryChunck *chk; | ||
49 | |||
50 | if ((chk = calloc(1, sizeof (GstBinaryChunck))) == NULL) | ||
51 | return FALSE; | ||
52 | |||
53 | chk->data = dest; | ||
54 | chk->size = sizeof (GstBinaryPluginFeature); | ||
55 | |||
56 | *list = g_list_append(*list, chk); | ||
57 | |||
58 | dest->rank = orig->rank; | ||
59 | if (!strncpy(dest->typename, name, GST_BINARY_REGISTRY_TYPENAME_TYPENAME_LEN) || | ||
60 | !strncpy(dest->name, orig->name, GST_BINARY_REGISTRY_TYPENAME_NAME_LEN)) | ||
61 | { | ||
62 | GST_ERROR("Failed to write binary registry feature"); | ||
63 | goto fail; | ||
64 | } | ||
65 | |||
66 | if (GST_IS_ELEMENT_FACTORY(orig)) | ||
67 | { | ||
68 | GstElementFactory *factory = GST_ELEMENT_FACTORY(orig); | ||
69 | |||
70 | if (!strncpy(dest->longname, factory->details.longname, GST_BINARY_REGISTRY_TYPENAME_LONGNAME_LEN) || | ||
71 | !strncpy(dest->class, factory->details.klass, GST_BINARY_REGISTRY_TYPENAME_CLASS_LEN) || | ||
72 | !strncpy(dest->description, factory->details.description, GST_BINARY_REGISTRY_TYPENAME_DESCRIPTION_LEN) || | ||
73 | !strncpy(dest->author, factory->details.author, GST_BINARY_REGISTRY_TYPENAME_AUTHOR_LEN)) | ||
74 | { | ||
75 | GST_ERROR("Failed to write binary registry feature"); | ||
76 | goto fail; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | dest->npadtemplates = dest->ninterfaces = dest->nuritypes = 0; | ||
81 | return TRUE; | ||
82 | |||
83 | fail: | ||
84 | free(chk); | ||
85 | return FALSE; | ||
86 | } | ||
87 | |||
88 | |||
89 | /* | ||
90 | ** Initialize the GstBinaryRegistryMagic, setting both our magic number and gstreamer major/minor version | ||
91 | */ | ||
92 | inline static gboolean | ||
93 | gst_registry_binary_initialize_magic(GstBinaryRegistryMagic *m) | ||
94 | { | ||
95 | if (!strncpy(m->magic, GST_MAGIC_BINARY_REGISTRY_STR, GST_MAGIC_BINARY_REGISTRY_LEN) || | ||
96 | !strncpy(m->version, GST_MAJORMINOR, GST_BINARY_REGISTRY_VERSION_LEN)) | ||
97 | { | ||
98 | GST_ERROR("Failed to write magic to the registry magic structure"); | ||
99 | return FALSE; | ||
100 | } | ||
101 | return TRUE; | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | ** Check GstBinaryRegistryMagic validity. | ||
106 | ** Return a pointer pointing right after the magic structure | ||
107 | */ | ||
108 | static gchar * | ||
109 | gst_registry_binary_check_magic(gchar *in) | ||
110 | { | ||
111 | GstBinaryRegistryMagic *m = (GstBinaryRegistryMagic *) in; | ||
112 | |||
113 | if (m == NULL || m->magic == NULL || m->version == NULL) | ||
114 | { | ||
115 | GST_ERROR("Binary registry magic structure is broken"); | ||
116 | return NULL; | ||
117 | } | ||
118 | if (strncmp(m->magic, GST_MAGIC_BINARY_REGISTRY_STR, GST_MAGIC_BINARY_REGISTRY_LEN) != 0) | ||
119 | { | ||
120 | GST_ERROR("Binary registry magic is different : %02x%02x%02x%02x != %02x%02x%02x%02x", | ||
121 | GST_MAGIC_BINARY_REGISTRY_STR[0] & 0xff, GST_MAGIC_BINARY_REGISTRY_STR[1] & 0xff, | ||
122 | GST_MAGIC_BINARY_REGISTRY_STR[2] & 0xff, GST_MAGIC_BINARY_REGISTRY_STR[3] & 0xff, | ||
123 | m->magic[0] & 0xff, m->magic[1] & 0xff, m->magic[2] & 0xff, m->magic[3] & 0xff); | ||
124 | return NULL; | ||
125 | } | ||
126 | if (strncmp(m->version, GST_MAJORMINOR, GST_BINARY_REGISTRY_VERSION_LEN)) | ||
127 | { | ||
128 | GST_ERROR("Binary registry magic version is different : %s != %s", | ||
129 | GST_MAJORMINOR, m->version); | ||
130 | return NULL; | ||
131 | } | ||
132 | return (in + sizeof (GstBinaryRegistryMagic)); | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | ** Adapt a GstPlugin to our GstBinaryPluginElement structure, and write it to the | ||
137 | ** registry file. | ||
138 | */ | ||
139 | static gboolean | ||
140 | gst_registry_binary_save_plugin(GList **list, GstRegistry *registry, GstPlugin *plugin) | ||
141 | { | ||
142 | GstBinaryPluginElement *e; | ||
143 | GstBinaryChunck *chk; | ||
144 | GList *walk; | ||
145 | |||
146 | if ((e = calloc(1, sizeof (GstBinaryPluginElement))) == NULL || | ||
147 | (chk = calloc(1, sizeof (GstBinaryChunck))) == NULL) | ||
148 | return FALSE; | ||
149 | |||
150 | chk->data = e; | ||
151 | chk->size = sizeof (GstBinaryPluginElement); | ||
152 | *list = g_list_append(*list, chk); | ||
153 | |||
154 | if (!strncpy(e->name, plugin->desc.name, GST_BINARY_REGISTRY_NAME_LEN) || | ||
155 | !strncpy(e->description, plugin->desc.description, GST_BINARY_REGISTRY_DESCRIPTION_LEN) || | ||
156 | !strncpy(e->filename, plugin->filename, _POSIX_PATH_MAX) || | ||
157 | !strncpy(e->version, plugin->desc.version, GST_BINARY_REGISTRY_VERSION_LEN) || | ||
158 | !strncpy(e->license, plugin->desc.license, GST_BINARY_REGISTRY_LICENSE_LEN) || | ||
159 | !strncpy(e->source, plugin->desc.source, GST_BINARY_REGISTRY_SOURCE_LEN) || | ||
160 | !strncpy(e->package, plugin->desc.package, GST_BINARY_REGISTRY_PACKAGE_LEN) || | ||
161 | !strncpy(e->origin, plugin->desc.origin, GST_BINARY_REGISTRY_ORIGIN_LEN)) | ||
162 | { | ||
163 | GST_DEBUG("Can't adapt GstPlugin to GstBinaryPluginElement"); | ||
164 | goto fail; | ||
165 | } | ||
166 | |||
167 | e->size = plugin->file_size; | ||
168 | e->m32p = plugin->file_mtime; | ||
169 | |||
170 | GList *ft_list = gst_registry_get_feature_list_by_plugin(registry, plugin->desc.name); | ||
171 | |||
172 | for (walk = ft_list; walk; walk = g_list_next(walk), e->nfeatures++) | ||
173 | { | ||
174 | GstPluginFeature *curfeat = GST_PLUGIN_FEATURE (walk->data); | ||
175 | GstBinaryPluginFeature *newfeat; | ||
176 | const char *feat_name = g_type_name(G_OBJECT_TYPE(curfeat)); | ||
177 | |||
178 | if ((newfeat = calloc(1, sizeof (GstBinaryPluginFeature))) == NULL) | ||
179 | goto fail; | ||
180 | |||
181 | if (!feat_name || !gst_registry_binary_fill_feature(list, curfeat, newfeat, feat_name)) | ||
182 | { | ||
183 | GST_ERROR("Can't fill plugin feature, aborting."); | ||
184 | goto fail; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | GST_DEBUG("Found %d features in plugin \"%s\"\n", e->nfeatures, e->name); | ||
189 | return TRUE; | ||
190 | |||
191 | fail: | ||
192 | free(chk); | ||
193 | free(e); | ||
194 | return FALSE; | ||
195 | } | ||
196 | |||
197 | /* | ||
198 | ** Write the cache to file. Part of the code was taken from gstregistryxml.c | ||
199 | */ | ||
200 | gboolean | ||
201 | gst_registry_binary_write_cache(GstRegistry *registry, const char *location) | ||
202 | { | ||
203 | GList *walk; | ||
204 | char *tmp_location; | ||
205 | GstBinaryRegistryMagic *magic; | ||
206 | GstBinaryChunck *magic_chunck; | ||
207 | GList *to_write = NULL; | ||
208 | |||
209 | GST_INFO("Writing binary registry cache"); | ||
210 | |||
211 | g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE); | ||
212 | tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL); | ||
213 | registry->cache_file = g_mkstemp (tmp_location); | ||
214 | if (registry->cache_file == -1) | ||
215 | { | ||
216 | char *dir; | ||
217 | |||
218 | /* oops, I bet the directory doesn't exist */ | ||
219 | dir = g_path_get_dirname (location); | ||
220 | g_mkdir_with_parents (dir, 0777); | ||
221 | g_free (dir); | ||
222 | |||
223 | registry->cache_file = g_mkstemp (tmp_location); | ||
224 | } | ||
225 | |||
226 | if (registry->cache_file == -1) | ||
227 | goto fail; | ||
228 | |||
229 | if ((magic = calloc(1, sizeof (GstBinaryRegistryMagic))) == NULL || | ||
230 | !gst_registry_binary_initialize_magic(magic)) | ||
231 | goto fail; | ||
232 | |||
233 | if ((magic_chunck = calloc(1, sizeof (GstBinaryChunck))) == NULL) | ||
234 | goto fail; | ||
235 | |||
236 | magic_chunck->data = magic; | ||
237 | magic_chunck->size = sizeof (GstBinaryRegistryMagic); | ||
238 | to_write = g_list_append(to_write, magic_chunck); | ||
239 | |||
240 | /* Iterate trough the list of plugins in the GstRegistry and adapt them to our structures */ | ||
241 | for (walk = g_list_last(registry->plugins); walk; walk = g_list_previous(walk)) | ||
242 | { | ||
243 | GstPlugin *plugin = GST_PLUGIN(walk->data); | ||
244 | |||
245 | if (!plugin->filename) | ||
246 | continue; | ||
247 | |||
248 | if (plugin->flags & GST_PLUGIN_FLAG_CACHED) | ||
249 | { | ||
250 | int ret; | ||
251 | struct stat statbuf; | ||
252 | |||
253 | ret = g_stat (plugin->filename, &statbuf); | ||
254 | if ((ret = g_stat (plugin->filename, &statbuf)) < 0 || | ||
255 | plugin->file_mtime != statbuf.st_mtime || | ||
256 | plugin->file_size != statbuf.st_size) | ||
257 | continue; | ||
258 | } | ||
259 | |||
260 | if (!gst_registry_binary_save_plugin(&to_write, registry, plugin)) | ||
261 | { | ||
262 | GST_ERROR("Can't write binary plugin information for \"%s\"", plugin->filename); | ||
263 | continue; /* Try anyway */ | ||
264 | } | ||
265 | } | ||
266 | |||
267 | for (walk = g_list_first(to_write); walk; walk = g_list_next(walk)) | ||
268 | { | ||
269 | GstBinaryChunck *cur = walk->data; | ||
270 | |||
271 | if (!gst_registry_binary_write(registry, cur->data, cur->size)) | ||
272 | { | ||
273 | free(cur->data); | ||
274 | free(cur); | ||
275 | g_list_free(to_write); | ||
276 | goto fail; | ||
277 | } | ||
278 | free(cur->data); | ||
279 | free(cur); | ||
280 | } | ||
281 | g_list_free(to_write); | ||
282 | |||
283 | if (close(registry->cache_file) < 0) | ||
284 | { | ||
285 | GST_DEBUG("Can't close registry file : %s", strerror(errno)); | ||
286 | goto fail; | ||
287 | } | ||
288 | |||
289 | if (g_file_test (tmp_location, G_FILE_TEST_EXISTS)) { | ||
290 | #ifdef WIN32 | ||
291 | remove (location); | ||
292 | #endif | ||
293 | rename (tmp_location, location); | ||
294 | } | ||
295 | |||
296 | g_free (tmp_location); | ||
297 | return TRUE; | ||
298 | |||
299 | fail: | ||
300 | g_free(tmp_location); | ||
301 | return FALSE; | ||
302 | } | ||
303 | |||
304 | static GstPluginFeature* | ||
305 | gst_registry_binary_load_feature(GstBinaryPluginFeature *in) | ||
306 | { | ||
307 | GstPluginFeature *feature; | ||
308 | GType type; | ||
309 | |||
310 | if (!in->typename || !*(in->typename)) | ||
311 | return NULL; | ||
312 | |||
313 | /* GST_INFO("Plugin feature typename : %s", in->typename);*/ | ||
314 | |||
315 | if (!(type = g_type_from_name(in->typename))) | ||
316 | { | ||
317 | GST_ERROR("Unknown type from typename"); | ||
318 | return NULL; | ||
319 | } | ||
320 | feature = g_object_new (type, NULL); | ||
321 | |||
322 | if (!feature) { | ||
323 | GST_ERROR("Can't create feature from type"); | ||
324 | return NULL; | ||
325 | } | ||
326 | |||
327 | if (!GST_IS_PLUGIN_FEATURE (feature)) { | ||
328 | /* don't really know what it is */ | ||
329 | if (GST_IS_OBJECT (feature)) | ||
330 | gst_object_unref (feature); | ||
331 | else | ||
332 | g_object_unref (feature); | ||
333 | return NULL; | ||
334 | } | ||
335 | |||
336 | feature->name = g_strdup(in->name); | ||
337 | feature->rank = in->rank; | ||
338 | |||
339 | if (GST_IS_ELEMENT_FACTORY(feature)) | ||
340 | { | ||
341 | GstElementFactory *factory = GST_ELEMENT_FACTORY(feature); | ||
342 | |||
343 | factory->details.longname = g_strdup(in->longname); | ||
344 | factory->details.klass = g_strdup(in->class); | ||
345 | factory->details.description = g_strdup(in->description); | ||
346 | factory->details.author = g_strdup(in->author); | ||
347 | |||
348 | /* GST_INFO("Element factory : %s", factory->details.longname); */ | ||
349 | } | ||
350 | |||
351 | GST_DEBUG("Added feature %p with name %s", feature, feature->name); | ||
352 | return feature; | ||
353 | } | ||
354 | |||
355 | /* | ||
356 | ** Make a new plugin from current GstBinaryPluginElement structure | ||
357 | ** and save it to the GstRegistry. Return an offset to the next | ||
358 | ** GstBinaryPluginElement structure. | ||
359 | */ | ||
360 | static unsigned long | ||
361 | gst_registry_binary_get_binary_plugin(GstRegistry *registry, gchar *in) | ||
362 | { | ||
363 | GstBinaryPluginElement *p = (GstBinaryPluginElement *) in; | ||
364 | GstPlugin *plugin = NULL; | ||
365 | GList *plugin_features = NULL; | ||
366 | GstBinaryPluginFeature *feat; | ||
367 | unsigned int i; | ||
368 | unsigned long offset; | ||
369 | |||
370 | plugin = g_object_new (GST_TYPE_PLUGIN, NULL); | ||
371 | |||
372 | plugin->flags |= GST_PLUGIN_FLAG_CACHED; | ||
373 | |||
374 | plugin->desc.name = g_strdup(p->name); | ||
375 | plugin->desc.description= g_strdup(p->description); | ||
376 | plugin->filename = g_strdup(p->filename); | ||
377 | plugin->desc.version = g_strdup(p->version); | ||
378 | plugin->desc.license = g_strdup(p->license); | ||
379 | plugin->desc.source = g_strdup(p->source); | ||
380 | plugin->desc.package = g_strdup(p->package); | ||
381 | plugin->desc.origin = g_strdup(p->origin); | ||
382 | plugin->file_mtime = p->m32p; | ||
383 | plugin->file_size = p->size; | ||
384 | plugin->basename = g_path_get_basename (plugin->filename); | ||
385 | |||
386 | if (plugin->file_mtime < 0 || plugin->file_size < 0) | ||
387 | { | ||
388 | GST_ERROR("Plugin time or file size is not valid !"); | ||
389 | g_free(plugin); | ||
390 | return -1; | ||
391 | } | ||
392 | |||
393 | if (p->nfeatures < 0) | ||
394 | { | ||
395 | GST_ERROR("The number of feature structure is not valid !"); | ||
396 | gst_object_unref(plugin); | ||
397 | return -1; | ||
398 | } | ||
399 | |||
400 | for (feat = (GstBinaryPluginFeature *) (in + sizeof (GstBinaryPluginElement)), i = 0; | ||
401 | i < p->nfeatures; i++, feat++) | ||
402 | { | ||
403 | GstPluginFeature *gstfeat; | ||
404 | |||
405 | if ((gstfeat = gst_registry_binary_load_feature(feat)) == NULL) | ||
406 | { | ||
407 | g_list_free(plugin_features); | ||
408 | g_free(plugin); | ||
409 | GST_ERROR("Error while loading binary feature"); | ||
410 | return -1; | ||
411 | } | ||
412 | gstfeat->plugin_name = g_strdup(plugin->desc.name); | ||
413 | plugin_features = g_list_prepend(plugin_features, gstfeat); | ||
414 | } | ||
415 | |||
416 | GST_DEBUG("Added plugin \"%s\" to global registry from binary registry", plugin->desc.name); | ||
417 | GList *g; | ||
418 | |||
419 | gst_registry_add_plugin (registry, plugin); | ||
420 | for (g = plugin_features; g; g = g_list_next (g)) | ||
421 | gst_registry_add_feature (registry, GST_PLUGIN_FEATURE (g->data)); | ||
422 | /* g_list_free(plugin_features); */ | ||
423 | |||
424 | offset = sizeof (GstBinaryPluginElement) + p->nfeatures * sizeof (GstBinaryPluginFeature); | ||
425 | return offset; | ||
426 | } | ||
427 | |||
428 | |||
429 | /* | ||
430 | ** Read the cache and adapt it to fill GstRegistry | ||
431 | */ | ||
432 | gboolean | ||
433 | gst_registry_binary_read_cache(GstRegistry *registry, const char *location) | ||
434 | { | ||
435 | GMappedFile *mapped = NULL; | ||
436 | GTimer *timer = NULL; | ||
437 | gchar *contents = NULL; | ||
438 | gdouble seconds; | ||
439 | unsigned long offset, inc; | ||
440 | gsize size; | ||
441 | |||
442 | /* make sure these types exist */ | ||
443 | GST_TYPE_ELEMENT_FACTORY; | ||
444 | GST_TYPE_TYPE_FIND_FACTORY; | ||
445 | GST_TYPE_INDEX_FACTORY; | ||
446 | |||
447 | timer = g_timer_new (); | ||
448 | |||
449 | if ((mapped = g_mapped_file_new(location, FALSE, NULL)) == NULL || | ||
450 | (contents = g_mapped_file_get_contents(mapped)) == NULL) | ||
451 | { | ||
452 | GST_ERROR("Can't load file : %s", strerror(errno)); | ||
453 | return FALSE; | ||
454 | } | ||
455 | if ((contents = gst_registry_binary_check_magic(contents)) == NULL) | ||
456 | { | ||
457 | GST_ERROR("Binary registry type not recognized (invalid magic)"); | ||
458 | g_mapped_file_free(mapped); | ||
459 | return FALSE; | ||
460 | } | ||
461 | |||
462 | if ((size = g_mapped_file_get_length(mapped)) < sizeof (GstBinaryPluginElement)) | ||
463 | { | ||
464 | GST_INFO("No binary plugins structure to read"); | ||
465 | return TRUE; /* This is not really an error */ | ||
466 | } | ||
467 | |||
468 | for (offset = inc = 0; (offset + sizeof (GstBinaryPluginElement)) < size && | ||
469 | (inc = gst_registry_binary_get_binary_plugin(registry, contents + offset)) > 0; | ||
470 | offset += inc) | ||
471 | ; /* May want in the future to do something here */ | ||
472 | if (inc < 0) | ||
473 | { | ||
474 | GST_DEBUG("Problem while reading binary registry"); | ||
475 | return FALSE; | ||
476 | } | ||
477 | |||
478 | g_timer_stop (timer); | ||
479 | seconds = g_timer_elapsed (timer, NULL); | ||
480 | g_timer_destroy (timer); | ||
481 | |||
482 | GST_INFO ("loaded %s in %f seconds", location, seconds); | ||
483 | |||
484 | if (mapped) | ||
485 | g_mapped_file_free (mapped); | ||
486 | return TRUE; | ||
487 | } | ||