gst/gstbin.c: (de)activate src pads before calling state_change on the childs.

Original commit message from CVS:
* gst/gstbin.c: (activate_pads),
(iterator_activate_fold_with_resync), (gst_bin_src_pads_activate),
(gst_bin_change_state_func):
(de)activate src pads before calling state_change on the childs.
This is to avoid the case where a src ghostpad is blocked (holding the
stream lock), which would block the deactivation of the ghostpad's
target pad.
* gst/gstghostpad.c: (gst_proxy_pad_do_query_type),
(gst_proxy_pad_do_event), (gst_proxy_pad_do_query),
(gst_proxy_pad_do_internal_link), (gst_proxy_pad_do_bufferalloc),
(gst_proxy_pad_do_chain), (gst_proxy_pad_do_getrange),
(gst_proxy_pad_do_checkgetrange), (gst_proxy_pad_do_getcaps),
(gst_proxy_pad_do_acceptcaps), (gst_proxy_pad_do_fixatecaps),
(gst_proxy_pad_do_setcaps), (gst_proxy_pad_set_target_unlocked),
(gst_proxy_pad_set_target), (gst_proxy_pad_get_internal),
(gst_proxy_pad_dispose), (gst_proxy_pad_init),
(gst_ghost_pad_parent_set), (gst_ghost_pad_parent_unset),
(gst_ghost_pad_class_init),
(gst_ghost_pad_internal_do_activate_push),
(gst_ghost_pad_internal_do_activate_pull),
(gst_ghost_pad_do_activate_push), (gst_ghost_pad_do_activate_pull),
(gst_ghost_pad_do_link), (gst_ghost_pad_do_unlink),
(gst_ghost_pad_dispose), (gst_ghost_pad_new_no_target),
(gst_ghost_pad_new), (gst_ghost_pad_set_target):
GhostPads now create their internal GstProxyPad at creation (and not
when they're linked, as it was being done previously).
The internal and target pads are linked straight away.
The data will also travel through the other pad in order to make
pad blocking and probes non-hackish (the probe/block now really happens
on the GhostPad and not on the target).
* gst/gstpad.c: (gst_pad_set_blocked_async),
(gst_pad_link_prepare), (gst_pad_push_event):
Remove previous ghostpad cruft.
* gst/gstutils.c: (gst_pad_add_data_probe),
(gst_pad_add_event_probe), (gst_pad_add_buffer_probe),
(gst_pad_remove_data_probe), (gst_pad_remove_event_probe),
(gst_pad_remove_buffer_probe):
Remove previous ghost pad cruft.
Added more detailed debug statements.
* tests/check/gst/gstghostpad.c: (GST_START_TEST):
Fix the testsuite for refcounting changes.
The comments about who has references were correct, but the refcount
being checked wasn't the same (!?!).
This commit is contained in:
Edward Hervey 2006-07-11 16:20:09 +00:00
parent c687975a3c
commit 4f9d5adb40
6 changed files with 456 additions and 322 deletions

View file

@ -1,3 +1,49 @@
2006-07-11 Edward Hervey <edward@fluendo.com>
* gst/gstbin.c: (activate_pads),
(iterator_activate_fold_with_resync), (gst_bin_src_pads_activate),
(gst_bin_change_state_func):
(de)activate src pads before calling state_change on the childs.
This is to avoid the case where a src ghostpad is blocked (holding the
stream lock), which would block the deactivation of the ghostpad's
target pad.
* gst/gstghostpad.c: (gst_proxy_pad_do_query_type),
(gst_proxy_pad_do_event), (gst_proxy_pad_do_query),
(gst_proxy_pad_do_internal_link), (gst_proxy_pad_do_bufferalloc),
(gst_proxy_pad_do_chain), (gst_proxy_pad_do_getrange),
(gst_proxy_pad_do_checkgetrange), (gst_proxy_pad_do_getcaps),
(gst_proxy_pad_do_acceptcaps), (gst_proxy_pad_do_fixatecaps),
(gst_proxy_pad_do_setcaps), (gst_proxy_pad_set_target_unlocked),
(gst_proxy_pad_set_target), (gst_proxy_pad_get_internal),
(gst_proxy_pad_dispose), (gst_proxy_pad_init),
(gst_ghost_pad_parent_set), (gst_ghost_pad_parent_unset),
(gst_ghost_pad_class_init),
(gst_ghost_pad_internal_do_activate_push),
(gst_ghost_pad_internal_do_activate_pull),
(gst_ghost_pad_do_activate_push), (gst_ghost_pad_do_activate_pull),
(gst_ghost_pad_do_link), (gst_ghost_pad_do_unlink),
(gst_ghost_pad_dispose), (gst_ghost_pad_new_no_target),
(gst_ghost_pad_new), (gst_ghost_pad_set_target):
GhostPads now create their internal GstProxyPad at creation (and not
when they're linked, as it was being done previously).
The internal and target pads are linked straight away.
The data will also travel through the other pad in order to make
pad blocking and probes non-hackish (the probe/block now really happens
on the GhostPad and not on the target).
* gst/gstpad.c: (gst_pad_set_blocked_async),
(gst_pad_link_prepare), (gst_pad_push_event):
Remove previous ghostpad cruft.
* gst/gstutils.c: (gst_pad_add_data_probe),
(gst_pad_add_event_probe), (gst_pad_add_buffer_probe),
(gst_pad_remove_data_probe), (gst_pad_remove_event_probe),
(gst_pad_remove_buffer_probe):
Remove previous ghost pad cruft.
Added more detailed debug statements.
* tests/check/gst/gstghostpad.c: (GST_START_TEST):
Fix the testsuite for refcounting changes.
The comments about who has references were correct, but the refcount
being checked wasn't the same (!?!).
2006-07-10 Stefan Kost <ensonic@users.sf.net>
* docs/gst/gstreamer-sections.txt:

View file

@ -1762,6 +1762,87 @@ done:
return ret;
}
/* gst_iterator_fold functions for pads_activate
* Note how we don't stop the iterator when we fail an activation. This is
* probably a FIXME since when one pad activation fails, we don't want to
* continue our state change. */
static gboolean
activate_pads (GstPad * pad, GValue * ret, gboolean * active)
{
if (!gst_pad_set_active (pad, *active))
g_value_set_boolean (ret, FALSE);
else if (!*active)
gst_pad_set_caps (pad, NULL);
/* unref the object that was reffed for us by _fold */
gst_object_unref (pad);
return TRUE;
}
/* returns false on error or early cutout (will never happen because the fold
* function always returns TRUE, see FIXME above) of the fold, true if all
* pads in @iter were (de)activated successfully. */
static gboolean
iterator_activate_fold_with_resync (GstIterator * iter, gpointer user_data)
{
GstIteratorResult ires;
GValue ret = { 0 };
/* no need to unset this later, it's just a boolean */
g_value_init (&ret, G_TYPE_BOOLEAN);
g_value_set_boolean (&ret, TRUE);
while (1) {
ires = gst_iterator_fold (iter, (GstIteratorFoldFunction) activate_pads,
&ret, user_data);
switch (ires) {
case GST_ITERATOR_RESYNC:
/* need to reset the result again */
g_value_set_boolean (&ret, TRUE);
gst_iterator_resync (iter);
break;
case GST_ITERATOR_DONE:
/* all pads iterated, return collected value */
goto done;
default:
/* iterator returned _ERROR or premature end with _OK,
* mark an error and exit */
g_value_set_boolean (&ret, FALSE);
goto done;
}
}
done:
/* return collected value */
return g_value_get_boolean (&ret);
}
/* is called with STATE_LOCK
*/
static gboolean
gst_bin_src_pads_activate (GstBin * bin, gboolean active)
{
GstIterator *iter;
gboolean fold_ok;
GST_DEBUG_OBJECT (bin, "src_pads_activate with active %d", active);
iter = gst_element_iterate_src_pads ((GstElement *) bin);
fold_ok = iterator_activate_fold_with_resync (iter, &active);
gst_iterator_free (iter);
if (G_UNLIKELY (!fold_ok))
goto failed;
GST_DEBUG_OBJECT (bin, "pads_activate successful");
return TRUE;
/* ERRORS */
failed:
{
GST_DEBUG_OBJECT (bin, "source pads_activate failed");
return FALSE;
}
}
static GstStateChangeReturn
gst_bin_change_state_func (GstElement * element, GstStateChange transition)
{
@ -1791,6 +1872,9 @@ gst_bin_change_state_func (GstElement * element, GstStateChange transition)
GST_DEBUG_OBJECT (element, "clearing EOS elements");
bin_remove_messages (bin, NULL, GST_MESSAGE_EOS);
GST_OBJECT_UNLOCK (bin);
if (current == GST_STATE_READY)
if (!(gst_bin_src_pads_activate (bin, TRUE)))
goto activate_failure;
break;
case GST_STATE_READY:
/* Clear message list on next READY */
@ -1798,6 +1882,14 @@ gst_bin_change_state_func (GstElement * element, GstStateChange transition)
GST_DEBUG_OBJECT (element, "clearing all cached messages");
bin_remove_messages (bin, NULL, GST_MESSAGE_ANY);
GST_OBJECT_UNLOCK (bin);
if (current == GST_STATE_PAUSED)
if (!(gst_bin_src_pads_activate (bin, FALSE)))
goto activate_failure;
break;
case GST_STATE_NULL:
if (current == GST_STATE_READY)
if (!(gst_bin_src_pads_activate (bin, FALSE)))
goto activate_failure;
break;
default:
break;
@ -1897,6 +1989,11 @@ done:
gst_element_state_get_name (GST_STATE (element)), ret);
return ret;
activate_failure:
GST_CAT_WARNING_OBJECT (GST_CAT_STATES, element,
"failure (de)activating src pads");
return GST_STATE_CHANGE_FAILURE;
}
/*

View file

@ -2,6 +2,7 @@
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
* 2005 Andy Wingo <wingo@pobox.com>
* 2006 Edward Hervey <bilboed@bilboed.com>
*
* gstghostpad.c: Proxy pads
*
@ -51,6 +52,7 @@
#define GST_PROXY_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PROXY_PAD, GstProxyPad))
#define GST_PROXY_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PROXY_PAD, GstProxyPadClass))
#define GST_PROXY_PAD_TARGET(pad) (GST_PROXY_PAD (pad)->target)
#define GST_PROXY_PAD_INTERNAL(pad) (GST_PROXY_PAD (pad)->internal)
typedef struct _GstProxyPad GstProxyPad;
@ -67,9 +69,7 @@ struct _GstProxyPad
/* with PROXY_LOCK */
GMutex *proxy_lock;
GstPad *target;
/*< private > */
gpointer _gst_reserved[1];
GstPad *internal;
};
struct _GstProxyPadClass
@ -84,6 +84,7 @@ struct _GstProxyPadClass
G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD);
static GstPad *gst_proxy_pad_get_target (GstPad * pad);
static GstPad *gst_proxy_pad_get_internal (GstPad * pad);
static void gst_proxy_pad_dispose (GObject * object);
static void gst_proxy_pad_finalize (GObject * object);
@ -116,26 +117,25 @@ const GstQueryType *
gst_proxy_pad_do_query_type (GstPad * pad)
{
GstPad *target = gst_proxy_pad_get_target (pad);
const GstQueryType *res;
g_return_val_if_fail (target != NULL, NULL);
res = gst_pad_get_query_types (target);
gst_object_unref (target);
const GstQueryType *res = NULL;
if (target) {
res = gst_pad_get_query_types (target);
gst_object_unref (target);
}
return res;
}
static gboolean
gst_proxy_pad_do_event (GstPad * pad, GstEvent * event)
{
gboolean res;
GstPad *target = gst_proxy_pad_get_target (pad);
gboolean res = FALSE;
GstPad *internal = gst_proxy_pad_get_internal (pad);
g_return_val_if_fail (target != NULL, FALSE);
g_return_val_if_fail (internal != NULL, FALSE);
res = gst_pad_send_event (target, event);
gst_object_unref (target);
res = gst_pad_push_event (internal, event);
gst_object_unref (internal);
return res;
}
@ -143,13 +143,13 @@ gst_proxy_pad_do_event (GstPad * pad, GstEvent * event)
static gboolean
gst_proxy_pad_do_query (GstPad * pad, GstQuery * query)
{
gboolean res;
gboolean res = FALSE;
GstPad *target = gst_proxy_pad_get_target (pad);
g_return_val_if_fail (target != NULL, FALSE);
res = gst_pad_query (target, query);
gst_object_unref (target);
if (target) {
res = gst_pad_query (target, query);
gst_object_unref (target);
}
return res;
}
@ -158,12 +158,12 @@ static GList *
gst_proxy_pad_do_internal_link (GstPad * pad)
{
GstPad *target = gst_proxy_pad_get_target (pad);
GList *res;
GList *res = NULL;
g_return_val_if_fail (target != NULL, NULL);
res = gst_pad_get_internal_links (target);
gst_object_unref (target);
if (target) {
res = gst_pad_get_internal_links (target);
gst_object_unref (target);
}
return res;
}
@ -173,23 +173,12 @@ gst_proxy_pad_do_bufferalloc (GstPad * pad, guint64 offset, guint size,
GstCaps * caps, GstBuffer ** buf)
{
GstFlowReturn result;
GstPad *target = gst_proxy_pad_get_target (pad);
GstPad *peer;
GstPad *internal = gst_proxy_pad_get_internal (pad);
g_return_val_if_fail (target != NULL, GST_FLOW_NOT_LINKED);
g_return_val_if_fail (internal != NULL, GST_FLOW_NOT_LINKED);
peer = gst_pad_get_peer (target);
if (peer) {
GST_DEBUG ("buffer alloc on %s:%s", GST_DEBUG_PAD_NAME (target));
result = gst_pad_alloc_buffer (peer, offset, size, caps, buf);
gst_object_unref (peer);
} else {
result = GST_FLOW_NOT_LINKED;
}
gst_object_unref (target);
result = gst_pad_alloc_buffer (internal, offset, size, caps, buf);
gst_object_unref (internal);
return result;
}
@ -197,13 +186,13 @@ gst_proxy_pad_do_bufferalloc (GstPad * pad, guint64 offset, guint size,
static GstFlowReturn
gst_proxy_pad_do_chain (GstPad * pad, GstBuffer * buffer)
{
GstPad *target = gst_proxy_pad_get_target (pad);
GstPad *internal = gst_proxy_pad_get_internal (pad);
GstFlowReturn res;
g_return_val_if_fail (target != NULL, GST_FLOW_NOT_LINKED);
g_return_val_if_fail (internal != NULL, GST_FLOW_NOT_LINKED);
res = gst_pad_chain (target, buffer);
gst_object_unref (target);
res = gst_pad_push (internal, buffer);
gst_object_unref (internal);
return res;
}
@ -212,13 +201,13 @@ static GstFlowReturn
gst_proxy_pad_do_getrange (GstPad * pad, guint64 offset, guint size,
GstBuffer ** buffer)
{
GstPad *target = gst_proxy_pad_get_target (pad);
GstPad *internal = gst_proxy_pad_get_internal (pad);
GstFlowReturn res;
g_return_val_if_fail (target != NULL, GST_FLOW_NOT_LINKED);
g_return_val_if_fail (internal != NULL, GST_FLOW_NOT_LINKED);
res = gst_pad_get_range (target, offset, size, buffer);
gst_object_unref (target);
res = gst_pad_pull_range (internal, offset, size, buffer);
gst_object_unref (internal);
return res;
}
@ -227,19 +216,12 @@ static gboolean
gst_proxy_pad_do_checkgetrange (GstPad * pad)
{
gboolean result;
GstPad *target = gst_proxy_pad_get_target (pad);
GstPad *peer;
GstPad *internal = gst_proxy_pad_get_internal (pad);
g_return_val_if_fail (target != NULL, FALSE);
g_return_val_if_fail (internal != NULL, FALSE);
peer = gst_pad_get_peer (target);
if (peer) {
result = gst_pad_check_pull_range (peer);
gst_object_unref (peer);
} else {
result = FALSE;
}
gst_object_unref (target);
result = gst_pad_check_pull_range (internal);
gst_object_unref (internal);
return result;
}
@ -250,11 +232,12 @@ gst_proxy_pad_do_getcaps (GstPad * pad)
GstPad *target = gst_proxy_pad_get_target (pad);
GstCaps *res;
g_return_val_if_fail (target != NULL, NULL);
res = gst_pad_get_caps (target);
gst_object_unref (target);
if (target) {
res = gst_pad_get_caps (target);
gst_object_unref (target);
} else {
res = gst_caps_new_any ();
}
return res;
}
@ -262,12 +245,12 @@ static gboolean
gst_proxy_pad_do_acceptcaps (GstPad * pad, GstCaps * caps)
{
GstPad *target = gst_proxy_pad_get_target (pad);
gboolean res;
gboolean res = FALSE;
g_return_val_if_fail (target != NULL, FALSE);
res = gst_pad_accept_caps (target, caps);
gst_object_unref (target);
if (target) {
res = gst_pad_accept_caps (target, caps);
gst_object_unref (target);
}
return res;
}
@ -277,10 +260,10 @@ gst_proxy_pad_do_fixatecaps (GstPad * pad, GstCaps * caps)
{
GstPad *target = gst_proxy_pad_get_target (pad);
g_return_if_fail (target != NULL);
gst_pad_fixate_caps (target, caps);
gst_object_unref (target);
if (target) {
gst_pad_fixate_caps (target, caps);
gst_object_unref (target);
}
}
static gboolean
@ -289,11 +272,17 @@ gst_proxy_pad_do_setcaps (GstPad * pad, GstCaps * caps)
GstPad *target = gst_proxy_pad_get_target (pad);
gboolean res;
g_return_val_if_fail (target != NULL, FALSE);
res = gst_pad_set_caps (target, caps);
gst_object_unref (target);
if (target) {
res = gst_pad_set_caps (target, caps);
gst_object_unref (target);
} else {
/*
We don't have any target, but we shouldn't return FALSE since this
would stop the actual push of a buffer (which might trigger a pad block
or probe, or properly return GST_FLOW_NOT_LINKED.
*/
res = TRUE;
}
return res;
}
@ -301,48 +290,38 @@ static gboolean
gst_proxy_pad_set_target_unlocked (GstPad * pad, GstPad * target)
{
GstPad *oldtarget;
GstPadTemplate **template_p;
GST_DEBUG ("set target %s:%s on %s:%s",
GST_DEBUG_PAD_NAME (target), GST_DEBUG_PAD_NAME (pad));
if (target) {
GST_LOG_OBJECT (pad, "setting target %s:%s", GST_DEBUG_PAD_NAME (target));
if (G_UNLIKELY (GST_PAD_DIRECTION (pad) != GST_PAD_DIRECTION (target))) {
GST_ERROR_OBJECT (pad,
"target pad doesn't have the same direction as ourself");
return FALSE;
}
} else
GST_LOG_OBJECT (pad, "clearing target");
/* clear old target */
if ((oldtarget = GST_PROXY_PAD_TARGET (pad))) {
gst_object_unref (oldtarget);
/* Clear previous pad template */
template_p = &GST_PAD_PAD_TEMPLATE (pad);
gst_object_replace ((GstObject **) template_p, NULL);
/* Get rid of target */
GST_PROXY_PAD_TARGET (pad) = NULL;
gst_object_unref (oldtarget);
}
if (target) {
/* set and ref new target if any */
GST_PROXY_PAD_TARGET (pad) = gst_object_ref (target);
gst_pad_set_query_type_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query_type));
gst_pad_set_event_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_event));
gst_pad_set_query_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query));
gst_pad_set_internal_link_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_internal_link));
gst_pad_set_getcaps_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getcaps));
gst_pad_set_acceptcaps_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_acceptcaps));
gst_pad_set_fixatecaps_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_fixatecaps));
gst_pad_set_setcaps_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_setcaps));
if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
gst_pad_set_bufferalloc_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc));
gst_pad_set_chain_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain));
} else {
gst_pad_set_getrange_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange));
gst_pad_set_checkgetrange_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange));
}
/* Set new pad template */
template_p = &GST_PAD_PAD_TEMPLATE (pad);
gst_object_replace ((GstObject **) template_p,
(GstObject *) GST_PAD_PAD_TEMPLATE (target));
}
return TRUE;
}
@ -373,10 +352,18 @@ gst_proxy_pad_get_target (GstPad * pad)
return target;
}
static void
gst_proxy_pad_init (GstProxyPad * pad)
static GstPad *
gst_proxy_pad_get_internal (GstPad * pad)
{
pad->proxy_lock = g_mutex_new ();
GstPad *internal;
GST_PROXY_LOCK (pad);
internal = GST_PROXY_PAD_INTERNAL (pad);
if (internal)
gst_object_ref (internal);
GST_PROXY_UNLOCK (pad);
return internal;
}
static void
@ -386,8 +373,13 @@ gst_proxy_pad_dispose (GObject * object)
GstPad **target_p;
GST_PROXY_LOCK (pad);
/* remove and unref the target */
target_p = &GST_PROXY_PAD_TARGET (pad);
gst_object_replace ((GstObject **) target_p, NULL);
/*
The internal is only cleared by GstGhostPad::dispose, since it is the
parent of non-ghost GstProxyPad and owns the refcount on the internal.
*/
GST_PROXY_UNLOCK (pad);
G_OBJECT_CLASS (gst_proxy_pad_parent_class)->dispose (object);
@ -404,6 +396,30 @@ gst_proxy_pad_finalize (GObject * object)
G_OBJECT_CLASS (gst_proxy_pad_parent_class)->finalize (object);
}
static void
gst_proxy_pad_init (GstProxyPad * ppad)
{
GstPad *pad = (GstPad *) ppad;
ppad->proxy_lock = g_mutex_new ();
gst_pad_set_query_type_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query_type));
gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_event));
gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query));
gst_pad_set_internal_link_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_internal_link));
gst_pad_set_getcaps_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getcaps));
gst_pad_set_acceptcaps_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_acceptcaps));
gst_pad_set_fixatecaps_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_fixatecaps));
gst_pad_set_setcaps_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_setcaps));
}
#ifndef GST_DISABLE_LOADSAVE
/**
* gst_proxy_pad_save_thyself:
@ -444,7 +460,6 @@ struct _GstGhostPad
GstProxyPad pad;
/* with PROXY_LOCK */
GstPad *internal;
gulong notify_id;
/*< private > */
@ -462,9 +477,6 @@ struct _GstGhostPadClass
G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD);
static gboolean gst_ghost_pad_set_internal (GstGhostPad * pad,
GstPad * internal);
static void gst_ghost_pad_dispose (GObject * object);
/* Work around g_logv's use of G_GNUC_PRINTF because gcc chokes on %P, which we
@ -479,26 +491,65 @@ gst_critical (const gchar * format, ...)
va_end (args);
}
static GstPad *
gst_ghost_pad_get_internal (GstPad * pad)
/*
* The parent_set and parent_unset are used to make sure that:
* _ the internal and target are only linked when the GhostPad has a parent,
* _ the internal and target are unlinked as soon as the GhostPad is removed
* from it's parent.
*/
static void
gst_ghost_pad_parent_set (GstObject * object, GstObject * parent)
{
GstPad *internal;
GstPad *gpad = GST_PAD (object);
GstPad *target = gst_proxy_pad_get_target (gpad);
GstPad *internal = gst_proxy_pad_get_internal (gpad);
GST_PROXY_LOCK (pad);
internal = GST_GHOST_PAD (pad)->internal;
if (internal)
gst_object_ref (internal);
GST_PROXY_UNLOCK (pad);
if (target) {
if (GST_PAD_IS_SRC (internal))
gst_pad_link (internal, target);
else
gst_pad_link (target, internal);
gst_object_unref (target);
}
gst_object_unref (internal);
return internal;
if (GST_OBJECT_CLASS (gst_ghost_pad_parent_class)->parent_set)
GST_OBJECT_CLASS (gst_ghost_pad_parent_class)->parent_set (object, parent);
}
static void
gst_ghost_pad_parent_unset (GstObject * object, GstObject * parent)
{
GstPad *gpad = GST_PAD (object);
GstPad *target = gst_proxy_pad_get_target (gpad);
GstPad *internal = gst_proxy_pad_get_internal (gpad);
if (target) {
if (GST_PAD_IS_SRC (internal))
gst_pad_unlink (internal, target);
else
gst_pad_unlink (target, internal);
gst_object_unref (target);
}
gst_object_unref (internal);
if (GST_OBJECT_CLASS (gst_ghost_pad_parent_class)->parent_unset)
GST_OBJECT_CLASS (gst_ghost_pad_parent_class)->parent_unset (object,
parent);
}
static void
gst_ghost_pad_class_init (GstGhostPadClass * klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
GstObjectClass *gstobject_class = (GstObjectClass *) klass;
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ghost_pad_dispose);
gstobject_class->parent_set = GST_DEBUG_FUNCPTR (gst_ghost_pad_parent_set);
gstobject_class->parent_unset =
GST_DEBUG_FUNCPTR (gst_ghost_pad_parent_unset);
}
/* see gstghostpad design docs */
@ -508,7 +559,7 @@ gst_ghost_pad_internal_do_activate_push (GstPad * pad, gboolean active)
gboolean ret;
if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
GstPad *parent = GST_PAD (gst_object_get_parent (GST_OBJECT (pad)));
GstPad *parent = gst_proxy_pad_get_internal (pad);
if (parent) {
g_return_val_if_fail (GST_IS_GHOST_PAD (parent), FALSE);
@ -548,7 +599,7 @@ gst_ghost_pad_internal_do_activate_pull (GstPad * pad, gboolean active)
ret = FALSE;
}
} else {
GstPad *parent = GST_PAD (gst_object_get_parent (GST_OBJECT (pad)));
GstPad *parent = gst_proxy_pad_get_internal (pad);
if (parent) {
g_return_val_if_fail (GST_IS_GHOST_PAD (parent), FALSE);
@ -570,7 +621,7 @@ gst_ghost_pad_do_activate_push (GstPad * pad, gboolean active)
gboolean ret;
if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
GstPad *internal = gst_ghost_pad_get_internal (pad);
GstPad *internal = gst_proxy_pad_get_internal (pad);
if (internal) {
ret = gst_pad_activate_push (internal, active);
@ -600,7 +651,7 @@ gst_ghost_pad_do_activate_pull (GstPad * pad, gboolean active)
ret = FALSE;
}
} else {
GstPad *internal = gst_ghost_pad_get_internal (pad);
GstPad *internal = gst_proxy_pad_get_internal (pad);
if (internal) {
ret = gst_pad_activate_pull (internal, active);
@ -617,25 +668,13 @@ static GstPadLinkReturn
gst_ghost_pad_do_link (GstPad * pad, GstPad * peer)
{
GstPad *internal, *target;
GstPadLinkReturn ret;
GstPadLinkReturn ret = GST_PAD_LINK_OK;
target = gst_proxy_pad_get_target (pad);
g_return_val_if_fail (target != NULL, GST_PAD_LINK_NOSCHED);
/* proxy the peer into the bin */
internal = g_object_new (GST_TYPE_PROXY_PAD,
"name", NULL,
"direction", GST_PAD_DIRECTION (peer),
"template", GST_PAD_PAD_TEMPLATE (peer), NULL);
internal = gst_proxy_pad_get_internal (pad);
gst_proxy_pad_set_target (internal, peer);
gst_ghost_pad_set_internal (GST_GHOST_PAD (pad), internal);
if (GST_PAD_IS_SRC (internal))
ret = gst_pad_link (internal, target);
else
ret = gst_pad_link (target, internal);
/* if we are a source pad, we should call the peer link function
* if the peer has one */
@ -645,11 +684,7 @@ gst_ghost_pad_do_link (GstPad * pad, GstPad * peer)
}
gst_object_unref (target);
if (ret == GST_PAD_LINK_OK)
gst_pad_set_active (internal, GST_PAD_ACTIVATE_MODE (pad));
else
gst_ghost_pad_set_internal (GST_GHOST_PAD (pad), NULL);
gst_object_unref (internal);
return ret;
}
@ -658,17 +693,20 @@ static void
gst_ghost_pad_do_unlink (GstPad * pad)
{
GstPad *target = gst_proxy_pad_get_target (pad);
GstPad *internal = gst_proxy_pad_get_internal (pad);
g_return_if_fail (target != NULL);
GST_DEBUG_OBJECT (pad, "unlinking ghostpad");
/* The target of the internal pad is no longer valid */
gst_proxy_pad_set_target (internal, NULL);
if (target->unlinkfunc)
target->unlinkfunc (target);
gst_ghost_pad_set_internal (GST_GHOST_PAD (pad), NULL);
gst_object_unref (target);
gst_object_unref (internal);
}
static void
@ -687,63 +725,6 @@ on_int_notify (GstPad * internal, GParamSpec * unused, GstGhostPad * pad)
gst_caps_unref (caps);
}
static gboolean
gst_ghost_pad_set_internal (GstGhostPad * pad, GstPad * internal)
{
GST_PROXY_LOCK (pad);
/* first remove old internal pad */
if (pad->internal) {
GstPad *intpeer;
gst_pad_set_activatepull_function (pad->internal, NULL);
gst_pad_set_activatepush_function (pad->internal, NULL);
g_signal_handler_disconnect (pad->internal, pad->notify_id);
intpeer = gst_pad_get_peer (pad->internal);
if (intpeer) {
if (GST_PAD_IS_SRC (pad->internal))
gst_pad_unlink (pad->internal, intpeer);
else
gst_pad_unlink (intpeer, pad->internal);
gst_object_unref (intpeer);
}
/* should dispose it */
gst_object_unparent (GST_OBJECT_CAST (pad->internal));
}
/* then set new internal pad */
if (internal) {
if (!gst_object_set_parent (GST_OBJECT_CAST (internal),
GST_OBJECT_CAST (pad)))
goto could_not_set;
/* could be more general here, iterating over all writable properties...
* taking the short road for now tho */
pad->notify_id = g_signal_connect (internal, "notify::caps",
G_CALLBACK (on_int_notify), pad);
on_int_notify (internal, NULL, pad);
gst_pad_set_activatepull_function (GST_PAD (internal),
GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_pull));
gst_pad_set_activatepush_function (GST_PAD (internal),
GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_push));
/* a ref was taken by set_parent */
}
pad->internal = internal;
GST_PROXY_UNLOCK (pad);
return TRUE;
/* ERRORS */
could_not_set:
{
gst_critical ("Could not set internal pad %" GST_PTR_FORMAT, internal);
GST_PROXY_UNLOCK (pad);
return FALSE;
}
}
static void
gst_ghost_pad_init (GstGhostPad * pad)
{
@ -756,7 +737,35 @@ gst_ghost_pad_init (GstGhostPad * pad)
static void
gst_ghost_pad_dispose (GObject * object)
{
gst_ghost_pad_set_internal (GST_GHOST_PAD (object), NULL);
GstPad *pad = GST_PAD (object);
GstPad *internal;
GstPad *intpeer;
GST_PROXY_LOCK (pad);
internal = GST_PROXY_PAD_INTERNAL (pad);
gst_pad_set_activatepull_function (internal, NULL);
gst_pad_set_activatepush_function (internal, NULL);
g_signal_handler_disconnect (internal, GST_GHOST_PAD (pad)->notify_id);
intpeer = gst_pad_get_peer (internal);
if (intpeer) {
if (GST_PAD_IS_SRC (internal))
gst_pad_unlink (internal, intpeer);
else
gst_pad_unlink (intpeer, internal);
gst_object_unref (intpeer);
}
GST_PROXY_PAD_INTERNAL (internal) = NULL;
/*
disposes of the internal pad, since the ghostpad is the only possible object
that has a refcount on the internal pad.
*/
gst_object_unparent (GST_OBJECT_CAST (internal));
GST_PROXY_UNLOCK (pad);
G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object);
}
@ -778,15 +787,84 @@ GstPad *
gst_ghost_pad_new_no_target (const gchar * name, GstPadDirection dir)
{
GstPad *ret;
GstPad *internal;
GST_LOG ("name:%s, direction:%d", name, dir);
/* OBJECT CREATION */
ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name, "direction", dir, NULL);
gst_pad_set_activatepush_function (ret,
GST_DEBUG_FUNCPTR (gst_ghost_pad_do_activate_push));
/* Set directional padfunctions for ghostpad */
if (dir == GST_PAD_SINK) {
gst_pad_set_bufferalloc_function (ret,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc));
gst_pad_set_chain_function (ret,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain));
} else {
gst_pad_set_getrange_function (ret,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange));
gst_pad_set_checkgetrange_function (ret,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange));
}
gst_pad_set_link_function (ret, GST_DEBUG_FUNCPTR (gst_ghost_pad_do_link));
gst_pad_set_unlink_function (ret,
GST_DEBUG_FUNCPTR (gst_ghost_pad_do_unlink));
/* INTERNAL PAD */
internal =
g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
"direction", (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC, NULL);
/* Set directional padfunctions for internal pad */
if (dir == GST_PAD_SRC) {
gst_pad_set_bufferalloc_function (internal,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc));
gst_pad_set_chain_function (internal,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain));
} else {
gst_pad_set_getrange_function (internal,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange));
gst_pad_set_checkgetrange_function (internal,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange));
}
GST_PROXY_LOCK (ret);
if (!gst_object_set_parent (GST_OBJECT_CAST (internal),
GST_OBJECT_CAST (ret))) {
gst_critical ("Could not set internal pad%" GST_PTR_FORMAT, internal);
goto beach;
}
/*
The ghostpad is the parent of the internal pad and is the only object that
can have a refcount on the internal pad.
At this point, the GstGhostPad has a refcount of 1, and the internal pad has
a refcount of 1.
When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose
it's refcount on the internal pad in the dispose method by un-parenting it.
This is why we don't take extra refcounts in the assignments below
*/
GST_PROXY_PAD_INTERNAL (ret) = internal;
GST_PROXY_PAD_INTERNAL (GST_PROXY_PAD_INTERNAL (ret)) = GST_PAD (ret);
/* could be more general here, iterating over all writable properties...
* taking the short road for now tho */
GST_GHOST_PAD (ret)->notify_id = g_signal_connect (internal, "notify::caps",
G_CALLBACK (on_int_notify), ret);
on_int_notify (internal, NULL, GST_GHOST_PAD (ret));
gst_pad_set_activatepull_function (GST_PAD (internal),
GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_pull));
gst_pad_set_activatepush_function (GST_PAD (internal),
GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_push));
beach:
GST_PROXY_UNLOCK (ret);
return ret;
}
@ -807,12 +885,12 @@ gst_ghost_pad_new (const gchar * name, GstPad * target)
{
GstPad *ret;
GST_LOG ("name:%s, target:%s:%s", name, GST_DEBUG_PAD_NAME (target));
g_return_val_if_fail (GST_IS_PAD (target), NULL);
g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
if ((ret = gst_ghost_pad_new_no_target (name, GST_PAD_DIRECTION (target)))) {
g_object_set (G_OBJECT (ret),
"template", GST_PAD_PAD_TEMPLATE (target), NULL);
gst_ghost_pad_set_target (GST_GHOST_PAD (ret), target);
}
return ret;
@ -850,15 +928,15 @@ gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
{
GstPad *internal;
GstPad *oldtarget;
GstObject *parent;
gboolean result;
g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
GST_PROXY_LOCK (gpad);
internal = gpad->internal;
internal = GST_PROXY_PAD_INTERNAL (GST_PAD (gpad));
GST_DEBUG ("set target %s:%s on %s:%s",
GST_DEBUG_PAD_NAME (newtarget), GST_DEBUG_PAD_NAME (gpad));
GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget));
/* clear old target */
if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) {
@ -874,12 +952,17 @@ gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget);
if (result && newtarget) {
/* and link to internal pad if we have one */
if (internal) {
/* and link to internal pad if we are not unparent-ed */
if ((parent = gst_object_get_parent (GST_OBJECT (gpad)))) {
if (GST_PAD_IS_SRC (internal))
result = gst_pad_link (internal, newtarget);
else
result = gst_pad_link (newtarget, internal);
gst_object_unref (parent);
} else {
/* we need to connect the internal pad once we have a parent */
GST_DEBUG_OBJECT (gpad,
"GhostPad doesn't have a parent, will connect internal pad later");
}
}
GST_PROXY_UNLOCK (gpad);

View file

@ -63,7 +63,6 @@
#include "gst_private.h"
#include "gstpad.h"
#include "gstghostpad.h"
#include "gstpadtemplate.h"
#include "gstenumtypes.h"
#include "gstmarshal.h"
@ -939,18 +938,10 @@ gboolean
gst_pad_set_blocked_async (GstPad * pad, gboolean blocked,
GstPadBlockCallback callback, gpointer user_data)
{
gboolean was_blocked, was_ghost = FALSE;
gboolean was_blocked = FALSE;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
if (GST_IS_GHOST_PAD (pad)) {
pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
if (!pad) {
return FALSE;
}
was_ghost = TRUE;
}
GST_OBJECT_LOCK (pad);
was_blocked = GST_PAD_IS_BLOCKED (pad);
@ -990,10 +981,6 @@ gst_pad_set_blocked_async (GstPad * pad, gboolean blocked,
}
GST_OBJECT_UNLOCK (pad);
if (was_ghost) {
gst_object_unref (pad);
}
return TRUE;
had_right_state:
@ -1003,9 +990,6 @@ had_right_state:
was_blocked);
GST_OBJECT_UNLOCK (pad);
if (was_ghost) {
gst_object_unref (pad);
}
return FALSE;
}
}
@ -1727,8 +1711,9 @@ not_srcpad:
}
src_was_linked:
{
GST_CAT_INFO (GST_CAT_PADS, "src %s:%s was already linked",
GST_DEBUG_PAD_NAME (srcpad));
GST_CAT_INFO (GST_CAT_PADS, "src %s:%s was already linked to %s:%s",
GST_DEBUG_PAD_NAME (srcpad),
GST_DEBUG_PAD_NAME (GST_PAD_PEER (srcpad)));
/* we do not emit a warning in this case because unlinking cannot
* be made MT safe.*/
GST_OBJECT_UNLOCK (srcpad);
@ -1743,8 +1728,9 @@ not_sinkpad:
}
sink_was_linked:
{
GST_CAT_INFO (GST_CAT_PADS, "sink %s:%s was already linked",
GST_DEBUG_PAD_NAME (sinkpad));
GST_CAT_INFO (GST_CAT_PADS, "sink %s:%s was already linked to %s:%s",
GST_DEBUG_PAD_NAME (sinkpad),
GST_DEBUG_PAD_NAME (GST_PAD_PEER (sinkpad)));
/* we do not emit a warning in this case because unlinking cannot
* be made MT safe.*/
GST_OBJECT_UNLOCK (sinkpad);
@ -3870,6 +3856,7 @@ dropping:
}
not_linked:
{
GST_DEBUG_OBJECT (pad, "Dropping event because pad is not linked");
gst_event_unref (event);
GST_OBJECT_UNLOCK (pad);
return FALSE;

View file

@ -2783,19 +2783,10 @@ gulong
gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data)
{
gulong sigid;
gboolean was_ghost = FALSE;
g_return_val_if_fail (GST_IS_PAD (pad), 0);
g_return_val_if_fail (handler != NULL, 0);
if (GST_IS_GHOST_PAD (pad)) {
pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
if (!pad) {
return 0;
}
was_ghost = TRUE;
}
GST_OBJECT_LOCK (pad);
sigid = g_signal_connect (pad, "have-data", handler, data);
GST_PAD_DO_EVENT_SIGNALS (pad)++;
@ -2805,10 +2796,6 @@ gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data)
GST_PAD_DO_BUFFER_SIGNALS (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
GST_OBJECT_UNLOCK (pad);
if (was_ghost) {
gst_object_unref (pad);
}
return sigid;
}
@ -2827,19 +2814,10 @@ gulong
gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data)
{
gulong sigid;
gboolean was_ghost = FALSE;
g_return_val_if_fail (GST_IS_PAD (pad), 0);
g_return_val_if_fail (handler != NULL, 0);
if (GST_IS_GHOST_PAD (pad)) {
pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
if (!pad) {
return 0;
}
was_ghost = TRUE;
}
GST_OBJECT_LOCK (pad);
sigid = g_signal_connect (pad, "have-data::event", handler, data);
GST_PAD_DO_EVENT_SIGNALS (pad)++;
@ -2847,10 +2825,6 @@ gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data)
GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
GST_OBJECT_UNLOCK (pad);
if (was_ghost) {
gst_object_unref (pad);
}
return sigid;
}
@ -2869,19 +2843,10 @@ gulong
gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data)
{
gulong sigid;
gboolean was_ghost = FALSE;
g_return_val_if_fail (GST_IS_PAD (pad), 0);
g_return_val_if_fail (handler != NULL, 0);
if (GST_IS_GHOST_PAD (pad)) {
pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
if (!pad) {
return 0;
}
was_ghost = TRUE;
}
GST_OBJECT_LOCK (pad);
sigid = g_signal_connect (pad, "have-data::buffer", handler, data);
GST_PAD_DO_BUFFER_SIGNALS (pad)++;
@ -2889,10 +2854,6 @@ gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data)
GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
GST_OBJECT_UNLOCK (pad);
if (was_ghost) {
gst_object_unref (pad);
}
return sigid;
}
@ -2906,19 +2867,9 @@ gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data)
void
gst_pad_remove_data_probe (GstPad * pad, guint handler_id)
{
gboolean was_ghost = FALSE;
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (handler_id > 0);
if (GST_IS_GHOST_PAD (pad)) {
pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
if (!pad) {
return;
}
was_ghost = TRUE;
}
GST_OBJECT_LOCK (pad);
g_signal_handler_disconnect (pad, handler_id);
GST_PAD_DO_BUFFER_SIGNALS (pad)--;
@ -2929,9 +2880,6 @@ gst_pad_remove_data_probe (GstPad * pad, guint handler_id)
GST_PAD_DO_BUFFER_SIGNALS (pad));
GST_OBJECT_UNLOCK (pad);
if (was_ghost) {
gst_object_unref (pad);
}
}
/**
@ -2944,29 +2892,15 @@ gst_pad_remove_data_probe (GstPad * pad, guint handler_id)
void
gst_pad_remove_event_probe (GstPad * pad, guint handler_id)
{
gboolean was_ghost = FALSE;
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (handler_id > 0);
if (GST_IS_GHOST_PAD (pad)) {
pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
if (!pad) {
return;
}
was_ghost = TRUE;
}
GST_OBJECT_LOCK (pad);
g_signal_handler_disconnect (pad, handler_id);
GST_PAD_DO_EVENT_SIGNALS (pad)--;
GST_DEBUG ("removed event probe from pad %s:%s, now %d event probes",
GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
GST_OBJECT_UNLOCK (pad);
if (was_ghost) {
gst_object_unref (pad);
}
}
/**
@ -2979,19 +2913,9 @@ gst_pad_remove_event_probe (GstPad * pad, guint handler_id)
void
gst_pad_remove_buffer_probe (GstPad * pad, guint handler_id)
{
gboolean was_ghost = FALSE;
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (handler_id > 0);
if (GST_IS_GHOST_PAD (pad)) {
pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
if (!pad) {
return;
}
was_ghost = TRUE;
}
GST_OBJECT_LOCK (pad);
g_signal_handler_disconnect (pad, handler_id);
GST_PAD_DO_BUFFER_SIGNALS (pad)--;
@ -2999,9 +2923,6 @@ gst_pad_remove_buffer_probe (GstPad * pad, guint handler_id)
GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
GST_OBJECT_UNLOCK (pad);
if (was_ghost) {
gst_object_unref (pad);
}
}
/**

View file

@ -306,27 +306,27 @@ GST_START_TEST (test_ghost_pads)
while (GST_OBJECT_REFCOUNT_VALUE (fsrc) > 2)
THREAD_SWITCH ();
ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 2); /* gisrc */
ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 1);
ASSERT_OBJECT_REFCOUNT (gsink, "gsink", 1);
ASSERT_OBJECT_REFCOUNT (gsrc, "gsink", 1);
ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 2); /* gisink */
ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 1);
ASSERT_OBJECT_REFCOUNT (gisrc, "gisrc", 1); /* gsink */
ASSERT_OBJECT_REFCOUNT (gisrc, "gisrc", 2); /* gsink */
ASSERT_OBJECT_REFCOUNT (isink, "isink", 2); /* gsink */
ASSERT_OBJECT_REFCOUNT (gisink, "gisink", 1); /* gsrc */
ASSERT_OBJECT_REFCOUNT (gisink, "gisink", 2); /* gsrc */
ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 2); /* gsrc */
gst_object_unref (gsink);
ASSERT_OBJECT_REFCOUNT (isink, "isink", 1);
ASSERT_OBJECT_REFCOUNT (gisrc, "gisrc", 1);
ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 2); /* gisrc */
ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 1);
gst_object_unref (gisrc);
ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 1);
gst_object_unref (gsrc);
ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 1);
ASSERT_OBJECT_REFCOUNT (gisink, "gisink", 1);
ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 2); /* gisrc */
ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 1);
gst_object_unref (gisink);
ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 1);