mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-09-27 14:31:01 +00:00
Implemented the plugable autopluggers.
Original commit message from CVS: Implemented the plugable autopluggers. - one can aad an autoplugger to a plugin with gst_plugin_add_autoplugger - the autopluggers can be queried using _get_list - save/load autoplugger descriptions in the XML registry - load the autoplugger only when needed - a signal can be attached to the autoplugger to be notified of new objects. - improved the media player to use the new autoplugger - updated gstreamer-inspect for the autoplugger and types added EOS to the disksrc fixed two bugs in properties loading (min/max, comment tags)
This commit is contained in:
parent
5a52fd4009
commit
fe586de094
20 changed files with 612 additions and 702 deletions
|
@ -656,6 +656,7 @@ gst/Makefile
|
|||
gst/types/Makefile
|
||||
gst/meta/Makefile
|
||||
gst/elements/Makefile
|
||||
gst/autoplug/Makefile
|
||||
libs/Makefile
|
||||
libs/riff/Makefile
|
||||
libs/colorspace/Makefile
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# cheap trick to build . first...
|
||||
SUBDIRS = . types meta elements
|
||||
SUBDIRS = . types meta elements autoplug
|
||||
|
||||
lib_LTLIBRARIES = libgst.la
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
|
||||
GstElementDetails gst_disksrc_details = {
|
||||
"hronous Disk Source",
|
||||
"asynchronous Disk Source",
|
||||
"Source/File",
|
||||
"Read from arbitrary point in a file",
|
||||
VERSION,
|
||||
|
|
|
@ -24,570 +24,248 @@
|
|||
#include "gst_private.h"
|
||||
|
||||
#include "gstautoplug.h"
|
||||
#include "gstbin.h"
|
||||
#include "gstplugin.h"
|
||||
|
||||
GList* _gst_autoplugfactories;
|
||||
|
||||
enum {
|
||||
NEW_OBJECT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
ARG_0,
|
||||
/* FILL ME */
|
||||
};
|
||||
|
||||
static void gst_autoplug_class_init (GstAutoplugClass *klass);
|
||||
static void gst_autoplug_init (GstAutoplug *autoplug);
|
||||
|
||||
static GList* gst_autoplug_func (gpointer src, gpointer sink,
|
||||
GstAutoplugListFunction list_function,
|
||||
GstAutoplugCostFunction cost_function,
|
||||
gpointer data);
|
||||
|
||||
struct _gst_autoplug_node
|
||||
{
|
||||
gpointer iNode;
|
||||
gpointer iPrev;
|
||||
gint iDist;
|
||||
};
|
||||
|
||||
typedef struct _gst_autoplug_node gst_autoplug_node;
|
||||
|
||||
static GstObjectClass *parent_class = NULL;
|
||||
static guint gst_autoplug_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
GtkType gst_autoplug_get_type(void) {
|
||||
GtkType gst_autoplug_get_type(void)
|
||||
{
|
||||
static GtkType autoplug_type = 0;
|
||||
|
||||
if (!autoplug_type) {
|
||||
static const GtkTypeInfo autoplug_info = {
|
||||
"GstAutoplug",
|
||||
sizeof(GstElement),
|
||||
sizeof(GstElementClass),
|
||||
sizeof(GstAutoplug),
|
||||
sizeof(GstAutoplugClass),
|
||||
(GtkClassInitFunc)gst_autoplug_class_init,
|
||||
(GtkObjectInitFunc)gst_autoplug_init,
|
||||
(GtkArgSetFunc)NULL,
|
||||
(GtkArgGetFunc)NULL,
|
||||
(GtkClassInitFunc)NULL,
|
||||
};
|
||||
autoplug_type = gtk_type_unique(GST_TYPE_AUTOPLUG,&autoplug_info);
|
||||
autoplug_type = gtk_type_unique (GTK_TYPE_OBJECT, &autoplug_info);
|
||||
}
|
||||
return autoplug_type;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_autoplug_class_init(GstAutoplugClass *klass) {
|
||||
parent_class = gtk_type_class(GST_TYPE_OBJECT);
|
||||
}
|
||||
|
||||
static void gst_autoplug_init(GstAutoplug *autoplug) {
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest)
|
||||
gst_autoplug_class_init(GstAutoplugClass *klass)
|
||||
{
|
||||
GList *srctemps, *desttemps;
|
||||
GtkObjectClass *gtkobject_class;
|
||||
|
||||
srctemps = src->padtemplates;
|
||||
gtkobject_class = (GtkObjectClass*) klass;
|
||||
|
||||
while (srctemps) {
|
||||
GstPadTemplate *srctemp = (GstPadTemplate *)srctemps->data;
|
||||
parent_class = gtk_type_class(GTK_TYPE_OBJECT);
|
||||
|
||||
desttemps = dest->padtemplates;
|
||||
gst_autoplug_signals[NEW_OBJECT] =
|
||||
gtk_signal_new ("new_object", GTK_RUN_LAST, gtkobject_class->type,
|
||||
GTK_SIGNAL_OFFSET (GstAutoplugClass, new_object),
|
||||
gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1,
|
||||
GST_TYPE_OBJECT);
|
||||
|
||||
while (desttemps) {
|
||||
GstPadTemplate *desttemp = (GstPadTemplate *)desttemps->data;
|
||||
|
||||
if (srctemp->direction == GST_PAD_SRC &&
|
||||
desttemp->direction == GST_PAD_SINK) {
|
||||
if (gst_caps_list_check_compatibility (srctemp->caps, desttemp->caps)) {
|
||||
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,
|
||||
"factory \"%s\" can connect with factory \"%s\"", src->name, dest->name);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
desttemps = g_list_next (desttemps);
|
||||
}
|
||||
srctemps = g_list_next (srctemps);
|
||||
}
|
||||
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,
|
||||
"factory \"%s\" cannot connect with factory \"%s\"", src->name, dest->name);
|
||||
return FALSE;
|
||||
gtk_object_class_add_signals (gtkobject_class, gst_autoplug_signals, LAST_SIGNAL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_autoplug_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink)
|
||||
static void gst_autoplug_init(GstAutoplug *autoplug)
|
||||
{
|
||||
GList *sinkpads;
|
||||
gboolean connected = FALSE;
|
||||
|
||||
GST_DEBUG (0,"gstpipeline: autoplug pad connect function for \"%s\" to \"%s\"\n",
|
||||
GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink));
|
||||
|
||||
sinkpads = gst_element_get_pad_list(sink);
|
||||
while (sinkpads) {
|
||||
GstPad *sinkpad = (GstPad *)sinkpads->data;
|
||||
|
||||
// if we have a match, connect the pads
|
||||
if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK &&
|
||||
!GST_PAD_CONNECTED(sinkpad))
|
||||
{
|
||||
if (gst_caps_list_check_compatibility (gst_pad_get_caps_list(pad), gst_pad_get_caps_list(sinkpad))) {
|
||||
gst_pad_connect(pad, sinkpad);
|
||||
GST_DEBUG (0,"gstpipeline: autoconnect pad \"%s\" in element %s <-> ", GST_PAD_NAME (pad),
|
||||
GST_ELEMENT_NAME(src));
|
||||
GST_DEBUG (0,"pad \"%s\" in element %s\n", GST_PAD_NAME (sinkpad),
|
||||
GST_ELEMENT_NAME(sink));
|
||||
connected = TRUE;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
GST_DEBUG (0,"pads incompatible %s, %s\n", GST_PAD_NAME (pad), GST_PAD_NAME (sinkpad));
|
||||
}
|
||||
}
|
||||
sinkpads = g_list_next(sinkpads);
|
||||
}
|
||||
|
||||
if (!connected) {
|
||||
GST_DEBUG (0,"gstpipeline: no path to sinks for type\n");
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_autoplug_pads_autoplug (GstElement *src, GstElement *sink)
|
||||
void
|
||||
_gst_autoplug_initialize (void)
|
||||
{
|
||||
GList *srcpads;
|
||||
gboolean connected = FALSE;
|
||||
|
||||
srcpads = gst_element_get_pad_list(src);
|
||||
|
||||
while (srcpads && !connected) {
|
||||
GstPad *srcpad = (GstPad *)srcpads->data;
|
||||
|
||||
if (gst_pad_get_direction(srcpad) == GST_PAD_SRC)
|
||||
connected = gst_autoplug_pads_autoplug_func (src, srcpad, sink);
|
||||
|
||||
srcpads = g_list_next(srcpads);
|
||||
}
|
||||
|
||||
if (!connected) {
|
||||
GST_DEBUG (0,"gstpipeline: delaying pad connections for \"%s\" to \"%s\"\n",
|
||||
GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink));
|
||||
gtk_signal_connect(GTK_OBJECT(src),"new_pad",
|
||||
GTK_SIGNAL_FUNC(gst_autoplug_pads_autoplug_func), sink);
|
||||
}
|
||||
_gst_autoplugfactories = NULL;
|
||||
}
|
||||
|
||||
static GList*
|
||||
gst_autoplug_elementfactory_get_list (gpointer data)
|
||||
void
|
||||
gst_autoplug_signal_new_object (GstAutoplug *autoplug, GstObject *object)
|
||||
{
|
||||
return gst_elementfactory_get_list ();
|
||||
gtk_signal_emit (GTK_OBJECT (autoplug), gst_autoplug_signals[NEW_OBJECT], object);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
GList *src;
|
||||
GList *sink;
|
||||
} caps_struct;
|
||||
|
||||
#define IS_CAPS(cap) (((cap) == caps->src) || (cap) == caps->sink)
|
||||
|
||||
static guint
|
||||
gst_autoplug_caps_find_cost (gpointer src, gpointer dest, gpointer data)
|
||||
GstElement*
|
||||
gst_autoplug_caps_list (GstAutoplug *autoplug, GList *srcpad, GList *sinkpad, ...)
|
||||
{
|
||||
caps_struct *caps = (caps_struct *)data;
|
||||
gboolean res;
|
||||
GstAutoplugClass *oclass;
|
||||
GstElement *element = NULL;
|
||||
va_list args;
|
||||
|
||||
if (IS_CAPS (src) && IS_CAPS (dest)) {
|
||||
res = gst_caps_list_check_compatibility ((GList *)src, (GList *)dest);
|
||||
//GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"caps %d to caps %d %d", ((GstCaps *)src)->id, ((GstCaps *)dest)->id, res);
|
||||
}
|
||||
else if (IS_CAPS (src)) {
|
||||
res = gst_elementfactory_can_sink_caps_list ((GstElementFactory *)dest, (GList *)src);
|
||||
//GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to src caps %d %d", ((GstElementFactory *)dest)->name, ((GstCaps *)src)->id, res);
|
||||
}
|
||||
else if (IS_CAPS (dest)) {
|
||||
res = gst_elementfactory_can_src_caps_list ((GstElementFactory *)src, (GList *)dest);
|
||||
//GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to sink caps %d %d", ((GstElementFactory *)src)->name, ((GstCaps *)dest)->id, res);
|
||||
}
|
||||
else {
|
||||
res = gst_autoplug_can_match ((GstElementFactory *)src, (GstElementFactory *)dest);
|
||||
}
|
||||
va_start (args, sinkpad);
|
||||
|
||||
if (res)
|
||||
return 1;
|
||||
else
|
||||
return GST_AUTOPLUG_MAX_COST;
|
||||
oclass = GST_AUTOPLUG_CLASS (GTK_OBJECT (autoplug)->klass);
|
||||
if (oclass->autoplug_caps_list)
|
||||
element = (oclass->autoplug_caps_list) (autoplug, srcpad, sinkpad, args);
|
||||
|
||||
va_end (args);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_autoplugfactory_new:
|
||||
* @name: name of autoplugfactory to create
|
||||
* @longdesc: long description of autoplugfactory to create
|
||||
* @type: the gtk type of the GstAutoplug element of this factory
|
||||
*
|
||||
* Create a new autoplugfactory with the given parameters
|
||||
*
|
||||
* Returns: a new #GstAutoplugFactory.
|
||||
*/
|
||||
GstAutoplugFactory*
|
||||
gst_autoplugfactory_new (const gchar *name, const gchar *longdesc, GtkType type)
|
||||
{
|
||||
GstAutoplugFactory *factory;
|
||||
|
||||
g_return_val_if_fail(name != NULL, NULL);
|
||||
|
||||
factory = g_new0(GstAutoplugFactory, 1);
|
||||
|
||||
factory->name = g_strdup(name);
|
||||
factory->longdesc = g_strdup (longdesc);
|
||||
factory->type = type;
|
||||
|
||||
_gst_autoplugfactories = g_list_prepend (_gst_autoplugfactories, factory);
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_autoplug_pads:
|
||||
* @srcpad: the source pad
|
||||
* @sinkpad: the sink pad
|
||||
* gst_autoplugfactory_destroy:
|
||||
* @autoplug: factory to destroy
|
||||
*
|
||||
* Perform autoplugging between the two given pads.
|
||||
*
|
||||
* Returns: a list of elementfactories that can connect
|
||||
* the two pads
|
||||
* Removes the autoplug from the global list.
|
||||
*/
|
||||
GstElement*
|
||||
gst_autoplug_caps_list (GList *srccaps, GList *sinkcaps, ...)
|
||||
void
|
||||
gst_autoplugfactory_destroy (GstAutoplugFactory *autoplug)
|
||||
{
|
||||
caps_struct caps;
|
||||
va_list args;
|
||||
GList *capslist;
|
||||
GstElement *result = NULL, *srcelement = NULL;
|
||||
GList **factories;
|
||||
GList *chains = NULL;
|
||||
GList *endcaps = NULL;
|
||||
guint numsinks = 0, i;
|
||||
gboolean have_common = FALSE;
|
||||
g_return_if_fail (autoplug != NULL);
|
||||
|
||||
va_start (args, sinkcaps);
|
||||
capslist = sinkcaps;
|
||||
_gst_autoplugfactories = g_list_remove (_gst_autoplugfactories, autoplug);
|
||||
|
||||
/*
|
||||
* We first create a list of elements that are needed
|
||||
* to convert the srcpad caps to the different sinkpad caps.
|
||||
* and add the list of elementfactories to a list (chains).
|
||||
// we don't free the struct bacause someone might have a handle to it..
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_autoplug_find:
|
||||
* @name: name of autoplugger to find
|
||||
*
|
||||
* Search for an autoplugger of the given name.
|
||||
*
|
||||
* Returns: #GstAutoplug if found, NULL otherwise
|
||||
*/
|
||||
caps.src = srccaps;
|
||||
GstAutoplugFactory*
|
||||
gst_autoplugfactory_find (const gchar *name)
|
||||
{
|
||||
GList *walk;
|
||||
GstAutoplugFactory *factory;
|
||||
|
||||
while (capslist) {
|
||||
GList *elements;
|
||||
g_return_val_if_fail(name != NULL, NULL);
|
||||
|
||||
caps.sink = capslist;
|
||||
GST_DEBUG (0,"gstautoplug: find \"%s\"\n", name);
|
||||
|
||||
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps structures");
|
||||
|
||||
elements = gst_autoplug_func (caps.src, caps.sink,
|
||||
gst_autoplug_elementfactory_get_list,
|
||||
gst_autoplug_caps_find_cost,
|
||||
&caps);
|
||||
|
||||
if (elements) {
|
||||
chains = g_list_append (chains, elements);
|
||||
endcaps = g_list_append (endcaps, capslist);
|
||||
numsinks++;
|
||||
}
|
||||
else {
|
||||
walk = _gst_autoplugfactories;
|
||||
while (walk) {
|
||||
factory = (GstAutoplugFactory *)(walk->data);
|
||||
if (!strcmp (name, factory->name))
|
||||
return factory;
|
||||
walk = g_list_next (walk);
|
||||
}
|
||||
|
||||
capslist = va_arg (args, GList *);
|
||||
}
|
||||
va_end (args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If no list could be found the pipeline cannot be autoplugged and
|
||||
* we return a NULL element
|
||||
/**
|
||||
* gst_autoplugfactory_get_list:
|
||||
*
|
||||
* Get the global list of elementfactories.
|
||||
*
|
||||
* Returns: GList of type #GstElementFactory
|
||||
*/
|
||||
if (numsinks == 0)
|
||||
GList*
|
||||
gst_autoplugfactory_get_list (void)
|
||||
{
|
||||
return _gst_autoplugfactories;
|
||||
}
|
||||
|
||||
GstAutoplug*
|
||||
gst_autoplugfactory_create (GstAutoplugFactory *factory)
|
||||
{
|
||||
GstAutoplug *new = NULL;
|
||||
|
||||
g_return_val_if_fail (factory != NULL, NULL);
|
||||
|
||||
if (factory->type == 0){
|
||||
factory = gst_plugin_load_autoplugfactory (factory->name);
|
||||
}
|
||||
g_return_val_if_fail (factory != NULL, NULL);
|
||||
g_return_val_if_fail (factory->type != 0, NULL);
|
||||
|
||||
new = GST_AUTOPLUG (gtk_type_new (factory->type));
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
GstAutoplug*
|
||||
gst_autoplugfactory_make (const gchar *name)
|
||||
{
|
||||
GstAutoplugFactory *factory;
|
||||
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
|
||||
factory = gst_autoplugfactory_find (name);
|
||||
|
||||
if (factory == NULL)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* We now have a list of lists. We will turn this into an array
|
||||
* of lists, this will make it much more easy to manipulate it
|
||||
* in the next steps.
|
||||
*/
|
||||
factories = g_new0 (GList *, numsinks);
|
||||
|
||||
for (i = 0; chains; i++) {
|
||||
GList *elements = (GList *) chains->data;
|
||||
|
||||
factories[i] = elements;
|
||||
|
||||
chains = g_list_next (chains);
|
||||
}
|
||||
//FIXME, free the list
|
||||
|
||||
result = gst_bin_new ("autoplug_bin");
|
||||
|
||||
/*
|
||||
* We now hav a list of lists that is probably like:
|
||||
*
|
||||
* !
|
||||
* A -> B -> C
|
||||
* !
|
||||
* A -> D -> E
|
||||
*
|
||||
* we now try to find the common elements (A) and add them to
|
||||
* the bin. We remove them from both lists too.
|
||||
*/
|
||||
while (factories[0]) {
|
||||
GstElementFactory *factory;
|
||||
GstElement *element;
|
||||
|
||||
// fase 3: add common elements
|
||||
factory = (GstElementFactory *) (factories[0]->data);
|
||||
|
||||
// check to other paths for matching elements (factories)
|
||||
for (i=1; i<numsinks; i++) {
|
||||
if (factory != (GstElementFactory *) (factories[i]->data)) {
|
||||
goto differ;
|
||||
}
|
||||
}
|
||||
|
||||
GST_DEBUG (0,"common factory \"%s\"\n", factory->name);
|
||||
|
||||
element = gst_elementfactory_create (factory, factory->name);
|
||||
gst_bin_add (GST_BIN(result), element);
|
||||
|
||||
if (srcelement != NULL) {
|
||||
gst_autoplug_pads_autoplug (srcelement, element);
|
||||
}
|
||||
// this is the first element, find a good ghostpad
|
||||
else {
|
||||
GList *pads;
|
||||
|
||||
pads = gst_element_get_pad_list (element);
|
||||
|
||||
while (pads) {
|
||||
GstPad *pad = GST_PAD (pads->data);
|
||||
|
||||
if (gst_caps_list_check_compatibility (srccaps, gst_pad_get_caps_list (pad))) {
|
||||
gst_element_add_ghost_pad (result, pad, "sink");
|
||||
break;
|
||||
}
|
||||
|
||||
pads = g_list_next (pads);
|
||||
}
|
||||
}
|
||||
|
||||
srcelement = element;
|
||||
|
||||
// advance the pointer in all lists
|
||||
for (i=0; i<numsinks; i++) {
|
||||
factories[i] = g_list_next (factories[i]);
|
||||
}
|
||||
|
||||
have_common = TRUE;
|
||||
}
|
||||
|
||||
differ:
|
||||
|
||||
// loop over all the sink elements
|
||||
for (i = 0; i < numsinks; i++) {
|
||||
GstElement *thesrcelement = srcelement;
|
||||
GstElement *thebin = GST_ELEMENT(result);
|
||||
gboolean use_thread;
|
||||
|
||||
use_thread = have_common;
|
||||
|
||||
while (factories[i]) {
|
||||
// fase 4: add other elements...
|
||||
GstElementFactory *factory;
|
||||
GstElement *element;
|
||||
|
||||
factory = (GstElementFactory *)(factories[i]->data);
|
||||
|
||||
GST_DEBUG (0,"factory \"%s\"\n", factory->name);
|
||||
element = gst_elementfactory_create(factory, factory->name);
|
||||
|
||||
// this element suggests the use of a thread, so we set one up...
|
||||
if (GST_ELEMENT_IS_THREAD_SUGGESTED(element) || use_thread) {
|
||||
GstElement *queue;
|
||||
GList *sinkpads;
|
||||
GstPad *srcpad, *sinkpad;
|
||||
|
||||
use_thread = FALSE;
|
||||
|
||||
GST_DEBUG (0,"sugest new thread for \"%s\" %08x\n", GST_ELEMENT_NAME (element), GST_FLAGS(element));
|
||||
|
||||
// create a new queue and add to the previous bin
|
||||
queue = gst_elementfactory_make("queue", g_strconcat("queue_", GST_ELEMENT_NAME(element), NULL));
|
||||
GST_DEBUG (0,"adding element \"%s\"\n", GST_ELEMENT_NAME (element));
|
||||
gst_bin_add(GST_BIN(thebin), queue);
|
||||
|
||||
// this will be the new bin for all following elements
|
||||
thebin = gst_elementfactory_make("thread", g_strconcat("thread_", GST_ELEMENT_NAME(element), NULL));
|
||||
|
||||
srcpad = gst_element_get_pad(queue, "src");
|
||||
|
||||
sinkpads = gst_element_get_pad_list(element);
|
||||
while (sinkpads) {
|
||||
sinkpad = (GstPad *)sinkpads->data;
|
||||
|
||||
// FIXME connect matching pads, not just the first one...
|
||||
if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK &&
|
||||
!GST_PAD_CONNECTED(sinkpad)) {
|
||||
GList *caps = gst_pad_get_caps_list (sinkpad);
|
||||
|
||||
// the queue has the type of the elements it connects
|
||||
gst_pad_set_caps_list (srcpad, caps);
|
||||
gst_pad_set_caps_list (gst_element_get_pad(queue, "sink"), caps);
|
||||
break;
|
||||
}
|
||||
sinkpads = g_list_next(sinkpads);
|
||||
}
|
||||
gst_autoplug_pads_autoplug(thesrcelement, queue);
|
||||
|
||||
GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (element));
|
||||
gst_bin_add(GST_BIN(thebin), element);
|
||||
GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (thebin));
|
||||
gst_bin_add(GST_BIN(result), thebin);
|
||||
thesrcelement = queue;
|
||||
}
|
||||
// no thread needed, easy case
|
||||
else {
|
||||
GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (element));
|
||||
gst_bin_add(GST_BIN(thebin), element);
|
||||
}
|
||||
gst_autoplug_pads_autoplug(thesrcelement, element);
|
||||
|
||||
// this element is now the new source element
|
||||
thesrcelement = element;
|
||||
|
||||
factories[i] = g_list_next(factories[i]);
|
||||
}
|
||||
/*
|
||||
* we're at the last element in the chain,
|
||||
* find a suitable pad to turn into a ghostpad
|
||||
*/
|
||||
{
|
||||
GList *endcap = (GList *)(endcaps->data);
|
||||
GList *pads = gst_element_get_pad_list (thesrcelement);
|
||||
endcaps = g_list_next (endcaps);
|
||||
|
||||
while (pads) {
|
||||
GstPad *pad = GST_PAD (pads->data);
|
||||
pads = g_list_next (pads);
|
||||
|
||||
if (gst_caps_list_check_compatibility (gst_pad_get_caps_list (pad), endcap)) {
|
||||
gst_element_add_ghost_pad (result, pad, g_strdup_printf("src_%02d", i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return gst_autoplugfactory_create (factory);;
|
||||
}
|
||||
|
||||
static gint
|
||||
find_factory (gst_autoplug_node *rgnNodes, gpointer factory)
|
||||
xmlNodePtr
|
||||
gst_autoplugfactory_save_thyself (GstAutoplugFactory *factory, xmlNodePtr parent)
|
||||
{
|
||||
gint i=0;
|
||||
g_return_val_if_fail(factory != NULL, NULL);
|
||||
|
||||
while (rgnNodes[i].iNode) {
|
||||
if (rgnNodes[i].iNode == factory) return i;
|
||||
i++;
|
||||
}
|
||||
return 0;
|
||||
xmlNewChild(parent,NULL,"name",factory->name);
|
||||
xmlNewChild(parent,NULL,"longdesc", factory->longdesc);
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
static GList*
|
||||
construct_path (gst_autoplug_node *rgnNodes, gpointer factory)
|
||||
GstAutoplugFactory*
|
||||
gst_autoplugfactory_load_thyself (xmlNodePtr parent)
|
||||
{
|
||||
GstElementFactory *current;
|
||||
GList *factories = NULL;
|
||||
GstAutoplugFactory *factory = g_new0(GstAutoplugFactory, 1);
|
||||
xmlNodePtr children = parent->xmlChildrenNode;
|
||||
|
||||
current = rgnNodes[find_factory(rgnNodes, factory)].iPrev;
|
||||
|
||||
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factories found in autoplugging (reversed order)");
|
||||
|
||||
while (current != NULL)
|
||||
{
|
||||
gpointer next = NULL;
|
||||
|
||||
next = rgnNodes[find_factory(rgnNodes, current)].iPrev;
|
||||
if (next) {
|
||||
factories = g_list_prepend (factories, current);
|
||||
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory: \"%s\"", current->name);
|
||||
while (children) {
|
||||
if (!strcmp(children->name, "name")) {
|
||||
factory->name = xmlNodeGetContent(children);
|
||||
}
|
||||
current = next;
|
||||
if (!strcmp(children->name, "longdesc")) {
|
||||
factory->longdesc = xmlNodeGetContent(children);
|
||||
}
|
||||
return factories;
|
||||
}
|
||||
|
||||
static GList*
|
||||
gst_autoplug_enqueue (GList *queue, gpointer iNode, gint iDist, gpointer iPrev)
|
||||
{
|
||||
gst_autoplug_node *node = g_malloc (sizeof (gst_autoplug_node));
|
||||
|
||||
node->iNode = iNode;
|
||||
node->iDist = iDist;
|
||||
node->iPrev = iPrev;
|
||||
|
||||
queue = g_list_append (queue, node);
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
||||
static GList*
|
||||
gst_autoplug_dequeue (GList *queue, gpointer *iNode, gint *iDist, gpointer *iPrev)
|
||||
{
|
||||
GList *head;
|
||||
gst_autoplug_node *node;
|
||||
|
||||
head = g_list_first (queue);
|
||||
|
||||
if (head) {
|
||||
node = (gst_autoplug_node *)head->data;
|
||||
*iNode = node->iNode;
|
||||
*iPrev = node->iPrev;
|
||||
*iDist = node->iDist;
|
||||
head = g_list_remove (queue, node);
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
static GList*
|
||||
gst_autoplug_func (gpointer src, gpointer sink,
|
||||
GstAutoplugListFunction list_function,
|
||||
GstAutoplugCostFunction cost_function,
|
||||
gpointer data)
|
||||
{
|
||||
gst_autoplug_node *rgnNodes;
|
||||
GList *queue = NULL;
|
||||
gpointer iNode, iPrev;
|
||||
gint iDist, i, iCost;
|
||||
|
||||
GList *elements = g_list_copy (list_function(data));
|
||||
GList *factories;
|
||||
guint num_factories;
|
||||
|
||||
elements = g_list_append (elements, sink);
|
||||
elements = g_list_append (elements, src);
|
||||
|
||||
factories = elements;
|
||||
|
||||
num_factories = g_list_length (factories);
|
||||
|
||||
rgnNodes = g_new0 (gst_autoplug_node, num_factories+1);
|
||||
|
||||
for (i=0; i< num_factories; i++) {
|
||||
gpointer fact = factories->data;
|
||||
|
||||
rgnNodes[i].iNode = fact;
|
||||
rgnNodes[i].iPrev = NULL;
|
||||
|
||||
if (fact == src) {
|
||||
rgnNodes[i].iDist = 0;
|
||||
}
|
||||
else {
|
||||
rgnNodes[i].iDist = GST_AUTOPLUG_MAX_COST;
|
||||
}
|
||||
|
||||
factories = g_list_next (factories);
|
||||
}
|
||||
rgnNodes[num_factories].iNode = NULL;
|
||||
|
||||
queue = gst_autoplug_enqueue (queue, src, 0, NULL);
|
||||
|
||||
while (g_list_length (queue) > 0) {
|
||||
GList *factories2 = elements;
|
||||
|
||||
queue = gst_autoplug_dequeue (queue, &iNode, &iDist, &iPrev);
|
||||
|
||||
for (i=0; i< num_factories; i++) {
|
||||
gpointer current = factories2->data;
|
||||
|
||||
iCost = cost_function (iNode, current, data);
|
||||
if (iCost != GST_AUTOPLUG_MAX_COST) {
|
||||
if((GST_AUTOPLUG_MAX_COST == rgnNodes[i].iDist) ||
|
||||
(rgnNodes[i].iDist > (iCost + iDist))) {
|
||||
rgnNodes[i].iDist = iDist + iCost;
|
||||
rgnNodes[i].iPrev = iNode;
|
||||
|
||||
queue = gst_autoplug_enqueue (queue, current, iDist + iCost, iNode);
|
||||
}
|
||||
}
|
||||
|
||||
factories2 = g_list_next (factories2);
|
||||
}
|
||||
}
|
||||
|
||||
return construct_path (rgnNodes, sink);
|
||||
children = children->next;
|
||||
}
|
||||
|
||||
_gst_autoplugfactories = g_list_prepend (_gst_autoplugfactories, factory);
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ extern "C" {
|
|||
#endif /* __cplusplus */
|
||||
|
||||
#define GST_TYPE_AUTOPLUG \
|
||||
(gst_object_get_type())
|
||||
(gst_autoplug_get_type())
|
||||
#define GST_AUTOPLUG(obj) \
|
||||
(GTK_CHECK_CAST((obj),GST_TYPE_AUTOPLUG,GstAutoplug))
|
||||
#define GST_AUTOPLUG_CLASS(klass) \
|
||||
|
@ -44,11 +44,6 @@ extern "C" {
|
|||
typedef struct _GstAutoplug GstAutoplug;
|
||||
typedef struct _GstAutoplugClass GstAutoplugClass;
|
||||
|
||||
#define GST_AUTOPLUG_MAX_COST 999999
|
||||
|
||||
typedef guint (*GstAutoplugCostFunction) (gpointer src, gpointer dest, gpointer data);
|
||||
typedef GList* (*GstAutoplugListFunction) (gpointer data);
|
||||
|
||||
struct _GstAutoplug {
|
||||
GtkObject object;
|
||||
};
|
||||
|
@ -57,19 +52,42 @@ struct _GstAutoplugClass {
|
|||
GtkObjectClass parent_class;
|
||||
|
||||
/* signal callbacks */
|
||||
void (*element_added) (GstAutoplug *eutoplug, GstElement *element);
|
||||
void (*new_object) (GstAutoplug *autoplug, GstObject *object);
|
||||
|
||||
/* perform the autoplugging */
|
||||
GstElement* (*autoplug_caps_list) (GstAutoplug *autoplug, GList *srcpad, GList *sinkpad, va_list args);
|
||||
};
|
||||
|
||||
typedef struct _GstAutoplugFactory GstAutoplugFactory;
|
||||
|
||||
struct _GstAutoplugFactory {
|
||||
gchar *name; /* name of element */
|
||||
gchar *name; /* name of autoplugger */
|
||||
gchar *longdesc; /* long description of the autoplugger (well, don't overdo it..) */
|
||||
GtkType type; /* unique GtkType of the autoplugger */
|
||||
};
|
||||
|
||||
GtkType gst_autoplug_get_type (void);
|
||||
|
||||
GstElement* gst_autoplug_caps_list (GList *srcpad, GList *sinkpad, ...);
|
||||
void gst_autoplug_signal_new_object (GstAutoplug *autoplug, GstObject *object);
|
||||
|
||||
GstElement* gst_autoplug_caps_list (GstAutoplug *autoplug, GList *srcpad, GList *sinkpad, ...);
|
||||
|
||||
|
||||
/*
|
||||
* creating autopluggers
|
||||
*
|
||||
*/
|
||||
GstAutoplugFactory* gst_autoplugfactory_new (const gchar *name, const gchar *longdesc, GtkType type);
|
||||
void gst_autoplugfactory_destroy (GstAutoplugFactory *factory);
|
||||
|
||||
GstAutoplugFactory* gst_autoplugfactory_find (const gchar *name);
|
||||
GList* gst_autoplugfactory_get_list (void);
|
||||
|
||||
GstAutoplug* gst_autoplugfactory_create (GstAutoplugFactory *factory);
|
||||
GstAutoplug* gst_autoplugfactory_make (const gchar *name);
|
||||
|
||||
xmlNodePtr gst_autoplugfactory_save_thyself (GstAutoplugFactory *factory, xmlNodePtr parent);
|
||||
GstAutoplugFactory* gst_autoplugfactory_load_thyself (xmlNodePtr parent);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -110,10 +110,12 @@ GstElementFactory*
|
|||
gst_elementfactory_new (const gchar *name, GtkType type,
|
||||
GstElementDetails *details)
|
||||
{
|
||||
GstElementFactory *factory = g_new0(GstElementFactory, 1);
|
||||
GstElementFactory *factory;
|
||||
|
||||
g_return_val_if_fail(name != NULL, NULL);
|
||||
|
||||
factory = g_new0(GstElementFactory, 1);
|
||||
|
||||
factory->name = g_strdup(name);
|
||||
factory->type = type;
|
||||
factory->details = details;
|
||||
|
|
|
@ -24,10 +24,6 @@
|
|||
#include "gst_private.h"
|
||||
|
||||
#include "gstpipeline.h"
|
||||
#include "gstthread.h"
|
||||
#include "gstutils.h"
|
||||
#include "gsttype.h"
|
||||
#include "gstautoplug.h"
|
||||
|
||||
|
||||
GstElementDetails gst_pipeline_details = {
|
||||
|
|
198
gst/gstplugin.c
198
gst/gstplugin.c
|
@ -80,6 +80,8 @@ _gst_plugin_initialize (void)
|
|||
PLUGINS_SRCDIR "/gst/elements");
|
||||
_gst_plugin_paths = g_list_prepend (_gst_plugin_paths,
|
||||
PLUGINS_SRCDIR "/gst/types");
|
||||
_gst_plugin_paths = g_list_prepend (_gst_plugin_paths,
|
||||
PLUGINS_SRCDIR "/gst/autoplug");
|
||||
#else /* PLUGINS_USE_SRCDIR */
|
||||
/* add the main (installed) library path */
|
||||
_gst_plugin_paths = g_list_prepend (_gst_plugin_paths, PLUGINS_DIR);
|
||||
|
@ -395,6 +397,8 @@ gst_plugin_new (const gchar *name)
|
|||
plugin->numelements = 0;
|
||||
plugin->types = NULL;
|
||||
plugin->numtypes = 0;
|
||||
plugin->autopluggers = NULL;
|
||||
plugin->numautopluggers = 0;
|
||||
plugin->loaded = TRUE;
|
||||
|
||||
return plugin;
|
||||
|
@ -529,15 +533,7 @@ gst_plugin_find (const gchar *name)
|
|||
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*
|
||||
static GstElementFactory*
|
||||
gst_plugin_find_elementfactory (const gchar *name)
|
||||
{
|
||||
GList *plugins, *factories;
|
||||
|
@ -609,6 +605,77 @@ gst_plugin_load_elementfactory (const gchar *name)
|
|||
return factory;
|
||||
}
|
||||
|
||||
static GstAutoplugFactory*
|
||||
gst_plugin_find_autoplugfactory (const gchar *name)
|
||||
{
|
||||
GList *plugins, *factories;
|
||||
GstAutoplugFactory *factory;
|
||||
|
||||
g_return_val_if_fail(name != NULL, NULL);
|
||||
|
||||
plugins = _gst_plugins;
|
||||
while (plugins) {
|
||||
factories = ((GstPlugin *)(plugins->data))->autopluggers;
|
||||
while (factories) {
|
||||
factory = (GstAutoplugFactory*)(factories->data);
|
||||
if (!strcmp(factory->name, name))
|
||||
return (GstAutoplugFactory*)(factory);
|
||||
factories = g_list_next(factories);
|
||||
}
|
||||
plugins = g_list_next(plugins);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/**
|
||||
* gst_plugin_load_autoplugfactory:
|
||||
* @name: name of autoplugfactory to load
|
||||
*
|
||||
* Load a registered autoplugfactory by name.
|
||||
*
|
||||
* Returns: @GstAutoplugFactory if loaded, NULL if not
|
||||
*/
|
||||
GstAutoplugFactory*
|
||||
gst_plugin_load_autoplugfactory (const gchar *name)
|
||||
{
|
||||
GList *plugins, *factories;
|
||||
GstAutoplugFactory *factory = NULL;
|
||||
GstPlugin *plugin;
|
||||
|
||||
g_return_val_if_fail(name != NULL, NULL);
|
||||
|
||||
plugins = _gst_plugins;
|
||||
while (plugins) {
|
||||
plugin = (GstPlugin *)plugins->data;
|
||||
factories = plugin->autopluggers;
|
||||
|
||||
while (factories) {
|
||||
factory = (GstAutoplugFactory*)(factories->data);
|
||||
|
||||
if (!strcmp(factory->name,name)) {
|
||||
if (!plugin->loaded) {
|
||||
gchar *filename = g_strdup (plugin->filename);
|
||||
gchar *pluginname = g_strdup (plugin->name);
|
||||
|
||||
GST_INFO (GST_CAT_PLUGIN_LOADING,"loaded autoplugfactory %s from plugin %s",name,plugin->name);
|
||||
gst_plugin_remove(plugin);
|
||||
if (!gst_plugin_load_absolute(filename)) {
|
||||
GST_DEBUG (0,"gstplugin: error loading autoplug factory %s from plugin %s\n", name, pluginname);
|
||||
}
|
||||
g_free (pluginname);
|
||||
g_free (filename);
|
||||
}
|
||||
factory = gst_plugin_find_autoplugfactory(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
|
||||
|
@ -696,6 +763,24 @@ gst_plugin_add_type (GstPlugin *plugin, GstTypeFactory *factory)
|
|||
gst_type_register (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_autoplugger (GstPlugin *plugin, GstAutoplugFactory *factory)
|
||||
{
|
||||
g_return_if_fail (plugin != NULL);
|
||||
g_return_if_fail (factory != NULL);
|
||||
|
||||
// g_print("adding factory to plugin\n");
|
||||
plugin->autopluggers = g_list_prepend (plugin->autopluggers, factory);
|
||||
plugin->numautopluggers++;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_plugin_get_list:
|
||||
*
|
||||
|
@ -704,7 +789,7 @@ gst_plugin_add_type (GstPlugin *plugin, GstTypeFactory *factory)
|
|||
* Returns; a GList of GstPlugin elements
|
||||
*/
|
||||
GList*
|
||||
gst_plugin_get_list(void)
|
||||
gst_plugin_get_list (void)
|
||||
{
|
||||
return _gst_plugins;
|
||||
}
|
||||
|
@ -721,34 +806,45 @@ xmlNodePtr
|
|||
gst_plugin_save_thyself (xmlNodePtr parent)
|
||||
{
|
||||
xmlNodePtr tree, subtree;
|
||||
GList *plugins = NULL, *elements = NULL, *types = NULL;
|
||||
GList *plugins = NULL, *elements = NULL, *types = NULL, *autopluggers = NULL;
|
||||
|
||||
plugins = gst_plugin_get_list();
|
||||
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);
|
||||
|
||||
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,"typefactory",NULL);
|
||||
subtree = xmlNewChild(tree, NULL, "typefactory", NULL);
|
||||
|
||||
gst_typefactory_save_thyself(factory, subtree);
|
||||
gst_typefactory_save_thyself (factory, subtree);
|
||||
|
||||
types = g_list_next(types);
|
||||
types = g_list_next (types);
|
||||
}
|
||||
elements = plugin->elements;
|
||||
while (elements) {
|
||||
GstElementFactory *factory = (GstElementFactory *)elements->data;
|
||||
subtree = xmlNewChild(tree,NULL,"elementfactory",NULL);
|
||||
subtree = xmlNewChild (tree, NULL, "elementfactory", NULL);
|
||||
|
||||
gst_elementfactory_save_thyself(factory, subtree);
|
||||
gst_elementfactory_save_thyself (factory, subtree);
|
||||
|
||||
elements = g_list_next(elements);
|
||||
elements = g_list_next (elements);
|
||||
}
|
||||
plugins = g_list_next(plugins);
|
||||
autopluggers = plugin->autopluggers;
|
||||
while (autopluggers) {
|
||||
GstAutoplugFactory *factory = (GstAutoplugFactory *)autopluggers->data;
|
||||
subtree = xmlNewChild (tree, NULL, "autoplugfactory", NULL);
|
||||
|
||||
gst_autoplugfactory_save_thyself (factory, subtree);
|
||||
|
||||
autopluggers = g_list_next (autopluggers);
|
||||
}
|
||||
plugins = g_list_next (plugins);
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
@ -764,43 +860,50 @@ gst_plugin_load_thyself (xmlNodePtr parent)
|
|||
{
|
||||
xmlNodePtr kinderen;
|
||||
gint elementcount = 0;
|
||||
gint autoplugcount = 0;
|
||||
gint typecount = 0;
|
||||
gchar *pluginname;
|
||||
|
||||
kinderen = parent->xmlChildrenNode; // Dutch invasion :-)
|
||||
while (kinderen) {
|
||||
if (!strcmp(kinderen->name, "plugin")) {
|
||||
if (!strcmp (kinderen->name, "plugin")) {
|
||||
xmlNodePtr field = kinderen->xmlChildrenNode;
|
||||
GstPlugin *plugin = g_new0 (GstPlugin, 1);
|
||||
|
||||
plugin->elements = NULL;
|
||||
plugin->types = NULL;
|
||||
plugin->loaded = FALSE;
|
||||
|
||||
while (field) {
|
||||
if (!strcmp(field->name, "name")) {
|
||||
pluginname = xmlNodeGetContent(field);
|
||||
if (gst_plugin_find(pluginname)) {
|
||||
g_free(pluginname);
|
||||
g_free(plugin);
|
||||
if (!strcmp (field->name, "name")) {
|
||||
pluginname = xmlNodeGetContent (field);
|
||||
if (gst_plugin_find (pluginname)) {
|
||||
g_free (pluginname);
|
||||
g_free (plugin);
|
||||
plugin = NULL;
|
||||
break;
|
||||
} else {
|
||||
plugin->name = pluginname;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(field->name, "longname")) {
|
||||
plugin->longname = xmlNodeGetContent(field);
|
||||
else if (!strcmp (field->name, "longname")) {
|
||||
plugin->longname = xmlNodeGetContent (field);
|
||||
}
|
||||
else if (!strcmp(field->name, "filename")) {
|
||||
plugin->filename = xmlNodeGetContent(field);
|
||||
else if (!strcmp (field->name, "filename")) {
|
||||
plugin->filename = xmlNodeGetContent (field);
|
||||
}
|
||||
else if (!strcmp(field->name, "elementfactory")) {
|
||||
GstElementFactory *factory = gst_elementfactory_load_thyself(field);
|
||||
else if (!strcmp (field->name, "elementfactory")) {
|
||||
GstElementFactory *factory = gst_elementfactory_load_thyself (field);
|
||||
gst_plugin_add_factory (plugin, factory);
|
||||
elementcount++;
|
||||
}
|
||||
else if (!strcmp(field->name, "typefactory")) {
|
||||
GstTypeFactory *factory = gst_typefactory_load_thyself(field);
|
||||
else if (!strcmp (field->name, "autoplugfactory")) {
|
||||
GstAutoplugFactory *factory = gst_autoplugfactory_load_thyself (field);
|
||||
gst_plugin_add_autoplugger (plugin, factory);
|
||||
autoplugcount++;
|
||||
}
|
||||
else if (!strcmp (field->name, "typefactory")) {
|
||||
GstTypeFactory *factory = gst_typefactory_load_thyself (field);
|
||||
gst_plugin_add_type (plugin, factory);
|
||||
elementcount++;
|
||||
typecount++;
|
||||
|
@ -810,13 +913,14 @@ gst_plugin_load_thyself (xmlNodePtr parent)
|
|||
}
|
||||
|
||||
if (plugin) {
|
||||
_gst_plugins = g_list_prepend(_gst_plugins, plugin);
|
||||
_gst_plugins = g_list_prepend (_gst_plugins, plugin);
|
||||
}
|
||||
}
|
||||
|
||||
kinderen = kinderen->next;
|
||||
}
|
||||
GST_INFO (GST_CAT_PLUGIN_LOADING,"added %d registered factories and %d types",elementcount,typecount);
|
||||
GST_INFO (GST_CAT_PLUGIN_LOADING, "added %d registered factories, %d autopluggers and %d types",
|
||||
elementcount, autoplugcount, typecount);
|
||||
}
|
||||
|
||||
|
||||
|
@ -851,3 +955,19 @@ gst_plugin_get_type_list (GstPlugin *plugin)
|
|||
|
||||
return plugin->types;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_plugin_get_autoplug_list:
|
||||
* @plugin: the plugin to get the autoplugfactories from
|
||||
*
|
||||
* get a list of all the autoplugfactories that this plugin provides
|
||||
*
|
||||
* Returns: a GList of factories
|
||||
*/
|
||||
GList*
|
||||
gst_plugin_get_autoplug_list (GstPlugin *plugin)
|
||||
{
|
||||
g_return_val_if_fail (plugin != NULL, NULL);
|
||||
|
||||
return plugin->autopluggers;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include <gst/gsttype.h>
|
||||
#include <gst/gstelement.h>
|
||||
#include <gst/gstautoplug.h>
|
||||
|
||||
|
||||
typedef struct _GstPlugin GstPlugin;
|
||||
|
@ -50,6 +51,8 @@ struct _GstPlugin {
|
|||
gint numtypes;
|
||||
GList *elements; /* list of elements provided */
|
||||
gint numelements;
|
||||
GList *autopluggers; /* list of autopluggers provided */
|
||||
gint numautopluggers;
|
||||
|
||||
gboolean loaded; /* if the plugin is in memory */
|
||||
};
|
||||
|
@ -71,6 +74,7 @@ gboolean gst_plugin_is_loaded (GstPlugin *plugin);
|
|||
|
||||
GList* gst_plugin_get_type_list (GstPlugin *plugin);
|
||||
GList* gst_plugin_get_factory_list (GstPlugin *plugin);
|
||||
GList* gst_plugin_get_autoplug_list (GstPlugin *plugin);
|
||||
|
||||
void gst_plugin_load_all (void);
|
||||
gboolean gst_plugin_load (const gchar *name);
|
||||
|
@ -79,14 +83,14 @@ gboolean gst_library_load (const gchar *name);
|
|||
|
||||
void gst_plugin_add_factory (GstPlugin *plugin, GstElementFactory *factory);
|
||||
void gst_plugin_add_type (GstPlugin *plugin, GstTypeFactory *factory);
|
||||
void gst_plugin_add_autoplugger (GstPlugin *plugin, GstAutoplugFactory *factory);
|
||||
|
||||
GstPlugin* gst_plugin_find (const gchar *name);
|
||||
GList* gst_plugin_get_list (void);
|
||||
|
||||
GstElementFactory* gst_plugin_find_elementfactory (const gchar *name);
|
||||
|
||||
GstElementFactory* gst_plugin_load_elementfactory (const gchar *name);
|
||||
void gst_plugin_load_typefactory (const gchar *mime);
|
||||
GstAutoplugFactory* gst_plugin_load_autoplugfactory (const gchar *name);
|
||||
|
||||
xmlNodePtr gst_plugin_save_thyself (xmlNodePtr parent);
|
||||
void gst_plugin_load_thyself (xmlNodePtr parent);
|
||||
|
|
|
@ -578,7 +578,7 @@ gst_props_load_thyself_func (xmlNodePtr field)
|
|||
prop = xmlGetProp (field, "min");
|
||||
sscanf (prop, "%d", &entry->data.int_range_data.min);
|
||||
g_free (prop);
|
||||
prop = xmlGetProp (field, "min");
|
||||
prop = xmlGetProp (field, "max");
|
||||
sscanf (prop, "%d", &entry->data.int_range_data.max);
|
||||
g_free (prop);
|
||||
}
|
||||
|
@ -601,6 +601,10 @@ gst_props_load_thyself_func (xmlNodePtr field)
|
|||
sscanf (prop, "%08x", &entry->data.fourcc_data);
|
||||
g_free (prop);
|
||||
}
|
||||
else {
|
||||
g_free (entry);
|
||||
entry = NULL;
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
@ -634,6 +638,7 @@ gst_props_load_thyself (xmlNodePtr parent)
|
|||
while (subfield) {
|
||||
GstPropsEntry *subentry = gst_props_load_thyself_func (subfield);
|
||||
|
||||
if (subentry)
|
||||
entry->data.list_data.entries = g_list_prepend (entry->data.list_data.entries, subentry);
|
||||
|
||||
subfield = subfield->next;
|
||||
|
|
|
@ -206,14 +206,20 @@ gst_play_audio_handoff (GstElement *element,
|
|||
}
|
||||
|
||||
static void
|
||||
gst_play_object_introspect (GstElement *element,
|
||||
gst_play_object_introspect (GstObject *object,
|
||||
const gchar *property,
|
||||
GstElement **target)
|
||||
{
|
||||
gchar *info;
|
||||
GtkArgInfo *arg;
|
||||
GstElement *element;
|
||||
|
||||
info = gtk_object_arg_get_info( GTK_OBJECT_TYPE(element), property, &arg);
|
||||
if (!GST_IS_ELEMENT (object))
|
||||
return;
|
||||
|
||||
element = GST_ELEMENT (object);
|
||||
|
||||
info = gtk_object_arg_get_info (GTK_OBJECT_TYPE (element), property, &arg);
|
||||
|
||||
if (info) {
|
||||
g_free(info);
|
||||
|
@ -229,8 +235,8 @@ gst_play_object_introspect (GstElement *element,
|
|||
* this will change with glib 1.4
|
||||
* */
|
||||
static void
|
||||
gst_play_object_added (GstElement *pipeline,
|
||||
GstElement *element,
|
||||
gst_play_object_added (GstAutoplug* autoplug,
|
||||
GstObject *object,
|
||||
GstPlay *play)
|
||||
{
|
||||
GstPlayPrivate *priv;
|
||||
|
@ -239,23 +245,23 @@ gst_play_object_added (GstElement *pipeline,
|
|||
|
||||
priv = (GstPlayPrivate *)play->priv;
|
||||
|
||||
if (GST_FLAG_IS_SET (element, GST_ELEMENT_NO_SEEK)) {
|
||||
if (GST_FLAG_IS_SET (object, GST_ELEMENT_NO_SEEK)) {
|
||||
priv->can_seek = FALSE;
|
||||
}
|
||||
|
||||
if (GST_IS_BIN (element)) {
|
||||
gtk_signal_connect (GTK_OBJECT (element), "object_added", gst_play_object_added, play);
|
||||
if (GST_IS_BIN (object)) {
|
||||
//gtk_signal_connect (GTK_OBJECT (object), "object_added", gst_play_object_added, play);
|
||||
}
|
||||
else {
|
||||
// first come first serve here...
|
||||
if (!priv->offset_element)
|
||||
gst_play_object_introspect (element, "offset", &priv->offset_element);
|
||||
gst_play_object_introspect (object, "offset", &priv->offset_element);
|
||||
if (!priv->bit_rate_element)
|
||||
gst_play_object_introspect (element, "bit_rate", &priv->bit_rate_element);
|
||||
gst_play_object_introspect (object, "bit_rate", &priv->bit_rate_element);
|
||||
if (!priv->media_time_element)
|
||||
gst_play_object_introspect (element, "media_time", &priv->media_time_element);
|
||||
gst_play_object_introspect (object, "media_time", &priv->media_time_element);
|
||||
if (!priv->current_time_element)
|
||||
gst_play_object_introspect (element, "current_time", &priv->current_time_element);
|
||||
gst_play_object_introspect (object, "current_time", &priv->current_time_element);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -337,6 +343,7 @@ gst_play_set_uri (GstPlay *play,
|
|||
GstPlayPrivate *priv;
|
||||
GstCaps *src_caps;
|
||||
GstElement *new_element;
|
||||
GstAutoplug *autoplug;
|
||||
|
||||
g_return_val_if_fail (play != NULL, GST_PLAY_ERROR);
|
||||
g_return_val_if_fail (GST_IS_PLAY (play), GST_PLAY_ERROR);
|
||||
|
@ -351,6 +358,7 @@ gst_play_set_uri (GstPlay *play,
|
|||
|
||||
priv->src = gst_elementfactory_make ("disksrc", "disk_src");
|
||||
//priv->src = gst_elementfactory_make ("dvdsrc", "disk_src");
|
||||
priv->offset_element = priv->src;
|
||||
|
||||
g_return_val_if_fail (priv->src != NULL, -1);
|
||||
gtk_object_set (GTK_OBJECT (priv->src), "location", uri, NULL);
|
||||
|
@ -363,8 +371,12 @@ gst_play_set_uri (GstPlay *play,
|
|||
return GST_PLAY_UNKNOWN_MEDIA;
|
||||
}
|
||||
|
||||
new_element = gst_autoplug_caps_list
|
||||
(gst_pad_get_caps_list (gst_element_get_pad (priv->src, "src")),
|
||||
autoplug = gst_autoplugfactory_make ("static");
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (autoplug), "new_object", gst_play_object_added, play);
|
||||
|
||||
new_element = gst_autoplug_caps_list (autoplug,
|
||||
gst_pad_get_caps_list (gst_element_get_pad (priv->src, "src")),
|
||||
gst_pad_get_caps_list (gst_element_get_pad (priv->video_queue, "sink")),
|
||||
gst_pad_get_caps_list (gst_element_get_pad (priv->audio_queue, "sink")),
|
||||
NULL);
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
|
||||
GstElementDetails gst_disksrc_details = {
|
||||
"hronous Disk Source",
|
||||
"asynchronous Disk Source",
|
||||
"Source/File",
|
||||
"Read from arbitrary point in a file",
|
||||
VERSION,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
SUBDIRS = sched eos
|
||||
|
||||
noinst_PROGRAMS = init loadall simplefake states caps queue registry \
|
||||
paranoia rip mp3encode autoplug props case4 markup load tee
|
||||
paranoia rip mp3encode autoplug props case4 markup load tee autoplug2
|
||||
|
||||
# we have nothing but apps here, we can do this safely
|
||||
LIBS += $(GST_LIBS)
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
static void
|
||||
new_object_added (GstAutoplug *autoplug, GstObject *object)
|
||||
{
|
||||
g_print ("added new object \"%s\"\n", gst_object_get_name (object));
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *element;
|
||||
GstElement *videosink, *audiosink;
|
||||
GstAutoplug *autoplugger;
|
||||
GList *testcaps;
|
||||
|
||||
gst_init(&argc,&argv);
|
||||
|
@ -22,9 +29,14 @@ main (int argc, char *argv[])
|
|||
"systemstream", GST_PROPS_BOOLEAN (TRUE),
|
||||
NULL)));
|
||||
|
||||
autoplugger = gst_autoplugfactory_make ("static");
|
||||
|
||||
element = gst_autoplug_caps_list (testcaps, gst_pad_get_caps_list (gst_element_get_pad (audiosink, "sink")),
|
||||
gst_pad_get_caps_list (gst_element_get_pad (videosink, "sink")), NULL);
|
||||
gtk_signal_connect (GTK_OBJECT (autoplugger), "new_object", new_object_added, NULL);
|
||||
|
||||
element = gst_autoplug_caps_list (autoplugger, testcaps,
|
||||
gst_pad_get_caps_list (gst_element_get_pad (audiosink, "sink")),
|
||||
gst_pad_get_caps_list (gst_element_get_pad (videosink, "sink")),
|
||||
NULL);
|
||||
g_assert (element != NULL);
|
||||
|
||||
xmlDocDump (stdout, gst_xml_write (element));
|
||||
|
|
52
tests/autoplug2.c
Normal file
52
tests/autoplug2.c
Normal file
|
@ -0,0 +1,52 @@
|
|||
#include <gst/gst.h>
|
||||
|
||||
static GstElement*
|
||||
autoplug_caps (gchar *mime1, gchar *mime2)
|
||||
{
|
||||
GList *caps1, *caps2;
|
||||
|
||||
caps1 = g_list_append (NULL, gst_caps_new ("tescaps1", mime1));
|
||||
caps2 = g_list_append (NULL, gst_caps_new ("tescaps2", mime2));
|
||||
|
||||
return gst_autoplug_caps_list (caps1, caps2, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *element;
|
||||
|
||||
gst_init(&argc,&argv);
|
||||
|
||||
element = autoplug_caps ("audio/mp3", "audio/raw");
|
||||
xmlSaveFile ("autoplug2_1.gst", gst_xml_write (element));
|
||||
|
||||
element = autoplug_caps ("video/mpeg", "audio/raw");
|
||||
xmlSaveFile ("autoplug2_2.gst", gst_xml_write (element));
|
||||
|
||||
element = gst_autoplug_caps_list (
|
||||
g_list_append (NULL, gst_caps_new_with_props(
|
||||
"testcaps3",
|
||||
"video/mpeg",
|
||||
gst_props_new (
|
||||
"mpegversion", GST_PROPS_INT (1),
|
||||
"systemstream", GST_PROPS_BOOLEAN (TRUE),
|
||||
NULL))),
|
||||
g_list_append (NULL, gst_caps_new("testcaps4","audio/raw")),
|
||||
NULL);
|
||||
xmlSaveFile ("autoplug2_3.gst", gst_xml_write (element));
|
||||
|
||||
element = gst_autoplug_caps_list (
|
||||
g_list_append (NULL, gst_caps_new_with_props(
|
||||
"testcaps5",
|
||||
"video/mpeg",
|
||||
gst_props_new (
|
||||
"mpegversion", GST_PROPS_INT (1),
|
||||
"systemstream", GST_PROPS_BOOLEAN (FALSE),
|
||||
NULL))),
|
||||
g_list_append (NULL, gst_caps_new("testcaps6", "video/raw")),
|
||||
NULL);
|
||||
xmlSaveFile ("autoplug2_4.gst", gst_xml_write (element));
|
||||
|
||||
exit (0);
|
||||
}
|
|
@ -42,7 +42,7 @@ void print_prop(GstPropsEntry *prop,gboolean showname,gchar *pfx) {
|
|||
g_free(longprefix);
|
||||
break;
|
||||
default:
|
||||
printf("\n");
|
||||
printf("unknown props %d\n", prop->propstype);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,30 +59,9 @@ void print_props(GstProps *properties,gchar *pfx) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
struct _GstPropsEntry {
|
||||
GQuark propid;
|
||||
GstPropsId propstype;
|
||||
|
||||
union {
|
||||
// flat values
|
||||
gboolean bool_data;
|
||||
guint32 fourcc_data;
|
||||
gint int_data;
|
||||
|
||||
// structured values
|
||||
struct {
|
||||
GList *entries;
|
||||
} list_data;
|
||||
struct {
|
||||
gint min;
|
||||
gint max;
|
||||
} int_range_data;
|
||||
} data;
|
||||
};
|
||||
*/
|
||||
|
||||
gint print_element_info(GstElementFactory *factory) {
|
||||
gint
|
||||
print_element_info (GstElementFactory *factory)
|
||||
{
|
||||
GstElement *element;
|
||||
GstObjectClass *gstobject_class;
|
||||
GstElementClass *gstelement_class;
|
||||
|
@ -322,11 +301,9 @@ void print_element_list() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void print_plugin_info(GstPlugin *plugin) {
|
||||
GList *factories;
|
||||
GstElementFactory *factory;
|
||||
|
||||
void
|
||||
print_plugin_info (GstPlugin *plugin)
|
||||
{
|
||||
printf("Plugin Details:\n");
|
||||
printf(" Name:\t\t%s\n",plugin->name);
|
||||
printf(" Long Name:\t%s\n",plugin->longname);
|
||||
|
@ -334,6 +311,9 @@ void print_plugin_info(GstPlugin *plugin) {
|
|||
printf("\n");
|
||||
|
||||
if (plugin->numelements) {
|
||||
GList *factories;
|
||||
GstElementFactory *factory;
|
||||
|
||||
printf("Element Factories:\n");
|
||||
|
||||
factories = gst_plugin_get_factory_list(plugin);
|
||||
|
@ -344,6 +324,36 @@ void print_plugin_info(GstPlugin *plugin) {
|
|||
printf(" %s: %s\n",factory->name,factory->details->longname);
|
||||
}
|
||||
}
|
||||
if (plugin->numautopluggers) {
|
||||
GList *factories;
|
||||
GstAutoplugFactory *factory;
|
||||
|
||||
printf("Autpluggers:\n");
|
||||
|
||||
factories = gst_plugin_get_autoplug_list(plugin);
|
||||
while (factories) {
|
||||
factory = (GstAutoplugFactory*)(factories->data);
|
||||
factories = g_list_next(factories);
|
||||
|
||||
printf(" %s: %s\n", factory->name, factory->longdesc);
|
||||
}
|
||||
}
|
||||
if (plugin->numtypes) {
|
||||
GList *factories;
|
||||
GstTypeFactory *factory;
|
||||
|
||||
printf("Types:\n");
|
||||
|
||||
factories = gst_plugin_get_type_list(plugin);
|
||||
while (factories) {
|
||||
factory = (GstTypeFactory*)(factories->data);
|
||||
factories = g_list_next(factories);
|
||||
|
||||
printf(" %s: %s\n", factory->mime, factory->exts);
|
||||
if (factory->typefindfunc)
|
||||
printf(" Has typefind function: %s\n",GST_DEBUG_FUNCPTR_NAME(factory->typefindfunc));
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue