mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-25 11:11:08 +00:00
9500bd2128
Original commit message from CVS: Code cleanup, make it adhere to the Gnome/Gtk+ code formatting, which is quite clean and more readable. Renamed parseavi to avidecoder Implemented seeking/time display/pause/play/stop/clean exit to gstmediaplay Added an element flag to indicate that it cannot deal with noncontigous buffers. If such an element is found in the pipeline, seeking is disabled for the complete stream (avidecoder cannot deal with seeking until we convert it to a loop based element with pull_region to fetch the indeces etc...)
572 lines
15 KiB
C
572 lines
15 KiB
C
/* Gnome-Streamer
|
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
|
*
|
|
* 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 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.
|
|
*/
|
|
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <dirent.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
|
|
#include <gst/gstplugin.h>
|
|
|
|
#include "config.h"
|
|
|
|
#undef PLUGINS_USE_SRCDIR
|
|
|
|
/* list of loaded modules and its sequence number */
|
|
GList *_gst_modules;
|
|
gint _gst_modules_seqno;
|
|
/* global list of plugins and its sequence number */
|
|
GList *_gst_plugins;
|
|
gint _gst_plugins_seqno;
|
|
/* list of paths to check for plugins */
|
|
GList *_gst_plugin_paths;
|
|
|
|
GList *_gst_libraries;
|
|
gint _gst_libraries_seqno;
|
|
|
|
/* whether or not to spew library load issues */
|
|
gboolean _gst_plugin_spew = FALSE;
|
|
|
|
|
|
void _gst_plugin_initialize() {
|
|
xmlDocPtr doc;
|
|
_gst_modules = NULL;
|
|
_gst_modules_seqno = 0;
|
|
_gst_plugins = NULL;
|
|
_gst_plugins_seqno = 0;
|
|
_gst_plugin_paths = NULL;
|
|
_gst_libraries = NULL;
|
|
_gst_libraries_seqno = 0;
|
|
|
|
/* add the main (installed) library path */
|
|
_gst_plugin_paths = g_list_append(_gst_plugin_paths,PLUGINS_DIR);
|
|
|
|
/* if this is set, we add build-directory paths to the list */
|
|
#ifdef PLUGINS_USE_SRCDIR
|
|
/* the catch-all plugins directory */
|
|
_gst_plugin_paths = g_list_append(_gst_plugin_paths,
|
|
PLUGINS_SRCDIR "/plugins");
|
|
/* the libreary directory */
|
|
_gst_plugin_paths = g_list_append(_gst_plugin_paths,
|
|
PLUGINS_SRCDIR "/libs");
|
|
/* location libgstelements.so */
|
|
_gst_plugin_paths = g_list_append(_gst_plugin_paths,
|
|
PLUGINS_SRCDIR "/gst/elements");
|
|
_gst_plugin_paths = g_list_append(_gst_plugin_paths,
|
|
PLUGINS_SRCDIR "/gst/types");
|
|
#endif /* PLUGINS_USE_SRCDIR */
|
|
|
|
doc = xmlParseFile("/etc/gstreamer/reg.xml");
|
|
|
|
if (!doc || strcmp(doc->root->name, "GST-PluginRegistry")) {
|
|
g_print("gstplugin: registry needs rebuild\n");
|
|
gst_plugin_load_all();
|
|
return;
|
|
}
|
|
gst_plugin_load_thyself(doc->root);
|
|
}
|
|
|
|
static gboolean gst_plugin_load_recurse(gchar *directory,gchar *name) {
|
|
DIR *dir;
|
|
struct dirent *dirent;
|
|
gboolean loaded = FALSE;
|
|
|
|
//g_print("recursive load of '%s' in '%s'\n", name, directory);
|
|
dir = opendir(directory);
|
|
if (dir) {
|
|
while ((dirent = readdir(dir))) {
|
|
/* don't want to recurse in place or backwards */
|
|
if (strcmp(dirent->d_name,".") && strcmp(dirent->d_name,"..")) {
|
|
loaded = gst_plugin_load_recurse(g_strjoin("/",directory,dirent->d_name,
|
|
NULL),name);
|
|
if (loaded && name) return TRUE;
|
|
}
|
|
}
|
|
closedir(dir);
|
|
} else {
|
|
if (strstr(directory,".so")) {
|
|
gchar *temp;
|
|
if (name) {
|
|
if ((temp = strstr(directory,name)) &&
|
|
(!strcmp(temp,name))) {
|
|
loaded = gst_plugin_load_absolute(directory);
|
|
return loaded;
|
|
}
|
|
} else if ((temp = strstr(directory,".so")) &&
|
|
(!strcmp(temp,".so"))) {
|
|
loaded = gst_plugin_load_absolute(directory);
|
|
//return loaded;
|
|
}
|
|
}
|
|
}
|
|
return loaded;
|
|
}
|
|
|
|
/**
|
|
* gst_plugin_load_all:
|
|
*
|
|
* Load all plugins in the path.
|
|
*/
|
|
void gst_plugin_load_all() {
|
|
GList *path;
|
|
|
|
path = _gst_plugin_paths;
|
|
while (path != NULL) {
|
|
gst_plugin_load_recurse(path->data,NULL);
|
|
path = g_list_next(path);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* gst_library_load:
|
|
* @name: name of library to load
|
|
*
|
|
* Load the named library. Name should be given as
|
|
* "liblibrary.so".
|
|
*
|
|
* Returns: whether the library was loaded or not
|
|
*/
|
|
gboolean gst_library_load(gchar *name) {
|
|
gboolean res;
|
|
GList *libraries = _gst_libraries;
|
|
|
|
while (libraries) {
|
|
if (!strcmp((gchar *)libraries->data, name)) return TRUE;
|
|
|
|
libraries = g_list_next(libraries);
|
|
}
|
|
|
|
// for now this is the same
|
|
res = gst_plugin_load(name);
|
|
|
|
if (res) {
|
|
_gst_libraries = g_list_prepend(_gst_libraries, name);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* gst_plugin_load:
|
|
* @name: name of plugin to load
|
|
*
|
|
* Load the named plugin. Name should be given as
|
|
* "libplugin.so".
|
|
*
|
|
* Returns: whether the plugin was loaded or not
|
|
*/
|
|
gboolean gst_plugin_load(gchar *name) {
|
|
GList *path;
|
|
gchar *libspath;
|
|
|
|
//g_print("attempting to load plugin '%s'\n",name);
|
|
|
|
path = _gst_plugin_paths;
|
|
while (path != NULL) {
|
|
if (gst_plugin_load_absolute(g_module_build_path(path->data,name)))
|
|
return TRUE;
|
|
libspath = g_strconcat(path->data,"/.libs",NULL);
|
|
//g_print("trying to load '%s'\n",g_module_build_path(libspath,name));
|
|
if (gst_plugin_load_absolute(g_module_build_path(libspath,name))) {
|
|
g_free(libspath);
|
|
return TRUE;
|
|
}
|
|
g_free(libspath);
|
|
//g_print("trying to load '%s' from '%s'\n",name,path->data);
|
|
if (gst_plugin_load_recurse(path->data,g_module_build_path("",name))) {
|
|
return TRUE;
|
|
}
|
|
path = g_list_next(path);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* gst_plugin_load_absolute:
|
|
* @name: name of plugin to load
|
|
*
|
|
* Returns: whether or not the plugin loaded
|
|
*/
|
|
gboolean gst_plugin_load_absolute(gchar *name) {
|
|
GModule *module;
|
|
GstPluginInitFunc initfunc;
|
|
GstPlugin *plugin;
|
|
GList *plugins;
|
|
|
|
|
|
if (g_module_supported() == FALSE) {
|
|
g_print("gstplugin: wow, you built this on a platform without dynamic loading???\n");
|
|
return FALSE;
|
|
}
|
|
|
|
plugins = _gst_plugins;
|
|
|
|
while (plugins) {
|
|
plugin = (GstPlugin *)plugins->data;
|
|
|
|
if (!strcmp(plugin->filename, name) && plugin->loaded) {
|
|
_gst_plugins = g_list_append(_gst_plugins,plugin);
|
|
return TRUE;
|
|
}
|
|
plugins = g_list_next(plugins);
|
|
}
|
|
//g_print("trying to absolute load '%s\n",name);
|
|
|
|
module = g_module_open(name,G_MODULE_BIND_LAZY);
|
|
if (module != NULL) {
|
|
if (g_module_symbol(module,"plugin_init",(gpointer *)&initfunc)) {
|
|
if ((plugin = (initfunc)(module))) {
|
|
GList *factories;
|
|
g_print("gstplugin: plugin %s loaded\n", plugin->name);
|
|
plugin->filename = g_strdup(name);
|
|
plugin->loaded = TRUE;
|
|
_gst_modules = g_list_append(_gst_modules,module);
|
|
_gst_modules_seqno++;
|
|
_gst_plugins = g_list_append(_gst_plugins,plugin);
|
|
_gst_plugins_seqno++;
|
|
factories = plugin->elements;
|
|
while (factories) {
|
|
gst_elementfactory_register((GstElementFactory*)(factories->data));
|
|
factories = g_list_next(factories);
|
|
}
|
|
return TRUE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
} else if (_gst_plugin_spew) {
|
|
// if (strstr(g_module_error(),"No such") == NULL)
|
|
gst_info("error loading plugin: %s, reason: %s\n", name, g_module_error());
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* gst_plugin_new:
|
|
* @name: name of new plugin
|
|
*
|
|
* Create a new plugin with given name.
|
|
*
|
|
* Returns: new plugin
|
|
*/
|
|
GstPlugin *gst_plugin_new(gchar *name) {
|
|
GstPlugin *plugin = (GstPlugin *)g_malloc(sizeof(GstPlugin));
|
|
|
|
plugin->name = g_strdup(name);
|
|
plugin->longname = NULL;
|
|
plugin->types = NULL;
|
|
plugin->elements = NULL;
|
|
plugin->loaded = FALSE;
|
|
|
|
return plugin;
|
|
}
|
|
|
|
/**
|
|
* gst_plugin_set_longname:
|
|
* @plugin: plugin to set long name of
|
|
* @longname: new long name
|
|
*
|
|
* Sets the long name (should be descriptive) of the plugin.
|
|
*/
|
|
void gst_plugin_set_longname(GstPlugin *plugin,gchar *longname) {
|
|
g_return_if_fail(plugin != NULL);
|
|
|
|
if (plugin->longname) g_free(plugin->longname);
|
|
plugin->longname = g_strdup(longname);
|
|
}
|
|
|
|
/**
|
|
* gst_plugin_find:
|
|
* @name: name of plugin to find
|
|
*
|
|
* Search the list of registered plugins for one of the given name
|
|
*
|
|
* Returns: pointer to the #GstPlugin if found, NULL otherwise
|
|
*/
|
|
GstPlugin *gst_plugin_find(const gchar *name) {
|
|
GList *plugins = _gst_plugins;
|
|
|
|
g_return_val_if_fail(name != NULL, NULL);
|
|
|
|
while (plugins) {
|
|
GstPlugin *plugin = (GstPlugin *)plugins->data;
|
|
// g_print("plugin name is '%s'\n",plugin->name);
|
|
if (plugin->name) {
|
|
if (!strcmp(plugin->name,name)) {
|
|
return plugin;
|
|
}
|
|
}
|
|
plugins = g_list_next(plugins);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* gst_plugin_find_elementfactory:
|
|
* @name: name of elementfactory to find
|
|
*
|
|
* Find a registered elementfactory by name.
|
|
*
|
|
* Returns: @GstElementFactory if found, NULL if not
|
|
*/
|
|
GstElementFactory *gst_plugin_find_elementfactory(gchar *name) {
|
|
GList *plugins, *factories;
|
|
GstElementFactory *factory;
|
|
|
|
g_return_val_if_fail(name != NULL, NULL);
|
|
|
|
plugins = _gst_plugins;
|
|
while (plugins) {
|
|
factories = ((GstPlugin *)(plugins->data))->elements;
|
|
while (factories) {
|
|
factory = (GstElementFactory*)(factories->data);
|
|
if (!strcmp(factory->name,name))
|
|
return (GstElementFactory*)(factory);
|
|
factories = g_list_next(factories);
|
|
}
|
|
plugins = g_list_next(plugins);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* gst_plugin_load_elementfactory:
|
|
* @name: name of elementfactory to load
|
|
*
|
|
* Load a registered elementfactory by name.
|
|
*
|
|
* Returns: @GstElementFactory if loaded, NULL if not
|
|
*/
|
|
GstElementFactory *gst_plugin_load_elementfactory(gchar *name) {
|
|
GList *plugins, *factories;
|
|
GstElementFactory *factory = NULL;
|
|
GstPlugin *plugin;
|
|
|
|
g_return_val_if_fail(name != NULL, NULL);
|
|
|
|
plugins = _gst_plugins;
|
|
while (plugins) {
|
|
plugin = (GstPlugin *)plugins->data;
|
|
factories = plugin->elements;
|
|
while (factories) {
|
|
factory = (GstElementFactory*)(factories->data);
|
|
if (!strcmp(factory->name,name)) {
|
|
if (!plugin->loaded) {
|
|
g_print("gstplugin: loading element factory %s from plugin %s\n", name, plugin->name);
|
|
_gst_plugins = g_list_remove(_gst_plugins, plugin);
|
|
if (!gst_plugin_load_absolute(plugin->filename)) {
|
|
g_print("gstplugin: error loading element factory %s from plugin %s\n", name, plugin->name);
|
|
}
|
|
factory = gst_plugin_find_elementfactory(factory->name);
|
|
}
|
|
return factory;
|
|
}
|
|
factories = g_list_next(factories);
|
|
}
|
|
plugins = g_list_next(plugins);
|
|
}
|
|
|
|
return factory;
|
|
}
|
|
|
|
/**
|
|
* gst_plugin_load_typefactory:
|
|
* @mime: name of typefactory to load
|
|
*
|
|
* Load a registered typefactory by mime type.
|
|
*/
|
|
void gst_plugin_load_typefactory(gchar *mime) {
|
|
GList *plugins, *factories;
|
|
GstTypeFactory *factory;
|
|
GstPlugin *plugin;
|
|
|
|
g_return_if_fail(mime != NULL);
|
|
|
|
plugins = _gst_plugins;
|
|
while (plugins) {
|
|
plugin = (GstPlugin *)plugins->data;
|
|
factories = plugin->types;
|
|
while (factories) {
|
|
factory = (GstTypeFactory*)(factories->data);
|
|
if (!strcmp(factory->mime,mime)) {
|
|
if (!plugin->loaded) {
|
|
g_print("gstplugin: loading type factory for \"%s\" from plugin %s\n", mime, plugin->name);
|
|
_gst_plugins = g_list_remove(_gst_plugins, plugin);
|
|
if (!gst_plugin_load_absolute(plugin->filename)) {
|
|
g_print("gstplugin: error loading type factory \"%s\" from plugin %s\n", mime, plugin->name);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
factories = g_list_next(factories);
|
|
}
|
|
plugins = g_list_next(plugins);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* gst_plugin_add_factory:
|
|
* @plugin: plugin to add factory to
|
|
* @factory: factory to add
|
|
*
|
|
* Add factory to the list of those provided by the plugin.
|
|
*/
|
|
void gst_plugin_add_factory(GstPlugin *plugin,GstElementFactory *factory) {
|
|
g_return_if_fail(plugin != NULL);
|
|
g_return_if_fail(factory != NULL);
|
|
|
|
// g_print("adding factory to plugin\n");
|
|
plugin->elements = g_list_append(plugin->elements,factory);
|
|
}
|
|
|
|
/**
|
|
* gst_plugin_add_type:
|
|
* @plugin: plugin to add type to
|
|
* @factory: the typefactory to add
|
|
*
|
|
* Add a typefactory to the list of those provided by the plugin.
|
|
*/
|
|
void gst_plugin_add_type(GstPlugin *plugin,GstTypeFactory *factory) {
|
|
g_return_if_fail(plugin != NULL);
|
|
g_return_if_fail(factory != NULL);
|
|
|
|
// g_print("adding factory to plugin\n");
|
|
plugin->types = g_list_append(plugin->types,factory);
|
|
}
|
|
|
|
/**
|
|
* gst_plugin_get_list:
|
|
*
|
|
* get the currently loaded plugins
|
|
*
|
|
* Returns; a GList of GstPlugin elements
|
|
*/
|
|
GList *gst_plugin_get_list() {
|
|
return _gst_plugins;
|
|
}
|
|
|
|
/**
|
|
* gst_plugin_save_thyself:
|
|
* @parent: the parent node to save the plugin to
|
|
*
|
|
* saves the plugin into an XML representation
|
|
*
|
|
* Returns: the new XML node
|
|
*/
|
|
xmlNodePtr gst_plugin_save_thyself(xmlNodePtr parent) {
|
|
xmlNodePtr tree, subtree;
|
|
GList *plugins = NULL, *elements = NULL, *types = NULL;
|
|
|
|
plugins = gst_plugin_get_list();
|
|
while (plugins) {
|
|
GstPlugin *plugin = (GstPlugin *)plugins->data;
|
|
tree = xmlNewChild(parent,NULL,"plugin",NULL);
|
|
xmlNewChild(tree,NULL,"name",plugin->name);
|
|
xmlNewChild(tree,NULL,"longname",plugin->longname);
|
|
xmlNewChild(tree,NULL,"filename",plugin->filename);
|
|
types = plugin->types;
|
|
while (types) {
|
|
GstTypeFactory *factory = (GstTypeFactory *)types->data;
|
|
subtree = xmlNewChild(tree,NULL,"type",NULL);
|
|
|
|
gst_typefactory_save_thyself(factory, subtree);
|
|
|
|
types = g_list_next(types);
|
|
}
|
|
elements = plugin->elements;
|
|
while (elements) {
|
|
GstElementFactory *factory = (GstElementFactory *)elements->data;
|
|
subtree = xmlNewChild(tree,NULL,"element",NULL);
|
|
|
|
gst_elementfactory_save_thyself(factory, subtree);
|
|
|
|
elements = g_list_next(elements);
|
|
}
|
|
plugins = g_list_next(plugins);
|
|
}
|
|
return parent;
|
|
}
|
|
|
|
/**
|
|
* gst_plugin_load_thyself:
|
|
* @parent: the parent node to load the plugin from
|
|
*
|
|
* load the plugin from an XML representation
|
|
*/
|
|
void gst_plugin_load_thyself(xmlNodePtr parent) {
|
|
xmlNodePtr kinderen;
|
|
gint elementcount = 0;
|
|
gint typecount = 0;
|
|
|
|
kinderen = parent->childs; // Dutch invasion :-)
|
|
while (kinderen) {
|
|
if (!strcmp(kinderen->name, "plugin")) {
|
|
xmlNodePtr field = kinderen->childs;
|
|
GstPlugin *plugin = (GstPlugin *)g_malloc(sizeof(GstPlugin));
|
|
plugin->elements = NULL;
|
|
plugin->types = NULL;
|
|
plugin->loaded = FALSE;
|
|
|
|
while (field) {
|
|
if (!strcmp(field->name, "name")) {
|
|
if (gst_plugin_find(xmlNodeGetContent(field))) {
|
|
g_free(plugin);
|
|
plugin = NULL;
|
|
break;
|
|
}
|
|
else {
|
|
plugin->name = g_strdup(xmlNodeGetContent(field));
|
|
}
|
|
}
|
|
else if (!strcmp(field->name, "longname")) {
|
|
plugin->longname = g_strdup(xmlNodeGetContent(field));
|
|
}
|
|
else if (!strcmp(field->name, "filename")) {
|
|
plugin->filename = g_strdup(xmlNodeGetContent(field));
|
|
}
|
|
else if (!strcmp(field->name, "element")) {
|
|
GstElementFactory *factory = gst_elementfactory_load_thyself(field);
|
|
plugin->elements = g_list_prepend(plugin->elements, factory);
|
|
elementcount++;
|
|
}
|
|
else if (!strcmp(field->name, "type")) {
|
|
GstTypeFactory *factory = gst_typefactory_load_thyself(field);
|
|
gst_type_register(factory);
|
|
plugin->types = g_list_prepend(plugin->types, factory);
|
|
typecount++;
|
|
}
|
|
|
|
field = field->next;
|
|
}
|
|
|
|
if (plugin) {
|
|
_gst_plugins = g_list_prepend(_gst_plugins, plugin);
|
|
}
|
|
}
|
|
|
|
kinderen = kinderen->next;
|
|
}
|
|
g_print("gstplugin: added %d registered factories and %d types\n", elementcount, typecount);
|
|
}
|
|
|