element: Enforce that elements created by gst_element_factory_create/make() are floating
[platform/upstream/gstreamer.git] / gst / gst.c
index 3cf067e..2f4c789 100644 (file)
--- a/gst/gst.c
+++ b/gst/gst.c
@@ -22,6 +22,7 @@
 
 /**
  * SECTION:gst
+ * @title: GStreamer
  * @short_description: Media library supporting arbitrary formats and filter
  *                     graphs.
  *
@@ -40,9 +41,9 @@
  * and argv variables so that GStreamer can process its own command line
  * options, as shown in the following example.
  *
- * <example>
- * <title>Initializing the gstreamer library</title>
- * <programlisting language="c">
+ * ## Initializing the gstreamer library
+ *
+ * |[ <!-- language="C" -->
  * int
  * main (int argc, char *argv[])
  * {
  *   gst_init (&amp;argc, &amp;argv);
  *   ...
  * }
- * </programlisting>
- * </example>
+ * ]|
  *
  * It's allowed to pass two %NULL pointers to gst_init() in case you don't want
  * to pass the command line args to GStreamer.
  *
  * You can also use GOption to initialize your own parameters as shown in
  * the next code fragment:
- * <example>
- * <title>Initializing own parameters when initializing gstreamer</title>
- * <programlisting>
+ *
+ * ## Initializing own parameters when initializing gstreamer
+ * |[ <!-- language="C" -->
  * static gboolean stats = FALSE;
  * ...
  * int
  *  g_option_context_free (ctx);
  * ...
  * }
- * </programlisting>
- * </example>
+ * ]|
  *
  * Use gst_version() to query the library version at runtime or use the
  * GST_VERSION_* macros to find the version at compile time. Optionally
  * gst_version_string() returns a printable string.
  *
  * The gst_deinit() call is used to clean up all internal resources used
- * by <application>GStreamer</application>. It is mostly used in unit tests 
- * to check for leaks.
+ * by GStreamer. It is mostly used in unit tests to check for leaks.
  */
 
 #include "gst_private.h"
 #define WIN32_LEAN_AND_MEAN     /* prevents from including too many things */
 #include <windows.h>            /* GetStdHandle, windows console */
 #endif
+#if defined (__APPLE__)
+#include "TargetConditionals.h"
+#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_EMBEDDED
+#include <libproc.h>            /* proc_pidpath, PROC_PIDPATHINFO_MAXSIZE */
+#endif
+#endif
 
 #include "gst-i18n-lib.h"
 #include <locale.h>             /* for LC_ALL */
@@ -135,6 +139,8 @@ extern gboolean _priv_gst_disable_registry;
 extern gboolean _priv_gst_disable_registry_update;
 #endif
 
+gchar *_gst_executable_path = NULL;
+
 #ifndef GST_DISABLE_GST_DEBUG
 const gchar *priv_gst_dump_dot_dir;
 #endif
@@ -231,7 +237,7 @@ DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
  * threading system as one of the very first things in your program
  * (see the example at the beginning of this section).
  *
- * Returns: (transfer full): a pointer to GStreamer's option group.
+ * Returns: (transfer full) (nullable): a pointer to GStreamer's option group.
  */
 
 GOptionGroup *
@@ -313,6 +319,73 @@ gst_init_get_option_group (void)
 #endif
 }
 
+#if defined(__linux__)
+static void
+find_executable_path (void)
+{
+  GError *error = NULL;
+
+  if (_gst_executable_path)
+    return;
+
+  _gst_executable_path = g_file_read_link ("/proc/self/exe", &error);
+  if (error)
+    g_error_free (error);
+}
+#elif defined(G_OS_WIN32)
+static void
+find_executable_path (void)
+{
+  char buffer[MAX_PATH];
+
+  if (!GetModuleFileName (NULL, buffer, MAX_PATH))
+    return;
+
+  _gst_executable_path = g_strdup (buffer);
+}
+#elif defined(__APPLE__) && !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_EMBEDDED
+static void
+find_executable_path (void)
+{
+  int ret;
+  pid_t pid;
+  char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
+
+  pid = getpid ();
+  ret = proc_pidpath (pid, pathbuf, sizeof (pathbuf));
+  if (ret > 0)
+    _gst_executable_path = g_strdup (pathbuf);
+}
+#else
+static void
+find_executable_path (void)
+{
+  GST_FIXME ("Couldn't look up executable path, add support for this platform");
+}
+#endif
+
+/**
+ * gst_get_main_executable_path:
+ *
+ * This helper is mostly helpful for plugins that need to
+ * inspect the folder of the main executable to determine
+ * their set of features.
+ *
+ * When a plugin is initialized from the gst-plugin-scanner
+ * external process, the returned path will be the same as from the
+ * parent process.
+ *
+ * Returns: (transfer none) (nullable): The path of the executable that
+ *   initialized GStreamer, or %NULL if it could not be determined.
+ *
+ * Since: 1.14
+ */
+const gchar *
+gst_get_main_executable_path (void)
+{
+  return _gst_executable_path;
+}
+
 /**
  * gst_init_check:
  * @argc: (inout) (allow-none): pointer to application's argc
@@ -381,11 +454,9 @@ gst_init_check (int *argc, char **argv[], GError ** err)
  * <link linkend="gst-running">Running GStreamer Applications</link>
  * for how to disable automatic registry updates.
  *
- * <note><para>
- * This function will terminate your program if it was unable to initialize
- * GStreamer for some reason.  If you want your program to fall back,
- * use gst_init_check() instead.
- * </para></note>
+ * > This function will terminate your program if it was unable to initialize
+ * > GStreamer for some reason.  If you want your program to fall back,
+ * > use gst_init_check() instead.
  *
  * WARNING: This function does not work in the same way as corresponding
  * functions in other glib-style libraries, such as gtk_init\(\). In
@@ -421,7 +492,8 @@ gst_is_initialized (void)
   return gst_initialized;
 }
 
-#ifndef GST_DISABLE_REGISTRY
+#ifndef GST_DISABLE_OPTION_PARSING
+#  ifndef GST_DISABLE_REGISTRY
 static void
 add_path_func (gpointer data, gpointer user_data)
 {
@@ -429,6 +501,7 @@ add_path_func (gpointer data, gpointer user_data)
   _priv_gst_plugin_paths =
       g_list_append (_priv_gst_plugin_paths, g_strdup (data));
 }
+#  endif
 #endif
 
 #ifndef GST_DISABLE_OPTION_PARSING
@@ -478,6 +551,8 @@ init_pre (GOptionContext * context, GOptionGroup * group, gpointer data,
     return TRUE;
   }
 
+  find_executable_path ();
+
   _priv_gst_start_time = gst_util_get_timestamp ();
 
 #ifndef GST_DISABLE_GST_DEBUG
@@ -558,7 +633,7 @@ gst_register_core_elements (GstPlugin * plugin)
 
 /*
  * this bit handles:
- * - initalization of threads if we use them
+ * - initialization of threads if we use them
  * - log handler
  * - initial output
  * - initializes gst_format
@@ -690,6 +765,8 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
   g_type_class_ref (gst_allocator_flags_get_type ());
   g_type_class_ref (gst_stream_flags_get_type ());
   g_type_class_ref (gst_stream_type_get_type ());
+  g_type_class_ref (gst_stack_trace_flags_get_type ());
+  g_type_class_ref (gst_promise_result_get_type ());
 
   _priv_gst_event_initialize ();
   _priv_gst_buffer_initialize ();
@@ -739,7 +816,8 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
   return TRUE;
 }
 
-#ifndef GST_DISABLE_GST_DEBUG
+#ifndef GST_DISABLE_OPTION_PARSING
+#  ifndef GST_DISABLE_GST_DEBUG
 static gboolean
 select_all (GstPlugin * plugin, gpointer user_data)
 {
@@ -861,7 +939,8 @@ gst_debug_help (void)
   g_slist_free (list);
   g_print ("\n");
 }
-#endif
+#  endif /* GST_DISABLE_OPTION_PARSING */
+#endif /* GST_DISABLE_GST_DEBUG */
 
 #ifndef GST_DISABLE_OPTION_PARSING
 static gboolean
@@ -990,7 +1069,7 @@ parse_goption_arg (const gchar * opt,
  * This function is therefore mostly used by testsuites and other memory
  * profiling tools.
  *
- * After this call GStreamer (including this method) should not be used anymore. 
+ * After this call GStreamer (including this method) should not be used anymore.
  */
 void
 gst_deinit (void)
@@ -998,6 +1077,9 @@ gst_deinit (void)
   GstBinClass *bin_class;
   GstClock *clock;
 
+  if (!gst_initialized)
+    return;
+
   GST_INFO ("deinitializing GStreamer");
 
   if (gst_deinitialized) {
@@ -1005,8 +1087,8 @@ gst_deinit (void)
     return;
   }
   g_thread_pool_set_max_unused_threads (0);
-  bin_class = GST_BIN_CLASS (g_type_class_peek (gst_bin_get_type ()));
-  if (bin_class->pool != NULL) {
+  bin_class = (GstBinClass *) g_type_class_peek (gst_bin_get_type ());
+  if (bin_class && bin_class->pool != NULL) {
     g_thread_pool_free (bin_class->pool, FALSE, TRUE);
     bin_class->pool = NULL;
   }
@@ -1022,6 +1104,11 @@ gst_deinit (void)
   _priv_gst_plugin_paths = NULL;
 #endif
 
+  if (_gst_executable_path) {
+    g_free (_gst_executable_path);
+    _gst_executable_path = NULL;
+  }
+
   clock = gst_system_clock_obtain ();
   gst_object_unref (clock);
   gst_object_unref (clock);
@@ -1038,6 +1125,7 @@ gst_deinit (void)
 
   _priv_gst_caps_features_cleanup ();
   _priv_gst_caps_cleanup ();
+  _priv_gst_debug_cleanup ();
 
   g_type_class_unref (g_type_class_peek (gst_object_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_pad_get_type ()));
@@ -1137,6 +1225,8 @@ gst_deinit (void)
   g_type_class_unref (g_type_class_peek (gst_allocator_flags_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_stream_flags_get_type ()));
   g_type_class_unref (g_type_class_peek (gst_debug_color_mode_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_stack_trace_flags_get_type ()));
+  g_type_class_unref (g_type_class_peek (gst_promise_result_get_type ()));
 
   gst_deinitialized = TRUE;
   GST_INFO ("deinitialized GStreamer");