From 2cb0dd9d9b6913b2c0a49eecb69aa21219f6feff Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Mon, 18 Feb 2002 00:40:56 +0000 Subject: [PATCH] many fixes related to dynamic pipelines. Original commit message from CVS: * many fixes related to dynamic pipelines. * addition of gst_element_disconnect_elements(), as per connect_elements() * don't have a cow if typefind changes state in its signal handlers * support of request pad -> request pad in connect_elements() * some fixes in int2float that will eventually need to be ported to float2int and adder the gstelement api is getting bloated, expect a rewrite within the next month. --- gst/gstelement.c | 123 ++++++++++++++++++-------- gst/gstelement.h | 1 + gst/gstelementfactory.c | 6 +- gst/gstpad.c | 7 ++ gst/gsttypefind.c | 4 +- gst/schedulers/gststandardscheduler.c | 11 +-- 6 files changed, 104 insertions(+), 48 deletions(-) diff --git a/gst/gstelement.c b/gst/gstelement.c index 2c8485e131..76a1d0cf09 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -780,12 +780,10 @@ gst_element_get_compatible_pad_filtered (GstElement *element, GstPad *pad, GstCa /* try to get an existing unconnected pad */ pads = gst_element_get_pad_list (element); - while (pads) - { + while (pads) { GstPad *current = GST_PAD (pads->data); if ((GST_PAD_PEER (GST_PAD_REALIZE (current)) == NULL) && - gst_pad_can_connect_filtered (pad, current, filtercaps)) - { + gst_pad_can_connect_filtered (pad, current, filtercaps)) { return current; } pads = g_list_next (pads); @@ -793,8 +791,7 @@ gst_element_get_compatible_pad_filtered (GstElement *element, GstPad *pad, GstCa /* try to create a new one */ /* requesting is a little crazy, we need a template. Let's create one */ - if (filtercaps != NULL) - { + if (filtercaps != NULL) { filtercaps = gst_caps_intersect (filtercaps, (GstCaps *) GST_RPAD_CAPS (pad)); if (filtercaps == NULL) return NULL; @@ -845,8 +842,9 @@ gboolean gst_element_connect_elements_filtered (GstElement *src, GstElement *dest, GstCaps *filtercaps) { - GList *srcpads, *destpads; + GList *srcpads, *destpads, *srctempls, *desttempls, *l; GstPad *srcpad, *destpad; + GstPadTemplate *srctempl, *desttempl; /* checks */ g_return_val_if_fail (src != NULL, FALSE); @@ -858,40 +856,66 @@ gst_element_connect_elements_filtered (GstElement *src, GstElement *dest, /* loop through the existing pads in the source */ srcpads = gst_element_get_pad_list (src); - while (srcpads) - { - srcpad = (GstPad *) GST_PAD_REALIZE (srcpads->data); - if ((GST_RPAD_DIRECTION (srcpad) == GST_PAD_SRC) && - (GST_PAD_PEER (srcpad) == NULL)) - { - destpad = gst_element_get_compatible_pad_filtered (dest, srcpad, filtercaps); - if (destpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) - { - GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s\n", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad)); - return TRUE; - } - } - srcpads = g_list_next (srcpads); - } - - /* loop through the existing pads in the destination */ destpads = gst_element_get_pad_list (dest); - while (destpads) - { - destpad = (GstPad *) GST_PAD_REALIZE (destpads->data); - if ((GST_RPAD_DIRECTION (destpad) == GST_PAD_SINK) && - (GST_PAD_PEER (destpad) == NULL)) - { - srcpad = gst_element_get_compatible_pad_filtered (src, destpad, filtercaps); - if (srcpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) - { - GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s\n", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad)); - return TRUE; + + if (srcpads || destpads) { + while (srcpads) { + srcpad = (GstPad *) GST_PAD_REALIZE (srcpads->data); + if ((GST_RPAD_DIRECTION (srcpad) == GST_PAD_SRC) && + (GST_PAD_PEER (srcpad) == NULL)) { + destpad = gst_element_get_compatible_pad_filtered (dest, srcpad, filtercaps); + if (destpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) { + GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s\n", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad)); + return TRUE; + } } + srcpads = g_list_next (srcpads); + } + + /* loop through the existing pads in the destination */ + while (destpads) { + destpad = (GstPad *) GST_PAD_REALIZE (destpads->data); + if ((GST_RPAD_DIRECTION (destpad) == GST_PAD_SINK) && + (GST_PAD_PEER (destpad) == NULL)) { + srcpad = gst_element_get_compatible_pad_filtered (src, destpad, filtercaps); + if (srcpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps)) { + GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s\n", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad)); + return TRUE; + } + } + destpads = g_list_next (destpads); } - destpads = g_list_next (destpads); } + GST_DEBUG (GST_CAT_ELEMENT_PADS, "we might have request pads on both sides, checking..."); + srctempls = gst_element_get_padtemplate_list (src); + desttempls = gst_element_get_padtemplate_list (dest); + + if (srctempls && desttempls) { + while (srctempls) { + srctempl = (GstPadTemplate*) srctempls->data; + if (srctempl->presence == GST_PAD_REQUEST) { + for (l=desttempls; l; l=l->next) { + desttempl = (GstPadTemplate*) desttempls->data; + if (desttempl->presence == GST_PAD_REQUEST && desttempl->direction != srctempl->direction) { + if (gst_caps_check_compatibility (gst_padtemplate_get_caps (srctempl), + gst_padtemplate_get_caps (desttempl))) { + srcpad = gst_element_request_pad_by_name (src, srctempl->name_template); + destpad = gst_element_request_pad_by_name (dest, desttempl->name_template); + if (gst_pad_connect_filtered (srcpad, destpad, filtercaps)) { + GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s\n", + GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad)); + return TRUE; + } + /* FIXME: we have extraneous request pads lying around */ + } + } + } + } + srctempls = srctempls->next; + } + } + GST_DEBUG (GST_CAT_ELEMENT_PADS, "no connection possible from %s to %s\n", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest)); return FALSE; } @@ -1018,6 +1042,33 @@ gst_element_disconnect (GstElement *src, const gchar *srcpadname, /* we're satisified they can be disconnected, let's do it */ gst_pad_disconnect(srcpad,destpad); } + +/** + * gst_element_disconnect_elements: + * @src: element 1 + * @dest: element 2 + * + * Disconnect all pads connecting the two elements. + */ +void +gst_element_disconnect_elements (GstElement *src, GstElement *dest) +{ + GstPad *src, *dst; + GList *srcpads, *destpads, *l; + + g_return_if_fail (GST_IS_ELEMENT(src)); + g_return_if_fail (GST_IS_ELEMENT(dest)); + + /* loop through the existing pads in the source */ + srcpads = gst_element_get_pad_list (src); + destpads = gst_element_get_pad_list (dest); + + for (; srcpads; srcpads=srcpads->next) + for (l=destpads; l; l=l->next) + if (GST_PAD_PEER ((GstPad*) srcpads->data) == (GstPad*) l->data) + gst_pad_disconnect ((GstPad*) srcpads->data, (GstPad*) l->data); +} + static void gst_element_error_func (GstElement* element, GstElement *source, gchar *errormsg) { diff --git a/gst/gstelement.h b/gst/gstelement.h index 76a74520fe..2725950437 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -223,6 +223,7 @@ gboolean gst_element_connect_filtered (GstElement *src, const gchar *srcpadname GstCaps *filtercaps); void gst_element_disconnect (GstElement *src, const gchar *srcpadname, GstElement *dest, const gchar *destpadname); +void gst_element_disconnect_elements (GstElement *src, GstElement *dest); void gst_element_set_eos (GstElement *element); diff --git a/gst/gstelementfactory.c b/gst/gstelementfactory.c index b35e1c2fcd..a27bb9cff1 100644 --- a/gst/gstelementfactory.c +++ b/gst/gstelementfactory.c @@ -251,9 +251,9 @@ gst_elementfactory_create (GstElementFactory *factory, GST_DEBUG (GST_CAT_ELEMENTFACTORY,"class %s\n", GST_OBJECT_NAME (factory)); oclass->elementfactory = factory; - /* copy pad template pointers to the element class */ - oclass->padtemplates = g_list_copy(factory->padtemplates); - oclass->numpadtemplates = factory->numpadtemplates; + /* copy pad template pointers to the element class, allow for custom padtemplates */ + oclass->padtemplates = g_list_concat (oclass->padtemplates, factory->padtemplates); + oclass->numpadtemplates += factory->numpadtemplates; } gst_object_set_name (GST_OBJECT (element),name); diff --git a/gst/gstpad.c b/gst/gstpad.c index de8130119e..21497a7cb5 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -565,12 +565,19 @@ gst_pad_disconnect (GstPad *srcpad, else if (GST_PAD_PARENT (realsink)->sched) gst_scheduler_pad_disconnect (GST_PAD_PARENT (realsink)->sched, (GstPad *)realsrc, (GstPad *)realsink); + /* hold a reference, as they can go away in the signal handlers */ + gst_object_ref (GST_OBJECT (realsrc)); + gst_object_ref (GST_OBJECT (realsink)); + /* fire off a signal to each of the pads telling them that they've been disconnected */ g_signal_emit (G_OBJECT (realsrc), gst_real_pad_signals[REAL_DISCONNECTED], 0, realsink); g_signal_emit (G_OBJECT (realsink), gst_real_pad_signals[REAL_DISCONNECTED], 0, realsrc); GST_INFO (GST_CAT_ELEMENT_PADS, "disconnected %s:%s and %s:%s", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); + + gst_object_unref (GST_OBJECT (realsrc)); + gst_object_unref (GST_OBJECT (realsink)); } /** diff --git a/gst/gsttypefind.c b/gst/gsttypefind.c index ef7e70be5d..44839bd193 100644 --- a/gst/gsttypefind.c +++ b/gst/gsttypefind.c @@ -196,10 +196,10 @@ gst_typefind_chain (GstPad *pad, GstBuffer *buf) gst_object_ref (GST_OBJECT (typefind)); g_signal_emit (G_OBJECT (typefind), gst_typefind_signals[HAVE_TYPE], 0, typefind->caps); - if (GST_STATE(typefind) != oldstate) { +/* if (GST_STATE(typefind) != oldstate) { GST_DEBUG(0, "state changed during signal, aborting\n"); gst_element_interrupt (GST_ELEMENT (typefind)); - } + } */ gst_object_unref (GST_OBJECT (typefind)); goto end; diff --git a/gst/schedulers/gststandardscheduler.c b/gst/schedulers/gststandardscheduler.c index e30c6f1f64..4676b8de66 100644 --- a/gst/schedulers/gststandardscheduler.c +++ b/gst/schedulers/gststandardscheduler.c @@ -294,8 +294,7 @@ gst_standard_scheduler_chain_wrapper (int argc, char *argv[]) GST_DEBUG (GST_CAT_DATAFLOW, "calling chain function of %s:%s\n", name, GST_PAD_NAME (pad)); GST_RPAD_CHAINFUNC (realpad) (pad, buf); - GST_DEBUG (GST_CAT_DATAFLOW, "calling chain function of %s:%s done\n", name, - GST_PAD_NAME (pad)); + GST_DEBUG (GST_CAT_DATAFLOW, "calling chain function of element %s done\n", name); } } else { @@ -763,7 +762,6 @@ gst_standard_scheduler_chain_remove_element (GstSchedulerChain * chain, GstEleme /* if there are no more elements in the chain, destroy the chain */ if (chain->num_elements == 0) gst_standard_scheduler_chain_destroy (chain); - } static void @@ -997,11 +995,10 @@ gst_standard_scheduler_remove_element (GstScheduler * sched, GstElement * elemen /* remove it from the list of elements */ bsched->elements = g_list_remove (bsched->elements, element); bsched->num_elements--; - - /* unset the scheduler pointer in the element */ - GST_ELEMENT_SCHED (element) = NULL; - } + + /* unset the scheduler pointer in the element */ + GST_ELEMENT_SCHED (element) = NULL; } static GstElementStateReturn