From 1c4ea6213b0dfe073c519a5eac8ccd6042cb30de Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 12 May 2005 19:45:44 +0000 Subject: [PATCH] gst/: Identify sinks by their flag to avoid overly complicated checks (fow now). Original commit message from CVS: * gst/base/gstbasesink.c: (gst_basesink_init), (gst_basesink_activate): * gst/base/gstbasesrc.c: (gst_basesrc_unlock), (gst_basesrc_is_seekable): * gst/gstbin.c: (gst_bin_add_func), (gst_bin_remove_func), (bin_element_is_sink), (gst_bin_change_state): * gst/gstelement.c: (gst_element_add_pad), (gst_element_query): * gst/gstelement.h: Identify sinks by their flag to avoid overly complicated checks (fow now). Do state changes even for elements not reachable from the sinks. BaseSink is a sink now :) Some more debugging info in the basesrc. --- ChangeLog | 18 ++++++ gst/base/gstbasesink.c | 2 + gst/base/gstbasesrc.c | 4 ++ gst/gstbin.c | 112 +++++++++++++++++------------------- gst/gstelement.c | 2 + gst/gstelement.h | 3 + libs/gst/base/gstbasesink.c | 2 + libs/gst/base/gstbasesrc.c | 4 ++ 8 files changed, 89 insertions(+), 58 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0c6313e76a..620bede4a6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2005-05-12 Wim Taymans + + * gst/base/gstbasesink.c: (gst_basesink_init), + (gst_basesink_activate): + * gst/base/gstbasesrc.c: (gst_basesrc_unlock), + (gst_basesrc_is_seekable): + * gst/gstbin.c: (gst_bin_add_func), (gst_bin_remove_func), + (bin_element_is_sink), (gst_bin_change_state): + * gst/gstelement.c: (gst_element_add_pad), (gst_element_query): + * gst/gstelement.h: + Identify sinks by their flag to avoid overly complicated + checks (fow now). + Do state changes even for elements not reachable from the + sinks. + BaseSink is a sink now :) + Some more debugging info in the basesrc. + + 2005-05-12 Ronald S. Bultje * gst/gstbin.c: (gst_bin_class_init), (gst_bin_query): diff --git a/gst/base/gstbasesink.c b/gst/base/gstbasesink.c index 8ae3d8330c..4382590fca 100644 --- a/gst/base/gstbasesink.c +++ b/gst/base/gstbasesink.c @@ -238,6 +238,8 @@ gst_basesink_init (GstBaseSink * basesink, gpointer g_class) basesink->pad_mode = GST_ACTIVATE_NONE; GST_RPAD_TASK (basesink->sinkpad) = NULL; + + GST_FLAG_SET (basesink, GST_ELEMENT_IS_SINK); } static void diff --git a/gst/base/gstbasesrc.c b/gst/base/gstbasesrc.c index 803cc9632c..80354fd9be 100644 --- a/gst/base/gstbasesrc.c +++ b/gst/base/gstbasesrc.c @@ -576,11 +576,13 @@ gst_basesrc_unlock (GstBaseSrc * basesrc) GstBaseSrcClass *bclass; gboolean result = FALSE; + GST_DEBUG ("unlock"); /* unblock whatever the subclass is doing */ bclass = GST_BASESRC_GET_CLASS (basesrc); if (bclass->unlock) result = bclass->unlock (basesrc); + GST_DEBUG ("unschedule clock"); /* and unblock the clock as well, if any */ GST_LOCK (basesrc); if (basesrc->clock_id) { @@ -588,6 +590,8 @@ gst_basesrc_unlock (GstBaseSrc * basesrc) } GST_UNLOCK (basesrc); + GST_DEBUG ("unlock done"); + return result; } diff --git a/gst/gstbin.c b/gst/gstbin.c index 4eccfc8a0a..090b994bef 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -79,6 +79,8 @@ static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent); static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self); #endif +static gint bin_element_is_sink (GstElement * child, GstBin * bin); + /* Bin signals and args */ enum { @@ -379,6 +381,9 @@ gst_bin_add_func (GstBin * bin, GstElement * element) GST_OBJECT_CAST (bin)))) goto had_parent; + if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK)) + GST_FLAG_SET (bin, GST_ELEMENT_IS_SINK); + bin->children = g_list_prepend (bin->children, element); bin->numchildren++; bin->children_cookie++; @@ -488,6 +493,20 @@ gst_bin_remove_func (GstBin * bin, GstElement * element) bin->children = g_list_remove (bin->children, element); bin->numchildren--; bin->children_cookie++; + + /* check if we a sink */ + if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK)) { + GList *other_sink; + + /* check if we removed the last sink */ + other_sink = g_list_find_custom (bin->children, + bin, (GCompareFunc) bin_element_is_sink); + if (!other_sink) { + /* yups, we're not a sink anymore */ + GST_FLAG_UNSET (bin, GST_ELEMENT_IS_SINK); + } + } + GST_UNLOCK (bin); GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"", @@ -674,70 +693,22 @@ gst_bin_iterate_recurse (GstBin * bin) static gint bin_element_is_sink (GstElement * child, GstBin * bin) { - gint ret = 1; + gint ret; /* we lock the child here for the remainder of the function to - * get its pads and name safely. */ + * get its name safely. */ GST_LOCK (child); - - /* check if this is a sink element, these are the elements - * without (linked) source pads. */ - if (child->numsrcpads == 0) { - /* shortcut */ + if (GST_FLAG_IS_SET (child, GST_ELEMENT_IS_SINK)) { GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, - "adding child %s as sink", GST_OBJECT_NAME (child)); + "finding child %s as sink", GST_OBJECT_NAME (child)); + GST_UNLOCK (child); ret = 0; } else { - /* loop over all pads, try to figure out if this element - * is a sink because it has no linked source pads */ - GList *pads; - gboolean connected_src = FALSE; - - for (pads = child->srcpads; pads; pads = g_list_next (pads)) { - GstPad *peer; - - peer = gst_pad_get_peer (GST_PAD_CAST (pads->data)); - if (peer) { - GstElement *parent; - - parent = gst_pad_get_parent (peer); - if (parent) { - GstObject *grandparent; - - grandparent = gst_object_get_parent (GST_OBJECT_CAST (parent)); - if (grandparent == GST_OBJECT_CAST (bin)) { - connected_src = TRUE; - } - if (grandparent) { - gst_object_unref (GST_OBJECT_CAST (grandparent)); - } - gst_object_unref (GST_OBJECT_CAST (parent)); - } - gst_object_unref (GST_OBJECT_CAST (peer)); - if (connected_src) { - break; - } - } - } - - if (connected_src) { - GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, - "not adding child %s as sink: linked source pads", - GST_OBJECT_NAME (child)); - } else { - GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, - "adding child %s as sink since it has unlinked source pads in this bin", - GST_OBJECT_NAME (child)); - ret = 0; - } + GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin, + "child %s is not a sink", GST_OBJECT_NAME (child)); + GST_UNLOCK (child); + ret = 1; } - GST_UNLOCK (child); - - /* we did not find the element, need to release the ref - * added by the iterator */ - if (ret == 1) - gst_object_unref (GST_OBJECT (child)); - return ret; } @@ -872,6 +843,7 @@ gst_bin_change_state (GstElement * element) GList *children; guint32 children_cookie; GQueue *elem_queue; /* list of elements waiting for a state change */ + GQueue *temp; /* temp queue of non sinks */ bin = GST_BIN (element); @@ -890,6 +862,7 @@ gst_bin_change_state (GstElement * element) /* all elements added to this queue should have their refcount * incremented */ elem_queue = g_queue_new (); + temp = g_queue_new (); /* first step, find all sink elements, these are the elements * without (linked) source pads. */ @@ -908,13 +881,17 @@ restart: * the _is_sink function unrefs the element when it is not * a sink. */ g_queue_push_tail (elem_queue, child); + } else { + g_queue_push_tail (temp, child); } GST_LOCK (bin); if (G_UNLIKELY (children_cookie != bin->children_cookie)) { /* undo what we had */ g_queue_foreach (elem_queue, (GFunc) gst_object_unref, NULL); + g_queue_foreach (temp, (GFunc) gst_object_unref, NULL); while (g_queue_pop_head (elem_queue)); + while (g_queue_pop_head (temp)); goto restart; } @@ -924,10 +901,27 @@ restart: /* second step, change state of elements in the queue */ while (!g_queue_is_empty (elem_queue)) { - GstElement *qelement = g_queue_pop_head (elem_queue); + GstElement *qelement; GList *pads; gboolean locked; + /* take element */ + qelement = g_queue_pop_head (elem_queue); + /* we don't need it in the temp anymore */ + g_queue_remove_all (temp, qelement); + + /* if queue is empty now, continue with a non-sink */ + if (g_queue_is_empty (elem_queue)) { + GstElement *non_sink; + + GST_DEBUG ("sinks and upstream elements exhausted"); + non_sink = g_queue_pop_head (temp); + if (non_sink) { + GST_DEBUG ("found lefover non-sink %s", GST_OBJECT_NAME (non_sink)); + g_queue_push_tail (elem_queue, non_sink); + } + } + /* queue all elements connected to the sinkpads of this element */ GST_LOCK (qelement); pads = qelement->sinkpads; @@ -1036,6 +1030,8 @@ exit: /* release refcounts in queue, should normally be empty */ g_queue_foreach (elem_queue, (GFunc) gst_object_unref, NULL); g_queue_free (elem_queue); + g_queue_foreach (temp, (GFunc) gst_object_unref, NULL); + g_queue_free (temp); return ret; } diff --git a/gst/gstelement.c b/gst/gstelement.c index 9dec706da2..326c1ce7a3 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -502,6 +502,8 @@ gst_element_add_pad (GstElement * element, GstPad * pad) break; default: /* can happen for ghost pads */ + g_warning ("adding pad %s:%s wothout direction", + GST_DEBUG_PAD_NAME (pad)); break; } element->pads = g_list_prepend (element->pads, pad); diff --git a/gst/gstelement.h b/gst/gstelement.h index be4e9f0a4f..5b56ed0101 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -113,6 +113,9 @@ typedef enum /* ignore state changes from parent */ GST_ELEMENT_LOCKED_STATE, + /* the element is a sink */ + GST_ELEMENT_IS_SINK, + /* use some padding for future expansion */ GST_ELEMENT_FLAG_LAST = GST_OBJECT_FLAG_LAST + 16 } GstElementFlags; diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c index 8ae3d8330c..4382590fca 100644 --- a/libs/gst/base/gstbasesink.c +++ b/libs/gst/base/gstbasesink.c @@ -238,6 +238,8 @@ gst_basesink_init (GstBaseSink * basesink, gpointer g_class) basesink->pad_mode = GST_ACTIVATE_NONE; GST_RPAD_TASK (basesink->sinkpad) = NULL; + + GST_FLAG_SET (basesink, GST_ELEMENT_IS_SINK); } static void diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c index 803cc9632c..80354fd9be 100644 --- a/libs/gst/base/gstbasesrc.c +++ b/libs/gst/base/gstbasesrc.c @@ -576,11 +576,13 @@ gst_basesrc_unlock (GstBaseSrc * basesrc) GstBaseSrcClass *bclass; gboolean result = FALSE; + GST_DEBUG ("unlock"); /* unblock whatever the subclass is doing */ bclass = GST_BASESRC_GET_CLASS (basesrc); if (bclass->unlock) result = bclass->unlock (basesrc); + GST_DEBUG ("unschedule clock"); /* and unblock the clock as well, if any */ GST_LOCK (basesrc); if (basesrc->clock_id) { @@ -588,6 +590,8 @@ gst_basesrc_unlock (GstBaseSrc * basesrc) } GST_UNLOCK (basesrc); + GST_DEBUG ("unlock done"); + return result; } -- 2.34.1