summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 7f2ea50)
raw | patch | inline | side by side (parent: 7f2ea50)
author | Wim Taymans <wim.taymans@gmail.com> | |
Tue, 27 Sep 2005 17:00:13 +0000 (17:00 +0000) | ||
committer | Wim Taymans <wim.taymans@gmail.com> | |
Tue, 27 Sep 2005 17:00:13 +0000 (17:00 +0000) |
Original commit message from CVS:
* docs/design/part-TODO.txt:
Update TODO.
* gst/gstbin.c: (add_to_queue), (clear_queue), (reset_outdegree),
(update_outdegree), (find_element), (gst_bin_sort_iterator_next),
(gst_bin_sort_iterator_resync), (gst_bin_sort_iterator_free),
(gst_bin_iterate_sorted), (gst_bin_element_set_state),
(gst_bin_change_state):
* gst/gstelement.h:
Remove element variable, we keep element info in the iterator now.
* docs/design/part-TODO.txt:
Update TODO.
* gst/gstbin.c: (add_to_queue), (clear_queue), (reset_outdegree),
(update_outdegree), (find_element), (gst_bin_sort_iterator_next),
(gst_bin_sort_iterator_resync), (gst_bin_sort_iterator_free),
(gst_bin_iterate_sorted), (gst_bin_element_set_state),
(gst_bin_change_state):
* gst/gstelement.h:
Remove element variable, we keep element info in the iterator now.
ChangeLog | patch | blob | history | |
docs/design/part-TODO.txt | patch | blob | history | |
gst/gstbin.c | patch | blob | history | |
gst/gstelement.h | patch | blob | history |
diff --git a/ChangeLog b/ChangeLog
index 13cb0e6cfa15618629def2c32c4108710af7e9a0..af0a35364e0e9ca2fc05a96b7936b34ad8e1105b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
+2005-09-27 Wim Taymans <wim@fluendo.com>
+
+ * docs/design/part-TODO.txt:
+ Update TODO.
+
+ * gst/gstbin.c: (add_to_queue), (clear_queue), (reset_outdegree),
+ (update_outdegree), (find_element), (gst_bin_sort_iterator_next),
+ (gst_bin_sort_iterator_resync), (gst_bin_sort_iterator_free),
+ (gst_bin_iterate_sorted), (gst_bin_element_set_state),
+ (gst_bin_change_state):
+ * gst/gstelement.h:
+ Remove element variable, we keep element info in the iterator now.
+
2005-09-27 Andy Wingo <wingo@pobox.com>
* libs/gst/dataprotocol/dataprotocol.c: Fix error-checking return
index 1acb746a0055d90df4a7fc33afea7cfb502d6da1..107b6dea9a9bf27124ab9e7ccf4cb7b2171cc927 100644 (file)
done by making the event contain a GstStructure with input/output values, similar
to GstMessage.
-- implement iterators for traversing elements upstream or dowstream. Use more simple
- algorithm using indegree topological sort.
-
- unlinking pads in the PAUSED state needs to make sure the stream thread is not
executing code. Can this be done with a flush to unlock all downstream chain
functions?
diff --git a/gst/gstbin.c b/gst/gstbin.c
index b8c5df55f261d949279be78d2e4b004b0542d5de..a5805182ffbea143306881cfd77a6c6c434accd1 100644 (file)
--- a/gst/gstbin.c
+++ b/gst/gstbin.c
typedef struct _GstBinSortIterator
{
GstIterator it;
- GQueue *queue;
- GstBin *bin;
- gint mode;
- GstElement *best;
+ GQueue *queue; /* elements queued for state change */
+ GstBin *bin; /* bin we iterate */
+ gint mode; /* adding or removing dependency */
+ GstElement *best; /* next element with least dependencies */
+ gint best_deg; /* best degree */
+ GHashTable *hash; /* has table with element dependencies */
} GstBinSortIterator;
+/* we add and subtract 1 to make sure we don't confuse NULL and 0 */
+#define HASH_SET_DEGREE(bit, elem, deg) \
+ g_hash_table_replace (bit->hash, elem, GINT_TO_POINTER(deg+1))
+#define HASH_GET_DEGREE(bit, elem) \
+ (GPOINTER_TO_INT(g_hash_table_lookup (bit->hash, elem))-1)
+
/* add element to queue of next elements in the iterator.
* We push at the tail to give higher priority elements a
* chance first */
static void
-add_to_queue (GQueue * queue, GstElement * element)
+add_to_queue (GstBinSortIterator * bit, GstElement * element)
{
GST_DEBUG ("%s add to queue", GST_ELEMENT_NAME (element));
gst_object_ref (element);
- g_queue_push_tail (queue, element);
- element->outdegree = -1;
+ g_queue_push_tail (bit->queue, element);
+ HASH_SET_DEGREE (bit, element, -1);
}
/* clear the queue, unref all objects as we took a ref when
{
/* sinks are added right away */
if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK)) {
- add_to_queue (bit->queue, element);
+ add_to_queue (bit, element);
} else {
/* others are marked with 0 and handled when sinks are done */
- element->outdegree = 0;
+ HASH_SET_DEGREE (bit, element, 0);
}
}
GST_LOCK (peer_element);
if (GST_OBJECT_CAST (peer_element)->parent ==
GST_OBJECT_CAST (bit->bin)) {
+ gint old_deg, new_deg;
+
+ old_deg = HASH_GET_DEGREE (bit, peer_element);
+ new_deg = old_deg + bit->mode;
GST_DEBUG ("change element %s, degree %d->%d, linked to %s",
GST_ELEMENT_NAME (peer_element),
- peer_element->outdegree, peer_element->outdegree + bit->mode,
- GST_ELEMENT_NAME (element));
+ old_deg, new_deg, GST_ELEMENT_NAME (element));
/* update outdegree */
- peer_element->outdegree += bit->mode;
- if (peer_element->outdegree == 0) {
+ if (new_deg == 0) {
/* outdegree hit 0, add to queue */
- add_to_queue (bit->queue, peer_element);
+ add_to_queue (bit, peer_element);
+ } else {
+ HASH_SET_DEGREE (bit, peer_element, new_deg);
}
linked = TRUE;
}
gint outdegree;
/* element is already handled */
- if ((outdegree = element->outdegree) < 0)
+ if ((outdegree = HASH_GET_DEGREE (bit, element)) < 0)
return;
/* first element or element with smaller outdegree */
- if (bit->best == NULL || bit->best->outdegree > outdegree) {
+ if (bit->best == NULL || bit->best_deg > outdegree) {
bit->best = element;
+ bit->best_deg = outdegree;
}
}
/* empty queue, we have to find a next best element */
if (g_queue_is_empty (bit->queue)) {
bit->best = NULL;
+ bit->best_deg = G_MAXINT;
g_list_foreach (bit->bin->children, (GFunc) find_element, bit);
if (bit->best) {
- if (bit->best->outdegree != 0) {
+ if (bit->best_deg != 0) {
/* we don't fail on this one yet */
g_warning ("loop detected in the graph !!");
}
- /* best unhandled elements, add to queue */
+ /* best unhandled elements, scheduler as next element */
GST_DEBUG ("queue empty, next best: %s", GST_ELEMENT_NAME (bit->best));
gst_object_ref (bit->best);
- bit->best->outdegree = -1;
+ HASH_SET_DEGREE (bit, bit->best, -1);
*result = bit->best;
} else {
GST_DEBUG ("queue empty, elements exhausted");
{
clear_queue (bit->queue);
g_queue_free (bit->queue);
+ g_hash_table_destroy (bit->hash);
gst_object_unref (bit->bin);
g_free (bit);
}
*
* MT safe.
*
- * FIXME: No two iterators can run at the same time since the iterators
- * use a shared element field.
- *
* Returns: a #GstIterator of #GstElements. gst_iterator_free after use.
*/
GstIterator *
(GstIteratorResyncFunction) gst_bin_sort_iterator_resync,
(GstIteratorFreeFunction) gst_bin_sort_iterator_free);
result->queue = g_queue_new ();
+ result->hash = g_hash_table_new (NULL, NULL);
result->bin = bin;
gst_bin_sort_iterator_resync (result);
GST_UNLOCK (bin);
diff --git a/gst/gstelement.h b/gst/gstelement.h
index bd50dd56616dab6115dbd81fff8f381fc4b2837e..9fc355f05e53b81bb2d95febc894a968387f11aa 100644 (file)
--- a/gst/gstelement.h
+++ b/gst/gstelement.h
GList *sinkpads;
guint32 pads_cookie;
- /* used in bin state change to calculate number of connections
- * on the srcpad */
- gint outdegree;
-
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};