gst/gstbin.c: Refactor the sort iterator so it can be used while holding the

Original commit message from CVS:
* gst/gstbin.c: (gst_bin_dispose), (gst_bin_provide_clock_func),
(gst_bin_sort_iterator_new), (gst_bin_iterate_sorted):
Refactor the sort iterator so it can be used while holding the
LOCK too.
Make clock selection select a clock closest to the source.
This commit is contained in:
Wim Taymans 2005-11-17 14:51:11 +00:00
parent 3f80a0d393
commit a1aa83c759
2 changed files with 85 additions and 51 deletions

View file

@ -1,3 +1,11 @@
2005-11-17 Wim Taymans <wim@fluendo.com>
* gst/gstbin.c: (gst_bin_dispose), (gst_bin_provide_clock_func),
(gst_bin_sort_iterator_new), (gst_bin_iterate_sorted):
Refactor the sort iterator so it can be used while holding the
LOCK too.
Make clock selection select a clock closest to the source.
2005-11-17 Michael Smith <msmith@fluendo.com>
* gst/gstclock.c: (gst_clock_init), (gst_clock_adjust_unlocked),

View file

@ -157,9 +157,13 @@ static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent);
static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self);
#endif
static void bin_remove_messages (GstBin * bin, GstObject * src,
GstMessageType types);
static void gst_bin_recalc_func (GstBin * child, gpointer data);
static gint bin_element_is_sink (GstElement * child, GstBin * bin);
static GstIterator *gst_bin_sort_iterator_new (GstBin * bin);
/* Bin signals and properties */
enum
{
@ -362,6 +366,29 @@ gst_bin_init (GstBin * bin)
gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bin_bus_handler, bin);
}
static void
gst_bin_dispose (GObject * object)
{
GstBin *bin = GST_BIN (object);
GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
bin_remove_messages (bin, NULL, GST_MESSAGE_ANY);
gst_object_unref (bin->child_bus);
bin->child_bus = NULL;
gst_object_replace ((GstObject **) & bin->provided_clock, NULL);
while (bin->children) {
gst_bin_remove (bin, GST_ELEMENT_CAST (bin->children->data));
}
if (G_UNLIKELY (bin->children != NULL)) {
g_critical ("could not remove elements from bin %s",
GST_STR_NULL (GST_OBJECT_NAME (object)));
}
G_OBJECT_CLASS (parent_class)->dispose (object);
}
/**
* gst_bin_new:
* @name: the name of the new bin
@ -426,19 +453,18 @@ gst_bin_set_clock_func (GstElement * element, GstClock * clock)
*
* The ref of the returned clock in increased so unref after usage.
*
* We loop the elements in state order and pick the last clock we can
* get. This makes sure we get a clock from the source.
*
* MT safe
*/
/*
* FIXME, clock selection is not correct here. We should loop the
* elements in state order and pick the last clock we can get. This
* makes sure we get a clock from the source.
*/
static GstClock *
gst_bin_provide_clock_func (GstElement * element)
{
GstClock *result = NULL;
GstBin *bin;
GList *children;
GstIterator *it;
gpointer val;
bin = GST_BIN (element);
@ -446,11 +472,21 @@ gst_bin_provide_clock_func (GstElement * element)
if (!bin->clock_dirty)
goto not_dirty;
for (children = bin->children; children; children = g_list_next (children)) {
GstElement *child = GST_ELEMENT (children->data);
GST_DEBUG_OBJECT (bin, "finding new clock");
if ((result = gst_element_provide_clock (child)))
break;
it = gst_bin_sort_iterator_new (bin);
while (it->next (it, &val) == GST_ITERATOR_OK) {
GstElement *child = GST_ELEMENT_CAST (val);
GstClock *clock;
clock = gst_element_provide_clock (child);
if (clock || result == NULL) {
GST_DEBUG_OBJECT (bin, "found candidate clock %p", clock);
if (result)
gst_object_unref (result);
result = clock;
}
}
gst_object_replace ((GstObject **) & bin->provided_clock,
(GstObject *) result);
@ -458,6 +494,8 @@ gst_bin_provide_clock_func (GstElement * element)
GST_DEBUG_OBJECT (bin, "provided new clock %p", result);
GST_UNLOCK (bin);
gst_iterator_free (it);
return result;
not_dirty:
@ -1486,6 +1524,32 @@ gst_bin_sort_iterator_free (GstBinSortIterator * bit)
g_free (bit);
}
/* should be called with the bin LOCK held */
static GstIterator *
gst_bin_sort_iterator_new (GstBin * bin)
{
GstBinSortIterator *result;
/* we don't need an ItemFunction because we ref the items in the _next
* method already */
result = (GstBinSortIterator *)
gst_iterator_new (sizeof (GstBinSortIterator),
GST_TYPE_ELEMENT,
GST_GET_LOCK (bin),
&bin->children_cookie,
(GstIteratorNextFunction) gst_bin_sort_iterator_next,
(GstIteratorItemFunction) NULL,
(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);
gst_object_ref (bin);
result->bin = bin;
gst_bin_sort_iterator_resync (result);
return (GstIterator *) result;
}
/**
* gst_bin_iterate_sorted:
* @bin: a #GstBin
@ -1507,30 +1571,15 @@ gst_bin_sort_iterator_free (GstBinSortIterator * bit)
GstIterator *
gst_bin_iterate_sorted (GstBin * bin)
{
GstBinSortIterator *result;
GstIterator *result;
g_return_val_if_fail (GST_IS_BIN (bin), NULL);
GST_LOCK (bin);
gst_object_ref (bin);
/* we don't need a NextFunction because we ref the items in the _next
* method already */
result = (GstBinSortIterator *)
gst_iterator_new (sizeof (GstBinSortIterator),
GST_TYPE_ELEMENT,
GST_GET_LOCK (bin),
&bin->children_cookie,
(GstIteratorNextFunction) gst_bin_sort_iterator_next,
(GstIteratorItemFunction) NULL,
(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);
result = gst_bin_sort_iterator_new (bin);
GST_UNLOCK (bin);
return (GstIterator *) result;
return result;
}
static GstStateChangeReturn
@ -1683,29 +1732,6 @@ done:
return ret;
}
static void
gst_bin_dispose (GObject * object)
{
GstBin *bin = GST_BIN (object);
GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
bin_remove_messages (bin, NULL, GST_MESSAGE_ANY);
gst_object_unref (bin->child_bus);
bin->child_bus = NULL;
gst_object_replace ((GstObject **) & bin->provided_clock, NULL);
while (bin->children) {
gst_bin_remove (bin, GST_ELEMENT_CAST (bin->children->data));
}
if (G_UNLIKELY (bin->children != NULL)) {
g_critical ("could not remove elements from bin %s",
GST_STR_NULL (GST_OBJECT_NAME (object)));
}
G_OBJECT_CLASS (parent_class)->dispose (object);
}
/*
* This function is a utility event handler for seek events.
* It will send the event to all sinks.