More MT fixes. Header cleanups, design doc update.

Original commit message from CVS:
* docs/design/part-MT-refcounting.txt:
* gst/gstbin.c: (gst_bin_set_index), (gst_bin_set_clock),
(gst_bin_add_func), (gst_bin_add), (gst_bin_remove_func),
(gst_bin_remove), (gst_bin_iterate_elements),
(bin_element_is_sink), (gst_bin_get_state), (gst_bin_change_state),
(gst_bin_get_by_name), (gst_bin_get_by_name_recurse_up),
(gst_bin_get_by_interface), (gst_bin_get_all_by_interface):
* gst/gstbin.h:
* gst/gstbuffer.h:
* gst/gstbus.h:
* gst/gstcaps.h:
* gst/gstclock.h:
* gst/gstdata.h:
* gst/gstelement.h:
* gst/gstevent.h:
* gst/gstmessage.h:
* gst/gststructure.h:
More MT fixes. Header cleanups, design doc update.
This commit is contained in:
Wim Taymans 2004-12-09 23:28:31 +00:00
parent aed37ff5c3
commit 5b1065d625
13 changed files with 251 additions and 115 deletions

View file

@ -1,3 +1,24 @@
2004-12-10 Wim Taymans <wim@fluendo.com>
* docs/design/part-MT-refcounting.txt:
* gst/gstbin.c: (gst_bin_set_index), (gst_bin_set_clock),
(gst_bin_add_func), (gst_bin_add), (gst_bin_remove_func),
(gst_bin_remove), (gst_bin_iterate_elements),
(bin_element_is_sink), (gst_bin_get_state), (gst_bin_change_state),
(gst_bin_get_by_name), (gst_bin_get_by_name_recurse_up),
(gst_bin_get_by_interface), (gst_bin_get_all_by_interface):
* gst/gstbin.h:
* gst/gstbuffer.h:
* gst/gstbus.h:
* gst/gstcaps.h:
* gst/gstclock.h:
* gst/gstdata.h:
* gst/gstelement.h:
* gst/gstevent.h:
* gst/gstmessage.h:
* gst/gststructure.h:
More MT fixes. Header cleanups, design doc update.
2004-12-09 Wim Taymans <wim@fluendo.com> 2004-12-09 Wim Taymans <wim@fluendo.com>
* gst/gstpad.c: (gst_pad_custom_new), (gst_pad_get_direction), * gst/gstpad.c: (gst_pad_custom_new), (gst_pad_get_direction),

View file

@ -225,15 +225,18 @@ Objects
* Accessing lists * Accessing lists
If the object property is a list concurrent list iteration is needed to get the If the object property is a list concurrent list iteration is needed to get the
contents of the list. GStreamer uses the cookie design pattern mechanism to contents of the list. GStreamer uses the cookie mechanism to mark the last update
mark the last update of a list. The list and the cookie are protected by the of a list. The list and the cookie are protected by the same lock. Each update to
same lock. Each update to a list requires the following actions: a list requires the following actions:
- acquire lock - acquire lock
- update list - update list
- update cookie - update cookie
- release lock - release lock
Updating the cookie is usually done by incrementing its value by one. Since cookies
use guint32 its wraparound is for all practical reasons is not a problem.
Iterating a list can safely be done by surrounding the list iteration with a Iterating a list can safely be done by surrounding the list iteration with a
lock/unlock of the lock. lock/unlock of the lock.
@ -266,9 +269,10 @@ Objects
GST_LOCK (lock); GST_LOCK (lock);
if (cookie != object->list_cookie) { if (cookie != object->list_cookie) {
/* concurrent modification of the list here */ /* handle rollback caused by concurrent modification
* of the list here */
...undo changes to items... ...rollback changes to items...
/* grab new cookie and list */ /* grab new cookie and list */
cookie = object->list_cookie; cookie = object->list_cookie;

View file

@ -62,8 +62,8 @@ static void gst_bin_set_index (GstElement * element, GstIndex * index);
static void gst_bin_set_clock (GstElement * element, GstClock * clock); static void gst_bin_set_clock (GstElement * element, GstClock * clock);
static GstClock *gst_bin_get_clock (GstElement * element); static GstClock *gst_bin_get_clock (GstElement * element);
static void gst_bin_add_func (GstBin * bin, GstElement * element); static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
static void gst_bin_remove_func (GstBin * bin, GstElement * element); static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
#ifndef GST_DISABLE_LOADSAVE #ifndef GST_DISABLE_LOADSAVE
static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent); static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent);
@ -252,46 +252,71 @@ gst_bin_get_clock (GstElement * element)
return result; return result;
} }
static void static gboolean
gst_bin_add_func (GstBin * bin, GstElement * element) gst_bin_add_func (GstBin * bin, GstElement * element)
{ {
GstPipeline *manager; GstPipeline *manager;
gchar *elem_name;
GST_LOCK (element);
/* the element must not already have a parent */ /* the element must not already have a parent */
g_return_if_fail (GST_ELEMENT_PARENT (element) == NULL); if (G_UNLIKELY (GST_ELEMENT_PARENT (element) != NULL))
goto had_parent;
elem_name = g_strdup (GST_ELEMENT_NAME (element));
GST_UNLOCK (element);
GST_LOCK (bin); GST_LOCK (bin);
/* we obviously can't add ourself to ourself */
if (G_UNLIKELY (GST_ELEMENT_CAST (element) == GST_ELEMENT_CAST (bin)))
goto adding_itself;
/* then check to see if the element's name is already taken in the bin, /* then check to see if the element's name is already taken in the bin,
* we can sefely take the lock here. */ * we can safely take the lock here. We can leave the element locked
if (gst_object_check_uniqueness (bin->children, * as it will not be in the bin. This check is probably bogus because
GST_ELEMENT_NAME (element)) == FALSE) { * you can safely change the element name after adding it to the bin. */
g_warning ("Name %s is not unique in bin %s, not adding\n", if (G_UNLIKELY (gst_object_check_uniqueness (bin->children,
GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin)); elem_name) == FALSE))
GST_UNLOCK (bin); goto duplicate_name;
return;
}
manager = GST_ELEMENT (bin)->manager; manager = GST_ELEMENT (bin)->manager;
gst_element_set_manager (element, manager); gst_element_set_manager (element, manager);
if (GST_STATE (element) > GST_STATE (bin)) {
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
"setting state to receive element \"%s\"", GST_OBJECT_NAME (element));
gst_element_set_state ((GstElement *) bin, GST_STATE (element));
}
/* set the element's parent and add the element to the bin's list of children */ /* set the element's parent and add the element to the bin's list of children */
gst_object_set_parent (GST_OBJECT (element), GST_OBJECT (bin)); gst_object_set_parent (GST_OBJECT (element), GST_OBJECT (bin));
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++;
GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"",
GST_OBJECT_NAME (element));
GST_UNLOCK (bin); GST_UNLOCK (bin);
GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"",
elem_name);
g_free (elem_name);
g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_ADDED], 0, element); g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_ADDED], 0, element);
return TRUE;
/* ERROR handling here */
had_parent:
g_warning ("Element %s already has parent %p", GST_ELEMENT_NAME (element),
bin);
GST_UNLOCK (element);
return FALSE;
adding_itself:
g_warning ("Cannot add bin %s to itself", GST_ELEMENT_NAME (bin));
GST_UNLOCK (bin);
g_free (elem_name);
return FALSE;
duplicate_name:
g_warning ("Name %s is not unique in bin %s, not adding",
elem_name, GST_ELEMENT_NAME (bin));
GST_UNLOCK (bin);
g_free (elem_name);
return FALSE;
} }
/** /**
@ -301,64 +326,88 @@ gst_bin_add_func (GstBin * bin, GstElement * element)
* *
* Adds the given element to the bin. Sets the element's parent, and thus * Adds the given element to the bin. Sets the element's parent, and thus
* takes ownership of the element. An element can only be added to one bin. * takes ownership of the element. An element can only be added to one bin.
*
* Returns: TRUE if the element could be added, FALSE on wrong parameters or
* the bin does not want to accept the element.
*
* MT safe.
*/ */
void gboolean
gst_bin_add (GstBin * bin, GstElement * element) gst_bin_add (GstBin * bin, GstElement * element)
{ {
GstBinClass *bclass; GstBinClass *bclass;
gboolean result;
g_return_if_fail (GST_IS_BIN (bin)); g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
g_return_if_fail (GST_IS_ELEMENT (element)); g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "adding element \"%s\"",
GST_OBJECT_NAME (element));
bclass = GST_BIN_GET_CLASS (bin); bclass = GST_BIN_GET_CLASS (bin);
if (bclass->add_element) { if (G_UNLIKELY (bclass->add_element == NULL))
bclass->add_element (bin, element); goto no_function;
} else {
g_warning ("cannot add element %s to bin %s", GST_CAT_DEBUG (GST_CAT_PARENTAGE, "adding element %s to bin %s",
GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin)); GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
}
result = bclass->add_element (bin, element);
return result;
no_function:
g_warning ("adding elements to bin %s is not supported",
GST_ELEMENT_NAME (bin));
return FALSE;
} }
static void static gboolean
gst_bin_remove_func (GstBin * bin, GstElement * element) gst_bin_remove_func (GstBin * bin, GstElement * element)
{ {
gchar *elem_name;
/* the element must have its parent set to the current bin */ /* the element must have its parent set to the current bin */
g_return_if_fail (GST_ELEMENT_PARENT (element) == (GstObject *) bin); GST_LOCK (element);
/* the element must not already have a parent */
if (G_UNLIKELY (GST_ELEMENT_PARENT (element) != GST_ELEMENT_CAST (bin)))
goto wrong_parent;
elem_name = g_strdup (GST_ELEMENT_NAME (element));
GST_UNLOCK (element);
GST_LOCK (bin); GST_LOCK (bin);
/* the element must be in the bin's list of children, is this
/* the element must be in the bin's list of children */ * check redundant with PARENT checking? */
if (g_list_find (bin->children, element) == NULL) { if (G_UNLIKELY (g_list_find (bin->children, element) == NULL))
g_warning ("no element \"%s\" in bin \"%s\"\n", GST_ELEMENT_NAME (element), goto not_in_bin;
GST_ELEMENT_NAME (bin));
GST_UNLOCK (bin);
return;
}
/* now remove the element from the list of elements */ /* now remove the element from the list of elements */
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++;
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\"",
GST_OBJECT_NAME (element)); elem_name);
g_free (elem_name);
GST_UNLOCK (bin);
gst_element_set_manager (element, NULL); gst_element_set_manager (element, NULL);
/* ref as we're going to emit a signal */ /* we should ref here to avoid bad app behaviour.. */
gst_object_ref (GST_OBJECT (element));
gst_object_unparent (GST_OBJECT (element)); gst_object_unparent (GST_OBJECT (element));
g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_REMOVED], 0, element); g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_REMOVED], 0, element);
/* element is really out of our control now */ return TRUE;
gst_object_unref (GST_OBJECT (element));
wrong_parent:
g_warning ("Element %s is not in bin %p", GST_ELEMENT_NAME (element), bin);
GST_UNLOCK (element);
return FALSE;
not_in_bin:
g_warning ("Element %s is not in bin %s", elem_name, GST_ELEMENT_NAME (bin));
GST_UNLOCK (bin);
g_free (elem_name);
return FALSE;
} }
/** /**
@ -372,27 +421,42 @@ gst_bin_remove_func (GstBin * bin, GstElement * element)
* will be freed in the process of removing it from the bin. If you * will be freed in the process of removing it from the bin. If you
* want the element to still exist after removing, you need to call * want the element to still exist after removing, you need to call
* #gst_object_ref before removing it from the bin. * #gst_object_ref before removing it from the bin.
*
* Returns: TRUE if the element could be removed, FALSE on wrong parameters or
* the bin does not want to remove the element.
*
* MT safe.
*/ */
void gboolean
gst_bin_remove (GstBin * bin, GstElement * element) gst_bin_remove (GstBin * bin, GstElement * element)
{ {
GstBinClass *bclass; GstBinClass *bclass;
gboolean result;
GST_CAT_DEBUG (GST_CAT_PARENTAGE, "[%s]: trying to remove child %s", g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
GST_ELEMENT_NAME (bin), GST_ELEMENT_NAME (element)); g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
g_return_if_fail (GST_IS_BIN (bin));
g_return_if_fail (GST_IS_ELEMENT (element));
bclass = GST_BIN_GET_CLASS (bin); bclass = GST_BIN_GET_CLASS (bin);
if (bclass->remove_element) { if (G_UNLIKELY (bclass->remove_element == NULL))
bclass->remove_element (bin, element); goto no_function;
} else {
g_warning ("cannot remove elements from bin %s\n", GST_ELEMENT_NAME (bin)); GST_CAT_DEBUG (GST_CAT_PARENTAGE, "removing element %s from bin %s",
} GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
result = bclass->remove_element (bin, element);
return result;
no_function:
g_warning ("removing elements from bin %s is not supported",
GST_ELEMENT_NAME (bin));
return FALSE;
} }
/*
* bin iterator
*/
typedef struct _GstBinIterator typedef struct _GstBinIterator
{ {
GstIterator iterator; GstIterator iterator;
@ -436,14 +500,18 @@ gst_bin_iterator_free (GstBinIterator * it)
* after usage. * after usage.
* *
* Returns: a #GstIterator of #GstElements. gst_iterator_free after * Returns: a #GstIterator of #GstElements. gst_iterator_free after
* use. * use. returns NULL when passing bad parameters.
*
* MT safe.
*/ */
GstIterator * GstIterator *
gst_bin_iterate_elements (GstBin * bin) gst_bin_iterate_elements (GstBin * bin)
{ {
GstBinIterator *result; GstBinIterator *result;
GST_LOCK (bin); g_return_val_if_fail (GST_IS_BIN (bin), NULL);
/* ne need to lock, nothing can change here */
result = (GstBinIterator *) gst_iterator_new (sizeof (GstBinIterator), result = (GstBinIterator *) gst_iterator_new (sizeof (GstBinIterator),
GST_GET_LOCK (bin), GST_GET_LOCK (bin),
&bin->children_cookie, &bin->children_cookie,
@ -451,6 +519,7 @@ gst_bin_iterate_elements (GstBin * bin)
(GstIteratorResyncFunction) gst_bin_iterator_resync, (GstIteratorResyncFunction) gst_bin_iterator_resync,
(GstIteratorFreeFunction) gst_bin_iterator_free); (GstIteratorFreeFunction) gst_bin_iterator_free);
GST_LOCK (bin);
result->bin = GST_BIN (gst_object_ref (GST_OBJECT (bin))); result->bin = GST_BIN (gst_object_ref (GST_OBJECT (bin)));
result->list = bin->children; result->list = bin->children;
GST_UNLOCK (bin); GST_UNLOCK (bin);
@ -478,6 +547,7 @@ bin_element_is_sink (GstElement * child, GstBin * bin)
GList *pads; GList *pads;
gboolean connected_src = FALSE; gboolean connected_src = FALSE;
/* FIXME not MT safe */
for (pads = child->srcpads; pads; pads = g_list_next (pads)) { for (pads = child->srcpads; pads; pads = g_list_next (pads)) {
GstPad *pad = GST_PAD (pads->data); GstPad *pad = GST_PAD (pads->data);
@ -514,6 +584,8 @@ bin_element_is_sink (GstElement * child, GstBin * bin)
* after usage. * after usage.
* *
* Returns: a #GstIterator of #GstElements. gst_iterator_free after use. * Returns: a #GstIterator of #GstElements. gst_iterator_free after use.
*
* MT safe.
*/ */
GstIterator * GstIterator *
gst_bin_iterate_sinks (GstBin * bin) gst_bin_iterate_sinks (GstBin * bin)
@ -556,6 +628,8 @@ gst_bin_get_state (GstElement * element, GstElementState * state,
/* we cannot take the state lock yet as we might block when querying /* we cannot take the state lock yet as we might block when querying
* the children, holding the lock too long for no reason */ * the children, holding the lock too long for no reason */
/* FIXME, we can loop the list ourselves instead of creating the
* iterator */
children = gst_bin_iterate_sinks (bin); children = gst_bin_iterate_sinks (bin);
child = gst_iterator_find_custom (children, timeout, child = gst_iterator_find_custom (children, timeout,
(GCompareFunc) bin_find_pending_child); (GCompareFunc) bin_find_pending_child);
@ -597,8 +671,6 @@ gst_bin_change_state (GstElement * element)
GQueue *elem_queue; /* list of elements waiting for a state change */ GQueue *elem_queue; /* list of elements waiting for a state change */
g_return_val_if_fail (GST_IS_BIN (element), GST_STATE_FAILURE);
bin = GST_BIN (element); bin = GST_BIN (element);
old_state = GST_STATE (element); old_state = GST_STATE (element);
@ -616,6 +688,7 @@ gst_bin_change_state (GstElement * element)
/* 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. */
/* FIXME, we can iterate the list ourselves */
sinks = gst_bin_iterate_sinks (bin); sinks = gst_bin_iterate_sinks (bin);
while (!done) { while (!done) {
gpointer child; gpointer child;
@ -767,27 +840,30 @@ gst_bin_dispose (GObject * object)
* Get the element with the given name from this bin. This * Get the element with the given name from this bin. This
* function recurses into subbins. * function recurses into subbins.
* *
* Returns: the element with the given name * Returns: the element with the given name. Returns NULL if the
* element is not found or when bad parameters were given.
*
* MT safe.
*/ */
GstElement * GstElement *
gst_bin_get_by_name (GstBin * bin, const gchar * name) gst_bin_get_by_name (GstBin * bin, const gchar * name)
{ {
const GList *children; GList *children;
GstElement *result = NULL; GstElement *result = NULL;
g_return_val_if_fail (bin != NULL, result); g_return_val_if_fail (GST_IS_BIN (bin), NULL);
g_return_val_if_fail (GST_IS_BIN (bin), result); g_return_val_if_fail (name != NULL, NULL);
g_return_val_if_fail (name != NULL, result);
GST_CAT_INFO (GST_CAT_PARENTAGE, "[%s]: looking up child element %s", GST_CAT_INFO (GST_CAT_PARENTAGE, "[%s]: looking up child element %s",
GST_ELEMENT_NAME (bin), name); GST_ELEMENT_NAME (bin), name);
GST_LOCK (bin); GST_LOCK (bin);
children = bin->children; for (children = bin->children; children; children = g_list_next (children)) {
while (children) { GstElement *child = GST_ELEMENT_CAST (children->data);
GstElement *child = GST_ELEMENT (children->data);
if (!strcmp (GST_OBJECT_NAME (child), name)) { GST_LOCK (child);
if (!strcmp (GST_ELEMENT_NAME (child), name)) {
GST_UNLOCK (child);
result = child; result = child;
break; break;
} }
@ -797,7 +873,6 @@ gst_bin_get_by_name (GstBin * bin, const gchar * name)
break; break;
} }
} }
children = g_list_next (children);
} }
GST_UNLOCK (bin); GST_UNLOCK (bin);
@ -812,25 +887,28 @@ gst_bin_get_by_name (GstBin * bin, const gchar * name)
* Get the element with the given name from this bin. If the * Get the element with the given name from this bin. If the
* element is not found, a recursion is performed on the parent bin. * element is not found, a recursion is performed on the parent bin.
* *
* Returns: the element with the given name * Returns: the element with the given name or NULL when the element
* was not found or bad parameters were given.
*
* MT safe.
*/ */
GstElement * GstElement *
gst_bin_get_by_name_recurse_up (GstBin * bin, const gchar * name) gst_bin_get_by_name_recurse_up (GstBin * bin, const gchar * name)
{ {
GstElement *result = NULL; GstElement *result;
GstObject *parent;
g_return_val_if_fail (bin != NULL, NULL);
g_return_val_if_fail (GST_IS_BIN (bin), NULL); g_return_val_if_fail (GST_IS_BIN (bin), NULL);
g_return_val_if_fail (name != NULL, NULL); g_return_val_if_fail (name != NULL, NULL);
result = gst_bin_get_by_name (bin, name); result = gst_bin_get_by_name (bin, name);
if (!result) { if (!result) {
parent = gst_object_get_parent (GST_OBJECT (bin)); GstObject *parent;
parent = gst_object_get_parent (GST_OBJECT_CAST (bin));
if (parent && GST_IS_BIN (parent)) { if (parent && GST_IS_BIN (parent)) {
result = gst_bin_get_by_name_recurse_up (GST_BIN (parent), name); result = gst_bin_get_by_name_recurse_up (GST_BIN_CAST (parent), name);
} }
gst_object_unref (parent); gst_object_unref (parent);
} }
@ -850,21 +928,22 @@ gst_bin_get_by_name_recurse_up (GstBin * bin, const gchar * name)
* gst_bin_get_all_by_interface(). The function recurses bins inside bins. * gst_bin_get_all_by_interface(). The function recurses bins inside bins.
* *
* Returns: An element inside the bin implementing the interface. * Returns: An element inside the bin implementing the interface.
*
* MT safe.
*/ */
GstElement * GstElement *
gst_bin_get_by_interface (GstBin * bin, GType interface) gst_bin_get_by_interface (GstBin * bin, GType interface)
{ {
const GList *walk; GList *walk;
GstElement *result = NULL; GstElement *result = NULL;
g_return_val_if_fail (GST_IS_BIN (bin), NULL); g_return_val_if_fail (GST_IS_BIN (bin), NULL);
g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface), NULL); g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface), NULL);
GST_LOCK (bin); GST_LOCK (bin);
walk = bin->children; for (walk = bin->children; walk; walk = g_list_next (walk)) {
while (walk) {
if (G_TYPE_CHECK_INSTANCE_TYPE (walk->data, interface)) { if (G_TYPE_CHECK_INSTANCE_TYPE (walk->data, interface)) {
result = GST_ELEMENT (walk->data); result = GST_ELEMENT_CAST (walk->data);
break; break;
} }
if (GST_IS_BIN (walk->data)) { if (GST_IS_BIN (walk->data)) {
@ -872,7 +951,6 @@ gst_bin_get_by_interface (GstBin * bin, GType interface)
if (result) if (result)
break; break;
} }
walk = g_list_next (walk);
} }
GST_UNLOCK (bin); GST_UNLOCK (bin);
@ -890,29 +968,27 @@ gst_bin_get_by_interface (GstBin * bin, GType interface)
* g_list_free() after use. * g_list_free() after use.
* *
* Returns: The elements inside the bin implementing the interface. * Returns: The elements inside the bin implementing the interface.
*
* MT safe.
*/ */
GList * GList *
gst_bin_get_all_by_interface (GstBin * bin, GType interface) gst_bin_get_all_by_interface (GstBin * bin, GType interface)
{ {
const GList *walk; GList *walk;
GList *ret = NULL; GList *ret = NULL;
g_return_val_if_fail (GST_IS_BIN (bin), NULL); g_return_val_if_fail (GST_IS_BIN (bin), NULL);
g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface), NULL); g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface), NULL);
GST_LOCK (bin); GST_LOCK (bin);
walk = bin->children; for (walk = bin->children; walk; walk = g_list_next (walk)) {
while (walk) {
if (G_TYPE_CHECK_INSTANCE_TYPE (walk->data, interface)) { if (G_TYPE_CHECK_INSTANCE_TYPE (walk->data, interface)) {
GST_DEBUG_OBJECT (bin, "element %s implements requested interface",
GST_ELEMENT_NAME (GST_ELEMENT (walk->data)));
ret = g_list_prepend (ret, walk->data); ret = g_list_prepend (ret, walk->data);
} }
if (GST_IS_BIN (walk->data)) { if (GST_IS_BIN (walk->data)) {
ret = g_list_concat (ret, ret = g_list_concat (ret,
gst_bin_get_all_by_interface (GST_BIN (walk->data), interface)); gst_bin_get_all_by_interface (GST_BIN (walk->data), interface));
} }
walk = g_list_next (walk);
} }
GST_UNLOCK (bin); GST_UNLOCK (bin);

View file

@ -37,6 +37,7 @@ GST_EXPORT GType _gst_bin_type;
#define GST_BIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BIN, GstBinClass)) #define GST_BIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BIN, GstBinClass))
#define GST_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_BIN, GstBin)) #define GST_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_BIN, GstBin))
#define GST_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_BIN, GstBinClass)) #define GST_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_BIN, GstBinClass))
#define GST_BIN_CAST(obj) ((GstBin*)(obj))
typedef enum { typedef enum {
GST_BIN_FLAG_FIXED_CLOCK, GST_BIN_FLAG_FIXED_CLOCK,
@ -56,25 +57,30 @@ struct _GstBin {
GstElement element; GstElement element;
/*< public >*/ /* with LOCK */ /*< public >*/ /* with LOCK */
/* our children */ /* our children, subclass are supposed to update these
* fields to reflect their state with _iterate_*() */
gint numchildren; gint numchildren;
GList *children; GList *children;
guint32 children_cookie; guint32 children_cookie;
/*< private >*/
gpointer _gst_reserved[GST_PADDING]; gpointer _gst_reserved[GST_PADDING];
}; };
struct _GstBinClass { struct _GstBinClass {
GstElementClass parent_class; GstElementClass parent_class;
/* vtable */ /*< public >*/
void (*add_element) (GstBin *bin, GstElement *element);
void (*remove_element) (GstBin *bin, GstElement *element);
/* signals */ /* signals */
void (*element_added) (GstBin *bin, GstElement *child); void (*element_added) (GstBin *bin, GstElement *child);
void (*element_removed) (GstBin *bin, GstElement *child); void (*element_removed) (GstBin *bin, GstElement *child);
/*< protected >*/
/* vtable */
gboolean (*add_element) (GstBin *bin, GstElement *element);
gboolean (*remove_element) (GstBin *bin, GstElement *element);
/*< private >*/
gpointer _gst_reserved[GST_PADDING]; gpointer _gst_reserved[GST_PADDING];
}; };
@ -82,8 +88,8 @@ GType gst_bin_get_type (void);
GstElement* gst_bin_new (const gchar *name); GstElement* gst_bin_new (const gchar *name);
/* add and remove elements from the bin */ /* add and remove elements from the bin */
void gst_bin_add (GstBin *bin, GstElement *element); gboolean gst_bin_add (GstBin *bin, GstElement *element);
void gst_bin_remove (GstBin *bin, GstElement *element); gboolean gst_bin_remove (GstBin *bin, GstElement *element);
/* retrieve a single child */ /* retrieve a single child */
GstElement* gst_bin_get_by_name (GstBin *bin, const gchar *name); GstElement* gst_bin_get_by_name (GstBin *bin, const gchar *name);

View file

@ -108,6 +108,7 @@ typedef enum {
struct _GstBuffer { struct _GstBuffer {
GstData data_type; GstData data_type;
/*< public >*/ /* with COW */
/* pointer to data and its size */ /* pointer to data and its size */
guint8 *data; /* pointer to buffer data */ guint8 *data; /* pointer to buffer data */
guint size; /* size of buffer data */ guint size; /* size of buffer data */
@ -130,9 +131,11 @@ struct _GstBuffer {
guint64 offset; guint64 offset;
guint64 offset_end; guint64 offset_end;
/*< protected >*/
GstBufferFreeDataFunc free_data; GstBufferFreeDataFunc free_data;
gpointer buffer_private; gpointer buffer_private;
/*< private >*/
gpointer _gst_reserved[GST_PADDING]; gpointer _gst_reserved[GST_PADDING];
}; };
@ -167,7 +170,7 @@ GstBuffer* gst_buffer_merge (GstBuffer *buf1, GstBuffer *buf2);
gboolean gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2); gboolean gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2);
GstBuffer* gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len); GstBuffer* gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len);
/* --- private --- */ /* --- protected --- */
void _gst_buffer_initialize (void); void _gst_buffer_initialize (void);
void gst_buffer_default_free (GstBuffer *buffer); void gst_buffer_default_free (GstBuffer *buffer);

View file

@ -34,6 +34,7 @@ G_BEGIN_DECLS
#define GST_BUS_CLASS(bclass) (G_TYPE_CHECK_CLASS_CAST ((bclass), GST_TYPE_BUS, GstBusClass)) #define GST_BUS_CLASS(bclass) (G_TYPE_CHECK_CLASS_CAST ((bclass), GST_TYPE_BUS, GstBusClass))
#define GST_IS_BUS_CLASS(bclass) (G_TYPE_CHECK_CLASS_TYPE ((bclass), GST_TYPE_BUS)) #define GST_IS_BUS_CLASS(bclass) (G_TYPE_CHECK_CLASS_TYPE ((bclass), GST_TYPE_BUS))
#define GST_BUS_GET_CLASS(bus) (G_TYPE_INSTANCE_GET_CLASS ((bus), GST_TYPE_BUS, GstBusClass)) #define GST_BUS_GET_CLASS(bus) (G_TYPE_INSTANCE_GET_CLASS ((bus), GST_TYPE_BUS, GstBusClass))
#define GST_BUS_CAST(bus) ((GstBus*)(bus))
typedef enum typedef enum
{ {
@ -51,6 +52,7 @@ typedef gboolean (*GstBusHandler) (GstBus *bus, GstMessage *message, gpointer da
struct _GstBus { struct _GstBus {
GstObject object; GstObject object;
/*< private >*/
GAsyncQueue *queue; GAsyncQueue *queue;
GstBusSyncHandler sync_handler; GstBusSyncHandler sync_handler;
@ -59,12 +61,14 @@ struct _GstBus {
gint control_socket[2]; gint control_socket[2];
GIOChannel *io_channel; GIOChannel *io_channel;
/*< private >*/
gpointer _gst_reserved[GST_PADDING]; gpointer _gst_reserved[GST_PADDING];
}; };
struct _GstBusClass { struct _GstBusClass {
GstObjectClass parent_class; GstObjectClass parent_class;
/*< private >*/
gpointer _gst_reserved[GST_PADDING]; gpointer _gst_reserved[GST_PADDING];
}; };

View file

@ -59,18 +59,23 @@ typedef struct _GstStaticCaps GstStaticCaps;
struct _GstCaps { struct _GstCaps {
GType type; GType type;
/*< public >*/ /* with COW */
/* refcounting */ /* refcounting */
GstAtomicInt refcount; GstAtomicInt refcount;
guint16 flags; guint16 flags;
GPtrArray *structs; GPtrArray *structs;
/*< private >*/
gpointer _gst_reserved[GST_PADDING]; gpointer _gst_reserved[GST_PADDING];
}; };
struct _GstStaticCaps { struct _GstStaticCaps {
/*< public >*/
GstCaps caps; GstCaps caps;
const char *string; const char *string;
/*< private >*/
gpointer _gst_reserved[GST_PADDING]; gpointer _gst_reserved[GST_PADDING];
}; };

View file

@ -34,6 +34,7 @@ G_BEGIN_DECLS
#define GST_CLOCK_CLASS(cclass) (G_TYPE_CHECK_CLASS_CAST ((cclass), GST_TYPE_CLOCK, GstClockClass)) #define GST_CLOCK_CLASS(cclass) (G_TYPE_CHECK_CLASS_CAST ((cclass), GST_TYPE_CLOCK, GstClockClass))
#define GST_IS_CLOCK_CLASS(cclass) (G_TYPE_CHECK_CLASS_TYPE ((cclass), GST_TYPE_CLOCK)) #define GST_IS_CLOCK_CLASS(cclass) (G_TYPE_CHECK_CLASS_TYPE ((cclass), GST_TYPE_CLOCK))
#define GST_CLOCK_GET_CLASS(clock) (G_TYPE_INSTANCE_GET_CLASS ((clock), GST_TYPE_CLOCK, GstClockClass)) #define GST_CLOCK_GET_CLASS(clock) (G_TYPE_INSTANCE_GET_CLASS ((clock), GST_TYPE_CLOCK, GstClockClass))
#define GST_CLOCK_CAST(clock) ((GstClock*)(clock))
typedef guint64 GstClockTime; typedef guint64 GstClockTime;
typedef gint64 GstClockTimeDiff; typedef gint64 GstClockTimeDiff;
@ -73,14 +74,14 @@ typedef gboolean (*GstClockCallback) (GstClock *clock, GstClockTime time,
GstClockID id, gpointer user_data); GstClockID id, gpointer user_data);
typedef enum { typedef enum {
/* --- protected --- */ /*< protected >*/
GST_CLOCK_ENTRY_OK, GST_CLOCK_ENTRY_OK,
GST_CLOCK_ENTRY_EARLY, GST_CLOCK_ENTRY_EARLY,
GST_CLOCK_ENTRY_RESTART GST_CLOCK_ENTRY_RESTART
} GstClockEntryStatus; } GstClockEntryStatus;
typedef enum { typedef enum {
/* --- protected --- */ /*< protected >*/
GST_CLOCK_ENTRY_SINGLE, GST_CLOCK_ENTRY_SINGLE,
GST_CLOCK_ENTRY_PERIODIC GST_CLOCK_ENTRY_PERIODIC
} GstClockEntryType; } GstClockEntryType;
@ -93,7 +94,7 @@ typedef enum {
#define GST_CLOCK_ENTRY_STATUS(entry) ((entry)->status) #define GST_CLOCK_ENTRY_STATUS(entry) ((entry)->status)
struct _GstClockEntry { struct _GstClockEntry {
/* --- protected --- */ /*< protected >*/
GstClock *clock; GstClock *clock;
GstClockEntryType type; GstClockEntryType type;
GstClockTime time; GstClockTime time;
@ -128,13 +129,14 @@ typedef enum
struct _GstClock { struct _GstClock {
GstObject object; GstObject object;
/*< public >*/
GstClockFlags flags; GstClockFlags flags;
/* --- protected --- */ /*< protected >*/
GstClockTime start_time; GstClockTime start_time;
GstClockTime last_time; GstClockTime last_time;
/* --- private --- */ /*< private >*/
guint64 resolution; guint64 resolution;
GList *entries; GList *entries;
GMutex *active_mutex; GMutex *active_mutex;
@ -147,6 +149,7 @@ struct _GstClock {
struct _GstClockClass { struct _GstClockClass {
GstObjectClass parent_class; GstObjectClass parent_class;
/*< protected >*/
/* vtable */ /* vtable */
gdouble (*change_speed) (GstClock *clock, gdouble (*change_speed) (GstClock *clock,
gdouble oldspeed, gdouble newspeed); gdouble oldspeed, gdouble newspeed);
@ -162,6 +165,8 @@ struct _GstClockClass {
GstClockEntryStatus (*wait_async) (GstClock *clock, GstClockEntry *entry); GstClockEntryStatus (*wait_async) (GstClock *clock, GstClockEntry *entry);
void (*unschedule) (GstClock *clock, GstClockEntry *entry); void (*unschedule) (GstClock *clock, GstClockEntry *entry);
void (*unlock) (GstClock *clock, GstClockEntry *entry); void (*unlock) (GstClock *clock, GstClockEntry *entry);
/*< private >*/
gpointer _gst_reserved[GST_PADDING]; gpointer _gst_reserved[GST_PADDING];
}; };

View file

@ -69,15 +69,18 @@ typedef enum
struct _GstData { struct _GstData {
GType type; GType type;
/*< public >*/ /* with COW */
/* refcounting */ /* refcounting */
GstAtomicInt refcount; GstAtomicInt refcount;
guint16 flags; guint16 flags;
/*< protected >*/
/* utility function pointers, can override default */ /* utility function pointers, can override default */
GstDataFreeFunction free; /* free the data */ GstDataFreeFunction free; /* free the data */
GstDataCopyFunction copy; /* copy the data */ GstDataCopyFunction copy; /* copy the data */
/*< private >*/
gpointer _gst_reserved[GST_PADDING]; gpointer _gst_reserved[GST_PADDING];
}; };

View file

@ -115,7 +115,7 @@ typedef enum {
} GstElementFlags; } GstElementFlags;
#define GST_ELEMENT_NAME(obj) (GST_OBJECT_NAME(obj)) #define GST_ELEMENT_NAME(obj) (GST_OBJECT_NAME(obj))
#define GST_ELEMENT_PARENT(obj) (GST_OBJECT_PARENT(obj)) #define GST_ELEMENT_PARENT(obj) (GST_ELEMENT_CAST(GST_OBJECT_PARENT(obj)))
#define GST_ELEMENT_MANAGER(obj) (GST_ELEMENT_CAST(obj)->manager) #define GST_ELEMENT_MANAGER(obj) (GST_ELEMENT_CAST(obj)->manager)
#define GST_ELEMENT_CLOCK(obj) (GST_ELEMENT_CAST(obj)->clock) #define GST_ELEMENT_CLOCK(obj) (GST_ELEMENT_CAST(obj)->clock)
#define GST_ELEMENT_PADS(obj) (GST_ELEMENT_CAST(obj)->pads) #define GST_ELEMENT_PADS(obj) (GST_ELEMENT_CAST(obj)->pads)
@ -182,6 +182,7 @@ struct _GstElement {
struct _GstElementClass { struct _GstElementClass {
GstObjectClass parent_class; GstObjectClass parent_class;
/*< public >*/
/* the element details */ /* the element details */
GstElementDetails details; GstElementDetails details;
@ -199,6 +200,7 @@ struct _GstElementClass {
void (*pad_removed) (GstElement *element, GstPad *pad); void (*pad_removed) (GstElement *element, GstPad *pad);
void (*no_more_pads) (GstElement *element); void (*no_more_pads) (GstElement *element);
/*< protected >*/
/* vtable */ /* vtable */
/* request/release pads */ /* request/release pads */
@ -232,6 +234,7 @@ struct _GstElementClass {
gboolean (*query) (GstElement *element, GstQueryType type, gboolean (*query) (GstElement *element, GstQueryType type,
GstFormat *format, gint64 *value); GstFormat *format, gint64 *value);
/*< private >*/
gpointer _gst_reserved[GST_PADDING - 1]; gpointer _gst_reserved[GST_PADDING - 1];
}; };

View file

@ -154,6 +154,7 @@ typedef struct
struct _GstEvent { struct _GstEvent {
GstData data; GstData data;
/*< public >*/ /* with COW */
GstEventType type; GstEventType type;
guint64 timestamp; guint64 timestamp;
GstObject *src; GstObject *src;
@ -182,6 +183,7 @@ struct _GstEvent {
} structure; } structure;
} event_data; } event_data;
/*< private >*/
gpointer _gst_reserved[GST_PADDING]; gpointer _gst_reserved[GST_PADDING];
}; };

View file

@ -62,13 +62,15 @@ typedef enum {
struct _GstMessage { struct _GstMessage {
GstData data; GstData data;
/*< public >*/ /* with MESSAGE_LOCK */
GMutex *lock; /* lock and cond for async delivery */
GCond *cond;
/*< public >*/ /* with COW */
GstMessageType type; GstMessageType type;
guint64 timestamp; guint64 timestamp;
GstObject *src; GstObject *src;
GMutex *lock; /* lock and cond for async delivery */
GCond *cond;
union { union {
struct { struct {
GError *error; GError *error;
@ -82,6 +84,7 @@ struct _GstMessage {
} tag; } tag;
} message_data; } message_data;
/*< private >*/
gpointer _gst_reserved[GST_PADDING]; gpointer _gst_reserved[GST_PADDING];
}; };

View file

@ -39,6 +39,7 @@ typedef gboolean (*GstStructureForeachFunc) (GQuark field_id,
struct _GstStructure { struct _GstStructure {
GType type; GType type;
/*< private >*/
GQuark name; GQuark name;
GArray *fields; GArray *fields;