mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 17:50:36 +00:00
343 lines
8.4 KiB
C
343 lines
8.4 KiB
C
/* GStreamer
|
|
*
|
|
* Copyright (C) 2013 Collabora Ltd.
|
|
* Author: Thiago Sousa Santos <thiago.sousa.santos@collabora.com>
|
|
*
|
|
* validate.c - Validate generic functions
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
/**
|
|
* SECTION:validate
|
|
* @short_description: Initialize GstValidate
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif /* HAVE_CONFIG_H */
|
|
|
|
#include <string.h>
|
|
/* For g_stat () */
|
|
#include <glib/gstdio.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "validate.h"
|
|
#include "gst-validate-utils.h"
|
|
#include "gst-validate-internal.h"
|
|
|
|
#ifdef G_OS_WIN32
|
|
#define WIN32_LEAN_AND_MEAN /* prevents from including too many things */
|
|
#include <windows.h> /* GetStdHandle, windows console */
|
|
HMODULE _priv_gstvalidate_dll_handle = NULL;
|
|
#endif /* G_OS_WIN32 */
|
|
|
|
GST_DEBUG_CATEGORY (gstvalidate_debug);
|
|
|
|
static GMutex _gst_validate_registry_mutex;
|
|
static GstRegistry *_gst_validate_registry_default = NULL;
|
|
|
|
static GList *core_config = NULL;
|
|
static gboolean validate_initialized = FALSE;
|
|
GstClockTime _priv_start_time;
|
|
|
|
#ifdef G_OS_WIN32
|
|
BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
|
|
BOOL WINAPI
|
|
DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|
{
|
|
if (fdwReason == DLL_PROCESS_ATTACH)
|
|
_priv_gstvalidate_dll_handle = (HMODULE) hinstDLL;
|
|
|
|
return TRUE;
|
|
}
|
|
#endif /* G_OS_WIN32 */
|
|
|
|
static GstRegistry *
|
|
gst_validate_registry_get (void)
|
|
{
|
|
GstRegistry *registry;
|
|
|
|
g_mutex_lock (&_gst_validate_registry_mutex);
|
|
if (G_UNLIKELY (!_gst_validate_registry_default)) {
|
|
_gst_validate_registry_default = g_object_new (GST_TYPE_REGISTRY, NULL);
|
|
gst_object_ref_sink (GST_OBJECT_CAST (_gst_validate_registry_default));
|
|
}
|
|
registry = _gst_validate_registry_default;
|
|
g_mutex_unlock (&_gst_validate_registry_mutex);
|
|
|
|
return registry;
|
|
}
|
|
|
|
#define GST_VALIDATE_PLUGIN_CONFIG "gst-validate-plugin-config"
|
|
|
|
static void
|
|
_free_plugin_config (gpointer data)
|
|
{
|
|
g_list_free_full (data, (GDestroyNotify) gst_structure_free);
|
|
}
|
|
|
|
static GList *
|
|
create_config (const gchar * path, const gchar * suffix)
|
|
{
|
|
GList *structures = NULL, *tmp, *result = NULL;
|
|
|
|
if (!suffix)
|
|
return NULL;
|
|
|
|
structures = gst_validate_utils_structs_parse_from_filename (path);
|
|
|
|
for (tmp = structures; tmp; tmp = tmp->next) {
|
|
GstStructure *structure = tmp->data;
|
|
|
|
if (gst_structure_has_name (structure, suffix))
|
|
result = g_list_append (result, structure);
|
|
else
|
|
gst_structure_free (structure);
|
|
}
|
|
|
|
g_list_free (structures);
|
|
return result;
|
|
}
|
|
|
|
/* Copied from gststructure.c to avoid assertion */
|
|
static gboolean
|
|
gst_structure_validate_name (const gchar * name)
|
|
{
|
|
const gchar *s;
|
|
|
|
g_return_val_if_fail (name != NULL, FALSE);
|
|
|
|
if (G_UNLIKELY (!g_ascii_isalpha (*name))) {
|
|
GST_INFO ("Invalid character '%c' at offset 0 in structure name: %s",
|
|
*name, name);
|
|
return FALSE;
|
|
}
|
|
|
|
/* FIXME: test name string more */
|
|
s = &name[1];
|
|
while (*s && (g_ascii_isalnum (*s) || strchr ("/-_.:+", *s) != NULL))
|
|
s++;
|
|
if (*s == ',')
|
|
return TRUE;
|
|
|
|
if (G_UNLIKELY (*s != '\0')) {
|
|
GST_INFO ("Invalid character '%c' at offset %" G_GUINTPTR_FORMAT " in"
|
|
" structure name: %s", *s, ((guintptr) s - (guintptr) name), name);
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* gst_validate_plugin_get_config:
|
|
* @plugin, a #GstPlugin, or #NULL
|
|
*
|
|
* Return the configuration specific to @plugin, or the "core" one if @plugin
|
|
* is #NULL
|
|
*
|
|
* Returns: (transfer none) (element-type GstStructure): a list of #GstStructure
|
|
*/
|
|
GList *
|
|
gst_validate_plugin_get_config (GstPlugin * plugin)
|
|
{
|
|
GList *plugin_conf = NULL;
|
|
const gchar *suffix;
|
|
const gchar *config;
|
|
GStrv tmp;
|
|
guint i;
|
|
|
|
if (plugin) {
|
|
if ((plugin_conf =
|
|
g_object_get_data (G_OBJECT (plugin), GST_VALIDATE_PLUGIN_CONFIG)))
|
|
return plugin_conf;
|
|
|
|
suffix = gst_plugin_get_name (plugin);
|
|
} else {
|
|
if (core_config)
|
|
return core_config;
|
|
|
|
suffix = "core";
|
|
}
|
|
|
|
config = g_getenv ("GST_VALIDATE_CONFIG");
|
|
if (!config)
|
|
return NULL;
|
|
|
|
tmp = g_strsplit (config, G_SEARCHPATH_SEPARATOR_S, -1);
|
|
for (i = 0; tmp[i] != NULL; i++) {
|
|
GList *l;
|
|
|
|
l = create_config (tmp[i], suffix);
|
|
if (l)
|
|
plugin_conf = g_list_concat (plugin_conf, l);
|
|
}
|
|
g_strfreev (tmp);
|
|
|
|
if (!plugin_conf) {
|
|
GstCaps *confs = NULL;
|
|
|
|
if (gst_structure_validate_name (config))
|
|
confs = gst_caps_from_string (config);
|
|
|
|
if (confs) {
|
|
gint i;
|
|
|
|
for (i = 0; i < gst_caps_get_size (confs); i++) {
|
|
GstStructure *structure = gst_caps_get_structure (confs, i);
|
|
|
|
if (gst_structure_has_name (structure, suffix))
|
|
plugin_conf =
|
|
g_list_append (plugin_conf, gst_structure_copy (structure));
|
|
}
|
|
|
|
gst_caps_unref (confs);
|
|
}
|
|
}
|
|
|
|
if (plugin)
|
|
g_object_set_data_full (G_OBJECT (plugin), GST_VALIDATE_PLUGIN_CONFIG,
|
|
plugin_conf, _free_plugin_config);
|
|
else
|
|
core_config = plugin_conf;
|
|
|
|
return plugin_conf;
|
|
}
|
|
|
|
static void
|
|
gst_validate_init_plugins (void)
|
|
{
|
|
GstRegistry *registry;
|
|
const gchar *plugin_path;
|
|
|
|
gst_registry_fork_set_enabled (FALSE);
|
|
registry = gst_validate_registry_get ();
|
|
|
|
plugin_path = g_getenv ("GST_VALIDATE_PLUGIN_PATH");
|
|
if (plugin_path) {
|
|
char **list;
|
|
int i;
|
|
|
|
GST_DEBUG ("GST_VALIDATE_PLUGIN_PATH set to %s", plugin_path);
|
|
list = g_strsplit (plugin_path, G_SEARCHPATH_SEPARATOR_S, 0);
|
|
for (i = 0; list[i]; i++) {
|
|
gst_registry_scan_path (registry, list[i]);
|
|
}
|
|
g_strfreev (list);
|
|
} else {
|
|
GST_DEBUG ("GST_VALIDATE_PLUGIN_PATH not set");
|
|
}
|
|
|
|
if (plugin_path == NULL) {
|
|
char *home_plugins;
|
|
|
|
/* plugins in the user's home directory take precedence over
|
|
* system-installed ones */
|
|
home_plugins = g_build_filename (g_get_user_data_dir (),
|
|
"gstreamer-" GST_API_VERSION, "plugins", NULL);
|
|
|
|
GST_DEBUG ("scanning home plugins %s", home_plugins);
|
|
gst_registry_scan_path (registry, home_plugins);
|
|
g_free (home_plugins);
|
|
|
|
/* add the main (installed) library path */
|
|
|
|
#ifdef G_OS_WIN32
|
|
{
|
|
char *base_dir;
|
|
char *dir;
|
|
|
|
base_dir =
|
|
g_win32_get_package_installation_directory_of_module
|
|
(_priv_gstvalidate_dll_handle);
|
|
|
|
dir = g_build_filename (base_dir,
|
|
"lib", "gstreamer-" GST_API_VERSION, "validate", NULL);
|
|
|
|
GST_DEBUG ("scanning DLL dir %s", dir);
|
|
|
|
gst_registry_scan_path (registry, dir);
|
|
|
|
g_free (dir);
|
|
g_free (base_dir);
|
|
}
|
|
#else
|
|
gst_registry_scan_path (registry, VALIDATEPLUGINDIR);
|
|
#endif
|
|
}
|
|
gst_registry_fork_set_enabled (TRUE);
|
|
}
|
|
|
|
/**
|
|
* gst_validate_init:
|
|
*
|
|
* Initializes GstValidate. Call this before any usage of GstValidate.
|
|
* You should take care of initializing GStreamer before calling this
|
|
* function.
|
|
*/
|
|
void
|
|
gst_validate_init (void)
|
|
{
|
|
if (validate_initialized) {
|
|
return;
|
|
}
|
|
|
|
GST_DEBUG_CATEGORY_INIT (gstvalidate_debug, "validate", 0,
|
|
"Validation library");
|
|
|
|
_priv_start_time = gst_util_get_timestamp ();
|
|
|
|
/* init the report system (can be called multiple times) */
|
|
gst_validate_report_init ();
|
|
|
|
/* Init the scenario system */
|
|
init_scenarios ();
|
|
|
|
/* Ensure we load overrides before any use of a monitor */
|
|
gst_validate_override_registry_preload ();
|
|
|
|
validate_initialized = TRUE;
|
|
|
|
gst_validate_init_plugins ();
|
|
gst_validate_init_runner ();
|
|
}
|
|
|
|
void
|
|
gst_validate_deinit (void)
|
|
{
|
|
g_mutex_lock (&_gst_validate_registry_mutex);
|
|
_free_plugin_config (core_config);
|
|
gst_validate_deinit_runner ();
|
|
|
|
gst_validate_scenario_deinit ();
|
|
|
|
g_clear_object (&_gst_validate_registry_default);
|
|
|
|
_priv_validate_override_registry_deinit ();
|
|
core_config = NULL;
|
|
validate_initialized = FALSE;
|
|
gst_validate_report_deinit ();
|
|
|
|
g_mutex_unlock (&_gst_validate_registry_mutex);
|
|
g_mutex_clear (&_gst_validate_registry_mutex);
|
|
}
|
|
|
|
gboolean
|
|
gst_validate_is_initialized (void)
|
|
{
|
|
return validate_initialized;
|
|
}
|