mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 06:58:56 +00:00
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.
This commit is contained in:
parent
e4c1ba46c8
commit
1c4ea6213b
8 changed files with 89 additions and 58 deletions
18
ChangeLog
18
ChangeLog
|
@ -1,3 +1,21 @@
|
||||||
|
2005-05-12 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* 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 <rbultje@ronald.bitfreak.net>
|
2005-05-12 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||||
|
|
||||||
* gst/gstbin.c: (gst_bin_class_init), (gst_bin_query):
|
* gst/gstbin.c: (gst_bin_class_init), (gst_bin_query):
|
||||||
|
|
|
@ -238,6 +238,8 @@ gst_basesink_init (GstBaseSink * basesink, gpointer g_class)
|
||||||
|
|
||||||
basesink->pad_mode = GST_ACTIVATE_NONE;
|
basesink->pad_mode = GST_ACTIVATE_NONE;
|
||||||
GST_RPAD_TASK (basesink->sinkpad) = NULL;
|
GST_RPAD_TASK (basesink->sinkpad) = NULL;
|
||||||
|
|
||||||
|
GST_FLAG_SET (basesink, GST_ELEMENT_IS_SINK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -576,11 +576,13 @@ gst_basesrc_unlock (GstBaseSrc * basesrc)
|
||||||
GstBaseSrcClass *bclass;
|
GstBaseSrcClass *bclass;
|
||||||
gboolean result = FALSE;
|
gboolean result = FALSE;
|
||||||
|
|
||||||
|
GST_DEBUG ("unlock");
|
||||||
/* unblock whatever the subclass is doing */
|
/* unblock whatever the subclass is doing */
|
||||||
bclass = GST_BASESRC_GET_CLASS (basesrc);
|
bclass = GST_BASESRC_GET_CLASS (basesrc);
|
||||||
if (bclass->unlock)
|
if (bclass->unlock)
|
||||||
result = bclass->unlock (basesrc);
|
result = bclass->unlock (basesrc);
|
||||||
|
|
||||||
|
GST_DEBUG ("unschedule clock");
|
||||||
/* and unblock the clock as well, if any */
|
/* and unblock the clock as well, if any */
|
||||||
GST_LOCK (basesrc);
|
GST_LOCK (basesrc);
|
||||||
if (basesrc->clock_id) {
|
if (basesrc->clock_id) {
|
||||||
|
@ -588,6 +590,8 @@ gst_basesrc_unlock (GstBaseSrc * basesrc)
|
||||||
}
|
}
|
||||||
GST_UNLOCK (basesrc);
|
GST_UNLOCK (basesrc);
|
||||||
|
|
||||||
|
GST_DEBUG ("unlock done");
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
112
gst/gstbin.c
112
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);
|
static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static gint bin_element_is_sink (GstElement * child, GstBin * bin);
|
||||||
|
|
||||||
/* Bin signals and args */
|
/* Bin signals and args */
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -379,6 +381,9 @@ gst_bin_add_func (GstBin * bin, GstElement * element)
|
||||||
GST_OBJECT_CAST (bin))))
|
GST_OBJECT_CAST (bin))))
|
||||||
goto had_parent;
|
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->children = g_list_prepend (bin->children, element);
|
||||||
bin->numchildren++;
|
bin->numchildren++;
|
||||||
bin->children_cookie++;
|
bin->children_cookie++;
|
||||||
|
@ -488,6 +493,20 @@ gst_bin_remove_func (GstBin * bin, GstElement * element)
|
||||||
bin->children = g_list_remove (bin->children, element);
|
bin->children = g_list_remove (bin->children, element);
|
||||||
bin->numchildren--;
|
bin->numchildren--;
|
||||||
bin->children_cookie++;
|
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_UNLOCK (bin);
|
||||||
|
|
||||||
GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"",
|
GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"",
|
||||||
|
@ -674,70 +693,22 @@ gst_bin_iterate_recurse (GstBin * bin)
|
||||||
static gint
|
static gint
|
||||||
bin_element_is_sink (GstElement * child, GstBin * bin)
|
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
|
/* 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);
|
GST_LOCK (child);
|
||||||
|
if (GST_FLAG_IS_SET (child, GST_ELEMENT_IS_SINK)) {
|
||||||
/* check if this is a sink element, these are the elements
|
|
||||||
* without (linked) source pads. */
|
|
||||||
if (child->numsrcpads == 0) {
|
|
||||||
/* shortcut */
|
|
||||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
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;
|
ret = 0;
|
||||||
} else {
|
} else {
|
||||||
/* loop over all pads, try to figure out if this element
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
||||||
* is a sink because it has no linked source pads */
|
"child %s is not a sink", GST_OBJECT_NAME (child));
|
||||||
GList *pads;
|
GST_UNLOCK (child);
|
||||||
gboolean connected_src = FALSE;
|
ret = 1;
|
||||||
|
|
||||||
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_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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -872,6 +843,7 @@ gst_bin_change_state (GstElement * element)
|
||||||
GList *children;
|
GList *children;
|
||||||
guint32 children_cookie;
|
guint32 children_cookie;
|
||||||
GQueue *elem_queue; /* list of elements waiting for a state change */
|
GQueue *elem_queue; /* list of elements waiting for a state change */
|
||||||
|
GQueue *temp; /* temp queue of non sinks */
|
||||||
|
|
||||||
bin = GST_BIN (element);
|
bin = GST_BIN (element);
|
||||||
|
|
||||||
|
@ -890,6 +862,7 @@ gst_bin_change_state (GstElement * element)
|
||||||
/* all elements added to this queue should have their refcount
|
/* all elements added to this queue should have their refcount
|
||||||
* incremented */
|
* incremented */
|
||||||
elem_queue = g_queue_new ();
|
elem_queue = g_queue_new ();
|
||||||
|
temp = g_queue_new ();
|
||||||
|
|
||||||
/* first step, find all sink elements, these are the elements
|
/* first step, find all sink elements, these are the elements
|
||||||
* without (linked) source pads. */
|
* without (linked) source pads. */
|
||||||
|
@ -908,13 +881,17 @@ restart:
|
||||||
* the _is_sink function unrefs the element when it is not
|
* the _is_sink function unrefs the element when it is not
|
||||||
* a sink. */
|
* a sink. */
|
||||||
g_queue_push_tail (elem_queue, child);
|
g_queue_push_tail (elem_queue, child);
|
||||||
|
} else {
|
||||||
|
g_queue_push_tail (temp, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_LOCK (bin);
|
GST_LOCK (bin);
|
||||||
if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
|
if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
|
||||||
/* undo what we had */
|
/* undo what we had */
|
||||||
g_queue_foreach (elem_queue, (GFunc) gst_object_unref, NULL);
|
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 (elem_queue));
|
||||||
|
while (g_queue_pop_head (temp));
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -924,10 +901,27 @@ restart:
|
||||||
|
|
||||||
/* second step, change state of elements in the queue */
|
/* second step, change state of elements in the queue */
|
||||||
while (!g_queue_is_empty (elem_queue)) {
|
while (!g_queue_is_empty (elem_queue)) {
|
||||||
GstElement *qelement = g_queue_pop_head (elem_queue);
|
GstElement *qelement;
|
||||||
GList *pads;
|
GList *pads;
|
||||||
gboolean locked;
|
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 */
|
/* queue all elements connected to the sinkpads of this element */
|
||||||
GST_LOCK (qelement);
|
GST_LOCK (qelement);
|
||||||
pads = qelement->sinkpads;
|
pads = qelement->sinkpads;
|
||||||
|
@ -1036,6 +1030,8 @@ exit:
|
||||||
/* release refcounts in queue, should normally be empty */
|
/* release refcounts in queue, should normally be empty */
|
||||||
g_queue_foreach (elem_queue, (GFunc) gst_object_unref, NULL);
|
g_queue_foreach (elem_queue, (GFunc) gst_object_unref, NULL);
|
||||||
g_queue_free (elem_queue);
|
g_queue_free (elem_queue);
|
||||||
|
g_queue_foreach (temp, (GFunc) gst_object_unref, NULL);
|
||||||
|
g_queue_free (temp);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -502,6 +502,8 @@ gst_element_add_pad (GstElement * element, GstPad * pad)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* can happen for ghost pads */
|
/* can happen for ghost pads */
|
||||||
|
g_warning ("adding pad %s:%s wothout direction",
|
||||||
|
GST_DEBUG_PAD_NAME (pad));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
element->pads = g_list_prepend (element->pads, pad);
|
element->pads = g_list_prepend (element->pads, pad);
|
||||||
|
|
|
@ -113,6 +113,9 @@ typedef enum
|
||||||
/* ignore state changes from parent */
|
/* ignore state changes from parent */
|
||||||
GST_ELEMENT_LOCKED_STATE,
|
GST_ELEMENT_LOCKED_STATE,
|
||||||
|
|
||||||
|
/* the element is a sink */
|
||||||
|
GST_ELEMENT_IS_SINK,
|
||||||
|
|
||||||
/* use some padding for future expansion */
|
/* use some padding for future expansion */
|
||||||
GST_ELEMENT_FLAG_LAST = GST_OBJECT_FLAG_LAST + 16
|
GST_ELEMENT_FLAG_LAST = GST_OBJECT_FLAG_LAST + 16
|
||||||
} GstElementFlags;
|
} GstElementFlags;
|
||||||
|
|
|
@ -238,6 +238,8 @@ gst_basesink_init (GstBaseSink * basesink, gpointer g_class)
|
||||||
|
|
||||||
basesink->pad_mode = GST_ACTIVATE_NONE;
|
basesink->pad_mode = GST_ACTIVATE_NONE;
|
||||||
GST_RPAD_TASK (basesink->sinkpad) = NULL;
|
GST_RPAD_TASK (basesink->sinkpad) = NULL;
|
||||||
|
|
||||||
|
GST_FLAG_SET (basesink, GST_ELEMENT_IS_SINK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -576,11 +576,13 @@ gst_basesrc_unlock (GstBaseSrc * basesrc)
|
||||||
GstBaseSrcClass *bclass;
|
GstBaseSrcClass *bclass;
|
||||||
gboolean result = FALSE;
|
gboolean result = FALSE;
|
||||||
|
|
||||||
|
GST_DEBUG ("unlock");
|
||||||
/* unblock whatever the subclass is doing */
|
/* unblock whatever the subclass is doing */
|
||||||
bclass = GST_BASESRC_GET_CLASS (basesrc);
|
bclass = GST_BASESRC_GET_CLASS (basesrc);
|
||||||
if (bclass->unlock)
|
if (bclass->unlock)
|
||||||
result = bclass->unlock (basesrc);
|
result = bclass->unlock (basesrc);
|
||||||
|
|
||||||
|
GST_DEBUG ("unschedule clock");
|
||||||
/* and unblock the clock as well, if any */
|
/* and unblock the clock as well, if any */
|
||||||
GST_LOCK (basesrc);
|
GST_LOCK (basesrc);
|
||||||
if (basesrc->clock_id) {
|
if (basesrc->clock_id) {
|
||||||
|
@ -588,6 +590,8 @@ gst_basesrc_unlock (GstBaseSrc * basesrc)
|
||||||
}
|
}
|
||||||
GST_UNLOCK (basesrc);
|
GST_UNLOCK (basesrc);
|
||||||
|
|
||||||
|
GST_DEBUG ("unlock done");
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue