From: Wim Taymans Date: Mon, 12 Mar 2001 21:02:12 +0000 (+0000) Subject: Merged the CAPSNEGO1 branch.. X-Git-Tag: BRANCH-INCSCHED1-200104161-ROOT~62 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3ec275832ac76431cd2efb853dc80d970568d6f6;p=platform%2Fupstream%2Fgstreamer.git Merged the CAPSNEGO1 branch.. Original commit message from CVS: Merged the CAPSNEGO1 branch.. --- diff --git a/configure.in b/configure.in index cf5e0b8..8a126eb 100644 --- a/configure.in +++ b/configure.in @@ -770,6 +770,7 @@ tests/Makefile tests/sched/Makefile tests/eos/Makefile testsuite/Makefile +tests/nego/Makefile examples/Makefile examples/autoplug/Makefile examples/helloworld/Makefile diff --git a/docs/random/wtay/caps-negociation b/docs/random/wtay/caps-negociation index 1207cd9..ad72b9b 100644 --- a/docs/random/wtay/caps-negociation +++ b/docs/random/wtay/caps-negociation @@ -128,7 +128,7 @@ the element when it knows the values for the caps. ----------------------- when two pads are connected the following steps will take -placei (not sure, FIXME): +place (not sure, FIXME): - if both pads have caps, the caps are checked. If the caps are incompatible, the padtemplates are checked, if they diff --git a/editor/gsteditorproperty.c b/editor/gsteditorproperty.c index 2e5e05a..ca77aed 100644 --- a/editor/gsteditorproperty.c +++ b/editor/gsteditorproperty.c @@ -329,14 +329,14 @@ gst_editor_pads_create (GstEditorProperty *property, GstEditorElement *element) while (pads) { GstPad *pad = (GstPad *)pads->data; - GList *caps = gst_pad_get_caps_list (pad); + GstCaps *caps = gst_pad_get_caps (pad); gchar *mime; gchar *data[2]; GtkCTreeNode *padnode; if (caps) { GstType *type; - type = gst_type_find_by_id (((GstCaps *)caps->data)->id); + type = gst_type_find_by_id (caps->id); mime = type->mime; } else { @@ -348,13 +348,8 @@ gst_editor_pads_create (GstEditorProperty *property, GstEditorElement *element) padnode = gtk_ctree_insert_node (GTK_CTREE (tree), NULL, NULL, data, 0, NULL, NULL, NULL, NULL, FALSE, TRUE); - while (caps) { - GstCaps *cap = (GstCaps *)caps->data; - gst_editor_add_caps_to_tree (cap, tree, padnode); - - caps = g_list_next (caps); - } + gst_editor_add_caps_to_tree (caps, tree, padnode); pads = g_list_next (pads); } diff --git a/gst/autoplug/gststaticautoplug.c b/gst/autoplug/gststaticautoplug.c index a39ac57..7d42d4b 100644 --- a/gst/autoplug/gststaticautoplug.c +++ b/gst/autoplug/gststaticautoplug.c @@ -41,7 +41,7 @@ static GList* gst_autoplug_func (gpointer src, gpointer sink, static GstElement* gst_static_autoplug_to_caps (GstAutoplug *autoplug, - GList *srccaps, GList *sinkcaps, va_list args); + GstCaps *srccaps, GstCaps *sinkcaps, va_list args); static GstAutoplugClass *parent_class = NULL; @@ -118,7 +118,8 @@ gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest) if (srctemp->direction == GST_PAD_SRC && desttemp->direction == GST_PAD_SINK) { - if (gst_caps_list_check_compatibility (srctemp->caps, desttemp->caps)) { + if (gst_caps_check_compatibility (gst_padtemplate_get_caps (srctemp), + gst_padtemplate_get_caps (desttemp))) { GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT, "factory \"%s\" can connect with factory \"%s\"", src->name, dest->name); return TRUE; @@ -151,7 +152,7 @@ gst_autoplug_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink) 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))) { + if (gst_caps_check_compatibility (gst_pad_get_caps(pad), gst_pad_get_caps(sinkpad))) { gst_pad_connect(pad, sinkpad); GST_DEBUG (0,"gstpipeline: autoconnect pad \"%s\" in element %s <-> ", GST_PAD_NAME (pad), GST_ELEMENT_NAME(src)); @@ -175,7 +176,7 @@ gst_autoplug_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink) typedef struct { GstElement *result; - GList *endcap; + GstCaps *endcap; gint i; } dynamic_pad_struct; @@ -190,9 +191,10 @@ autoplug_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) while (pads) { GstPad *pad = GST_PAD (pads->data); + GstPadTemplate *templ = GST_PAD_PADTEMPLATE (pad); pads = g_list_next (pads); - if (gst_caps_list_check_compatibility (gst_pad_get_caps_list (pad), info->endcap)) { + if (gst_caps_check_compatibility (GST_PADTEMPLATE_CAPS (templ), info->endcap)) { gst_element_add_ghost_pad (info->result, pad, g_strdup_printf("src_%02d", info->i)); GST_DEBUG (0,"gstpipeline: new dynamic pad %s\n", GST_PAD_NAME (pad)); break; @@ -232,8 +234,8 @@ gst_autoplug_elementfactory_get_list (gpointer data) } typedef struct { - GList *src; - GList *sink; + GstCaps *src; + GstCaps *sink; } caps_struct; #define IS_CAPS(cap) (((cap) == caps->src) || (cap) == caps->sink) @@ -245,16 +247,13 @@ gst_autoplug_caps_find_cost (gpointer src, gpointer dest, gpointer data) gboolean res; 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); + res = gst_caps_check_compatibility ((GstCaps *)src, (GstCaps *)dest); } 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); + res = gst_elementfactory_can_sink_caps ((GstElementFactory *)dest, (GstCaps *)src); } 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); + res = gst_elementfactory_can_src_caps ((GstElementFactory *)src, (GstCaps *)dest); } else { res = gst_autoplug_can_match ((GstElementFactory *)src, (GstElementFactory *)dest); @@ -267,10 +266,10 @@ gst_autoplug_caps_find_cost (gpointer src, gpointer dest, gpointer data) } static GstElement* -gst_static_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, va_list args) +gst_static_autoplug_to_caps (GstAutoplug *autoplug, GstCaps *srccaps, GstCaps *sinkcaps, va_list args) { caps_struct caps; - GList *capslist; + GstCaps *capslist; GstElement *result = NULL, *srcelement = NULL; GList **factories; GList *chains = NULL; @@ -307,7 +306,7 @@ gst_static_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkc else { } - capslist = va_arg (args, GList *); + capslist = va_arg (args, GstCaps *); } /* @@ -376,8 +375,9 @@ gst_static_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkc while (pads) { GstPad *pad = GST_PAD (pads->data); + GstPadTemplate *templ = GST_PAD_PADTEMPLATE (pad); - if (gst_caps_list_check_compatibility (srccaps, gst_pad_get_caps_list (pad))) { + if (gst_caps_check_compatibility (srccaps, GST_PADTEMPLATE_CAPS (templ))) { gst_element_add_ghost_pad (result, pad, "sink"); break; } @@ -430,7 +430,7 @@ differ: * find a suitable pad to turn into a ghostpad */ { - GList *endcap = (GList *)(endcaps->data); + GstCaps *endcap = (GstCaps *)(endcaps->data); GList *pads = gst_element_get_pad_list (thesrcelement); gboolean have_pad = FALSE; endcaps = g_list_next (endcaps); @@ -439,9 +439,10 @@ differ: while (pads) { GstPad *pad = GST_PAD (pads->data); + GstPadTemplate *templ = GST_PAD_PADTEMPLATE (pad); pads = g_list_next (pads); - if (gst_caps_list_check_compatibility (gst_pad_get_caps_list (pad), endcap)) { + if (gst_caps_check_compatibility (GST_PADTEMPLATE_CAPS (templ), endcap)) { gst_element_add_ghost_pad (result, pad, g_strdup_printf("src_%02d", i)); have_pad = TRUE; break; diff --git a/gst/autoplug/gststaticautoplugrender.c b/gst/autoplug/gststaticautoplugrender.c index 5533d69..180c29f 100644 --- a/gst/autoplug/gststaticautoplugrender.c +++ b/gst/autoplug/gststaticautoplugrender.c @@ -41,7 +41,7 @@ static GList* gst_autoplug_func (gpointer src, gpointer sink, static GstElement* gst_static_autoplug_to_render (GstAutoplug *autoplug, - GList *srccaps, GstElement *target, va_list args); + GstCaps *srccaps, GstElement *target, va_list args); static GstAutoplugClass *parent_class = NULL; @@ -118,7 +118,7 @@ gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest) if (srctemp->direction == GST_PAD_SRC && desttemp->direction == GST_PAD_SINK) { - if (gst_caps_list_check_compatibility (srctemp->caps, desttemp->caps)) { + if (gst_caps_check_compatibility (GST_PADTEMPLATE_CAPS (srctemp), GST_PADTEMPLATE_CAPS (desttemp))) { GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT, "factory \"%s\" can connect with factory \"%s\"", src->name, dest->name); return TRUE; @@ -148,20 +148,14 @@ gst_autoplug_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink) 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_pad_get_direction(sinkpad) == GST_PAD_SINK && + !GST_PAD_CONNECTED (pad) && !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; + if ((connected = gst_pad_connect (pad, sinkpad))) { + break; } else { - GST_DEBUG (0,"pads incompatible %s, %s\n", GST_PAD_NAME (pad), GST_PAD_NAME (sinkpad)); + GST_DEBUG (0,"pads incompatible %s, %s\n", GST_PAD_NAME (pad), GST_PAD_NAME (sinkpad)); } } sinkpads = g_list_next(sinkpads); @@ -173,33 +167,6 @@ gst_autoplug_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink) return connected; } -typedef struct { - GstElement *result; - GList *endcap; - gint i; -} dynamic_pad_struct; - -static void -autoplug_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) -{ - dynamic_pad_struct *info = (dynamic_pad_struct *)data; - GList *pads = gst_element_get_pad_list (element); - - GST_DEBUG (0,"attempting to dynamically create a ghostpad for %s=%s\n", GST_ELEMENT_NAME (element), - GST_PAD_NAME (pad)); - - 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), info->endcap)) { - gst_element_add_ghost_pad (info->result, pad, g_strdup_printf("src_%02d", info->i)); - GST_DEBUG (0,"gstpipeline: new dynamic pad %s\n", GST_PAD_NAME (pad)); - break; - } - } -} - static void gst_autoplug_pads_autoplug (GstElement *src, GstElement *sink) { @@ -211,8 +178,11 @@ gst_autoplug_pads_autoplug (GstElement *src, GstElement *sink) while (srcpads && !connected) { GstPad *srcpad = (GstPad *)srcpads->data; - if (gst_pad_get_direction(srcpad) == GST_PAD_SRC) + if (gst_pad_get_direction(srcpad) == GST_PAD_SRC) { connected = gst_autoplug_pads_autoplug_func (src, srcpad, sink); + if (connected) + break; + } srcpads = g_list_next(srcpads); } @@ -234,8 +204,8 @@ gst_autoplug_elementfactory_get_list (gpointer data) } typedef struct { - GList *src; - GList *sink; + GstCaps *src; + GstCaps *sink; } caps_struct; #define IS_CAPS(cap) (((cap) == caps->src) || (cap) == caps->sink) @@ -247,15 +217,15 @@ gst_autoplug_caps_find_cost (gpointer src, gpointer dest, gpointer data) gboolean res; if (IS_CAPS (src) && IS_CAPS (dest)) { - res = gst_caps_list_check_compatibility ((GList *)src, (GList *)dest); + res = gst_caps_check_compatibility ((GstCaps *)src, (GstCaps *)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); + res = gst_elementfactory_can_sink_caps ((GstElementFactory *)dest, (GstCaps *)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); + res = gst_elementfactory_can_src_caps ((GstElementFactory *)src, (GstCaps *)dest); //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to sink caps %d %d", ((GstElementFactory *)src)->name, ((GstCaps *)dest)->id, res); } else { @@ -269,7 +239,7 @@ gst_autoplug_caps_find_cost (gpointer src, gpointer dest, gpointer data) } static GstElement* -gst_static_autoplug_to_render (GstAutoplug *autoplug, GList *srccaps, GstElement *target, va_list args) +gst_static_autoplug_to_render (GstAutoplug *autoplug, GstCaps *srccaps, GstElement *target, va_list args) { caps_struct caps; GstElement *targetelement; @@ -292,10 +262,12 @@ gst_static_autoplug_to_render (GstAutoplug *autoplug, GList *srccaps, GstElement while (targetelement) { GList *elements; GstPad *pad; + GstPadTemplate *templ; pad = GST_PAD (gst_element_get_pad_list (targetelement)->data); + templ = GST_PAD_PADTEMPLATE (pad); - caps.sink = gst_pad_get_caps_list (pad); + caps.sink = GST_PADTEMPLATE_CAPS (templ); GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps structures"); @@ -381,8 +353,9 @@ gst_static_autoplug_to_render (GstAutoplug *autoplug, GList *srccaps, GstElement while (pads) { GstPad *pad = GST_PAD (pads->data); + GstPadTemplate *templ = GST_PAD_PADTEMPLATE (pad); - if (gst_caps_list_check_compatibility (srccaps, gst_pad_get_caps_list (pad))) { + if (gst_caps_check_compatibility (srccaps, GST_PADTEMPLATE_CAPS (templ))) { gst_element_add_ghost_pad (result, pad, "sink"); break; } @@ -435,8 +408,7 @@ differ: // 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; + GstPad *srcpad; use_thread = FALSE; @@ -453,22 +425,6 @@ differ: 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)); diff --git a/gst/elements/gstaudiosink.c b/gst/elements/gstaudiosink.c index 1027729..5499e3a 100644 --- a/gst/elements/gstaudiosink.c +++ b/gst/elements/gstaudiosink.c @@ -417,8 +417,9 @@ gst_audiosink_change_state (GstElement *element) /* otherwise (READY or higher) we need to open the sound card */ } else { if (!GST_FLAG_IS_SET (element, GST_AUDIOSINK_OPEN)) { - if (!gst_audiosink_open_audio (GST_AUDIOSINK (element))) - return GST_STATE_FAILURE; + if (!gst_audiosink_open_audio (GST_AUDIOSINK (element))) { + //return GST_STATE_FAILURE; + } } } diff --git a/gst/gstautoplug.c b/gst/gstautoplug.c index 3f74b25..dc2c017 100644 --- a/gst/gstautoplug.c +++ b/gst/gstautoplug.c @@ -102,7 +102,7 @@ gst_autoplug_signal_new_object (GstAutoplug *autoplug, GstObject *object) GstElement* -gst_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, ...) +gst_autoplug_to_caps (GstAutoplug *autoplug, GstCaps *srccaps, GstCaps *sinkcaps, ...) { GstAutoplugClass *oclass; GstElement *element = NULL; @@ -120,7 +120,7 @@ gst_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, .. } GstElement* -gst_autoplug_to_renderers (GstAutoplug *autoplug, GList *srccaps, GstElement *target, ...) +gst_autoplug_to_renderers (GstAutoplug *autoplug, GstCaps *srccaps, GstElement *target, ...) { GstAutoplugClass *oclass; GstElement *element = NULL; diff --git a/gst/gstautoplug.h b/gst/gstautoplug.h index 14d96d5..6bb03c6 100644 --- a/gst/gstautoplug.h +++ b/gst/gstautoplug.h @@ -63,8 +63,8 @@ struct _GstAutoplugClass { void (*new_object) (GstAutoplug *autoplug, GstObject *object); /* perform the autoplugging */ - GstElement* (*autoplug_to_caps) (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, va_list args); - GstElement* (*autoplug_to_renderers) (GstAutoplug *autoplug, GList *srccaps, GstElement *target, va_list args); + GstElement* (*autoplug_to_caps) (GstAutoplug *autoplug, GstCaps *srccaps, GstCaps *sinkcaps, va_list args); + GstElement* (*autoplug_to_renderers) (GstAutoplug *autoplug, GstCaps *srccaps, GstElement *target, va_list args); }; typedef struct _GstAutoplugFactory GstAutoplugFactory; @@ -79,8 +79,8 @@ GtkType gst_autoplug_get_type (void); void gst_autoplug_signal_new_object (GstAutoplug *autoplug, GstObject *object); -GstElement* gst_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, ...); -GstElement* gst_autoplug_to_renderers (GstAutoplug *autoplug, GList *srccaps, +GstElement* gst_autoplug_to_caps (GstAutoplug *autoplug, GstCaps *srccaps, GstCaps *sinkcaps, ...); +GstElement* gst_autoplug_to_renderers (GstAutoplug *autoplug, GstCaps *srccaps, GstElement *target, ...); diff --git a/gst/gstcaps.c b/gst/gstcaps.c index ebdaccc..24e45b8 100644 --- a/gst/gstcaps.c +++ b/gst/gstcaps.c @@ -72,6 +72,7 @@ gst_caps_new (const gchar *name, const gchar *mime) caps->name = g_strdup (name); caps->id = get_type_for_mime (mime); caps->properties = NULL; + caps->next = NULL; return caps; } @@ -297,20 +298,77 @@ gst_caps_get_props (GstCaps *caps) } /** - * gst_caps_check_compatibility: - * @fromcaps: a capabilty - * @tocaps: a capabilty + * gst_caps_append: + * @caps: a capabilty + * @capstoadd: the capability to append * - * Checks whether two capabilities are compatible. + * Appends a capability to the existing capability. * - * Returns: TRUE if compatible, FALSE otherwise + * Returns: the new capability */ -gboolean -gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps) +GstCaps* +gst_caps_append (GstCaps *caps, GstCaps *capstoadd) { - g_return_val_if_fail (fromcaps != NULL, FALSE); - g_return_val_if_fail (tocaps != NULL, FALSE); + GstCaps *orig = caps; + + if (caps == NULL) + return capstoadd; + + while (caps->next) { + caps = caps->next; + } + caps->next = capstoadd; + + return orig; +} + +/** + * gst_caps_prepend: + * @caps: a capabilty + * @capstoadd: a capabilty to prepend + * + * prepend the capability to the list of capabilities + * + * Returns: the new capability + */ +GstCaps* +gst_caps_prepend (GstCaps *caps, GstCaps *capstoadd) +{ + GstCaps *orig = capstoadd; + + if (capstoadd == NULL) + return caps; + + while (capstoadd->next) { + capstoadd = capstoadd->next; + } + capstoadd->next = caps; + return orig; +} + +GstCaps* +gst_caps_get_by_name (GstCaps *caps, const gchar *name) +{ + g_return_val_if_fail (caps != NULL, NULL); + g_return_val_if_fail (name != NULL, NULL); + + while (caps) { + if (!strcmp (caps->name, name)) + return caps; + caps = caps->next; + } + + return NULL; +} + +static gboolean +gst_caps_check_compatibility_func (GstCaps *fromcaps, GstCaps *tocaps) +{ + if (fromcaps == NULL || + tocaps == NULL) + return TRUE; + if (fromcaps->id != tocaps->id) { GST_DEBUG (0,"gstcaps: mime types differ (%d to %d)\n", fromcaps->id, tocaps->id); @@ -343,21 +401,18 @@ gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps) * Returns: TRUE if compatible, FALSE otherwise */ gboolean -gst_caps_list_check_compatibility (GList *fromcaps, GList *tocaps) +gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps) { while (fromcaps) { - GstCaps *fromcap = (GstCaps *)fromcaps->data; - GList *destcaps = tocaps; + GstCaps *destcaps = tocaps; while (destcaps) { - GstCaps *destcap = (GstCaps *)destcaps->data; - - if (gst_caps_check_compatibility (fromcap, destcap)) + if (gst_caps_check_compatibility_func (fromcaps, destcaps)) return TRUE; - destcaps = g_list_next (destcaps); + destcaps = destcaps->next; } - fromcaps = g_list_next (fromcaps); + fromcaps = fromcaps->next; } return FALSE; } @@ -375,15 +430,20 @@ xmlNodePtr gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent) { xmlNodePtr subtree; + xmlNodePtr subsubtree; - g_return_val_if_fail (caps != NULL, NULL); + while (caps) { + subtree = xmlNewChild (parent, NULL, "capscomp", NULL); - xmlNewChild (parent, NULL, "name", caps->name); - xmlNewChild (parent, NULL, "type", gst_type_find_by_id (caps->id)->mime); - if (caps->properties) { - subtree = xmlNewChild (parent, NULL, "properties", NULL); + xmlNewChild (subtree, NULL, "name", caps->name); + xmlNewChild (subtree, NULL, "type", gst_type_find_by_id (caps->id)->mime); + if (caps->properties) { + subsubtree = xmlNewChild (subtree, NULL, "properties", NULL); - gst_props_save_thyself (caps->properties, subtree); + gst_props_save_thyself (caps->properties, subsubtree); + } + + caps = caps->next; } return parent; @@ -400,26 +460,36 @@ gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent) GstCaps* gst_caps_load_thyself (xmlNodePtr parent) { - GstCaps *caps = g_new0 (GstCaps, 1); + GstCaps *result = NULL; xmlNodePtr field = parent->xmlChildrenNode; - gchar *content; while (field) { - if (!strcmp (field->name, "name")) { - caps->name = xmlNodeGetContent (field); - } - if (!strcmp (field->name, "type")) { - content = xmlNodeGetContent (field); - caps->id = get_type_for_mime (content); - g_free (content); - } - else if (!strcmp (field->name, "properties")) { - caps->properties = gst_props_load_thyself (field); + if (!strcmp (field->name, "capscomp")) { + xmlNodePtr subfield = field->xmlChildrenNode; + GstCaps *caps = g_new0 (GstCaps, 1); + gchar *content; + + while (subfield) { + if (!strcmp (subfield->name, "name")) { + caps->name = xmlNodeGetContent (subfield); + } + if (!strcmp (subfield->name, "type")) { + content = xmlNodeGetContent (subfield); + caps->id = get_type_for_mime (content); + g_free (content); + } + else if (!strcmp (subfield->name, "properties")) { + caps->properties = gst_props_load_thyself (subfield); + } + + subfield = subfield->next; + } + result = gst_caps_append (result, caps); } field = field->next; } - return caps; + return result; } diff --git a/gst/gstcaps.h b/gst/gstcaps.h index dffa1cd..8bb6256 100644 --- a/gst/gstcaps.h +++ b/gst/gstcaps.h @@ -49,6 +49,8 @@ struct _GstCaps { guint16 id; /* type id (major type) */ GstProps *properties; /* properties for this capability */ + + GstCaps *next; }; /* initialize the subsystem */ @@ -71,8 +73,12 @@ void gst_caps_set_type_id (GstCaps *caps, guint16 type_id); GstCaps* gst_caps_set_props (GstCaps *caps, GstProps *props); GstProps* gst_caps_get_props (GstCaps *caps); +GstCaps* gst_caps_get_by_name (GstCaps *caps, const gchar *name); + +GstCaps* gst_caps_append (GstCaps *caps, GstCaps *capstoadd); +GstCaps* gst_caps_prepend (GstCaps *caps, GstCaps *capstoadd); + gboolean gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps); -gboolean gst_caps_list_check_compatibility (GList *fromcaps, GList *tocaps); xmlNodePtr gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent); GstCaps* gst_caps_load_thyself (xmlNodePtr parent); diff --git a/gst/gstelement.c b/gst/gstelement.c index e8dc9ce..7241b40 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -461,14 +461,14 @@ gst_element_get_padtemplate_by_compatible (GstElement *element, GstPadTemplate * if (padtempl->direction == GST_PAD_SRC && compattempl->direction == GST_PAD_SINK) { GST_DEBUG(0,"compatible direction: found src pad template\n"); - compat = gst_caps_list_check_compatibility(padtempl->caps, - compattempl->caps); + compat = gst_caps_check_compatibility(GST_PADTEMPLATE_CAPS (padtempl), + GST_PADTEMPLATE_CAPS (compattempl)); GST_DEBUG(0,"caps are %scompatible\n", (compat?"":"not ")); } else if (padtempl->direction == GST_PAD_SINK && compattempl->direction == GST_PAD_SRC) { GST_DEBUG(0,"compatible direction: found sink pad template\n"); - compat = gst_caps_list_check_compatibility(compattempl->caps, - padtempl->caps); + compat = gst_caps_check_compatibility(GST_PADTEMPLATE_CAPS (compattempl), + GST_PADTEMPLATE_CAPS (padtempl)); GST_DEBUG(0,"caps are %scompatible\n", (compat?"":"not ")); } diff --git a/gst/gstelement.h b/gst/gstelement.h index 655d18f..87cae5e 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -251,10 +251,10 @@ gboolean gst_elementfactory_can_src_caps (GstElementFactory *factory, GstCaps *caps); gboolean gst_elementfactory_can_sink_caps (GstElementFactory *factory, GstCaps *caps); -gboolean gst_elementfactory_can_src_caps_list (GstElementFactory *factory, - GList *caps); -gboolean gst_elementfactory_can_sink_caps_list (GstElementFactory *factory, - GList *caps); +gboolean gst_elementfactory_can_src_caps (GstElementFactory *factory, + GstCaps *caps); +gboolean gst_elementfactory_can_sink_caps (GstElementFactory *factory, + GstCaps *caps); GstElement* gst_elementfactory_create (GstElementFactory *factory, const gchar *name); diff --git a/gst/gstelementfactory.c b/gst/gstelementfactory.c index eced12e..997cb20 100644 --- a/gst/gstelementfactory.c +++ b/gst/gstelementfactory.c @@ -222,17 +222,17 @@ gst_elementfactory_add_padtemplate (GstElementFactory *factory, } /** - * gst_elementfactory_can_src_caps_list : + * gst_elementfactory_can_src_caps : * @factory: factory to query - * @caps: the caps list to check + * @caps: the caps to check * - * Checks if the factory can source the given capability list. + * Checks if the factory can source the given capability. * * Returns: true if it can src the capabilities */ gboolean -gst_elementfactory_can_src_caps_list (GstElementFactory *factory, - GList *caps) +gst_elementfactory_can_src_caps (GstElementFactory *factory, + GstCaps *caps) { GList *templates; @@ -245,7 +245,7 @@ gst_elementfactory_can_src_caps_list (GstElementFactory *factory, GstPadTemplate *template = (GstPadTemplate *)templates->data; if (template->direction == GST_PAD_SRC) { - if (gst_caps_list_check_compatibility (template->caps, caps)) + if (gst_caps_check_compatibility (GST_PADTEMPLATE_CAPS (template), caps)) return TRUE; } templates = g_list_next (templates); @@ -255,17 +255,17 @@ gst_elementfactory_can_src_caps_list (GstElementFactory *factory, } /** - * gst_elementfactory_can_sink_caps_list : + * gst_elementfactory_can_sink_caps : * @factory: factory to query - * @caps: the caps list to check + * @caps: the caps to check * - * Checks if the factory can sink the given capability list. + * Checks if the factory can sink the given capability. * * Returns: true if it can sink the capabilities */ gboolean -gst_elementfactory_can_sink_caps_list (GstElementFactory *factory, - GList *caps) +gst_elementfactory_can_sink_caps (GstElementFactory *factory, + GstCaps *caps) { GList *templates; @@ -278,7 +278,7 @@ gst_elementfactory_can_sink_caps_list (GstElementFactory *factory, GstPadTemplate *template = (GstPadTemplate *)templates->data; if (template->direction == GST_PAD_SINK) { - if (gst_caps_list_check_compatibility (caps, template->caps)) + if (gst_caps_check_compatibility (caps, GST_PADTEMPLATE_CAPS (template))) return TRUE; } templates = g_list_next (templates); @@ -288,56 +288,6 @@ gst_elementfactory_can_sink_caps_list (GstElementFactory *factory, } /** - * gst_elementfactory_can_src_caps : - * @factory: factory to query - * @caps: the caps to check - * - * Checks if the factory can src the given capability. - * - * Returns: true if it can sink the capability - */ -gboolean -gst_elementfactory_can_src_caps (GstElementFactory *factory, - GstCaps *caps) -{ - GList *dummy; - gboolean ret; - - dummy = g_list_prepend (NULL, caps); - - ret = gst_elementfactory_can_src_caps_list (factory, dummy); - - g_list_free (dummy); - - return ret; -} - -/** - * gst_elementfactory_can_sink_caps : - * @factory: factory to query - * @caps: the caps to check - * - * Checks if the factory can sink the given capability. - * - * Returns: true if it can sink the capability - */ -gboolean -gst_elementfactory_can_sink_caps (GstElementFactory *factory, - GstCaps *caps) -{ - GList *dummy; - gboolean ret; - - dummy = g_list_prepend (NULL, caps); - - ret = gst_elementfactory_can_sink_caps_list (factory, dummy); - - g_list_free (dummy); - - return ret; -} - -/** * gst_elementfactory_save_thyself: * @factory: factory to save * @parent: the parent xmlNodePtr diff --git a/gst/gstpad.c b/gst/gstpad.c index e613add..4aaab8d 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -259,8 +259,8 @@ gst_pad_new_from_template (GstPadTemplate *templ, g_return_val_if_fail (templ != NULL, NULL); pad = gst_pad_new (name, templ->direction); - GST_PAD_CAPS(pad) = templ->caps; GST_PAD_PADTEMPLATE(pad) = templ; + GST_PAD_CAPS (pad) = GST_PADTEMPLATE_CAPS (templ); return pad; } @@ -410,6 +410,25 @@ gst_pad_set_eos_function (GstPad *pad, GST_DEBUG_PAD_NAME(pad),pad,&GST_RPAD_EOSFUNC(pad),eos); } +/** + * gst_pad_set_eos_function: + * @pad: the pad to set the eos function for + * @eos: the eos function + * + * Set the given EOS function for the pad. + */ +void +gst_pad_set_negotiate_function (GstPad *pad, + GstPadNegotiateFunction nego) +{ + g_return_if_fail (pad != NULL); + g_return_if_fail (GST_IS_REAL_PAD (pad)); + + GST_RPAD_NEGOTIATEFUNC(pad) = nego; + GST_DEBUG (0,"negotiatefunc for %s:%s(@%p) at %p is set to %p\n", + GST_DEBUG_PAD_NAME(pad),pad,&GST_RPAD_NEGOTIATEFUNC(pad),nego); +} + static void @@ -503,26 +522,32 @@ gst_pad_disconnect (GstPad *srcpad, * @sinkpad: the sink pad to connect * * Connects the source pad to the sink pad. + * + * Returns: TRUE if the pad could be connected */ -void +gboolean gst_pad_connect (GstPad *srcpad, GstPad *sinkpad) { GstRealPad *realsrc, *realsink; GstRealPad *temppad; + gboolean negotiated = FALSE; /* generic checks */ - g_return_if_fail(srcpad != NULL); - g_return_if_fail(GST_IS_PAD(srcpad)); - g_return_if_fail(sinkpad != NULL); - g_return_if_fail(GST_IS_PAD(sinkpad)); + g_return_val_if_fail(srcpad != NULL, FALSE); + g_return_val_if_fail(GST_IS_PAD(srcpad), FALSE); + g_return_val_if_fail(sinkpad != NULL, FALSE); + g_return_val_if_fail(GST_IS_PAD(sinkpad), FALSE); + + GST_INFO (GST_CAT_ELEMENT_PADS, "about to connect %s:%s and %s:%s", + GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad)); // now we need to deal with the real/ghost stuff realsrc = GST_PAD_REALIZE(srcpad); realsink = GST_PAD_REALIZE(sinkpad); - g_return_if_fail(GST_RPAD_PEER(realsrc) == NULL); - g_return_if_fail(GST_RPAD_PEER(realsink) == NULL); + g_return_val_if_fail(GST_RPAD_PEER(realsrc) == NULL, FALSE); + g_return_val_if_fail(GST_RPAD_PEER(realsink) == NULL, FALSE); /* check for reversed directions and swap if necessary */ if ((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SINK) && @@ -531,27 +556,31 @@ gst_pad_connect (GstPad *srcpad, realsrc = realsink; realsink = temppad; } - g_return_if_fail((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SRC) && - (GST_RPAD_DIRECTION(realsink) == GST_PAD_SINK)); + g_return_val_if_fail((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SRC) && + (GST_RPAD_DIRECTION(realsink) == GST_PAD_SINK), FALSE); - if (!gst_pad_check_compatibility (srcpad, sinkpad)) { - g_warning ("gstpad: connecting incompatible pads (%s:%s) and (%s:%s)\n", - GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); - } - else { - GST_DEBUG (0,"gstpad: connecting compatible pads (%s:%s) and (%s:%s)\n", - GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); - } /* first set peers */ GST_RPAD_PEER(realsrc) = realsink; GST_RPAD_PEER(realsink) = realsrc; - /* set the connected flag */ /* FIXME: set connected flag */ GST_INFO (GST_CAT_ELEMENT_PADS, "connected %s:%s and %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad)); + + if (GST_PAD_CAPS (srcpad)) { + negotiated = gst_pad_renegotiate (srcpad); + } + else { + negotiated = gst_pad_renegotiate (sinkpad); + } + + if (!negotiated) { + gst_pad_disconnect (srcpad, sinkpad); + return FALSE; + } + return TRUE; } /** @@ -583,6 +612,23 @@ gst_pad_set_parent (GstPad *pad, * * Returns: the parent object */ +GstPadTemplate* +gst_pad_get_padtemplate (GstPad *pad) +{ + g_return_val_if_fail (pad != NULL, NULL); + g_return_val_if_fail (GST_IS_PAD (pad), NULL); + + return GST_PAD_PADTEMPLATE (pad); +} + +/** + * gst_pad_get_parent: + * @pad: the pad to get the parent from + * + * Get the parent object of this pad. + * + * Returns: the parent object + */ GstObject* gst_pad_get_parent (GstPad *pad) { @@ -676,20 +722,22 @@ gst_pad_get_ghost_pad_list (GstPad *pad) } /** - * gst_pad_set_caps_list: + * gst_pad_set_caps: * @pad: the pad to set the caps to * @caps: a GList of the capabilities to attach to this pad * * Set the capabilities of this pad. */ void -gst_pad_set_caps_list (GstPad *pad, - GList *caps) +gst_pad_set_caps (GstPad *pad, + GstCaps *caps) { g_return_if_fail (pad != NULL); g_return_if_fail (GST_IS_REAL_PAD (pad)); // NOTE this restriction GST_PAD_CAPS(pad) = caps; + + gst_pad_renegotiate (pad); } /** @@ -700,8 +748,8 @@ gst_pad_set_caps_list (GstPad *pad, * * Returns: a list of the capabilities of this pad */ -GList * -gst_pad_get_caps_list (GstPad *pad) +GstCaps* +gst_pad_get_caps (GstPad *pad) { g_return_val_if_fail (pad != NULL, NULL); g_return_val_if_fail (GST_IS_PAD (pad), NULL); @@ -718,26 +766,18 @@ gst_pad_get_caps_list (GstPad *pad) * * Returns: a capability or NULL if not found */ -GstCaps * -gst_pad_get_caps_by_name (GstPad *pad, gchar *name) +GstCaps* +gst_padtemplate_get_caps_by_name (GstPadTemplate *templ, const gchar *name) { - GList *caps; - - g_return_val_if_fail (pad != NULL, NULL); - g_return_val_if_fail (GST_IS_PAD (pad), NULL); + GstCaps *caps; - caps = GST_PAD_CAPS(pad); - - while (caps) { - GstCaps *cap = (GstCaps *)caps->data; - - if (!strcmp (cap->name, name)) - return cap; + g_return_val_if_fail (templ != NULL, NULL); - caps = g_list_next (caps); - } + caps = GST_PADTEMPLATE_CAPS (templ); + if (!caps) + return NULL; - return NULL; + return gst_caps_get_by_name (caps, name); } /** @@ -753,18 +793,13 @@ gst_pad_get_caps_by_name (GstPad *pad, gchar *name) gboolean gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad) { - GstRealPad *realsrc, *realsink; - g_return_val_if_fail (srcpad != NULL, FALSE); g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE); g_return_val_if_fail (sinkpad != NULL, FALSE); g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE); - realsrc = GST_PAD_REALIZE(srcpad); - realsink = GST_PAD_REALIZE(sinkpad); - - if (GST_RPAD_CAPS(realsrc) && GST_RPAD_CAPS(realsink)) { - if (!gst_caps_list_check_compatibility (GST_RPAD_CAPS(realsrc), GST_RPAD_CAPS(realsink))) { + if (GST_PAD_CAPS(srcpad) && GST_PAD_CAPS(sinkpad)) { + if (!gst_caps_check_compatibility (GST_PAD_CAPS(srcpad), GST_PAD_CAPS(sinkpad))) { return FALSE; } else { @@ -772,8 +807,9 @@ gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad) } } else { - GST_DEBUG (0,"gstpad: could not check capabilities of pads (%s:%s) and (%s:%s)\n", - GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); + GST_DEBUG (0,"gstpad: could not check capabilities of pads (%s:%s) and (%s:%s) %p %p\n", + GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad), + GST_PAD_CAPS (srcpad), GST_PAD_CAPS (sinkpad)); return TRUE; } } @@ -864,6 +900,143 @@ cleanup: g_strfreev (split); } +/** + * gst_pad_renegotiate: + * @pad: the pad to perform the negotiation on + * + * Perform the negotiation process with the peer pad. + * + * Returns: TRUE if the negotiation process succeded + */ +gboolean +gst_pad_renegotiate (GstPad *pad) +{ + gint counter = 0; + GstCaps *newcaps = NULL; + GstRealPad *peerpad, *currentpad, *otherpad; + GstCaps *currentcaps; + + g_return_val_if_fail (pad != NULL, FALSE); + + peerpad = GST_PAD_PEER (pad); + + currentpad = GST_PAD_REALIZE (pad); + + if (!peerpad) { + GST_DEBUG (GST_CAT_ELEMENT_PADS, "no peer pad for pad %s:%s\n", + GST_DEBUG_PAD_NAME(currentpad)); + return TRUE; + } + + otherpad = GST_REAL_PAD (peerpad); + + GST_INFO (GST_CAT_ELEMENT_PADS, "negotiating pad %s:%s and %s:%s", + GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(peerpad)); + + newcaps = GST_PAD_CAPS (pad); + + do { + currentcaps = newcaps; + + /* this pad wants to negotiate */ + if (currentpad->negotiatefunc) { + + GST_DEBUG (GST_CAT_ELEMENT_PADS, "calling negotiate function on pad %s:%s, count=%d\n", + GST_DEBUG_PAD_NAME(currentpad), counter); + newcaps = (currentpad->negotiatefunc) (GST_PAD (currentpad), currentcaps, counter); + + if (newcaps == NULL) { + GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s has refused, negotiation failed :(, count=%d\n", + GST_DEBUG_PAD_NAME(currentpad), counter); + return FALSE; + } + if (newcaps == currentcaps) { + GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s aggreed with caps, count=%d\n", + GST_DEBUG_PAD_NAME(currentpad), counter); + break; + } + } + /* this pad doesn't want to negotiate, take its caps and that will be it then */ + else { + GST_DEBUG (GST_CAT_ELEMENT_PADS, "getting caps from pad %s:%s, count=%d\n", + GST_DEBUG_PAD_NAME(currentpad), counter); + newcaps = GST_PAD_CAPS (currentpad); + } + /* we have a caps structure now */ + + /* check if the other pad wants to negotiate */ + if (!otherpad->negotiatefunc) { + /* the pad doesn't want to negotiate, so we check if the caps + * we got from the current pad are compatible */ + GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s doesn't want to negotiate, count=%d\n", + GST_DEBUG_PAD_NAME(otherpad), counter); + if (!otherpad->caps || + gst_caps_check_compatibility (newcaps, otherpad->caps)) { + GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s has compatible caps, count=%d\n", + GST_DEBUG_PAD_NAME(otherpad), counter); + /* we're lucky */ + break; + } + /* else, we let the current pad select another caps */ + } + /* if the other pad wants to negotiate, setup the pointers */ + else { + GstRealPad *temp; + + GST_DEBUG (GST_CAT_ELEMENT_PADS, "switching pads for next phase\n"); + + temp = currentpad; + currentpad = otherpad; + otherpad = temp; + } + + counter++; + + } while (counter < 100); // FIXME + + GST_DEBUG (GST_CAT_ELEMENT_PADS, "pads aggreed on caps :)\n"); + + /* here we have some sort of aggreement of the caps */ + GST_PAD_CAPS (currentpad) = newcaps; + GST_PAD_CAPS (otherpad) = newcaps; + + return TRUE; +} + +GstCaps* +gst_pad_negotiate_proxy (GstPad *pad, GstCaps *caps, gint count) +{ + GstRealPad *peer; + GstCaps *newcaps = caps; + + g_return_val_if_fail (pad != NULL, NULL); + + GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad (%s:%s) proxied\n", GST_DEBUG_PAD_NAME (pad)); + + peer = GST_RPAD_PEER (pad); + + GST_PAD_CAPS (pad) = caps; + + if (peer) { + if (peer->negotiatefunc) { + GST_DEBUG (GST_CAT_ELEMENT_PADS, "calling negotiate on peer (%s:%s)\n", GST_DEBUG_PAD_NAME (peer)); + newcaps = peer->negotiatefunc (pad, caps, count); + } + else if (!peer->caps || + gst_caps_check_compatibility (newcaps, peer->caps)) { + GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s has compatible caps\n", + GST_DEBUG_PAD_NAME(peer)); + } + else return NULL; + } + + if (caps == newcaps) { + GST_PAD_CAPS (pad) = newcaps; + if (peer) GST_PAD_CAPS (peer) = newcaps; + } + + return newcaps; +} /** * gst_pad_save_thyself: @@ -1113,8 +1286,9 @@ gst_padtemplate_new (GstPadFactory *factory) tag = (*factory)[i++]; - while (GPOINTER_TO_INT (tag) == 1) { - new->caps = g_list_append (new->caps, gst_caps_register_count ((GstCapsFactory *)&(*factory)[i], &counter)); + while (GPOINTER_TO_INT (tag) == GST_PAD_FACTORY_CAPS_ID) { + GST_PADTEMPLATE_CAPS (new) = gst_caps_append (GST_PADTEMPLATE_CAPS (new), + gst_caps_register_count ((GstCapsFactory *)&(*factory)[i], &counter)); i+=counter; tag = (*factory)[i++]; } @@ -1136,7 +1310,7 @@ gst_padtemplate_new (GstPadFactory *factory) GstPadTemplate* gst_padtemplate_create (gchar *name_template, GstPadDirection direction, GstPadPresence presence, - GList *caps) + GstCaps *caps) { GstPadTemplate *new; @@ -1144,14 +1318,29 @@ gst_padtemplate_create (gchar *name_template, new = gtk_type_new (gst_padtemplate_get_type ()); - new->name_template = name_template; - new->direction = direction; - new->presence = presence; - new->caps = caps; + GST_PADTEMPLATE_NAME_TEMPLATE (new) = name_template; + GST_PADTEMPLATE_DIRECTION (new) = direction; + GST_PADTEMPLATE_PRESENCE (new) = presence; + GST_PADTEMPLATE_CAPS (new) = caps; return new; } +/** + * gst_padtemplate_get_caps: + * @templ: the padtemplate to use + * + * Get the capabilities of the padtemplate + * + * Returns: a GstCaps* + */ +GstCaps* +gst_padtemplate_get_caps (GstPadTemplate *templ) +{ + g_return_val_if_fail (templ != NULL, NULL); + + return GST_PADTEMPLATE_CAPS (templ); +} /** * gst_padtemplate_save_thyself: @@ -1166,9 +1355,10 @@ xmlNodePtr gst_padtemplate_save_thyself (GstPadTemplate *templ, xmlNodePtr parent) { xmlNodePtr subtree; - GList *caps; guchar *presence; + GST_DEBUG (0,"saving padtemplate %s\n", templ->name_template); + xmlNewChild(parent,NULL,"nametemplate", templ->name_template); xmlNewChild(parent,NULL,"direction", (templ->direction == GST_PAD_SINK? "sink":"src")); @@ -1188,14 +1378,9 @@ gst_padtemplate_save_thyself (GstPadTemplate *templ, xmlNodePtr parent) } xmlNewChild(parent,NULL,"presence", presence); - caps = templ->caps; - while (caps) { - GstCaps *cap = (GstCaps *)caps->data; - + if (GST_PADTEMPLATE_CAPS (templ)) { subtree = xmlNewChild (parent, NULL, "caps", NULL); - gst_caps_save_thyself (cap, subtree); - - caps = g_list_next (caps); + gst_caps_save_thyself (GST_PADTEMPLATE_CAPS (templ), subtree); } return parent; @@ -1217,7 +1402,7 @@ gst_padtemplate_load_thyself (xmlNodePtr parent) gchar *name_template = NULL; GstPadDirection direction = GST_PAD_UNKNOWN; GstPadPresence presence = GST_PAD_ALWAYS; - GList *caps = NULL; + GstCaps *caps = NULL; while (field) { if (!strcmp(field->name, "nametemplate")) { @@ -1249,7 +1434,7 @@ gst_padtemplate_load_thyself (xmlNodePtr parent) g_free (value); } else if (!strcmp(field->name, "caps")) { - caps = g_list_append (caps, gst_caps_load_thyself (field)); + caps = gst_caps_load_thyself (field); } field = field->next; } diff --git a/gst/gstpad.h b/gst/gstpad.h index ef21617..a392719 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -92,6 +92,7 @@ typedef void (*GstPadPushFunction) (GstPad *pad, GstBuffer *buf); typedef GstBuffer *(*GstPadPullFunction) (GstPad *pad); typedef GstBuffer *(*GstPadPullRegionFunction) (GstPad *pad, GstRegionType type, guint64 offset, guint64 len); typedef gboolean (*GstPadEOSFunction) (GstPad *pad); +typedef GstCaps* (*GstPadNegotiateFunction) (GstPad *pad, GstCaps *caps, gint count); typedef enum { GST_PAD_UNKNOWN, @@ -121,7 +122,7 @@ struct _GstPadClass { struct _GstRealPad { GstPad pad; - GList *caps; + GstCaps *caps; GstPadDirection direction; cothread_state *threadstate; @@ -143,6 +144,8 @@ struct _GstRealPad { GstPadPullFunction pullfunc; GstPadPullRegionFunction pullregionfunc; + GstPadNegotiateFunction negotiatefunc; + GList *ghostpads; }; @@ -186,6 +189,7 @@ struct _GstGhostPadClass { #define GST_RPAD_PULLREGIONFUNC(pad) (((GstRealPad *)(pad))->pullregionfunc) #define GST_RPAD_QOSFUNC(pad) (((GstRealPad *)(pad))->qosfunc) #define GST_RPAD_EOSFUNC(pad) (((GstRealPad *)(pad))->eosfunc) +#define GST_RPAD_NEGOTIATEFUNC(pad) (((GstRealPad *)(pad))->negotiatefunc) #define GST_RPAD_REGIONTYPE(pad) (((GstRealPad *)(pad))->regiontype) #define GST_RPAD_OFFSET(pad) (((GstRealPad *)(pad))->offset) @@ -201,7 +205,7 @@ struct _GstGhostPadClass { #define GST_PAD_PEER(pad) GST_RPAD_PEER(GST_PAD_REALIZE(pad)) /* Some check functions (unused?) */ -#define GST_PAD_CONNECTED(pad) (GST_IS_REAL_PAD(pad) && GST_REAL_PAD(pad)->peer != NULL) +#define GST_PAD_CONNECTED(pad) (GST_PAD_PEER(pad) != NULL) #define GST_PAD_CAN_PULL(pad) (GST_IS_REAL_PAD(pad) && GST_REAL_PAD(pad)->pullfunc != NULL) @@ -218,13 +222,18 @@ typedef enum { GST_PAD_REQUEST, } GstPadPresence; +#define GST_PADTEMPLATE_NAME_TEMPLATE(templ) (((GstPadTemplate *)(templ))->name_template) +#define GST_PADTEMPLATE_DIRECTION(templ) (((GstPadTemplate *)(templ))->direction) +#define GST_PADTEMPLATE_PRESENCE(templ) (((GstPadTemplate *)(templ))->presence) +#define GST_PADTEMPLATE_CAPS(templ) (((GstPadTemplate *)(templ))->caps) + struct _GstPadTemplate { GstObject object; gchar *name_template; GstPadDirection direction; GstPadPresence presence; - GList *caps; + GstCaps *caps; }; struct _GstPadTemplateClass { @@ -246,7 +255,8 @@ typedef GstPadFactoryEntry GstPadFactory[]; #define GST_PAD_FACTORY_SRC GINT_TO_POINTER(GST_PAD_SRC) #define GST_PAD_FACTORY_SINK GINT_TO_POINTER(GST_PAD_SINK) -#define GST_PAD_FACTORY_CAPS(a...) GINT_TO_POINTER(1),##a,NULL +#define GST_PAD_FACTORY_CAPS_ID 1 +#define GST_PAD_FACTORY_CAPS(a...) GINT_TO_POINTER(GST_PAD_FACTORY_CAPS_ID),##a,NULL GtkType gst_pad_get_type (void); @@ -264,10 +274,10 @@ void gst_pad_set_get_function (GstPad *pad, GstPadGetFunction get); void gst_pad_set_getregion_function (GstPad *pad, GstPadGetRegionFunction getregion); void gst_pad_set_qos_function (GstPad *pad, GstPadQoSFunction qos); void gst_pad_set_eos_function (GstPad *pad, GstPadEOSFunction eos); +void gst_pad_set_negotiate_function (GstPad *pad, GstPadNegotiateFunction nego); -void gst_pad_set_caps_list (GstPad *pad, GList *caps); -GList* gst_pad_get_caps_list (GstPad *pad); -GstCaps* gst_pad_get_caps_by_name (GstPad *pad, gchar *name); +void gst_pad_set_caps (GstPad *pad, GstCaps *caps); +GstCaps* gst_pad_get_caps (GstPad *pad); gboolean gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad); void gst_pad_set_element_private (GstPad *pad, gpointer priv); @@ -284,11 +294,16 @@ void gst_pad_add_ghost_pad (GstPad *pad, GstPad *ghostpad); void gst_pad_remove_ghost_pad (GstPad *pad, GstPad *ghostpad); GList* gst_pad_get_ghost_pad_list (GstPad *pad); +GstPadTemplate* gst_pad_get_padtemplate (GstPad *pad); + GstPad* gst_pad_get_peer (GstPad *pad); -void gst_pad_connect (GstPad *srcpad, GstPad *sinkpad); +gboolean gst_pad_connect (GstPad *srcpad, GstPad *sinkpad); void gst_pad_disconnect (GstPad *srcpad, GstPad *sinkpad); +gboolean gst_pad_renegotiate (GstPad *pad); +GstCaps* gst_pad_negotiate_proxy (GstPad *pad, GstCaps* caps, gint count); + #if 1 void gst_pad_push (GstPad *pad, GstBuffer *buf); #else @@ -325,7 +340,10 @@ GtkType gst_padtemplate_get_type (void); GstPadTemplate* gst_padtemplate_new (GstPadFactory *factory); GstPadTemplate* gst_padtemplate_create (gchar *name_template, GstPadDirection direction, GstPadPresence presence, - GList *caps); + GstCaps *caps); + +GstCaps* gst_padtemplate_get_caps (GstPadTemplate *templ); +GstCaps* gst_padtemplate_get_caps_by_name (GstPadTemplate *templ, const gchar *name); xmlNodePtr gst_padtemplate_save_thyself (GstPadTemplate *templ, xmlNodePtr parent); GstPadTemplate* gst_padtemplate_load_thyself (xmlNodePtr parent); diff --git a/gst/gstqueue.c b/gst/gstqueue.c index a500f91..3f2eea8 100644 --- a/gst/gstqueue.c +++ b/gst/gstqueue.c @@ -66,6 +66,8 @@ static void gst_queue_set_arg (GtkObject *object, GtkArg *arg, guint id); static void gst_queue_get_arg (GtkObject *object, GtkArg *arg, guint id); static gboolean gst_queue_handle_eos (GstPad *pad); +static GstCaps* gst_queue_handle_negotiate_src (GstPad *pad, GstCaps *caps, gint count); +static GstCaps* gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps *caps, gint count); static void gst_queue_chain (GstPad *pad, GstBuffer *buf); static GstBuffer * gst_queue_get (GstPad *pad); @@ -131,10 +133,12 @@ gst_queue_init (GstQueue *queue) gst_pad_set_chain_function (queue->sinkpad, GST_DEBUG_FUNCPTR(gst_queue_chain)); gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad); gst_pad_set_eos_function (queue->sinkpad, gst_queue_handle_eos); + gst_pad_set_negotiate_function (queue->sinkpad, gst_queue_handle_negotiate_sink); queue->srcpad = gst_pad_new ("src", GST_PAD_SRC); gst_pad_set_get_function (queue->srcpad, GST_DEBUG_FUNCPTR(gst_queue_get)); gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad); + gst_pad_set_negotiate_function (queue->srcpad, gst_queue_handle_negotiate_src); queue->queue = NULL; queue->level_buffers = 0; @@ -148,6 +152,26 @@ gst_queue_init (GstQueue *queue) queue->fullcond = g_cond_new (); } +static GstCaps* +gst_queue_handle_negotiate_src (GstPad *pad, GstCaps *caps, gint count) +{ + GstQueue *queue; + + queue = GST_QUEUE (GST_OBJECT_PARENT (pad)); + + return gst_pad_negotiate_proxy (queue->sinkpad, caps, count); +} + +static GstCaps* +gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps *caps, gint count) +{ + GstQueue *queue; + + queue = GST_QUEUE (GST_OBJECT_PARENT (pad)); + + return gst_pad_negotiate_proxy (queue->srcpad, caps, count); +} + static gboolean gst_queue_handle_eos (GstPad *pad) { diff --git a/gstplay/gstplay.c b/gstplay/gstplay.c index f0b7459..1310588 100644 --- a/gstplay/gstplay.c +++ b/gstplay/gstplay.c @@ -285,7 +285,7 @@ gst_play_typefind (GstBin *bin, GstElement *element) if (found) { caps = gst_util_get_pointer_arg (GTK_OBJECT (typefind), "caps"); - gst_pad_set_caps_list (gst_element_get_pad (element, "src"), g_list_prepend (NULL, caps)); + gst_pad_set_caps (gst_element_get_pad (element, "src"), caps); } gst_pad_disconnect (gst_element_get_pad (element, "src"), @@ -360,7 +360,7 @@ gst_play_set_uri (GstPlay *play, gtk_signal_connect (GTK_OBJECT (autoplug), "new_object", gst_play_object_added, play); new_element = gst_autoplug_to_renderers (autoplug, - gst_pad_get_caps_list (gst_element_get_pad (priv->src, "src")), + gst_pad_get_caps (gst_element_get_pad (priv->src, "src")), priv->video_element, priv->audio_element, NULL); diff --git a/plugins/elements/gstaudiosink.c b/plugins/elements/gstaudiosink.c index 1027729..5499e3a 100644 --- a/plugins/elements/gstaudiosink.c +++ b/plugins/elements/gstaudiosink.c @@ -417,8 +417,9 @@ gst_audiosink_change_state (GstElement *element) /* otherwise (READY or higher) we need to open the sound card */ } else { if (!GST_FLAG_IS_SET (element, GST_AUDIOSINK_OPEN)) { - if (!gst_audiosink_open_audio (GST_AUDIOSINK (element))) - return GST_STATE_FAILURE; + if (!gst_audiosink_open_audio (GST_AUDIOSINK (element))) { + //return GST_STATE_FAILURE; + } } } diff --git a/plugins/elements/gstqueue.c b/plugins/elements/gstqueue.c index a500f91..3f2eea8 100644 --- a/plugins/elements/gstqueue.c +++ b/plugins/elements/gstqueue.c @@ -66,6 +66,8 @@ static void gst_queue_set_arg (GtkObject *object, GtkArg *arg, guint id); static void gst_queue_get_arg (GtkObject *object, GtkArg *arg, guint id); static gboolean gst_queue_handle_eos (GstPad *pad); +static GstCaps* gst_queue_handle_negotiate_src (GstPad *pad, GstCaps *caps, gint count); +static GstCaps* gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps *caps, gint count); static void gst_queue_chain (GstPad *pad, GstBuffer *buf); static GstBuffer * gst_queue_get (GstPad *pad); @@ -131,10 +133,12 @@ gst_queue_init (GstQueue *queue) gst_pad_set_chain_function (queue->sinkpad, GST_DEBUG_FUNCPTR(gst_queue_chain)); gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad); gst_pad_set_eos_function (queue->sinkpad, gst_queue_handle_eos); + gst_pad_set_negotiate_function (queue->sinkpad, gst_queue_handle_negotiate_sink); queue->srcpad = gst_pad_new ("src", GST_PAD_SRC); gst_pad_set_get_function (queue->srcpad, GST_DEBUG_FUNCPTR(gst_queue_get)); gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad); + gst_pad_set_negotiate_function (queue->srcpad, gst_queue_handle_negotiate_src); queue->queue = NULL; queue->level_buffers = 0; @@ -148,6 +152,26 @@ gst_queue_init (GstQueue *queue) queue->fullcond = g_cond_new (); } +static GstCaps* +gst_queue_handle_negotiate_src (GstPad *pad, GstCaps *caps, gint count) +{ + GstQueue *queue; + + queue = GST_QUEUE (GST_OBJECT_PARENT (pad)); + + return gst_pad_negotiate_proxy (queue->sinkpad, caps, count); +} + +static GstCaps* +gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps *caps, gint count) +{ + GstQueue *queue; + + queue = GST_QUEUE (GST_OBJECT_PARENT (pad)); + + return gst_pad_negotiate_proxy (queue->srcpad, caps, count); +} + static gboolean gst_queue_handle_eos (GstPad *pad) { diff --git a/tests/.gitignore b/tests/.gitignore index fc4f7a1..2c686c0 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -26,3 +26,4 @@ padfactory tee autoplug2 autoplug3 +capsconnect diff --git a/tests/Makefile.am b/tests/Makefile.am index 1d82923..27b8a74 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,7 +1,8 @@ SUBDIRS = sched eos noinst_PROGRAMS = init loadall simplefake states caps queue registry \ -paranoia rip mp3encode autoplug props case4 markup load tee autoplug2 autoplug3 +paranoia rip mp3encode autoplug props case4 markup load tee autoplug2 autoplug3 \ +capsconnect # we have nothing but apps here, we can do this safely LIBS += $(GST_LIBS) diff --git a/tests/autoplug.c b/tests/autoplug.c index 87913c6..4c1a05c 100644 --- a/tests/autoplug.c +++ b/tests/autoplug.c @@ -34,8 +34,8 @@ main (int argc, char *argv[]) gtk_signal_connect (GTK_OBJECT (autoplugger), "new_object", new_object_added, NULL); element = gst_autoplug_to_caps (autoplugger, testcaps, - gst_pad_get_caps_list (gst_element_get_pad (audiosink, "sink")), - gst_pad_get_caps_list (gst_element_get_pad (videosink, "sink")), + gst_pad_get_caps (gst_element_get_pad (audiosink, "sink")), + gst_pad_get_caps (gst_element_get_pad (videosink, "sink")), NULL); g_assert (element != NULL); diff --git a/tests/capsconnect.c b/tests/capsconnect.c new file mode 100644 index 0000000..01e8e7b --- /dev/null +++ b/tests/capsconnect.c @@ -0,0 +1,62 @@ +#include + +int main(int argc,char *argv[]) +{ + gboolean testret; + xmlDocPtr doc; + xmlNodePtr parent; + GstElement *mpg123; + GstElement *mp3parse; + GstElement *queue; + GstPad *sinkpad; + GstPad *srcpad; + GstPad *qsinkpad; + + doc = xmlNewDoc ("1.0"); + doc->xmlRootNode = xmlNewDocNode (doc, NULL, "Capabilities", NULL); + + gst_init (&argc, &argv); + + mpg123 = gst_elementfactory_make ("mpg123", "mpg123"); + g_assert (mpg123 != NULL); + + sinkpad = gst_element_get_pad (mpg123, "sink"); + g_assert (sinkpad != NULL); + + queue = gst_elementfactory_make ("queue", "queue"); + g_assert (queue != NULL); + + srcpad = gst_element_get_pad (queue, "src"); + g_assert (srcpad != NULL); + qsinkpad = gst_element_get_pad (queue, "sink"); + g_assert (qsinkpad != NULL); + + parent = xmlNewChild (doc->xmlRootNode, NULL, "mpg123 caps", NULL); + gst_caps_save_thyself (gst_pad_get_caps (sinkpad), parent); + + parent = xmlNewChild (doc->xmlRootNode, NULL, "queue caps", NULL); + gst_caps_save_thyself (gst_pad_get_caps (srcpad), parent); + + gst_pad_connect (srcpad, sinkpad); + + parent = xmlNewChild (doc->xmlRootNode, NULL, "queue caps after connect src", NULL); + gst_caps_save_thyself (gst_pad_get_caps (srcpad), parent); + + parent = xmlNewChild (doc->xmlRootNode, NULL, "queue caps after connect sink", NULL); + gst_caps_save_thyself (gst_pad_get_caps (qsinkpad), parent); + + mp3parse = gst_elementfactory_make ("mp3parse", "mp3parse"); + g_assert (mp3parse != NULL); + + gst_pad_connect (gst_element_get_pad (mp3parse, "src"), qsinkpad); + + parent = xmlNewChild (doc->xmlRootNode, NULL, "queue caps after connect sink", NULL); + gst_caps_save_thyself (gst_pad_get_caps (qsinkpad), parent); + + parent = xmlNewChild (doc->xmlRootNode, NULL, "mpg123 caps after connect sink", NULL); + gst_caps_save_thyself (gst_pad_get_caps (sinkpad), parent); + + xmlDocDump(stdout, doc); + + return 0; +} diff --git a/tests/nego/.gitignore b/tests/nego/.gitignore new file mode 100644 index 0000000..3224b98 --- /dev/null +++ b/tests/nego/.gitignore @@ -0,0 +1,9 @@ +Makefile +Makefile.in +*.o +*.lo +*.la +.deps +.libs +*.xml +nego1 diff --git a/tests/nego/Makefile.am b/tests/nego/Makefile.am new file mode 100644 index 0000000..4260472 --- /dev/null +++ b/tests/nego/Makefile.am @@ -0,0 +1,5 @@ +noinst_PROGRAMS = nego1 + +# jsut apps here, this is safe +LIBS += $(GST_LIBS) +CFLAGS += $(GST_CFLAGS) diff --git a/tests/nego/nego1.c b/tests/nego/nego1.c new file mode 100644 index 0000000..23848bc --- /dev/null +++ b/tests/nego/nego1.c @@ -0,0 +1,59 @@ +#include + +/* this is an example of the src pad dictating the caps + * the sink pad only accepts audio/raw */ + +static GstCaps* +negotiate (GstPad *pad, GstCaps *caps, gint count) +{ + g_print ("negotiation entered\n"); + + if (!strcmp (gst_caps_get_mime (caps), "audio/raw")) + return caps; + + return NULL; +} + +int +main(int argc,char *argv[]) +{ + GstPad *srcpad, *sinkpad; + GstCaps *new; + + gst_init(&argc,&argv); + + srcpad = gst_pad_new ("src", GST_PAD_SRC); + sinkpad = gst_pad_new ("sink", GST_PAD_SINK); + + gst_pad_connect (srcpad, sinkpad); + + gst_pad_set_negotiate_function (sinkpad, negotiate); + + /* fill in our desired caps */ + new = gst_caps_new_with_props ( + "src_caps", /* name */ + "audio/raw", /* mime */ + gst_props_new ( + "format", GST_PROPS_INT (16), + "depth", GST_PROPS_INT (16), + "rate", GST_PROPS_INT (48000), + "channels", GST_PROPS_INT (2), + NULL + ) + ); + + gst_pad_set_caps (srcpad, new); + + new = gst_caps_new_with_props ( + "src_caps", /* name */ + "video/raw", /* mime */ + gst_props_new ( + "format", GST_PROPS_FOURCC ('Y','U','Y','V'), + NULL + ) + ); + + gst_pad_set_caps (srcpad, new); + + exit (0); +}