1 /* GStreamer
2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
4 *
5 * gst.c: Initialization and non-pipeline operations
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 /**
24 * SECTION:gst
25 * @title: GStreamer
26 * @short_description: Media library supporting arbitrary formats and filter
27 * graphs.
28 *
29 * GStreamer is a framework for constructing graphs of various filters
30 * (termed elements here) that will handle streaming media.
31 *
32 * Any discrete (packetizable) media type is supported, with provisions for
33 * automatically determining source type.
34 *
35 * Formatting/framing information is provided with a powerful negotiation
36 * framework.
37 *
38 * Plugins are heavily used to provide for all elements, allowing one to
39 * construct plugins outside of the GST library, even released binary-only if
40 * license require (please don't).
41 *
42 * GStreamer covers a wide range of use cases including: playback, recording,
43 * editing, serving streams, voice over ip and video calls.
44 *
45 * The `GStreamer` library should be initialized with
46 * gst_init() before it can be used. You should pass pointers to the main `argc`
47 * and `argv` variables so that GStreamer can process its own command line
48 * options, as shown in the following example.
49 *
50 * ## Initializing the gstreamer library
51 *
52 * ``` C
53 * int main (int argc, char *argv[])
54 * {
55 * // initialize the GStreamer library
56 * gst_init (&argc, &argv);
57 * ...
58 * }
59 * ```
60 *
61 * It's allowed to pass two %NULL pointers to gst_init() in case you don't want
62 * to pass the command line args to GStreamer.
63 *
64 * You can also use #GOptionContext to initialize your own parameters as shown in
65 * the next code fragment:
66 *
67 * ## Initializing own parameters when initializing GStreamer
68 *
69 * ``` C
70 * static gboolean stats = FALSE;
71 * ...
72 * int
73 * main (int argc, char *argv[])
74 * {
75 * GOptionEntry options[] = {
76 * {"tags", 't', 0, G_OPTION_ARG_NONE, &tags,
77 * N_("Output tags (also known as metadata)"), NULL},
78 * {NULL}
79 * };
80 * ctx = g_option_context_new ("[ADDITIONAL ARGUMENTS]");
81 * g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
82 * g_option_context_add_group (ctx, gst_init_get_option_group ());
83 * if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
84 * g_print ("Error initializing: %s\n", GST_STR_NULL (err->message));
85 * exit (1);
86 * }
87 * g_option_context_free (ctx);
88 * ...
89 * }
90 * ```
91 *
92 * Use gst_version() to query the library version at runtime or use the
93 * GST_VERSION_* macros to find the version at compile time. Optionally
94 * gst_version_string() returns a printable string.
95 *
96 * The gst_deinit() call is used to clean up all internal resources used
97 * by GStreamer. It is mostly used in unit tests to check for leaks.
98 */
99
100 #include "gst_private.h"
101 #include "gstconfig.h"
102 #include <stdlib.h>
103 #include <stdio.h>
104 #include <sys/types.h>
105 #ifdef HAVE_SYS_UTSNAME_H
106 #include <sys/utsname.h>
107 #endif
108 #ifdef HAVE_UNISTD_H
109 #include <unistd.h>
110 #endif
111 #ifdef G_OS_WIN32
112 #define WIN32_LEAN_AND_MEAN /* prevents from including too many things */
113 #include <windows.h> /* GetStdHandle, windows console */
114 #endif
115 #if defined (__APPLE__)
116 #include "TargetConditionals.h"
117 #if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_EMBEDDED
118 #include <libproc.h> /* proc_pidpath, PROC_PIDPATHINFO_MAXSIZE */
119 #endif
120 #endif
121
122 #include "gst-i18n-lib.h"
123 #include <locale.h> /* for LC_ALL */
124
125 #include "gst.h"
126
127 #define GST_CAT_DEFAULT GST_CAT_GST_INIT
128
129 #define MAX_PATH_SPLIT 16
130 #define GST_PLUGIN_SEPARATOR ","
131
132 static gboolean gst_initialized = FALSE;
133 static gboolean gst_deinitialized = FALSE;
134 static GMutex init_lock;
135
136 GstClockTime _priv_gst_start_time;
137
138 #ifdef G_OS_WIN32
139 HMODULE _priv_gst_dll_handle = NULL;
140 #endif
141
142 #ifndef GST_DISABLE_REGISTRY
143 GList *_priv_gst_plugin_paths = NULL; /* for delayed processing in init_post */
144
145 extern gboolean _priv_gst_disable_registry;
146 extern gboolean _priv_gst_disable_registry_update;
147 #endif
148
149 gchar *_gst_executable_path = NULL;
150
151 #ifndef GST_DISABLE_GST_DEBUG
152 const gchar *priv_gst_dump_dot_dir;
153 #endif
154
155 /* defaults */
156
157 /* set to TRUE when segfaults need to be left as is */
158 static gboolean _gst_disable_segtrap = FALSE;
159
160 static gboolean init_pre (GOptionContext * context, GOptionGroup * group,
161 gpointer data, GError ** error);
162 static gboolean init_post (GOptionContext * context, GOptionGroup * group,
163 gpointer data, GError ** error);
164 #ifndef GST_DISABLE_OPTION_PARSING
165 static gboolean parse_goption_arg (const gchar * s_opt,
166 const gchar * arg, gpointer data, GError ** err);
167 #endif
168
169 GSList *_priv_gst_preload_plugins = NULL;
170
171 static void
debug_log_handler(const gchar * log_domain,GLogLevelFlags log_level,const gchar * message,gpointer user_data)172 debug_log_handler (const gchar * log_domain,
173 GLogLevelFlags log_level, const gchar * message, gpointer user_data)
174 {
175 g_log_default_handler (log_domain, log_level, message, user_data);
176 /* FIXME: do we still need this ? fatal errors these days are all
177 * other than core errors */
178 /* g_on_error_query (NULL); */
179 }
180
181 enum
182 {
183 ARG_VERSION = 1,
184 ARG_FATAL_WARNINGS,
185 #ifndef GST_DISABLE_GST_DEBUG
186 ARG_DEBUG_LEVEL,
187 ARG_DEBUG,
188 ARG_DEBUG_DISABLE,
189 ARG_DEBUG_NO_COLOR,
190 ARG_DEBUG_COLOR_MODE,
191 ARG_DEBUG_HELP,
192 #endif
193 ARG_PLUGIN_SPEW,
194 ARG_PLUGIN_PATH,
195 ARG_PLUGIN_LOAD,
196 ARG_SEGTRAP_DISABLE,
197 ARG_REGISTRY_UPDATE_DISABLE,
198 ARG_REGISTRY_FORK_DISABLE
199 };
200
201 /* debug-spec ::= category-spec [, category-spec]*
202 * category-spec ::= category:val | val
203 * category ::= [^:]+
204 * val ::= [0-5]
205 */
206
207 #ifdef G_OS_WIN32
208 /* Note: DllMain is only called when DLLs are loaded or unloaded, so this will
209 * never be called if libgstreamer-1.0 is linked statically. Do not add any code
210 * here to, say, initialize variables or set things up since that will only
211 * happen for dynamically-built GStreamer.
212 *
213 * Also, ideally this should not be defined when GStreamer is built statically.
214 * i.e., it should be conditional on #ifdef DLL_EXPORT. It will be ignored, but
215 * if other libraries make the same mistake of defining it when building
216 * statically, there will be a symbol collision during linking. Fixing this
217 * requires one to build two object files: one for static linking and another
218 * for dynamic linking. */
219 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
220 BOOL WINAPI
DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)221 DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
222 {
223 if (fdwReason == DLL_PROCESS_ATTACH)
224 _priv_gst_dll_handle = (HMODULE) hinstDLL;
225 return TRUE;
226 }
227
228 #endif
229
230 /**
231 * gst_init_get_option_group: (skip)
232 *
233 * Returns a #GOptionGroup with GStreamer's argument specifications. The
234 * group is set up to use standard GOption callbacks, so when using this
235 * group in combination with GOption parsing methods, all argument parsing
236 * and initialization is automated.
237 *
238 * This function is useful if you want to integrate GStreamer with other
239 * libraries that use GOption (see g_option_context_add_group() ).
240 *
241 * If you use this function, you should make sure you initialise the GLib
242 * threading system as one of the very first things in your program
243 * (see the example at the beginning of this section).
244 *
245 * Returns: (transfer full) (nullable): a pointer to GStreamer's option group.
246 */
247
248 GOptionGroup *
gst_init_get_option_group(void)249 gst_init_get_option_group (void)
250 {
251 #ifndef GST_DISABLE_OPTION_PARSING
252 GOptionGroup *group;
253 static const GOptionEntry gst_args[] = {
254 {"gst-version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
255 (gpointer) parse_goption_arg, N_("Print the GStreamer version"), NULL},
256 {"gst-fatal-warnings", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
257 (gpointer) parse_goption_arg, N_("Make all warnings fatal"), NULL},
258 #ifndef GST_DISABLE_GST_DEBUG
259 {"gst-debug-help", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
260 (gpointer) parse_goption_arg,
261 N_("Print available debug categories and exit"),
262 NULL},
263 {"gst-debug-level", 0, 0, G_OPTION_ARG_CALLBACK,
264 (gpointer) parse_goption_arg,
265 N_("Default debug level from 1 (only error) to 9 (anything) or "
266 "0 for no output"),
267 N_("LEVEL")},
268 {"gst-debug", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) parse_goption_arg,
269 N_("Comma-separated list of category_name:level pairs to set "
270 "specific levels for the individual categories. Example: "
271 "GST_AUTOPLUG:5,GST_ELEMENT_*:3"),
272 N_("LIST")},
273 {"gst-debug-no-color", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
274 (gpointer) parse_goption_arg, N_("Disable colored debugging output"),
275 NULL},
276 {"gst-debug-color-mode", 0, 0, G_OPTION_ARG_CALLBACK,
277 (gpointer) parse_goption_arg,
278 N_("Changes coloring mode of the debug log. "
279 "Possible modes: off, on, disable, auto, unix"),
280 NULL},
281 {"gst-debug-disable", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
282 (gpointer) parse_goption_arg, N_("Disable debugging"), NULL},
283 #endif
284 {"gst-plugin-spew", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
285 (gpointer) parse_goption_arg,
286 N_("Enable verbose plugin loading diagnostics"),
287 NULL},
288 {"gst-plugin-path", 0, 0, G_OPTION_ARG_CALLBACK,
289 (gpointer) parse_goption_arg,
290 N_("Colon-separated paths containing plugins"), N_("PATHS")},
291 {"gst-plugin-load", 0, 0, G_OPTION_ARG_CALLBACK,
292 (gpointer) parse_goption_arg,
293 N_("Comma-separated list of plugins to preload in addition to the "
294 "list stored in environment variable GST_PLUGIN_PATH"),
295 N_("PLUGINS")},
296 {"gst-disable-segtrap", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
297 (gpointer) parse_goption_arg,
298 N_("Disable trapping of segmentation faults during plugin loading"),
299 NULL},
300 {"gst-disable-registry-update", 0, G_OPTION_FLAG_NO_ARG,
301 G_OPTION_ARG_CALLBACK,
302 (gpointer) parse_goption_arg,
303 N_("Disable updating the registry"),
304 NULL},
305 {"gst-disable-registry-fork", 0, G_OPTION_FLAG_NO_ARG,
306 G_OPTION_ARG_CALLBACK,
307 (gpointer) parse_goption_arg,
308 N_("Disable spawning a helper process while scanning the registry"),
309 NULL},
310 {NULL}
311 };
312
313 group = g_option_group_new ("gst", _("GStreamer Options"),
314 _("Show GStreamer Options"), NULL, NULL);
315 g_option_group_set_parse_hooks (group, (GOptionParseFunc) init_pre,
316 (GOptionParseFunc) init_post);
317
318 g_option_group_add_entries (group, gst_args);
319 g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
320
321 return group;
322 #else
323 return NULL;
324 #endif
325 }
326
327 #if defined(__linux__)
328 static void
find_executable_path(void)329 find_executable_path (void)
330 {
331 GError *error = NULL;
332
333 if (_gst_executable_path)
334 return;
335
336 _gst_executable_path = g_file_read_link ("/proc/self/exe", &error);
337 if (error)
338 g_error_free (error);
339 }
340 #elif defined(G_OS_WIN32)
341 static void
find_executable_path(void)342 find_executable_path (void)
343 {
344 char buffer[MAX_PATH];
345
346 if (!GetModuleFileName (NULL, buffer, MAX_PATH))
347 return;
348
349 _gst_executable_path = g_strdup (buffer);
350 }
351 #elif defined(__APPLE__) && !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_EMBEDDED
352 static void
find_executable_path(void)353 find_executable_path (void)
354 {
355 int ret;
356 pid_t pid;
357 char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
358
359 pid = getpid ();
360 ret = proc_pidpath (pid, pathbuf, sizeof (pathbuf));
361 if (ret > 0)
362 _gst_executable_path = g_strdup (pathbuf);
363 }
364 #else
365 static void
find_executable_path(void)366 find_executable_path (void)
367 {
368 GST_FIXME ("Couldn't look up executable path, add support for this platform");
369 }
370 #endif
371
372 /**
373 * gst_get_main_executable_path:
374 *
375 * This helper is mostly helpful for plugins that need to
376 * inspect the folder of the main executable to determine
377 * their set of features.
378 *
379 * When a plugin is initialized from the gst-plugin-scanner
380 * external process, the returned path will be the same as from the
381 * parent process.
382 *
383 * Returns: (transfer none) (nullable): The path of the executable that
384 * initialized GStreamer, or %NULL if it could not be determined.
385 *
386 * Since: 1.14
387 */
388 const gchar *
gst_get_main_executable_path(void)389 gst_get_main_executable_path (void)
390 {
391 return _gst_executable_path;
392 }
393
394 /**
395 * gst_init_check:
396 * @argc: (inout) (allow-none): pointer to application's argc
397 * @argv: (inout) (array length=argc) (allow-none): pointer to application's argv
398 * @error: pointer to a #GError to which a message will be posted on error
399 *
400 * Initializes the GStreamer library, setting up internal path lists,
401 * registering built-in elements, and loading standard plugins.
402 *
403 * This function will return %FALSE if GStreamer could not be initialized
404 * for some reason. If you want your program to fail fatally,
405 * use gst_init() instead.
406 *
407 * Returns: %TRUE if GStreamer could be initialized.
408 */
409 gboolean
gst_init_check(int * argc,char ** argv[],GError ** error)410 gst_init_check (int *argc, char **argv[], GError ** error)
411 {
412 #ifndef GST_DISABLE_OPTION_PARSING
413 GOptionGroup *group;
414 GOptionContext *ctx;
415 #endif
416 gboolean res;
417
418 g_mutex_lock (&init_lock);
419
420 if (gst_initialized) {
421 GST_DEBUG ("already initialized gst");
422 g_mutex_unlock (&init_lock);
423 return TRUE;
424 }
425 #ifndef GST_DISABLE_OPTION_PARSING
426 ctx = g_option_context_new ("- GStreamer initialization");
427 g_option_context_set_ignore_unknown_options (ctx, TRUE);
428 g_option_context_set_help_enabled (ctx, FALSE);
429 group = gst_init_get_option_group ();
430 g_option_context_add_group (ctx, group);
431 res = g_option_context_parse (ctx, argc, argv, error);
432 g_option_context_free (ctx);
433 #else
434 init_pre (NULL, NULL, NULL, NULL);
435 init_post (NULL, NULL, NULL, NULL);
436 res = TRUE;
437 #endif
438
439 gst_initialized = res;
440
441 g_mutex_unlock (&init_lock);
442
443 return res;
444 }
445
446 /**
447 * gst_init:
448 * @argc: (inout) (allow-none): pointer to application's argc
449 * @argv: (inout) (array length=argc) (allow-none): pointer to application's argv
450 *
451 * Initializes the GStreamer library, setting up internal path lists,
452 * registering built-in elements, and loading standard plugins.
453 *
454 * Unless the plugin registry is disabled at compile time, the registry will be
455 * loaded. By default this will also check if the registry cache needs to be
456 * updated and rescan all plugins if needed. See gst_update_registry() for
457 * details and section
458 * <link linkend="gst-running">Running GStreamer Applications</link>
459 * for how to disable automatic registry updates.
460 *
461 * WARNING: This function will terminate your program if it was unable to
462 * initialize GStreamer for some reason. If you want your program to fall back,
463 * use gst_init_check() instead.
464 *
465 * WARNING: This function does not work in the same way as corresponding
466 * functions in other glib-style libraries, such as gtk_init\(\). In
467 * particular, unknown command line options cause this function to
468 * abort program execution.
469 */
470 void
gst_init(int * argc,char ** argv[])471 gst_init (int *argc, char **argv[])
472 {
473 GError *err = NULL;
474
475 if (!gst_init_check (argc, argv, &err)) {
476 g_print ("Could not initialize GStreamer: %s\n",
477 err ? err->message : "unknown error occurred");
478 if (err) {
479 g_error_free (err);
480 }
481 exit (1);
482 }
483 }
484
485 /**
486 * gst_is_initialized:
487 *
488 * Use this function to check if GStreamer has been initialized with gst_init()
489 * or gst_init_check().
490 *
491 * Returns: %TRUE if initialization has been done, %FALSE otherwise.
492 */
493 gboolean
gst_is_initialized(void)494 gst_is_initialized (void)
495 {
496 return gst_initialized;
497 }
498
499 #ifndef GST_DISABLE_OPTION_PARSING
500 # ifndef GST_DISABLE_REGISTRY
501 static void
add_path_func(gpointer data,gpointer user_data)502 add_path_func (gpointer data, gpointer user_data)
503 {
504 GST_INFO ("Adding plugin path: \"%s\", will scan later", (gchar *) data);
505 _priv_gst_plugin_paths =
506 g_list_append (_priv_gst_plugin_paths, g_strdup (data));
507 }
508 # endif
509 #endif
510
511 #ifndef GST_DISABLE_OPTION_PARSING
512 static void
prepare_for_load_plugin_func(gpointer data,gpointer user_data)513 prepare_for_load_plugin_func (gpointer data, gpointer user_data)
514 {
515 _priv_gst_preload_plugins =
516 g_slist_prepend (_priv_gst_preload_plugins, g_strdup (data));
517 }
518 #endif
519
520 #ifndef GST_DISABLE_OPTION_PARSING
521 static void
split_and_iterate(const gchar * stringlist,const gchar * separator,GFunc iterator,gpointer user_data)522 split_and_iterate (const gchar * stringlist, const gchar * separator,
523 GFunc iterator, gpointer user_data)
524 {
525 gchar **strings;
526 gint j = 0;
527 gchar *lastlist = g_strdup (stringlist);
528
529 while (lastlist) {
530 strings = g_strsplit (lastlist, separator, MAX_PATH_SPLIT);
531 g_free (lastlist);
532 lastlist = NULL;
533
534 while (strings[j]) {
535 iterator (strings[j], user_data);
536 if (++j == MAX_PATH_SPLIT) {
537 lastlist = g_strdup (strings[j]);
538 j = 0;
539 break;
540 }
541 }
542 g_strfreev (strings);
543 }
544 }
545 #endif
546
547 /* we have no fail cases yet, but maybe in the future */
548 static gboolean
init_pre(GOptionContext * context,GOptionGroup * group,gpointer data,GError ** error)549 init_pre (GOptionContext * context, GOptionGroup * group, gpointer data,
550 GError ** error)
551 {
552 gchar *libdir;
553 if (gst_initialized) {
554 GST_DEBUG ("already initialized");
555 return TRUE;
556 }
557
558 find_executable_path ();
559
560 _priv_gst_start_time = gst_util_get_timestamp ();
561
562 #ifndef GST_DISABLE_GST_DEBUG
563 _priv_gst_debug_init ();
564 priv_gst_dump_dot_dir = g_getenv ("GST_DEBUG_DUMP_DOT_DIR");
565 #endif
566
567 #ifdef ENABLE_NLS
568 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
569 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
570 #endif /* ENABLE_NLS */
571
572 /* This is the earliest we can make stuff show up in the logs.
573 * So give some useful info about GStreamer here */
574 #ifdef G_OS_WIN32
575 {
576 gchar *basedir =
577 g_win32_get_package_installation_directory_of_module
578 (_priv_gst_dll_handle);
579
580 libdir = g_build_filename (basedir,
581 #ifdef _DEBUG
582 "debug"
583 #endif
584 "lib", NULL);
585 g_free (basedir);
586 }
587 #else
588 libdir = priv_gst_get_relocated_libgstreamer ();
589 if (!libdir)
590 libdir = g_strdup (LIBDIR);
591 #endif
592 GST_INFO ("Initializing GStreamer Core Library version %s", VERSION);
593 GST_INFO ("Using library installed in %s", libdir);
594 g_free (libdir);
595
596 #ifndef GST_DISABLE_REGISTRY
597 {
598 const gchar *disable_registry;
599 if ((disable_registry = g_getenv ("GST_REGISTRY_DISABLE"))) {
600 _priv_gst_disable_registry = (strcmp (disable_registry, "yes") == 0);
601 }
602 }
603 #endif
604
605 /* Print some basic system details if possible (OS/architecture) */
606 #ifdef HAVE_SYS_UTSNAME_H
607 {
608 struct utsname sys_details;
609
610 if (uname (&sys_details) == 0) {
611 GST_INFO ("%s %s %s %s %s", sys_details.sysname,
612 sys_details.nodename, sys_details.release, sys_details.version,
613 sys_details.machine);
614 }
615 }
616 #endif
617
618 #ifndef G_ATOMIC_LOCK_FREE
619 GST_CAT_WARNING (GST_CAT_PERFORMANCE, "GLib atomic operations are NOT "
620 "implemented using real hardware atomic operations!");
621 #endif
622
623 return TRUE;
624 }
625
626 static gboolean
gst_register_core_elements(GstPlugin * plugin)627 gst_register_core_elements (GstPlugin * plugin)
628 {
629 /* register some standard builtin types */
630 if (!gst_element_register (plugin, "bin", GST_RANK_PRIMARY,
631 GST_TYPE_BIN) ||
632 !gst_element_register (plugin, "pipeline", GST_RANK_PRIMARY,
633 GST_TYPE_PIPELINE)
634 )
635 g_assert_not_reached ();
636
637 return TRUE;
638 }
639
640 static void
init_static_plugins(void)641 init_static_plugins (void)
642 {
643 GModule *module;
644
645 /* Call gst_init_static_plugins() defined in libgstreamer-full-1.0 in the case
646 * libgstreamer is static linked with some plugins. */
647 module = g_module_open (NULL, G_MODULE_BIND_LOCAL);
648 if (module) {
649 void (*func) (void);
650 if (g_module_symbol (module, "gst_init_static_plugins",
651 (gpointer *) & func)) {
652 func ();
653 }
654 g_module_close (module);
655 }
656 }
657
658 /*
659 * this bit handles:
660 * - initialization of threads if we use them
661 * - log handler
662 * - initial output
663 * - initializes gst_format
664 * - registers a bunch of types for gst_objects
665 *
666 * - we don't have cases yet where this fails, but in the future
667 * we might and then it's nice to be able to return that
668 */
669 static gboolean
init_post(GOptionContext * context,GOptionGroup * group,gpointer data,GError ** error)670 init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
671 GError ** error)
672 {
673 GLogLevelFlags llf;
674
675 if (gst_initialized) {
676 GST_DEBUG ("already initialized");
677 return TRUE;
678 }
679
680 llf = G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL;
681 /* TODO: should we also set up a handler for the other gst libs/domains? */
682 g_log_set_handler (G_LOG_DOMAIN, llf, debug_log_handler, NULL);
683
684 _priv_gst_mini_object_initialize ();
685 _priv_gst_quarks_initialize ();
686 _priv_gst_allocator_initialize ();
687 _priv_gst_memory_initialize ();
688 _priv_gst_format_initialize ();
689 _priv_gst_query_initialize ();
690 _priv_gst_structure_initialize ();
691 _priv_gst_caps_initialize ();
692 _priv_gst_caps_features_initialize ();
693 _priv_gst_meta_initialize ();
694 _priv_gst_message_initialize ();
695
696 g_type_class_ref (gst_object_get_type ());
697 g_type_class_ref (gst_pad_get_type ());
698 g_type_class_ref (gst_element_factory_get_type ());
699 g_type_class_ref (gst_element_get_type ());
700 g_type_class_ref (gst_tracer_factory_get_type ());
701 g_type_class_ref (gst_type_find_factory_get_type ());
702 g_type_class_ref (gst_bin_get_type ());
703 g_type_class_ref (gst_bus_get_type ());
704 g_type_class_ref (gst_task_get_type ());
705 g_type_class_ref (gst_clock_get_type ());
706 g_type_class_ref (gst_debug_color_mode_get_type ());
707
708 gst_uri_handler_get_type ();
709
710 g_type_class_ref (gst_object_flags_get_type ());
711 g_type_class_ref (gst_bin_flags_get_type ());
712 g_type_class_ref (gst_buffer_flags_get_type ());
713 g_type_class_ref (gst_buffer_copy_flags_get_type ());
714 g_type_class_ref (gst_bus_flags_get_type ());
715 g_type_class_ref (gst_bus_sync_reply_get_type ());
716 g_type_class_ref (gst_caps_flags_get_type ());
717 g_type_class_ref (gst_clock_return_get_type ());
718 g_type_class_ref (gst_clock_entry_type_get_type ());
719 g_type_class_ref (gst_clock_flags_get_type ());
720 g_type_class_ref (gst_clock_type_get_type ());
721 g_type_class_ref (gst_debug_graph_details_get_type ());
722 g_type_class_ref (gst_state_get_type ());
723 g_type_class_ref (gst_state_change_return_get_type ());
724 g_type_class_ref (gst_state_change_get_type ());
725 g_type_class_ref (gst_element_flags_get_type ());
726 g_type_class_ref (gst_tracer_value_scope_get_type ());
727 g_type_class_ref (gst_tracer_value_flags_get_type ());
728 g_type_class_ref (gst_core_error_get_type ());
729 g_type_class_ref (gst_library_error_get_type ());
730 g_type_class_ref (gst_resource_error_get_type ());
731 g_type_class_ref (gst_stream_error_get_type ());
732 g_type_class_ref (gst_event_type_flags_get_type ());
733 g_type_class_ref (gst_event_type_get_type ());
734 g_type_class_ref (gst_seek_type_get_type ());
735 g_type_class_ref (gst_seek_flags_get_type ());
736 g_type_class_ref (gst_qos_type_get_type ());
737 g_type_class_ref (gst_format_get_type ());
738 g_type_class_ref (gst_debug_level_get_type ());
739 g_type_class_ref (gst_debug_color_flags_get_type ());
740 g_type_class_ref (gst_iterator_result_get_type ());
741 g_type_class_ref (gst_iterator_item_get_type ());
742 g_type_class_ref (gst_message_type_get_type ());
743 g_type_class_ref (gst_mini_object_flags_get_type ());
744 g_type_class_ref (gst_pad_link_return_get_type ());
745 g_type_class_ref (gst_pad_link_check_get_type ());
746 g_type_class_ref (gst_flow_return_get_type ());
747 g_type_class_ref (gst_pad_mode_get_type ());
748 g_type_class_ref (gst_pad_direction_get_type ());
749 g_type_class_ref (gst_pad_flags_get_type ());
750 g_type_class_ref (gst_pad_presence_get_type ());
751 g_type_class_ref (gst_pad_template_flags_get_type ());
752 g_type_class_ref (gst_pipeline_flags_get_type ());
753 g_type_class_ref (gst_plugin_error_get_type ());
754 g_type_class_ref (gst_plugin_flags_get_type ());
755 g_type_class_ref (gst_plugin_dependency_flags_get_type ());
756 g_type_class_ref (gst_rank_get_type ());
757 g_type_class_ref (gst_query_type_flags_get_type ());
758 g_type_class_ref (gst_query_type_get_type ());
759 g_type_class_ref (gst_buffering_mode_get_type ());
760 g_type_class_ref (gst_stream_status_type_get_type ());
761 g_type_class_ref (gst_structure_change_type_get_type ());
762 g_type_class_ref (gst_tag_merge_mode_get_type ());
763 g_type_class_ref (gst_tag_flag_get_type ());
764 g_type_class_ref (gst_tag_scope_get_type ());
765 g_type_class_ref (gst_task_pool_get_type ());
766 g_type_class_ref (gst_task_state_get_type ());
767 g_type_class_ref (gst_toc_entry_type_get_type ());
768 g_type_class_ref (gst_type_find_probability_get_type ());
769 g_type_class_ref (gst_uri_error_get_type ());
770 g_type_class_ref (gst_uri_type_get_type ());
771 g_type_class_ref (gst_parse_error_get_type ());
772 g_type_class_ref (gst_parse_flags_get_type ());
773 g_type_class_ref (gst_search_mode_get_type ());
774 g_type_class_ref (gst_progress_type_get_type ());
775 g_type_class_ref (gst_buffer_pool_acquire_flags_get_type ());
776 g_type_class_ref (gst_memory_flags_get_type ());
777 g_type_class_ref (gst_map_flags_get_type ());
778 g_type_class_ref (gst_caps_intersect_mode_get_type ());
779 g_type_class_ref (gst_pad_probe_type_get_type ());
780 g_type_class_ref (gst_pad_probe_return_get_type ());
781 g_type_class_ref (gst_segment_flags_get_type ());
782 g_type_class_ref (gst_scheduling_flags_get_type ());
783 g_type_class_ref (gst_meta_flags_get_type ());
784 g_type_class_ref (gst_toc_entry_type_get_type ());
785 g_type_class_ref (gst_toc_scope_get_type ());
786 g_type_class_ref (gst_toc_loop_type_get_type ());
787 g_type_class_ref (gst_control_binding_get_type ());
788 g_type_class_ref (gst_control_source_get_type ());
789 g_type_class_ref (gst_lock_flags_get_type ());
790 g_type_class_ref (gst_allocator_flags_get_type ());
791 g_type_class_ref (gst_stream_flags_get_type ());
792 g_type_class_ref (gst_stream_type_get_type ());
793 g_type_class_ref (gst_stack_trace_flags_get_type ());
794 g_type_class_ref (gst_promise_result_get_type ());
795
796 _priv_gst_event_initialize ();
797 _priv_gst_buffer_initialize ();
798 _priv_gst_buffer_list_initialize ();
799 _priv_gst_sample_initialize ();
800 _priv_gst_context_initialize ();
801 _priv_gst_date_time_initialize ();
802 _priv_gst_value_initialize ();
803 _priv_gst_tag_initialize ();
804 _priv_gst_toc_initialize ();
805
806 g_type_class_ref (gst_param_spec_fraction_get_type ());
807 gst_parse_context_get_type ();
808
809 _priv_gst_plugin_initialize ();
810
811 /* register core plugins */
812 gst_plugin_register_static (GST_VERSION_MAJOR, GST_VERSION_MINOR,
813 "staticelements", "core elements linked into the GStreamer library",
814 gst_register_core_elements, VERSION, GST_LICENSE, PACKAGE,
815 GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
816
817 init_static_plugins ();
818
819 /*
820 * Any errors happening below this point are non-fatal, we therefore mark
821 * gstreamer as being initialized, since it is the case from a plugin point of
822 * view.
823 *
824 * If anything fails, it will be put back to %FALSE in gst_init_check().
825 * This allows some special plugins that would call gst_init() to not cause a
826 * looping effect (i.e. initializing GStreamer twice).
827 */
828 gst_initialized = TRUE;
829
830 if (!gst_update_registry ())
831 return FALSE;
832
833 GST_INFO ("GLib runtime version: %d.%d.%d", glib_major_version,
834 glib_minor_version, glib_micro_version);
835 GST_INFO ("GLib headers version: %d.%d.%d", GLIB_MAJOR_VERSION,
836 GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
837 GST_INFO ("initialized GStreamer successfully");
838
839 /* Adjust initial plugin rank based on the GST_PLUGIN_FEATURE_RANK
840 * environment variable */
841 _priv_gst_plugin_feature_rank_initialize ();
842
843 #ifndef GST_DISABLE_GST_DEBUG
844 _priv_gst_tracing_init ();
845 #endif
846
847 return TRUE;
848 }
849
850 #ifndef GST_DISABLE_OPTION_PARSING
851 # ifndef GST_DISABLE_GST_DEBUG
852 static gboolean
select_all(GstPlugin * plugin,gpointer user_data)853 select_all (GstPlugin * plugin, gpointer user_data)
854 {
855 return TRUE;
856 }
857
858 static gint
sort_by_category_name(gconstpointer a,gconstpointer b)859 sort_by_category_name (gconstpointer a, gconstpointer b)
860 {
861 return strcmp (gst_debug_category_get_name ((GstDebugCategory *) a),
862 gst_debug_category_get_name ((GstDebugCategory *) b));
863 }
864
865 static void
gst_debug_help(void)866 gst_debug_help (void)
867 {
868 GSList *list, *walk;
869 GList *list2, *g;
870
871 /* Need to ensure the registry is loaded to get debug categories */
872 if (!init_post (NULL, NULL, NULL, NULL))
873 exit (1);
874
875 list2 = gst_registry_plugin_filter (gst_registry_get (),
876 select_all, FALSE, NULL);
877
878 /* FIXME this is gross. why don't debug have categories PluginFeatures? */
879 for (g = list2; g; g = g_list_next (g)) {
880 GstPlugin *plugin = GST_PLUGIN_CAST (g->data);
881 GList *features, *orig_features;
882
883 if (GST_OBJECT_FLAG_IS_SET (plugin, GST_PLUGIN_FLAG_BLACKLISTED))
884 continue;
885
886 gst_plugin_load (plugin);
887 /* Now create one of each feature so the class_init functions
888 * are called, as that's where most debug categories are
889 * registered. FIXME: If debug categories were a plugin feature,
890 * this would be unneeded */
891 orig_features = features =
892 gst_registry_get_feature_list_by_plugin (gst_registry_get (),
893 gst_plugin_get_name (plugin));
894 while (features) {
895 GstPluginFeature *feature;
896
897 if (G_UNLIKELY (features->data == NULL))
898 goto next;
899
900 feature = GST_PLUGIN_FEATURE (features->data);
901 if (GST_IS_ELEMENT_FACTORY (feature)) {
902 GstElementFactory *factory;
903 GstElement *e;
904
905 factory = GST_ELEMENT_FACTORY (feature);
906 e = gst_element_factory_create (factory, NULL);
907 if (e)
908 gst_object_unref (e);
909 }
910
911 next:
912 features = g_list_next (features);
913 }
914
915 gst_plugin_feature_list_free (orig_features);
916 }
917 g_list_free (list2);
918
919 list = gst_debug_get_all_categories ();
920 walk = list = g_slist_sort (list, sort_by_category_name);
921
922 g_print ("\n");
923 g_print ("name level description\n");
924 g_print ("---------------------+--------+--------------------------------\n");
925
926 while (walk) {
927 gboolean on_unix;
928 GstDebugCategory *cat = (GstDebugCategory *) walk->data;
929 GstDebugColorMode coloring = gst_debug_get_color_mode ();
930 #ifdef G_OS_UNIX
931 on_unix = TRUE;
932 #else
933 on_unix = FALSE;
934 #endif
935
936 if (GST_DEBUG_COLOR_MODE_UNIX == coloring
937 || (on_unix && GST_DEBUG_COLOR_MODE_ON == coloring)) {
938 gchar *color = gst_debug_construct_term_color (cat->color);
939
940 g_print ("%s%-20s\033[00m %1d %s %s%s\033[00m\n",
941 color,
942 gst_debug_category_get_name (cat),
943 gst_debug_category_get_threshold (cat),
944 gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
945 color, gst_debug_category_get_description (cat));
946 g_free (color);
947 } else if (GST_DEBUG_COLOR_MODE_ON == coloring && !on_unix) {
948 #ifdef G_OS_WIN32
949 gint color = gst_debug_construct_win_color (cat->color);
950 const gint clear = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
951
952 SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), color);
953 g_print ("%-20s", gst_debug_category_get_name (cat));
954 SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), clear);
955 g_print (" %1d %s ", gst_debug_category_get_threshold (cat),
956 gst_debug_level_get_name (gst_debug_category_get_threshold (cat)));
957 SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), color);
958 g_print ("%s", gst_debug_category_get_description (cat));
959 SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), clear);
960 g_print ("\n");
961 #endif /* G_OS_WIN32 */
962 } else {
963 g_print ("%-20s %1d %s %s\n", gst_debug_category_get_name (cat),
964 gst_debug_category_get_threshold (cat),
965 gst_debug_level_get_name (gst_debug_category_get_threshold (cat)),
966 gst_debug_category_get_description (cat));
967 }
968 walk = g_slist_next (walk);
969 }
970 g_slist_free (list);
971 g_print ("\n");
972 }
973 # endif /* GST_DISABLE_OPTION_PARSING */
974 #endif /* GST_DISABLE_GST_DEBUG */
975
976 #ifndef GST_DISABLE_OPTION_PARSING
977 static gboolean
parse_one_option(gint opt,const gchar * arg,GError ** err)978 parse_one_option (gint opt, const gchar * arg, GError ** err)
979 {
980 switch (opt) {
981 case ARG_VERSION:
982 g_print ("GStreamer Core Library version %s\n", PACKAGE_VERSION);
983 exit (0);
984 case ARG_FATAL_WARNINGS:{
985 GLogLevelFlags fatal_mask;
986
987 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
988 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
989 g_log_set_always_fatal (fatal_mask);
990 break;
991 }
992 #ifndef GST_DISABLE_GST_DEBUG
993 case ARG_DEBUG_LEVEL:{
994 GstDebugLevel tmp = GST_LEVEL_NONE;
995
996 tmp = (GstDebugLevel) strtol (arg, NULL, 0);
997 if (((guint) tmp) < GST_LEVEL_COUNT) {
998 gst_debug_set_default_threshold (tmp);
999 }
1000 break;
1001 }
1002 case ARG_DEBUG:
1003 gst_debug_set_threshold_from_string (arg, FALSE);
1004 break;
1005 case ARG_DEBUG_NO_COLOR:
1006 gst_debug_set_colored (FALSE);
1007 break;
1008 case ARG_DEBUG_COLOR_MODE:
1009 gst_debug_set_color_mode_from_string (arg);
1010 break;
1011 case ARG_DEBUG_DISABLE:
1012 gst_debug_set_active (FALSE);
1013 break;
1014 case ARG_DEBUG_HELP:
1015 gst_debug_help ();
1016 exit (0);
1017 #endif
1018 case ARG_PLUGIN_SPEW:
1019 break;
1020 case ARG_PLUGIN_PATH:
1021 #ifndef GST_DISABLE_REGISTRY
1022 if (!_priv_gst_disable_registry)
1023 split_and_iterate (arg, G_SEARCHPATH_SEPARATOR_S, add_path_func, NULL);
1024 #endif /* GST_DISABLE_REGISTRY */
1025 break;
1026 case ARG_PLUGIN_LOAD:
1027 split_and_iterate (arg, ",", prepare_for_load_plugin_func, NULL);
1028 break;
1029 case ARG_SEGTRAP_DISABLE:
1030 _gst_disable_segtrap = TRUE;
1031 break;
1032 case ARG_REGISTRY_UPDATE_DISABLE:
1033 #ifndef GST_DISABLE_REGISTRY
1034 if (!_priv_gst_disable_registry)
1035 _priv_gst_disable_registry_update = TRUE;
1036 #endif
1037 break;
1038 case ARG_REGISTRY_FORK_DISABLE:
1039 gst_registry_fork_set_enabled (FALSE);
1040 break;
1041 default:
1042 g_set_error (err, G_OPTION_ERROR, G_OPTION_ERROR_UNKNOWN_OPTION,
1043 _("Unknown option"));
1044 return FALSE;
1045 }
1046
1047 return TRUE;
1048 }
1049
1050 /* *INDENT-OFF* */
1051 static gboolean
parse_goption_arg(const gchar * opt,const gchar * arg,gpointer data,GError ** err)1052 parse_goption_arg (const gchar * opt,
1053 const gchar * arg, gpointer data, GError ** err)
1054 {
1055 static const struct
1056 {
1057 const gchar *opt;
1058 int val;
1059 } options[] = {
1060 {
1061 "--gst-version", ARG_VERSION}, {
1062 "--gst-fatal-warnings", ARG_FATAL_WARNINGS},
1063 #ifndef GST_DISABLE_GST_DEBUG
1064 {
1065 "--gst-debug-level", ARG_DEBUG_LEVEL}, {
1066 "--gst-debug", ARG_DEBUG}, {
1067 "--gst-debug-disable", ARG_DEBUG_DISABLE}, {
1068 "--gst-debug-no-color", ARG_DEBUG_NO_COLOR}, {
1069 "--gst-debug-color-mode", ARG_DEBUG_COLOR_MODE}, {
1070 "--gst-debug-help", ARG_DEBUG_HELP},
1071 #endif
1072 {
1073 "--gst-plugin-spew", ARG_PLUGIN_SPEW}, {
1074 "--gst-plugin-path", ARG_PLUGIN_PATH}, {
1075 "--gst-plugin-load", ARG_PLUGIN_LOAD}, {
1076 "--gst-disable-segtrap", ARG_SEGTRAP_DISABLE}, {
1077 "--gst-disable-registry-update", ARG_REGISTRY_UPDATE_DISABLE}, {
1078 "--gst-disable-registry-fork", ARG_REGISTRY_FORK_DISABLE}, {
1079 NULL}
1080 };
1081 gint val = 0, n;
1082
1083 for (n = 0; options[n].opt; n++) {
1084 if (!strcmp (opt, options[n].opt)) {
1085 val = options[n].val;
1086 break;
1087 }
1088 }
1089
1090 return parse_one_option (val, arg, err);
1091 }
1092 #endif
1093 /* *INDENT-ON* */
1094
1095 /**
1096 * gst_deinit:
1097 *
1098 * Clean up any resources created by GStreamer in gst_init().
1099 *
1100 * It is normally not needed to call this function in a normal application
1101 * as the resources will automatically be freed when the program terminates.
1102 * This function is therefore mostly used by testsuites and other memory
1103 * profiling tools.
1104 *
1105 * After this call GStreamer (including this method) should not be used anymore.
1106 */
1107 void
gst_deinit(void)1108 gst_deinit (void)
1109 {
1110 GstBinClass *bin_class;
1111 GstClock *clock;
1112
1113 g_mutex_lock (&init_lock);
1114
1115 if (!gst_initialized) {
1116 g_mutex_unlock (&init_lock);
1117 return;
1118 }
1119 if (gst_deinitialized) {
1120 /* tell the user how naughty they've been */
1121 g_error ("GStreamer should not be deinitialized a second time.");
1122 }
1123
1124 GST_INFO ("deinitializing GStreamer");
1125 g_thread_pool_set_max_unused_threads (0);
1126 bin_class = (GstBinClass *) g_type_class_peek (gst_bin_get_type ());
1127 if (bin_class && bin_class->pool != NULL) {
1128 g_thread_pool_free (bin_class->pool, FALSE, TRUE);
1129 bin_class->pool = NULL;
1130 }
1131 gst_task_cleanup_all ();
1132
1133 g_slist_foreach (_priv_gst_preload_plugins, (GFunc) g_free, NULL);
1134 g_slist_free (_priv_gst_preload_plugins);
1135 _priv_gst_preload_plugins = NULL;
1136
1137 #ifndef GST_DISABLE_REGISTRY
1138 g_list_foreach (_priv_gst_plugin_paths, (GFunc) g_free, NULL);
1139 g_list_free (_priv_gst_plugin_paths);
1140 _priv_gst_plugin_paths = NULL;
1141 #endif
1142
1143 if (_gst_executable_path) {
1144 g_free (_gst_executable_path);
1145 _gst_executable_path = NULL;
1146 }
1147
1148 clock = gst_system_clock_obtain ();
1149 gst_object_unref (clock);
1150 gst_object_unref (clock);
1151
1152 _priv_gst_registry_cleanup ();
1153 _priv_gst_allocator_cleanup ();
1154
1155 /* We want to destroy tracers as late as possible for the leaks tracer
1156 * but still need to keep the caps system alive as it may have to use
1157 * gst_caps_to_string() to display leaked caps. */
1158 #ifndef GST_DISABLE_GST_DEBUG
1159 _priv_gst_tracing_deinit ();
1160 #endif
1161
1162 _priv_gst_caps_features_cleanup ();
1163 _priv_gst_caps_cleanup ();
1164 _priv_gst_meta_cleanup ();
1165
1166 g_type_class_unref (g_type_class_peek (gst_object_get_type ()));
1167 g_type_class_unref (g_type_class_peek (gst_pad_get_type ()));
1168 g_type_class_unref (g_type_class_peek (gst_element_factory_get_type ()));
1169 g_type_class_unref (g_type_class_peek (gst_element_get_type ()));
1170 g_type_class_unref (g_type_class_peek (gst_tracer_factory_get_type ()));
1171 g_type_class_unref (g_type_class_peek (gst_type_find_factory_get_type ()));
1172 g_type_class_unref (g_type_class_peek (gst_bin_get_type ()));
1173 g_type_class_unref (g_type_class_peek (gst_bus_get_type ()));
1174 g_type_class_unref (g_type_class_peek (gst_task_get_type ()));
1175 g_type_class_unref (g_type_class_peek (gst_object_flags_get_type ()));
1176 g_type_class_unref (g_type_class_peek (gst_bin_flags_get_type ()));
1177 g_type_class_unref (g_type_class_peek (gst_buffer_flags_get_type ()));
1178 g_type_class_unref (g_type_class_peek (gst_buffer_copy_flags_get_type ()));
1179 g_type_class_unref (g_type_class_peek (gst_bus_flags_get_type ()));
1180 g_type_class_unref (g_type_class_peek (gst_bus_sync_reply_get_type ()));
1181 g_type_class_unref (g_type_class_peek (gst_caps_flags_get_type ()));
1182 g_type_class_unref (g_type_class_peek (gst_clock_type_get_type ()));
1183 g_type_class_unref (g_type_class_peek (gst_clock_return_get_type ()));
1184 g_type_class_unref (g_type_class_peek (gst_clock_entry_type_get_type ()));
1185 g_type_class_unref (g_type_class_peek (gst_clock_flags_get_type ()));
1186 g_type_class_unref (g_type_class_peek (gst_debug_graph_details_get_type ()));
1187 g_type_class_unref (g_type_class_peek (gst_state_get_type ()));
1188 g_type_class_unref (g_type_class_peek (gst_state_change_return_get_type ()));
1189 g_type_class_unref (g_type_class_peek (gst_state_change_get_type ()));
1190 g_type_class_unref (g_type_class_peek (gst_element_flags_get_type ()));
1191 g_type_class_unref (g_type_class_peek (gst_tracer_value_scope_get_type ()));
1192 g_type_class_unref (g_type_class_peek (gst_tracer_value_flags_get_type ()));
1193 g_type_class_unref (g_type_class_peek (gst_core_error_get_type ()));
1194 g_type_class_unref (g_type_class_peek (gst_library_error_get_type ()));
1195 g_type_class_unref (g_type_class_peek (gst_plugin_dependency_flags_get_type
1196 ()));
1197 g_type_class_unref (g_type_class_peek (gst_parse_flags_get_type ()));
1198 g_type_class_unref (g_type_class_peek (gst_resource_error_get_type ()));
1199 g_type_class_unref (g_type_class_peek (gst_search_mode_get_type ()));
1200 g_type_class_unref (g_type_class_peek (gst_stream_error_get_type ()));
1201 g_type_class_unref (g_type_class_peek (gst_stream_status_type_get_type ()));
1202 g_type_class_unref (g_type_class_peek (gst_structure_change_type_get_type
1203 ()));
1204 g_type_class_unref (g_type_class_peek (gst_event_type_flags_get_type ()));
1205 g_type_class_unref (g_type_class_peek (gst_event_type_get_type ()));
1206 g_type_class_unref (g_type_class_peek (gst_seek_type_get_type ()));
1207 g_type_class_unref (g_type_class_peek (gst_seek_flags_get_type ()));
1208 g_type_class_unref (g_type_class_peek (gst_qos_type_get_type ()));
1209 g_type_class_unref (g_type_class_peek (gst_format_get_type ()));
1210 g_type_class_unref (g_type_class_peek (gst_debug_level_get_type ()));
1211 g_type_class_unref (g_type_class_peek (gst_debug_color_flags_get_type ()));
1212 g_type_class_unref (g_type_class_peek (gst_iterator_result_get_type ()));
1213 g_type_class_unref (g_type_class_peek (gst_iterator_item_get_type ()));
1214 g_type_class_unref (g_type_class_peek (gst_message_type_get_type ()));
1215 g_type_class_unref (g_type_class_peek (gst_meta_flags_get_type ()));
1216 g_type_class_unref (g_type_class_peek (gst_mini_object_flags_get_type ()));
1217 g_type_class_unref (g_type_class_peek (gst_pad_link_return_get_type ()));
1218 g_type_class_unref (g_type_class_peek (gst_pad_link_check_get_type ()));
1219 g_type_class_unref (g_type_class_peek (gst_flow_return_get_type ()));
1220 g_type_class_unref (g_type_class_peek (gst_pad_mode_get_type ()));
1221 g_type_class_unref (g_type_class_peek (gst_pad_direction_get_type ()));
1222 g_type_class_unref (g_type_class_peek (gst_pad_flags_get_type ()));
1223 g_type_class_unref (g_type_class_peek (gst_pad_presence_get_type ()));
1224 g_type_class_unref (g_type_class_peek (gst_pad_template_flags_get_type ()));
1225 g_type_class_unref (g_type_class_peek (gst_pipeline_flags_get_type ()));
1226 g_type_class_unref (g_type_class_peek (gst_plugin_error_get_type ()));
1227 g_type_class_unref (g_type_class_peek (gst_plugin_flags_get_type ()));
1228 g_type_class_unref (g_type_class_peek (gst_rank_get_type ()));
1229 g_type_class_unref (g_type_class_peek (gst_query_type_flags_get_type ()));
1230 g_type_class_unref (g_type_class_peek (gst_query_type_get_type ()));
1231 g_type_class_unref (g_type_class_peek (gst_buffering_mode_get_type ()));
1232 g_type_class_unref (g_type_class_peek (gst_tag_merge_mode_get_type ()));
1233 g_type_class_unref (g_type_class_peek (gst_tag_flag_get_type ()));
1234 g_type_class_unref (g_type_class_peek (gst_tag_scope_get_type ()));
1235 g_type_class_unref (g_type_class_peek (gst_task_state_get_type ()));
1236 g_type_class_unref (g_type_class_peek (gst_toc_entry_type_get_type ()));
1237 g_type_class_unref (g_type_class_peek (gst_toc_scope_get_type ()));
1238 g_type_class_unref (g_type_class_peek (gst_type_find_probability_get_type
1239 ()));
1240 g_type_class_unref (g_type_class_peek (gst_uri_type_get_type ()));
1241 g_type_class_unref (g_type_class_peek (gst_uri_error_get_type ()));
1242 g_type_class_unref (g_type_class_peek (gst_parse_error_get_type ()));
1243 g_type_class_unref (g_type_class_peek (gst_param_spec_fraction_get_type ()));
1244 g_type_class_unref (g_type_class_peek (gst_progress_type_get_type ()));
1245 g_type_class_unref (g_type_class_peek (gst_buffer_pool_acquire_flags_get_type
1246 ()));
1247 g_type_class_unref (g_type_class_peek (gst_memory_flags_get_type ()));
1248 g_type_class_unref (g_type_class_peek (gst_map_flags_get_type ()));
1249 g_type_class_unref (g_type_class_peek (gst_caps_intersect_mode_get_type ()));
1250 g_type_class_unref (g_type_class_peek (gst_pad_probe_type_get_type ()));
1251 g_type_class_unref (g_type_class_peek (gst_pad_probe_return_get_type ()));
1252 g_type_class_unref (g_type_class_peek (gst_segment_flags_get_type ()));
1253 g_type_class_unref (g_type_class_peek (gst_scheduling_flags_get_type ()));
1254 g_type_class_unref (g_type_class_peek (gst_stream_type_get_type ()));
1255
1256 g_type_class_unref (g_type_class_peek (gst_control_binding_get_type ()));
1257 g_type_class_unref (g_type_class_peek (gst_control_source_get_type ()));
1258 g_type_class_unref (g_type_class_peek (gst_toc_entry_type_get_type ()));
1259 g_type_class_unref (g_type_class_peek (gst_toc_loop_type_get_type ()));
1260 g_type_class_unref (g_type_class_peek (gst_lock_flags_get_type ()));
1261 g_type_class_unref (g_type_class_peek (gst_allocator_flags_get_type ()));
1262 g_type_class_unref (g_type_class_peek (gst_stream_flags_get_type ()));
1263 g_type_class_unref (g_type_class_peek (gst_debug_color_mode_get_type ()));
1264 g_type_class_unref (g_type_class_peek (gst_stack_trace_flags_get_type ()));
1265 g_type_class_unref (g_type_class_peek (gst_promise_result_get_type ()));
1266
1267 gst_deinitialized = TRUE;
1268 GST_INFO ("deinitialized GStreamer");
1269 g_mutex_unlock (&init_lock);
1270
1271 /* Doing this as the very last step to allow the above GST_INFO() to work
1272 * correctly. It's of course making the above statement a lie: for a short
1273 * while we're not deinitialized yet */
1274 _priv_gst_debug_cleanup ();
1275 }
1276
1277 /**
1278 * gst_version:
1279 * @major: (out): pointer to a guint to store the major version number
1280 * @minor: (out): pointer to a guint to store the minor version number
1281 * @micro: (out): pointer to a guint to store the micro version number
1282 * @nano: (out): pointer to a guint to store the nano version number
1283 *
1284 * Gets the version number of the GStreamer library.
1285 */
1286 void
gst_version(guint * major,guint * minor,guint * micro,guint * nano)1287 gst_version (guint * major, guint * minor, guint * micro, guint * nano)
1288 {
1289 g_return_if_fail (major);
1290 g_return_if_fail (minor);
1291 g_return_if_fail (micro);
1292 g_return_if_fail (nano);
1293
1294 *major = GST_VERSION_MAJOR;
1295 *minor = GST_VERSION_MINOR;
1296 *micro = GST_VERSION_MICRO;
1297 *nano = GST_VERSION_NANO;
1298 }
1299
1300 /**
1301 * gst_version_string:
1302 *
1303 * This function returns a string that is useful for describing this version
1304 * of GStreamer to the outside world: user agent strings, logging, ...
1305 *
1306 * Returns: (transfer full): a newly allocated string describing this version
1307 * of GStreamer.
1308 */
1309
1310 gchar *
gst_version_string(void)1311 gst_version_string (void)
1312 {
1313 guint major, minor, micro, nano;
1314
1315 gst_version (&major, &minor, µ, &nano);
1316 if (nano == 0)
1317 return g_strdup_printf ("GStreamer %d.%d.%d", major, minor, micro);
1318 else if (nano == 1)
1319 return g_strdup_printf ("GStreamer %d.%d.%d (GIT)", major, minor, micro);
1320 else
1321 return g_strdup_printf ("GStreamer %d.%d.%d (prerelease)", major, minor,
1322 micro);
1323 }
1324
1325 /**
1326 * gst_segtrap_is_enabled:
1327 *
1328 * Some functions in the GStreamer core might install a custom SIGSEGV handler
1329 * to better catch and report errors to the application. Currently this feature
1330 * is enabled by default when loading plugins.
1331 *
1332 * Applications might want to disable this behaviour with the
1333 * gst_segtrap_set_enabled() function. This is typically done if the application
1334 * wants to install its own handler without GStreamer interfering.
1335 *
1336 * Returns: %TRUE if GStreamer is allowed to install a custom SIGSEGV handler.
1337 */
1338 gboolean
gst_segtrap_is_enabled(void)1339 gst_segtrap_is_enabled (void)
1340 {
1341 /* yeps, it's enabled when it's not disabled */
1342 return !_gst_disable_segtrap;
1343 }
1344
1345 /**
1346 * gst_segtrap_set_enabled:
1347 * @enabled: whether a custom SIGSEGV handler should be installed.
1348 *
1349 * Applications might want to disable/enable the SIGSEGV handling of
1350 * the GStreamer core. See gst_segtrap_is_enabled() for more information.
1351 */
1352 void
gst_segtrap_set_enabled(gboolean enabled)1353 gst_segtrap_set_enabled (gboolean enabled)
1354 {
1355 _gst_disable_segtrap = !enabled;
1356 }
1357