- use autoplugging instead of predefined way on sometimes pads

Original commit message from CVS:
- use autoplugging instead of predefined way on sometimes pads
- exchange plugtype with factories in the spider
- revamp the spider, now messier than before...
- bugfixing
- style corrections
This commit is contained in:
Benjamin Otte 2002-02-05 17:08:08 +00:00
parent a9e40dee74
commit b97f4f91c8
5 changed files with 385 additions and 339 deletions

View file

@ -24,6 +24,7 @@
#include "gstsearchfuncs.h" #include "gstsearchfuncs.h"
/* function that really misses in GLib /* function that really misses in GLib
* though the GLib version should take a function as argument...
*/ */
void void
g_list_free_list_and_elements (GList *list) g_list_free_list_and_elements (GList *list)
@ -279,9 +280,7 @@ gst_autoplug_sp (GstCaps *srccaps, GstCaps *sinkcaps, GList *factories)
guint curcost = GST_AUTOPLUG_MAX_COST; /* below this cost, there is no path */ guint curcost = GST_AUTOPLUG_MAX_COST; /* below this cost, there is no path */
GstAutoplugNode *bestnode = NULL; /* best (unconnected) endpoint currently */ GstAutoplugNode *bestnode = NULL; /* best (unconnected) endpoint currently */
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT, "attempting to autoplug via shortest path"); GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT, "attempting to autoplug via shortest path from %s to %s\n", gst_caps_get_mime (srccaps), gst_caps_get_mime (sinkcaps));
GST_DEBUG (GST_CAT_AUTOPLUG_ATTEMPT, "trying to plug %s to %s\n", gst_caps_get_mime (srccaps), gst_caps_get_mime (sinkcaps));
/* g_print ("trying to plug %s to %s\n", gst_caps_get_mime (srccaps), gst_caps_get_mime (sinkcaps)); */
/* wrap all factories as GstAutoplugNode /* wrap all factories as GstAutoplugNode
* initialize the cost */ * initialize the cost */
while (factories) while (factories)
@ -292,7 +291,7 @@ gst_autoplug_sp (GstCaps *srccaps, GstCaps *sinkcaps, GList *factories)
node->templ = gst_autoplug_can_connect_src (node->fac, srccaps); node->templ = gst_autoplug_can_connect_src (node->fac, srccaps);
node->cost = (node->templ ? gst_autoplug_get_cost (node->fac) : GST_AUTOPLUG_MAX_COST); node->cost = (node->templ ? gst_autoplug_get_cost (node->fac) : GST_AUTOPLUG_MAX_COST);
node->endpoint = gst_autoplug_can_connect_sink (node->fac, sinkcaps); node->endpoint = gst_autoplug_can_connect_sink (node->fac, sinkcaps);
if ((node->endpoint != NULL) && (bestnode == NULL || (node->cost < bestnode->cost))) if ((node->endpoint != NULL) && ((bestnode == NULL) || (node->cost < bestnode->cost)))
{ {
bestnode = node; bestnode = node;
} }
@ -383,9 +382,3 @@ gst_autoplug_sp (GstCaps *srccaps, GstCaps *sinkcaps, GList *factories)

View file

@ -24,7 +24,9 @@
* TODO: * TODO:
* - handle automatic removal of unneeded elements * - handle automatic removal of unneeded elements
* - make the spider handle and send events (esp. new media) * - make the spider handle and send events (esp. new media)
* - decide if we plug pads or elements, currently it's a mess
* - allow disconnecting * - allow disconnecting
* - implement proper saving/loading from xml
* - implement a way to allow merging/splitting (aka tee) * - implement a way to allow merging/splitting (aka tee)
* - find ways to define which elements to use when plugging * - find ways to define which elements to use when plugging
* - remove pads * - remove pads
@ -51,7 +53,7 @@ enum {
enum { enum {
ARG_0, ARG_0,
ARG_PLUGTYPE, ARG_FACTORIES,
/* FILL ME TOO */ /* FILL ME TOO */
}; };
@ -81,7 +83,7 @@ static void gst_spider_get_property
/* autoplugging functions */ /* autoplugging functions */
static GstElement * gst_spider_find_element_to_plug (GstElement *src, GstElementFactory *fac, GstPadDirection dir); static GstElement * gst_spider_find_element_to_plug (GstElement *src, GstElementFactory *fac, GstPadDirection dir);
static GstPadConnectReturn gst_spider_plug_peers (GstSpider *spider, GstSpiderIdentity *src, GstSpiderIdentity *sink); static GstPadConnectReturn gst_spider_plug_peers (GstSpider *spider, GstPad *srcpad, GstPad *sinkpad);
static GstPadConnectReturn gst_spider_create_and_plug (GstSpider *spider, GstElement *src, GstElement *sink, GList *plugpath); static GstPadConnectReturn gst_spider_create_and_plug (GstSpider *spider, GstElement *src, GstElement *sink, GList *plugpath);
/* random functions */ /* random functions */
@ -101,9 +103,10 @@ gst_spider_get_type(void)
if (!spider_type) { if (!spider_type) {
static const GTypeInfo spider_info = { static const GTypeInfo spider_info = {
sizeof(GstSpiderClass), NULL, sizeof(GstSpiderClass),
NULL, NULL,
(GClassInitFunc)gst_spider_class_init, NULL,
(GClassInitFunc) gst_spider_class_init,
NULL, NULL,
NULL, NULL,
sizeof(GstSpider), sizeof(GstSpider),
@ -127,21 +130,33 @@ gst_spider_class_init (GstSpiderClass *klass)
parent_class = g_type_class_ref(GST_TYPE_BIN); parent_class = g_type_class_ref(GST_TYPE_BIN);
/* properties */ /* properties */
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PLUGTYPE, g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FACTORIES,
g_param_spec_int ("plugtype", "plug direction", "encoding, decoding or anything", g_param_spec_pointer ("factories", "allowed factories", "allowed factories for autoplugging", G_PARAM_READWRITE));
GST_SPIDER_ANY, GST_SPIDER_PLUGTYPES - 1, 0, G_PARAM_READWRITE));
gobject_class->set_property = gst_spider_set_property; gobject_class->set_property = gst_spider_set_property;
gobject_class->get_property = gst_spider_get_property; gobject_class->get_property = gst_spider_get_property;
gobject_class->dispose = gst_spider_dispose;
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_spider_request_new_pad); gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_spider_request_new_pad);
} }
static void static void
gst_spider_init (GstSpider *spider) gst_spider_init (GstSpider *spider)
{ {
spider->plugtype = GST_SPIDER_ANY; /* use only elements which have sources and sinks and where the sinks have caps */
/* FIXME: How do we handle factories that are added after the spider was constructed? */
spider->factories = gst_autoplug_factories_filters_with_sink_caps ((GList *) gst_elementfactory_get_list ());
} }
static void
gst_spider_dispose (GObject *object)
{
GstSpider *spider;
spider = GST_SPIDER (object);
g_list_free (spider->factories);
((GObjectClass *) parent_class)->dispose (object);
}
static GstPad * static GstPad *
gst_spider_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *name) gst_spider_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *name)
{ {
@ -161,10 +176,12 @@ gst_spider_request_new_pad (GstElement *element, GstPadTemplate *templ, const gc
case GST_PAD_SRC: case GST_PAD_SRC:
padname = gst_spider_unused_elementname ((GstBin *)spider, "src_"); padname = gst_spider_unused_elementname ((GstBin *)spider, "src_");
identity = gst_spider_identity_new_src (padname); identity = gst_spider_identity_new_src (padname);
returnpad = identity->src;
break; break;
case GST_PAD_SINK: case GST_PAD_SINK:
padname = gst_spider_unused_elementname ((GstBin *)spider, "sink_"); padname = gst_spider_unused_elementname ((GstBin *)spider, "sink_");
identity = gst_spider_identity_new_sink (padname); identity = gst_spider_identity_new_sink (padname);
returnpad = identity->sink;
break; break;
case GST_PAD_UNKNOWN: case GST_PAD_UNKNOWN:
default: default:
@ -172,9 +189,6 @@ gst_spider_request_new_pad (GstElement *element, GstPadTemplate *templ, const gc
return NULL; return NULL;
} }
/* connect a ghost pad on the right side of the identity and set the requested template */
returnpad = gst_spider_identity_request_new_pad (GST_ELEMENT (identity), templ, NULL);
/* FIXME: use the requested name for the pad */ /* FIXME: use the requested name for the pad */
gst_object_ref (GST_OBJECT (templ)); gst_object_ref (GST_OBJECT (templ));
@ -192,6 +206,7 @@ static void
gst_spider_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) gst_spider_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{ {
GstSpider *spider; GstSpider *spider;
GList *list;
/* it's not null if we got it, but it might not be ours */ /* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_SPIDER (object)); g_return_if_fail (GST_IS_SPIDER (object));
@ -199,25 +214,16 @@ gst_spider_set_property (GObject *object, guint prop_id, const GValue *value, GP
spider = GST_SPIDER (object); spider = GST_SPIDER (object);
switch (prop_id) { switch (prop_id) {
case ARG_PLUGTYPE: case ARG_FACTORIES:
switch (g_value_get_int (value)) list = (GList *) g_value_get_pointer (value);
while (list)
{ {
case GST_SPIDER_ANY: g_return_if_fail (list->data != NULL);
spider->plugtype = GST_SPIDER_ANY; g_return_if_fail (GST_IS_ELEMENTFACTORY (list->data));
GST_DEBUG (0,"spider: setting plugtype to ANY\n"); list = g_list_next (list);
break;
case GST_SPIDER_ENCODE:
spider->plugtype = GST_SPIDER_ENCODE;
GST_DEBUG (0,"spider: setting plugtype to ENCODE\n");
break;
case GST_SPIDER_DECODE:
spider->plugtype = GST_SPIDER_DECODE;
GST_DEBUG (0,"spider: setting plugtype to DECODE\n");
break;
default:
GST_DEBUG (0,"spider: invalid value %d while setting plugtype\n", g_value_get_int (value));
break;
} }
g_list_free (spider->factories);
spider->factories = (GList *) g_value_get_pointer (value);
break; break;
default: default:
break; break;
@ -232,8 +238,8 @@ gst_spider_get_property (GObject *object, guint prop_id, GValue *value, GParamSp
spider = GST_SPIDER(object); spider = GST_SPIDER(object);
switch (prop_id) { switch (prop_id) {
case ARG_PLUGTYPE: case ARG_FACTORIES:
g_value_set_int (value, spider->plugtype); g_value_set_pointer (value, spider->factories);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -259,26 +265,43 @@ gst_spider_unused_elementname (GstBin *bin, const gchar *startwith)
typedef struct { typedef struct {
GstSpider *spider; GstSpider *spider;
GstElement *sink; GstElement *sink;
GList *plugpath;
gulong signal_id; gulong signal_id;
} GstSpiderConnectSometimes; } GstSpiderConnectSometimes;
static void static void
gst_spider_connect_sometimes (GstElement *src, GstPad *pad, GstSpiderConnectSometimes *data) gst_spider_connect_sometimes (GstElement *src, GstPad *pad, GstSpiderConnectSometimes *data)
{ {
gboolean restart = FALSE; gboolean restart = FALSE;
GstPad *sinkpad;
GList *sinkpads = gst_element_get_pad_list (data->sink);
if (gst_element_get_state ((GstElement *) data->spider) == GST_STATE_PLAYING) if (gst_element_get_state ((GstElement *) data->spider) == GST_STATE_PLAYING)
{ {
restart = TRUE; restart = TRUE;
gst_element_set_state ((GstElement *) data->spider, GST_STATE_PAUSED); gst_element_set_state ((GstElement *) data->spider, GST_STATE_PAUSED);
} }
gst_spider_create_and_plug (data->spider, src, data->sink, data->plugpath); /* try to autoplug the elements */
while (sinkpads)
{
sinkpad = (GstPad *) sinkpads->data;
if ((GST_RPAD_DIRECTION (sinkpad) == GST_PAD_SINK) && gst_spider_plug_peers (data->spider, pad, sinkpad) != GST_PAD_CONNECT_REFUSED) {
GST_DEBUG (GST_CAT_AUTOPLUG_ATTEMPT, "%s:%s was autoplugged to %s:%s, removing callback\n", GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (sinkpad));
g_signal_handler_disconnect (src, data->signal_id); g_signal_handler_disconnect (src, data->signal_id);
/* do the restarting here, because we want to free the data */
if (restart) if (restart)
{ {
gst_element_set_state ((GstElement *) data->spider, GST_STATE_PLAYING); gst_element_set_state ((GstElement *) data->spider, GST_STATE_PLAYING);
} }
restart = FALSE;
g_free (data); g_free (data);
break;
}
sinkpads = g_list_next (sinkpads);
}
if (restart)
{
gst_element_set_state ((GstElement *) data->spider, GST_STATE_PLAYING);
}
/* do we need this? */
gst_element_interrupt (src); gst_element_interrupt (src);
} }
/* connects newsrc to newsink using the elementfactories in plugpath */ /* connects newsrc to newsink using the elementfactories in plugpath */
@ -287,6 +310,7 @@ gst_spider_create_and_plug (GstSpider *spider, GstElement *src, GstElement *sink
{ {
GstElement *element; GstElement *element;
/* g_print ("C&P: from %s to %s\n", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (sink)); */
/* get the next element */ /* get the next element */
if (plugpath == NULL) if (plugpath == NULL)
{ {
@ -295,6 +319,7 @@ gst_spider_create_and_plug (GstSpider *spider, GstElement *src, GstElement *sink
element = gst_elementfactory_create ((GstElementFactory *) plugpath->data, element = gst_elementfactory_create ((GstElementFactory *) plugpath->data,
gst_spider_unused_elementname (GST_BIN (spider), GST_OBJECT_NAME (plugpath->data))); gst_spider_unused_elementname (GST_BIN (spider), GST_OBJECT_NAME (plugpath->data)));
gst_bin_add (GST_BIN (spider), element); gst_bin_add (GST_BIN (spider), element);
/* g_print ("C&P: trying element %s\n", GST_ELEMENT_NAME (element)); */
} }
/* insert and connect new element */ /* insert and connect new element */
if (!gst_element_connect_elements (src, element)) if (!gst_element_connect_elements (src, element))
@ -314,7 +339,6 @@ gst_spider_create_and_plug (GstSpider *spider, GstElement *src, GstElement *sink
GST_DEBUG (GST_CAT_AUTOPLUG_ATTEMPT, "adding callback to connect element %s to %s\n", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (element)); GST_DEBUG (GST_CAT_AUTOPLUG_ATTEMPT, "adding callback to connect element %s to %s\n", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (element));
data->spider = spider; data->spider = spider;
data->sink = sink; data->sink = sink;
data->plugpath = plugpath;
data->signal_id = g_signal_connect (G_OBJECT (src), "new_pad", data->signal_id = g_signal_connect (G_OBJECT (src), "new_pad",
G_CALLBACK (gst_spider_connect_sometimes), data); G_CALLBACK (gst_spider_connect_sometimes), data);
@ -322,12 +346,11 @@ gst_spider_create_and_plug (GstSpider *spider, GstElement *src, GstElement *sink
} }
templs = g_list_next (templs); templs = g_list_next (templs);
} }
GST_DEBUG (GST_CAT_AUTOPLUG_ATTEMPT, "no chance to connect element %s to %s\n", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (element)); GST_DEBUG (GST_CAT_AUTOPLUG_ATTEMPT, "no chance to connect element %s to %s\n", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (sink));
g_list_free (plugpath);
return GST_PAD_CONNECT_REFUSED; return GST_PAD_CONNECT_REFUSED;
} }
GST_DEBUG (GST_CAT_AUTOPLUG_ATTEMPT, "added element %s and attached it to element %s\n", GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (src)); GST_DEBUG (GST_CAT_AUTOPLUG_ATTEMPT, "added element %s and attached it to element %s\n", GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (src));
plugpath = g_list_delete_link (plugpath, plugpath); plugpath = g_list_next (plugpath);
/* recursively connect the rest of the elements */ /* recursively connect the rest of the elements */
if (element != sink) { if (element != sink) {
@ -413,9 +436,9 @@ gst_spider_plug (GstSpiderIdentity *ident)
/* plug in the right direction */ /* plug in the right direction */
if (plugpad == ident->src) if (plugpad == ident->src)
{ {
gst_spider_plug_peers (spider, peer, ident); gst_spider_plug_peers (spider, peer->src, ident->sink);
} else { } else {
gst_spider_plug_peers (spider, ident, peer); gst_spider_plug_peers (spider, ident->src, peer->sink);
} }
} }
} }
@ -429,42 +452,36 @@ gst_spider_plug (GstSpiderIdentity *ident)
* if no connection was possible * if no connection was possible
*/ */
static GstPadConnectReturn static GstPadConnectReturn
gst_spider_plug_peers (GstSpider *spider, GstSpiderIdentity *src, GstSpiderIdentity *sink) gst_spider_plug_peers (GstSpider *spider, GstPad *srcpad, GstPad *sinkpad)
{ {
GstElement *element, *newsrc, *newsink; GstElement *element, *src, *sink, *newsrc, *newsink;
GstPad *pad, *compat;
GList *plugpath; GList *plugpath;
GList *neededfactories;
GList *templist; GList *templist;
gboolean result = TRUE; gboolean result = TRUE;
GST_DEBUG (GST_CAT_AUTOPLUG_ATTEMPT, "trying to plug from %s to %s\n", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (sink)); GST_DEBUG (GST_CAT_AUTOPLUG_ATTEMPT, "trying to plug from %s:%s to %s:%s\n", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
neededfactories = (GList *) gst_elementfactory_get_list (); /* get src and sink element */
/* use only elements which have sources and sinks and where the sinks have caps */ src = (GstElement *) GST_PAD_PARENT (srcpad);
neededfactories = gst_autoplug_factories_filters_with_sink_caps (neededfactories); sink = (GstElement *) GST_PAD_PARENT (sinkpad);
/* use only the elements with exactly 1 sink/src when decoding/encoding */
if (spider->plugtype == GST_SPIDER_ENCODE)
{
templist = neededfactories;
neededfactories = gst_autoplug_factories_at_most_templates (neededfactories, GST_PAD_SRC, 1);
g_list_free (templist);
}
if (spider->plugtype == GST_SPIDER_DECODE)
{
templist = neededfactories;
neededfactories = gst_autoplug_factories_at_most_templates (neededfactories, GST_PAD_SINK, 1);
g_list_free (templist);
}
/* find a path from src to sink */ /* find a path from src to sink */
plugpath = gst_autoplug_sp (gst_pad_get_caps ((GstPad *) GST_RPAD_PEER (src->sink)), gst_pad_get_caps ((GstPad *) GST_RPAD_PEER (sink->src)), neededfactories); plugpath = gst_autoplug_sp (gst_pad_get_caps (srcpad), gst_pad_get_caps (sinkpad), spider->factories);
/* prints out the path that was found for plugging
templist = plugpath;
while (templist)
{
g_print("%s\n", GST_OBJECT_NAME (templist->data));
templist = g_list_next (templist);
} */
/* if there is no way to plug: return */ /* if there is no way to plug: return */
if (plugpath == NULL) { if (plugpath == NULL) {
GST_DEBUG (GST_CAT_AUTOPLUG_ATTEMPT, "no chance to plug from %s to %s\n", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (sink)); GST_DEBUG (GST_CAT_AUTOPLUG_ATTEMPT, "no chance to plug from %s to %s\n", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (sink));
return FALSE; return GST_PAD_CONNECT_REFUSED;
} }
GST_DEBUG (GST_CAT_AUTOPLUG_ATTEMPT, "found a connection that needs %d elements\n", g_list_length (plugpath)); GST_DEBUG (GST_CAT_AUTOPLUG_ATTEMPT, "found a connection that needs %d elements\n", g_list_length (plugpath));
@ -472,16 +489,16 @@ gst_spider_plug_peers (GstSpider *spider, GstSpiderIdentity *src, GstSpiderIdent
* alter src to point to the new element where we need to start * alter src to point to the new element where we need to start
* plugging and alter the plugpath to represent the elements, that must be plugged * plugging and alter the plugpath to represent the elements, that must be plugged
*/ */
newsrc = (GstElement *) src; newsrc = src;
while (element = gst_spider_find_element_to_plug (newsrc, (GstElementFactory *) plugpath->data, GST_PAD_SRC)) while ((element = gst_spider_find_element_to_plug (newsrc, (GstElementFactory *) plugpath->data, GST_PAD_SRC)))
{ {
newsrc = element; newsrc = element;
plugpath = g_list_delete_link (plugpath, plugpath); plugpath = g_list_delete_link (plugpath, plugpath);
} }
/* now do the same at the end */ /* now do the same at the end */
newsink = (GstElement *) sink; newsink = sink;
templist = g_list_last (plugpath); templist = g_list_last (plugpath);
while (element = gst_spider_find_element_to_plug (newsink, (GstElementFactory *) plugpath->data, GST_PAD_SINK)) while ((element = gst_spider_find_element_to_plug (newsink, (GstElementFactory *) plugpath->data, GST_PAD_SINK)))
{ {
GList *cur = templist; GList *cur = templist;
newsink = element; newsink = element;
@ -494,7 +511,7 @@ gst_spider_plug_peers (GstSpider *spider, GstSpiderIdentity *src, GstSpiderIdent
result = gst_spider_create_and_plug (spider, newsrc, newsink, plugpath); result = gst_spider_create_and_plug (spider, newsrc, newsink, plugpath);
/* free no longer needed data */ /* free no longer needed data */
g_list_free (neededfactories); g_list_free (plugpath);
return result; return result;
} }

View file

@ -26,13 +26,6 @@
#include <gst/gst.h> #include <gst/gst.h>
#include "gstspideridentity.h" #include "gstspideridentity.h"
typedef enum {
GST_SPIDER_ANY = 0,
GST_SPIDER_ENCODE = 1,
GST_SPIDER_DECODE = 2,
GST_SPIDER_PLUGTYPES
} GstSpiderPlugtype;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
@ -56,7 +49,7 @@ typedef struct _GstSpiderClass GstSpiderClass;
struct _GstSpider { struct _GstSpider {
GstBin parent; GstBin parent;
GstSpiderPlugtype plugtype; /* direction to plug */ GList * factories; /* factories to use for plugging */
}; };
struct _GstSpiderClass { struct _GstSpiderClass {

View file

@ -39,14 +39,14 @@ GstElementDetails gst_spider_identity_details = {
* delete me when meging with spider.c * delete me when meging with spider.c
*/ */
GST_PADTEMPLATE_FACTORY (spider_src_factory, GST_PADTEMPLATE_FACTORY (spider_src_factory,
"src_%02d", "src",
GST_PAD_SRC, GST_PAD_SRC,
GST_PAD_REQUEST, GST_PAD_REQUEST,
NULL /* no caps */ NULL /* no caps */
); );
GST_PADTEMPLATE_FACTORY (spider_sink_factory, GST_PADTEMPLATE_FACTORY (spider_sink_factory,
"sink_%02d", "sink",
GST_PAD_SINK, GST_PAD_SINK,
GST_PAD_REQUEST, GST_PAD_REQUEST,
NULL /* no caps */ NULL /* no caps */
@ -140,18 +140,25 @@ gst_spider_identity_get_bufferpool (GstPad *pad)
} }
static void static void
gst_spider_identity_init (GstSpiderIdentity *spider_identity) gst_spider_identity_init (GstSpiderIdentity *ident)
{ {
/* pads */ /* sink */
spider_identity->sink = NULL; ident->sink = gst_pad_new_from_template (GST_PADTEMPLATE_GET (spider_sink_factory), "sink");
spider_identity->src = NULL; gst_element_add_pad (GST_ELEMENT (ident), ident->sink);
gst_pad_set_connect_function (ident->sink, GST_DEBUG_FUNCPTR (gst_spider_identity_connect));
gst_pad_set_getcaps_function (ident->sink, GST_DEBUG_FUNCPTR (gst_spider_identity_getcaps));
/* src */
ident->src = gst_pad_new_from_template (GST_PADTEMPLATE_GET (spider_src_factory), "src");
gst_element_add_pad (GST_ELEMENT (ident), ident->src);
gst_pad_set_connect_function (ident->src, GST_DEBUG_FUNCPTR (gst_spider_identity_connect));
gst_pad_set_getcaps_function (ident->src, GST_DEBUG_FUNCPTR (gst_spider_identity_getcaps));
/* variables */ /* variables */
spider_identity->plugged = FALSE; ident->plugged = FALSE;
/* caching */ /* caching */
spider_identity->cache_start = NULL; ident->cache_start = NULL;
spider_identity->cache_end = NULL; ident->cache_end = NULL;
} }
@ -198,6 +205,9 @@ gst_spider_identity_new_sink (gchar *name)
GST_ELEMENT_NAME (ret) = name; GST_ELEMENT_NAME (ret) = name;
/* set the right functions */
gst_element_set_loop_function (GST_ELEMENT (ret), (GstElementLoopFunction) GST_DEBUG_FUNCPTR (gst_spider_identity_dumb_loop));
return ret; return ret;
} }
@ -300,7 +310,7 @@ gst_spider_identity_change_state (GstElement *element)
switch (GST_STATE_TRANSITION (element)) { switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_PAUSED_TO_PLAYING: case GST_STATE_PAUSED_TO_PLAYING:
/* start typefinding or plugging */ /* start typefinding or plugging */
if ((ident->sink != NULL) && (ident->src == NULL)) if ((GST_RPAD_PEER (ident->sink) != NULL) && (GST_RPAD_PEER (ident->src) == NULL))
{ {
if (gst_pad_get_caps ((GstPad *) GST_PAD_PEER (ident->sink)) == NULL) if (gst_pad_get_caps ((GstPad *) GST_PAD_PEER (ident->sink)) == NULL)
{ {
@ -311,7 +321,7 @@ gst_spider_identity_change_state (GstElement *element)
} }
} }
/* autoplug on src */ /* autoplug on src */
if ((ident->src != NULL) && (ident->sink == NULL)) if ((GST_RPAD_PEER (ident->src) != NULL) && (GST_RPAD_PEER (ident->sink) == NULL))
{ {
gst_spider_plug (ident); gst_spider_plug (ident);
} }
@ -330,7 +340,7 @@ gst_spider_identity_start_typefinding (GstSpiderIdentity *ident)
{ {
GstElement* typefind; GstElement* typefind;
GST_DEBUG (GST_CAT_AUTOPLUG, "element %s starts typefinding", GST_ELEMENT_NAME(ident)); GST_DEBUG (GST_CAT_AUTOPLUG, "element %s starts typefinding\n", GST_ELEMENT_NAME(ident));
/* create and connect typefind object */ /* create and connect typefind object */
typefind = gst_elementfactory_make ("typefind", g_strdup_printf("%s%s", "typefind", GST_ELEMENT_NAME(ident))); typefind = gst_elementfactory_make ("typefind", g_strdup_printf("%s%s", "typefind", GST_ELEMENT_NAME(ident)));
@ -362,7 +372,7 @@ callback_typefind_have_type (GstElement *typefind, GstCaps *caps, GstSpiderIdent
{ {
gboolean restart_spider = FALSE; gboolean restart_spider = FALSE;
GST_INFO (GST_CAT_AUTOPLUG, "element %s has found caps", GST_ELEMENT_NAME(ident)); GST_INFO (GST_CAT_AUTOPLUG, "element %s has found caps\n", GST_ELEMENT_NAME(ident));
/* checks */ /* checks */
/* we have to ref the typefind, because if me remove it the scheduler segfaults /* we have to ref the typefind, because if me remove it the scheduler segfaults

View file

@ -1,6 +1,36 @@
#include <stdlib.h> #include <stdlib.h>
#include <gst/gst.h> #include <gst/gst.h>
/* returns all factories which have a maximum of maxtemplates GstPadTemplates in direction dir
*/
GList *
gst_factories_at_most_templates(GList *factories, GstPadDirection dir, guint maxtemplates)
{
GList *ret = NULL;
while (factories)
{
guint count = 0;
GList *templs = ((GstElementFactory *) factories->data)->padtemplates;
while (templs)
{
if (GST_PADTEMPLATE_DIRECTION (templs->data) == dir)
{
count++;
}
if (count > maxtemplates)
break;
templs = g_list_next (templs);
}
if (count <= maxtemplates)
ret = g_list_prepend (ret, factories->data);
factories = g_list_next (factories);
}
return ret;
}
/* 1:1 copy of gstpropsprivate.h, needed for INFO events */ /* 1:1 copy of gstpropsprivate.h, needed for INFO events */
#define GST_PROPS_ENTRY_IS_VARIABLE(a) (((GstPropsEntry*)(a))->propstype > GST_PROPS_VAR_ID) #define GST_PROPS_ENTRY_IS_VARIABLE(a) (((GstPropsEntry*)(a))->propstype > GST_PROPS_VAR_ID)
@ -87,8 +117,9 @@ event_func (GstElement *element, GstEvent *event)
int main(int argc,char *argv[]) int main(int argc,char *argv[])
{ {
GstElement *bin, *filesrc, *decoder, *osssink, *videosink; GstElement *bin, *filesrc, *decoder, *osssink, *videosink;
GList *facs;
if (argc != 2) { if (argc < 2) {
g_print("usage: %s <file>\n", argv[0]); g_print("usage: %s <file>\n", argv[0]);
exit(-1); exit(-1);
} }
@ -111,7 +142,9 @@ int main(int argc,char *argv[])
} }
/* only use decoding plugins */ /* only use decoding plugins */
g_object_set(G_OBJECT(decoder),"plugtype", 2, NULL); g_object_get (decoder, "factories", &facs, NULL);
facs = gst_factories_at_most_templates(facs, GST_PAD_SINK, 1);
g_object_set (decoder, "factories", facs, NULL);
/* create video and audio sink */ /* create video and audio sink */
osssink = gst_elementfactory_make("osssink", "audio"); osssink = gst_elementfactory_make("osssink", "audio");