diff --git a/docs/manual/outline.txt b/docs/manual/outline.txt index 3cbe975562..ee0aece6e7 100644 --- a/docs/manual/outline.txt +++ b/docs/manual/outline.txt @@ -49,6 +49,11 @@ Building apps (fdsrc->mp3decoder->audiosink) (step by step explanation) More on factories + problems with helloworld + MIME types + GStreamer types + Basic types + advanced concepts threads diff --git a/gst/elements/gstaudiosink.c b/gst/elements/gstaudiosink.c index b363db2aa5..1c1eea8e70 100644 --- a/gst/elements/gstaudiosink.c +++ b/gst/elements/gstaudiosink.c @@ -133,9 +133,9 @@ gst_audiosink_class_init(GstAudioSinkClass *klass) { static void gst_audiosink_init(GstAudioSink *audiosink) { audiosink->sinkpad = gst_pad_new("sink",GST_PAD_SINK); gst_element_add_pad(GST_ELEMENT(audiosink),audiosink->sinkpad); - if (!gst_audiosink_type_audio) - gst_audiosink_type_audio = gst_type_find_by_mime("audio/raw"); + gst_pad_set_type_id(audiosink->sinkpad,gst_audiosink_type_audio); + gst_pad_set_chain_function(audiosink->sinkpad,gst_audiosink_chain); audiosink->fd = -1; @@ -342,3 +342,14 @@ static GstElementStateReturn gst_audiosink_change_state(GstElement *element) { return GST_ELEMENT_CLASS(parent_class)->change_state(element); return GST_STATE_SUCCESS; } + +gboolean gst_audiosink_factory_init(GstElementFactory *factory) { + + if (!gst_audiosink_type_audio) + gst_audiosink_type_audio = gst_type_find_by_mime("audio/raw"); + + gst_type_add_sink(gst_audiosink_type_audio, factory); + + return TRUE; +} + diff --git a/gst/elements/gstaudiosink.h b/gst/elements/gstaudiosink.h index 45ffa1fac6..03e1faa689 100644 --- a/gst/elements/gstaudiosink.h +++ b/gst/elements/gstaudiosink.h @@ -79,6 +79,8 @@ struct _GstAudioSinkClass { GtkType gst_audiosink_get_type(void); +gboolean gst_audiosink_factory_init(GstElementFactory *factory); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/gst/elements/gstelements.c b/gst/elements/gstelements.c index e7464e3bd3..9900496a47 100644 --- a/gst/elements/gstelements.c +++ b/gst/elements/gstelements.c @@ -42,25 +42,26 @@ struct _elements_entry { gchar *name; GtkType (*type) (void); GstElementDetails *details; + gboolean (*factoryinit) (GstElementFactory *factory); }; struct _elements_entry _elements[] = { - { "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details }, - { "fakesink", gst_fakesink_get_type, &gst_fakesink_details }, - { "asyncdisksrc", gst_asyncdisksrc_get_type, &gst_asyncdisksrc_details }, - { "audiosink", gst_audiosink_get_type, &gst_audiosink_details }, - { "audiosrc", gst_audiosrc_get_type, &gst_audiosrc_details }, - { "disksrc", gst_disksrc_get_type, &gst_disksrc_details }, - { "identity", gst_identity_get_type, &gst_identity_details }, - { "fdsink", gst_fdsink_get_type, &gst_fdsink_details }, - { "fdsrc", gst_fdsrc_get_type, &gst_fdsrc_details }, + { "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details, NULL }, + { "fakesink", gst_fakesink_get_type, &gst_fakesink_details, NULL }, + { "asyncdisksrc", gst_asyncdisksrc_get_type, &gst_asyncdisksrc_details, NULL }, + { "audiosink", gst_audiosink_get_type, &gst_audiosink_details, gst_audiosink_factory_init }, + { "audiosrc", gst_audiosrc_get_type, &gst_audiosrc_details, NULL }, + { "disksrc", gst_disksrc_get_type, &gst_disksrc_details, NULL }, + { "identity", gst_identity_get_type, &gst_identity_details, NULL }, + { "fdsink", gst_fdsink_get_type, &gst_fdsink_details, NULL }, + { "fdsrc", gst_fdsrc_get_type, &gst_fdsrc_details, NULL }, #if HAVE_LIBGHTTP - { "httpsrc", gst_httpsrc_get_type, &gst_httpsrc_details }, + { "httpsrc", gst_httpsrc_get_type, &gst_httpsrc_details, NULL }, #endif /* HAVE_LIBGHTTP */ - { "pipefilter", gst_pipefilter_get_type, &gst_pipefilter_details }, - { "queue", gst_queue_get_type, &gst_queue_details }, - { "sinesrc", gst_sinesrc_get_type, &gst_sinesrc_details }, - { "typefind", gst_typefind_get_type, &gst_typefind_details }, + { "pipefilter", gst_pipefilter_get_type, &gst_pipefilter_details, NULL }, + { "queue", gst_queue_get_type, &gst_queue_details, NULL }, + { "sinesrc", gst_sinesrc_get_type, &gst_sinesrc_details, NULL }, + { "typefind", gst_typefind_get_type, &gst_typefind_details, NULL }, { NULL, 0 }, }; @@ -82,7 +83,10 @@ GstPlugin *plugin_init(GModule *module) { _elements[i].details); if (factory != NULL) { gst_plugin_add_factory(plugin,factory); -// DEBUG("added factory '%s'\n",_elements[i].name); + if (_elements[i].factoryinit) { + _elements[i].factoryinit(factory); + } +// g_print("added factory '%s'\n",_elements[i].name); } i++; } diff --git a/gst/gstbin.c b/gst/gstbin.c index adcaaab4b3..11da06fd70 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -17,10 +17,12 @@ * Boston, MA 02111-1307, USA. */ +//#define DEBUG_ENABLED #include #include "config.h" + GstElementDetails gst_bin_details = { "Generic bin", "Bin", @@ -542,6 +544,7 @@ gst_element_get_name(element),gst_pad_get_name(pad)); g_print("gstbin: don't need cothreads, looking for entry points\n"); // clear previous plan state g_list_free(bin->entries); + bin->entries = NULL; bin->numentries = 0; // we have to find which elements will drive an iteration elements = bin->children; @@ -617,5 +620,4 @@ void gst_bin_iterate_func(GstBin *bin) { entries = g_list_next(entries); } } -// g_print(","); } diff --git a/gst/gstbin.h b/gst/gstbin.h index 7952c2855a..f169c99c9a 100644 --- a/gst/gstbin.h +++ b/gst/gstbin.h @@ -84,6 +84,7 @@ struct _GstBinClass { GtkType gst_bin_get_type(void); GstElement *gst_bin_new(gchar *name); +#define gst_bin_destroy(bin) gst_object_destroy(GST_OBJECT(bin)) /* add and remove elements from the bin */ void gst_bin_add(GstBin *bin,GstElement *element); diff --git a/gst/gstelement.c b/gst/gstelement.c index f3c366c1be..579e951d2b 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -306,6 +306,17 @@ gint gst_element_set_state(GstElement *element,GstElementState state) { return return_val; } +GstElementFactory *gst_element_get_factory(GstElement *element) { + GstElementClass *oclass; + + g_return_val_if_fail(element != NULL, NULL); + g_return_val_if_fail(GST_IS_ELEMENT(element), NULL); + + oclass = GST_ELEMENT_CLASS(GTK_OBJECT(element)->klass); + + return oclass->elementfactory; +} + /** * gst_element_change_state: * @element: element to change state of diff --git a/gst/gstelement.h b/gst/gstelement.h index f7c44bb135..ffdee7fc7c 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -144,6 +144,9 @@ struct _GstElementFactory { GtkType type; /* unique GtkType of element */ GstElementDetails *details; /* pointer to details struct */ + + GList *src_types; + GList *sink_types; }; @@ -172,6 +175,8 @@ gint gst_element_set_state(GstElement *element,GstElementState state); void gst_element_error(GstElement *element,gchar *error); +GstElementFactory *gst_element_get_factory(GstElement *element); + #define gst_element_destroy(element) gst_object_destroy(GST_OBJECT(element)) /* XML write and read */ @@ -182,6 +187,9 @@ GstElementFactory *gst_elementfactory_new(gchar *name,GtkType type, GstElementDetails *details); void gst_elementfactory_register(GstElementFactory *elementfactory); +void gst_elementfactory_add_src(GstElementFactory *elementfactory, guint16 id); +void gst_elementfactory_add_sink(GstElementFactory *elementfactory, guint16 id); + GstElementFactory *gst_elementfactory_find(gchar *name); GList *gst_elementfactory_get_list(); diff --git a/gst/gstelementfactory.c b/gst/gstelementfactory.c index 51f65d8b78..699fada6fd 100644 --- a/gst/gstelementfactory.c +++ b/gst/gstelementfactory.c @@ -91,6 +91,8 @@ GstElementFactory *gst_elementfactory_new(gchar *name,GtkType type, factory->name = g_strdup(name); factory->type = type; factory->details = details; + factory->src_types = NULL; + factory->sink_types = NULL; return factory; } @@ -136,3 +138,16 @@ GstElement *gst_elementfactory_make(gchar *factoryname,gchar *name) { element = gst_elementfactory_create(factory,name); return element; } + +void gst_elementfactory_add_src(GstElementFactory *elementfactory, guint16 id) { + guint type = id; + + elementfactory->src_types = g_list_prepend(elementfactory->src_types, GUINT_TO_POINTER(type)); +} + +void gst_elementfactory_add_sink(GstElementFactory *elementfactory, guint16 id) { + guint type = id; + + elementfactory->sink_types = g_list_prepend(elementfactory->sink_types, GUINT_TO_POINTER(type)); +} + diff --git a/gst/gstpipeline.c b/gst/gstpipeline.c index 428281bfed..56bdd1ba39 100644 --- a/gst/gstpipeline.c +++ b/gst/gstpipeline.c @@ -18,6 +18,9 @@ */ #include +#include +#include +#include #include "config.h" @@ -50,6 +53,7 @@ static GstElementStateReturn gst_pipeline_change_state(GstElement *element); static void gst_pipeline_prepare(GstPipeline *pipeline); +static void gst_pipeline_have_type(GstSink *sink, GstSink *sink2, gpointer data); static GstBin *parent_class = NULL; //static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 }; @@ -109,6 +113,164 @@ static void gst_pipeline_prepare(GstPipeline *pipeline) { g_print("GstPipeline: preparing pipeline \"%s\" for playing\n", gst_element_get_name(GST_ELEMENT(pipeline))); } +static void gst_pipeline_have_type(GstSink *sink, GstSink *sink2, gpointer data) { + g_print("GstPipeline: pipeline have type %p\n", (gboolean *)data); + + *(gboolean *)data = TRUE; +} + +static guint16 gst_pipeline_typefind(GstPipeline *pipeline, GstElement *element) { + gboolean found = FALSE; + GstElement *typefind; + guint16 type_id = 0; + + g_print("GstPipeline: typefind for element \"%s\" %p\n", gst_element_get_name(element), &found); + + typefind = gst_elementfactory_make("typefind","typefind"); + g_return_val_if_fail(typefind != NULL, FALSE); + + gtk_signal_connect(GTK_OBJECT(typefind),"have_type", + GTK_SIGNAL_FUNC(gst_pipeline_have_type), &found); + + gst_pad_connect(gst_element_get_pad(element,"src"), + gst_element_get_pad(typefind,"sink")); + + gst_bin_add(GST_BIN(pipeline), typefind); + + gst_bin_create_plan(GST_BIN(pipeline)); + gst_element_set_state(GST_ELEMENT(element),GST_STATE_READY); + gst_element_set_state(GST_ELEMENT(element),GST_STATE_PLAYING); + + while (!found) { + gst_src_push(GST_SRC(element)); + } + + gst_element_set_state(GST_ELEMENT(element),GST_STATE_NULL); + + if (found) { + type_id = gst_util_get_int_arg(GTK_OBJECT(typefind),"type"); + } + + gst_pad_set_type_id(gst_element_get_pad(element, "src"), type_id); + + gst_pad_disconnect(gst_element_get_pad(element,"src"), + gst_element_get_pad(typefind,"sink")); + gst_bin_remove(GST_BIN(pipeline), typefind); + + return type_id; +} + +gboolean gst_pipeline_autoplug(GstPipeline *pipeline) { + GList *elements; + GstElement *element, *srcelement, *sinkelement; + GList *factories; + GstElementFactory *factory; + GList *src_types, *sink_types; + guint16 src_type = 0, sink_type = 0; + gboolean complete = FALSE; + + g_return_val_if_fail(GST_IS_PIPELINE(pipeline), FALSE); + + g_print("GstPipeline: autopluging pipeline \"%s\"\n", gst_element_get_name(GST_ELEMENT(pipeline))); + + elements = gst_bin_get_list(GST_BIN(pipeline)); + + // fase 1, find all the sinks and sources... + while (elements) { + element = GST_ELEMENT(elements->data); + + if (GST_IS_SINK(element)) { + g_print("GstPipeline: found sink \"%s\"\n", gst_element_get_name(element)); + + if (sink_type) { + g_print("GstPipeline: multiple sinks detected, can't autoplug pipeline \"%s\"\n", gst_element_get_name(GST_ELEMENT(pipeline))); + return FALSE; + } + sinkelement = element; + factory = gst_element_get_factory(element); + + sink_types = factory->sink_types; + if (sink_types == NULL) { + g_print("GstPipeline: sink \"%s\" has no MIME type, can't autoplug \n", gst_element_get_name(element)); + return FALSE; + } + else { + sink_type = GPOINTER_TO_UINT(sink_types->data); + g_print("GstPipeline: sink \"%s\" has MIME type %d \n", gst_element_get_name(element), sink_type); + } + } + else if (GST_IS_SRC(element)) { + g_print("GstPipeline: found source \"%s\"\n", gst_element_get_name(element)); + + if (src_type) { + g_print("GstPipeline: multiple sources detected, can't autoplug pipeline \"%s\"\n", gst_element_get_name(GST_ELEMENT(pipeline))); + return FALSE; + } + + srcelement = element; + + factory = gst_element_get_factory(element); + + src_types = factory->src_types; + if (src_types == NULL) { + g_print("GstPipeline: source \"%s\" has no MIME type, running typefind...\n", gst_element_get_name(element)); + + src_type = gst_pipeline_typefind(pipeline, element); + + if (src_type) { + g_print("GstPipeline: source \"%s\" type found %d\n", gst_element_get_name(element), src_type); + } + else { + g_print("GstPipeline: source \"%s\" has no type\n", gst_element_get_name(element)); + return FALSE; + } + } + else { + while (src_types) { + src_types = g_list_next(src_types); + } + } + } + else { + g_print("GstPipeline: found invalid element \"%s\", not source or sink\n", gst_element_get_name(element)); + } + + elements = g_list_next(elements); + } + + factories = gst_type_get_sink_to_src(src_type, sink_type); + + while (factories) { + // fase 2: find elements to form a pad + + factory = (GstElementFactory *)(factories->data); + + g_print("GstPipeline: factory \"%s\"\n", factory->name); + + element = gst_elementfactory_create(factory, factory->name); + gst_bin_add(GST_BIN(pipeline), element); + + // FIXME match paths to connect with MIME types instead + // of names. + gst_pad_connect(gst_element_get_pad(srcelement,"src"), + gst_element_get_pad(element,"sink")); + + srcelement = element; + + factories = g_list_next(factories); + + complete = TRUE; + } + + if (complete) { + gst_pad_connect(gst_element_get_pad(srcelement,"src"), + gst_element_get_pad(sinkelement,"sink")); + return TRUE; + } + + g_print("GstPipeline: unable to autoplug pipeline \"%s\"\n", gst_element_get_name(GST_ELEMENT(pipeline))); + return FALSE; +} static GstElementStateReturn gst_pipeline_change_state(GstElement *element) { GstPipeline *pipeline; diff --git a/gst/gstpipeline.h b/gst/gstpipeline.h index 589d02be8f..97772657c3 100644 --- a/gst/gstpipeline.h +++ b/gst/gstpipeline.h @@ -41,7 +41,7 @@ GstElementDetails gst_pipeline_details; #define GST_IS_PIPELINE(obj) \ (GTK_CHECK_TYPE((obj),GST_TYPE_PIPELINE)) #define GST_IS_PIPELINE_CLASS(obj) \ - (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_PIPELINE))) + (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_PIPELINE)) typedef struct _GstPipeline GstPipeline; typedef struct _GstPipelineClass GstPipelineClass; @@ -58,6 +58,8 @@ GtkType gst_pipeline_get_type(void); GstPipeline *gst_pipeline_new(guchar *name); #define gst_pipeline_destroy(pipeline) gst_object_destroy(GST_OBJECT(pipeline)) +gboolean gst_pipeline_autoplug(GstPipeline *pipeline); + void gst_pipeline_iterate(GstPipeline *pipeline); #ifdef __cplusplus diff --git a/gst/gsttype.c b/gst/gsttype.c index 117dfa9895..a3aea32e62 100644 --- a/gst/gsttype.c +++ b/gst/gsttype.c @@ -33,6 +33,27 @@ GList *_gst_types; guint16 _gst_maxtype; +struct _gst_type_node +{ + int iNode; + int iDist; + int iPrev; +}; +typedef struct _gst_type_node gst_type_node; + +/* we keep a (spase) matrix in the hashtable like: + * + * type_id list of factories hashed by src type_id + * + * 1 -> (1, factory1, factory2), (3, factory3) + * 2 -> NULL + * 3 -> (4, factory4) + * 4 -> NULL + * + * That way, we can quickly find all factories that convert + * 1 to 2. + * + **/ void _gst_type_initialize() { _gst_types = NULL; @@ -58,6 +79,7 @@ guint16 gst_type_register(GstTypeFactory *factory) { type->typefindfunc = factory->typefindfunc; type->srcs = NULL; type->sinks = NULL; + type->converters = g_hash_table_new(NULL, NULL); _gst_types = g_list_prepend(_gst_types,type); id = type->id; @@ -122,22 +144,102 @@ GstType *gst_type_find_by_id(guint16 id) { return NULL; } +static void gst_type_dump_converter(gpointer key, gpointer value, gpointer data) { + GList *walk = (GList *)value; + GstElementFactory *factory; + + g_print("%u, (", GPOINTER_TO_UINT(key)); + + while (walk) { + factory = (GstElementFactory *) walk->data; + g_print("%s, ", factory->name); + walk = g_list_next(walk); + } + g_print("NULL)), "); +} + +void gst_type_dump() { + GList *walk = _gst_types; + GstType *type; + + g_print("gst_type_dump() : \n"); + + while (walk) { + type = (GstType *)walk->data; + + g_print("gst_type: %d (%s) -> (", type->id, type->mime); + g_hash_table_foreach(type->converters, gst_type_dump_converter, NULL); + g_print("NULL)\n"); + + walk = g_list_next(walk); + } +} + void gst_type_add_src(guint16 id,GstElementFactory *src) { + GList *walk; GstType *type = gst_type_find_by_id(id); g_return_if_fail(type != NULL); g_return_if_fail(src != NULL); type->srcs = g_list_prepend(type->srcs,src); + gst_elementfactory_add_src(src, id); + + // find out if the element has to be indexed in the matrix + walk = src->sink_types; + + while (walk) { + GstType *type2 = gst_type_find_by_id(GPOINTER_TO_UINT(walk->data)); + GList *converters = (GList *)g_hash_table_lookup(type2->converters, GUINT_TO_POINTER((guint)id)); + GList *orig = converters; + + while (converters) { + if (converters->data == src) { + break; + } + converters = g_list_next(converters); + } + + if (!converters) { + orig = g_list_prepend(orig, src); + g_hash_table_insert(type2->converters, GUINT_TO_POINTER((guint)id), orig); + } + + walk = g_list_next(walk); + } } void gst_type_add_sink(guint16 id,GstElementFactory *sink) { + GList *walk; GstType *type = gst_type_find_by_id(id); g_return_if_fail(type != NULL); g_return_if_fail(sink != NULL); type->sinks = g_list_prepend(type->sinks,sink); + gst_elementfactory_add_sink(sink, id); + + // find out if the element has to be indexed in the matrix + walk = sink->src_types; + + while (walk) { + GList *converters = (GList *)g_hash_table_lookup(type->converters, walk->data); + GList *orig = converters; + + while (converters) { + if (converters->data == sink) { + break; + } + converters = g_list_next(converters); + } + + if (!converters) { + orig = g_list_prepend(orig, sink); + g_hash_table_insert(type->converters, walk->data, orig); + } + + walk = g_list_next(walk); + } } GList *gst_type_get_srcs(guint16 id) { @@ -156,6 +258,117 @@ GList *gst_type_get_sinks(guint16 id) { return type->sinks; } +/* + * An implementation of Dijkstra's shortest path + * algorithm to find the best set of GstElementFactories + * to connnect two GstTypes + * + **/ + +static GList *gst_type_enqueue(GList *queue, gint iNode, gint iDist, gint iPrev) { + gst_type_node *node = g_malloc(sizeof(gst_type_node)); + + node->iNode = iNode; + node->iDist = iDist; + node->iPrev = iPrev; + + queue = g_list_append(queue, node); + + return queue; +} + +static GList *gst_type_dequeue(GList *queue, gint *iNode, gint *iDist, gint *iPrev) { + GList *head; + gst_type_node *node; + + head = g_list_first(queue); + + if (head) { + node = (gst_type_node *)head->data; + *iNode = node->iNode; + *iPrev = node->iPrev; + *iDist = node->iDist; + head = g_list_remove(queue, node); + } + + return head; +} + +static GList *construct_path (gst_type_node *rgnNodes, gint chNode) +{ + guint src = chNode; + guint current = rgnNodes[chNode].iPrev; + GList *factories = NULL; + GstType *type; + GList *converters; + + while (current != 999) + { + type = gst_type_find_by_id(current); + converters = (GList *)g_hash_table_lookup(type->converters, GUINT_TO_POINTER(src)); + + g_print("(%d %d)", src, current); + factories = g_list_prepend(factories, converters->data); + src = current; + current = rgnNodes[current].iPrev; + } + g_print("\n"); + return factories; +} + +static guint gst_type_find_cost(gint src, gint dest) { + GstType *type = gst_type_find_by_id(src); + + GList *converters = (GList *)g_hash_table_lookup(type->converters, GUINT_TO_POINTER(dest)); + + if (converters) return 1; + return 999; +} + +GList *gst_type_get_sink_to_src(guint16 sinkid, guint16 srcid) { + gst_type_node *rgnNodes; + GList *queue = NULL; + gint iNode, iDist, iPrev, i, iCost; + + if (sinkid == srcid) { + //FIXME return an identity element + return NULL; + } + else { + rgnNodes = g_malloc(sizeof(gst_type_node) * _gst_maxtype); + + for (i=0; i< _gst_maxtype; i++) { + rgnNodes[i].iNode = i; + rgnNodes[i].iDist = 999; + rgnNodes[i].iPrev = 999; + } + rgnNodes[sinkid].iDist = 0; + rgnNodes[sinkid].iPrev = 999; + + queue = gst_type_enqueue(queue, sinkid, 0, 999); + + while (g_list_length(queue) > 0) { + + queue = gst_type_dequeue(queue, &iNode, &iDist, &iPrev); + + for (i=0; i< _gst_maxtype; i++) { + iCost = gst_type_find_cost(iNode, i); + if (iCost != 999) { + if((999 == rgnNodes[i].iDist) || + (rgnNodes[i].iDist > (iCost + iDist))) { + rgnNodes[i].iDist = iDist + iCost; + rgnNodes[i].iPrev = iNode; + + queue = gst_type_enqueue(queue, i, iDist + iCost, iNode); + } + } + } + } + } + + return construct_path(rgnNodes, srcid); +} + GList *gst_type_get_list() { return _gst_types; } diff --git a/gst/gsttype.h b/gst/gsttype.h index dc48eefcfb..e8cdb593f4 100644 --- a/gst/gsttype.h +++ b/gst/gsttype.h @@ -27,7 +27,7 @@ /* type of function used to check a stream for equality with type */ -typedef gboolean (*GstTypeFindFunc) (GstBuffer *buf,gpointer *private); +typedef gboolean (*GstTypeFindFunc) (GstBuffer *buf,gpointer *priv); typedef struct _GstType GstType; typedef struct _GstTypeFactory GstTypeFactory; @@ -42,6 +42,10 @@ struct _GstType { GList *srcs; /* list of src objects for this type */ GList *sinks; /* list of sink objects for type */ + + GHashTable *converters; /* a hashtable of factories that can convert + from this type to destination type. The + factories are indexed by destination type */ }; struct _GstTypeFactory { @@ -70,7 +74,11 @@ GList *gst_type_get_sinks(guint16 id); /* get GstType by id */ GstType *gst_type_find_by_id(guint16 id); + +GList *gst_type_get_sink_to_src(guint16 sinkid, guint16 srcid); + /* get the list of registered types (returns list of GstType!) */ GList *gst_type_get_list(); +void gst_type_dump(); #endif /* __GST_TYPE_H__ */ diff --git a/plugins/elements/gstaudiosink.c b/plugins/elements/gstaudiosink.c index b363db2aa5..1c1eea8e70 100644 --- a/plugins/elements/gstaudiosink.c +++ b/plugins/elements/gstaudiosink.c @@ -133,9 +133,9 @@ gst_audiosink_class_init(GstAudioSinkClass *klass) { static void gst_audiosink_init(GstAudioSink *audiosink) { audiosink->sinkpad = gst_pad_new("sink",GST_PAD_SINK); gst_element_add_pad(GST_ELEMENT(audiosink),audiosink->sinkpad); - if (!gst_audiosink_type_audio) - gst_audiosink_type_audio = gst_type_find_by_mime("audio/raw"); + gst_pad_set_type_id(audiosink->sinkpad,gst_audiosink_type_audio); + gst_pad_set_chain_function(audiosink->sinkpad,gst_audiosink_chain); audiosink->fd = -1; @@ -342,3 +342,14 @@ static GstElementStateReturn gst_audiosink_change_state(GstElement *element) { return GST_ELEMENT_CLASS(parent_class)->change_state(element); return GST_STATE_SUCCESS; } + +gboolean gst_audiosink_factory_init(GstElementFactory *factory) { + + if (!gst_audiosink_type_audio) + gst_audiosink_type_audio = gst_type_find_by_mime("audio/raw"); + + gst_type_add_sink(gst_audiosink_type_audio, factory); + + return TRUE; +} + diff --git a/plugins/elements/gstaudiosink.h b/plugins/elements/gstaudiosink.h index 45ffa1fac6..03e1faa689 100644 --- a/plugins/elements/gstaudiosink.h +++ b/plugins/elements/gstaudiosink.h @@ -79,6 +79,8 @@ struct _GstAudioSinkClass { GtkType gst_audiosink_get_type(void); +gboolean gst_audiosink_factory_init(GstElementFactory *factory); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/plugins/elements/gstelements.c b/plugins/elements/gstelements.c index e7464e3bd3..9900496a47 100644 --- a/plugins/elements/gstelements.c +++ b/plugins/elements/gstelements.c @@ -42,25 +42,26 @@ struct _elements_entry { gchar *name; GtkType (*type) (void); GstElementDetails *details; + gboolean (*factoryinit) (GstElementFactory *factory); }; struct _elements_entry _elements[] = { - { "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details }, - { "fakesink", gst_fakesink_get_type, &gst_fakesink_details }, - { "asyncdisksrc", gst_asyncdisksrc_get_type, &gst_asyncdisksrc_details }, - { "audiosink", gst_audiosink_get_type, &gst_audiosink_details }, - { "audiosrc", gst_audiosrc_get_type, &gst_audiosrc_details }, - { "disksrc", gst_disksrc_get_type, &gst_disksrc_details }, - { "identity", gst_identity_get_type, &gst_identity_details }, - { "fdsink", gst_fdsink_get_type, &gst_fdsink_details }, - { "fdsrc", gst_fdsrc_get_type, &gst_fdsrc_details }, + { "fakesrc", gst_fakesrc_get_type, &gst_fakesrc_details, NULL }, + { "fakesink", gst_fakesink_get_type, &gst_fakesink_details, NULL }, + { "asyncdisksrc", gst_asyncdisksrc_get_type, &gst_asyncdisksrc_details, NULL }, + { "audiosink", gst_audiosink_get_type, &gst_audiosink_details, gst_audiosink_factory_init }, + { "audiosrc", gst_audiosrc_get_type, &gst_audiosrc_details, NULL }, + { "disksrc", gst_disksrc_get_type, &gst_disksrc_details, NULL }, + { "identity", gst_identity_get_type, &gst_identity_details, NULL }, + { "fdsink", gst_fdsink_get_type, &gst_fdsink_details, NULL }, + { "fdsrc", gst_fdsrc_get_type, &gst_fdsrc_details, NULL }, #if HAVE_LIBGHTTP - { "httpsrc", gst_httpsrc_get_type, &gst_httpsrc_details }, + { "httpsrc", gst_httpsrc_get_type, &gst_httpsrc_details, NULL }, #endif /* HAVE_LIBGHTTP */ - { "pipefilter", gst_pipefilter_get_type, &gst_pipefilter_details }, - { "queue", gst_queue_get_type, &gst_queue_details }, - { "sinesrc", gst_sinesrc_get_type, &gst_sinesrc_details }, - { "typefind", gst_typefind_get_type, &gst_typefind_details }, + { "pipefilter", gst_pipefilter_get_type, &gst_pipefilter_details, NULL }, + { "queue", gst_queue_get_type, &gst_queue_details, NULL }, + { "sinesrc", gst_sinesrc_get_type, &gst_sinesrc_details, NULL }, + { "typefind", gst_typefind_get_type, &gst_typefind_details, NULL }, { NULL, 0 }, }; @@ -82,7 +83,10 @@ GstPlugin *plugin_init(GModule *module) { _elements[i].details); if (factory != NULL) { gst_plugin_add_factory(plugin,factory); -// DEBUG("added factory '%s'\n",_elements[i].name); + if (_elements[i].factoryinit) { + _elements[i].factoryinit(factory); + } +// g_print("added factory '%s'\n",_elements[i].name); } i++; }