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> 2006-07-10 Stefan Kost <ensonic@users.sf.net>
* docs/gst/gstreamer-sections.txt: * docs/gst/gstreamer-sections.txt:

View file

@ -1762,6 +1762,87 @@ done:
return ret; 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 static GstStateChangeReturn
gst_bin_change_state_func (GstElement * element, GstStateChange transition) 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"); GST_DEBUG_OBJECT (element, "clearing EOS elements");
bin_remove_messages (bin, NULL, GST_MESSAGE_EOS); bin_remove_messages (bin, NULL, GST_MESSAGE_EOS);
GST_OBJECT_UNLOCK (bin); GST_OBJECT_UNLOCK (bin);
if (current == GST_STATE_READY)
if (!(gst_bin_src_pads_activate (bin, TRUE)))
goto activate_failure;
break; break;
case GST_STATE_READY: case GST_STATE_READY:
/* Clear message list on next 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"); GST_DEBUG_OBJECT (element, "clearing all cached messages");
bin_remove_messages (bin, NULL, GST_MESSAGE_ANY); bin_remove_messages (bin, NULL, GST_MESSAGE_ANY);
GST_OBJECT_UNLOCK (bin); 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; break;
default: default:
break; break;
@ -1897,6 +1989,11 @@ done:
gst_element_state_get_name (GST_STATE (element)), ret); gst_element_state_get_name (GST_STATE (element)), ret);
return 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> * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be> * 2000 Wim Taymans <wtay@chello.be>
* 2005 Andy Wingo <wingo@pobox.com> * 2005 Andy Wingo <wingo@pobox.com>
* 2006 Edward Hervey <bilboed@bilboed.com>
* *
* gstghostpad.c: Proxy pads * 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(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_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_TARGET(pad) (GST_PROXY_PAD (pad)->target)
#define GST_PROXY_PAD_INTERNAL(pad) (GST_PROXY_PAD (pad)->internal)
typedef struct _GstProxyPad GstProxyPad; typedef struct _GstProxyPad GstProxyPad;
@ -67,9 +69,7 @@ struct _GstProxyPad
/* with PROXY_LOCK */ /* with PROXY_LOCK */
GMutex *proxy_lock; GMutex *proxy_lock;
GstPad *target; GstPad *target;
GstPad *internal;
/*< private > */
gpointer _gst_reserved[1];
}; };
struct _GstProxyPadClass struct _GstProxyPadClass
@ -84,6 +84,7 @@ struct _GstProxyPadClass
G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD); 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_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_dispose (GObject * object);
static void gst_proxy_pad_finalize (GObject * object); static void gst_proxy_pad_finalize (GObject * object);
@ -116,26 +117,25 @@ const GstQueryType *
gst_proxy_pad_do_query_type (GstPad * pad) gst_proxy_pad_do_query_type (GstPad * pad)
{ {
GstPad *target = gst_proxy_pad_get_target (pad); GstPad *target = gst_proxy_pad_get_target (pad);
const GstQueryType *res; const GstQueryType *res = NULL;
g_return_val_if_fail (target != NULL, NULL);
res = gst_pad_get_query_types (target);
gst_object_unref (target);
if (target) {
res = gst_pad_get_query_types (target);
gst_object_unref (target);
}
return res; return res;
} }
static gboolean static gboolean
gst_proxy_pad_do_event (GstPad * pad, GstEvent * event) gst_proxy_pad_do_event (GstPad * pad, GstEvent * event)
{ {
gboolean res; gboolean res = FALSE;
GstPad *target = gst_proxy_pad_get_target (pad); 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); res = gst_pad_push_event (internal, event);
gst_object_unref (target); gst_object_unref (internal);
return res; return res;
} }
@ -143,13 +143,13 @@ gst_proxy_pad_do_event (GstPad * pad, GstEvent * event)
static gboolean static gboolean
gst_proxy_pad_do_query (GstPad * pad, GstQuery * query) gst_proxy_pad_do_query (GstPad * pad, GstQuery * query)
{ {
gboolean res; gboolean res = FALSE;
GstPad *target = gst_proxy_pad_get_target (pad); GstPad *target = gst_proxy_pad_get_target (pad);
g_return_val_if_fail (target != NULL, FALSE); if (target) {
res = gst_pad_query (target, query);
res = gst_pad_query (target, query); gst_object_unref (target);
gst_object_unref (target); }
return res; return res;
} }
@ -158,12 +158,12 @@ static GList *
gst_proxy_pad_do_internal_link (GstPad * pad) gst_proxy_pad_do_internal_link (GstPad * pad)
{ {
GstPad *target = gst_proxy_pad_get_target (pad); GstPad *target = gst_proxy_pad_get_target (pad);
GList *res; GList *res = NULL;
g_return_val_if_fail (target != NULL, NULL); if (target) {
res = gst_pad_get_internal_links (target);
res = gst_pad_get_internal_links (target); gst_object_unref (target);
gst_object_unref (target); }
return res; return res;
} }
@ -173,23 +173,12 @@ gst_proxy_pad_do_bufferalloc (GstPad * pad, guint64 offset, guint size,
GstCaps * caps, GstBuffer ** buf) GstCaps * caps, GstBuffer ** buf)
{ {
GstFlowReturn result; GstFlowReturn result;
GstPad *target = gst_proxy_pad_get_target (pad); GstPad *internal = gst_proxy_pad_get_internal (pad);
GstPad *peer;
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); result = gst_pad_alloc_buffer (internal, offset, size, caps, buf);
if (peer) { gst_object_unref (internal);
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);
return result; return result;
} }
@ -197,13 +186,13 @@ gst_proxy_pad_do_bufferalloc (GstPad * pad, guint64 offset, guint size,
static GstFlowReturn static GstFlowReturn
gst_proxy_pad_do_chain (GstPad * pad, GstBuffer * buffer) 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; 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); res = gst_pad_push (internal, buffer);
gst_object_unref (target); gst_object_unref (internal);
return res; return res;
} }
@ -212,13 +201,13 @@ static GstFlowReturn
gst_proxy_pad_do_getrange (GstPad * pad, guint64 offset, guint size, gst_proxy_pad_do_getrange (GstPad * pad, guint64 offset, guint size,
GstBuffer ** buffer) GstBuffer ** buffer)
{ {
GstPad *target = gst_proxy_pad_get_target (pad); GstPad *internal = gst_proxy_pad_get_internal (pad);
GstFlowReturn res; 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); res = gst_pad_pull_range (internal, offset, size, buffer);
gst_object_unref (target); gst_object_unref (internal);
return res; return res;
} }
@ -227,19 +216,12 @@ static gboolean
gst_proxy_pad_do_checkgetrange (GstPad * pad) gst_proxy_pad_do_checkgetrange (GstPad * pad)
{ {
gboolean result; gboolean result;
GstPad *target = gst_proxy_pad_get_target (pad); GstPad *internal = gst_proxy_pad_get_internal (pad);
GstPad *peer;
g_return_val_if_fail (target != NULL, FALSE); g_return_val_if_fail (internal != NULL, FALSE);
peer = gst_pad_get_peer (target); result = gst_pad_check_pull_range (internal);
if (peer) { gst_object_unref (internal);
result = gst_pad_check_pull_range (peer);
gst_object_unref (peer);
} else {
result = FALSE;
}
gst_object_unref (target);
return result; return result;
} }
@ -250,11 +232,12 @@ gst_proxy_pad_do_getcaps (GstPad * pad)
GstPad *target = gst_proxy_pad_get_target (pad); GstPad *target = gst_proxy_pad_get_target (pad);
GstCaps *res; GstCaps *res;
g_return_val_if_fail (target != NULL, NULL); if (target) {
res = gst_pad_get_caps (target);
res = gst_pad_get_caps (target); gst_object_unref (target);
gst_object_unref (target); } else {
res = gst_caps_new_any ();
}
return res; return res;
} }
@ -262,12 +245,12 @@ static gboolean
gst_proxy_pad_do_acceptcaps (GstPad * pad, GstCaps * caps) gst_proxy_pad_do_acceptcaps (GstPad * pad, GstCaps * caps)
{ {
GstPad *target = gst_proxy_pad_get_target (pad); GstPad *target = gst_proxy_pad_get_target (pad);
gboolean res; gboolean res = FALSE;
g_return_val_if_fail (target != NULL, FALSE); if (target) {
res = gst_pad_accept_caps (target, caps);
res = gst_pad_accept_caps (target, caps); gst_object_unref (target);
gst_object_unref (target); }
return res; return res;
} }
@ -277,10 +260,10 @@ gst_proxy_pad_do_fixatecaps (GstPad * pad, GstCaps * caps)
{ {
GstPad *target = gst_proxy_pad_get_target (pad); GstPad *target = gst_proxy_pad_get_target (pad);
g_return_if_fail (target != NULL); if (target) {
gst_pad_fixate_caps (target, caps);
gst_pad_fixate_caps (target, caps); gst_object_unref (target);
gst_object_unref (target); }
} }
static gboolean static gboolean
@ -289,11 +272,17 @@ gst_proxy_pad_do_setcaps (GstPad * pad, GstCaps * caps)
GstPad *target = gst_proxy_pad_get_target (pad); GstPad *target = gst_proxy_pad_get_target (pad);
gboolean res; gboolean res;
g_return_val_if_fail (target != NULL, FALSE); if (target) {
res = gst_pad_set_caps (target, caps);
res = gst_pad_set_caps (target, caps); gst_object_unref (target);
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; return res;
} }
@ -301,48 +290,38 @@ static gboolean
gst_proxy_pad_set_target_unlocked (GstPad * pad, GstPad * target) gst_proxy_pad_set_target_unlocked (GstPad * pad, GstPad * target)
{ {
GstPad *oldtarget; GstPad *oldtarget;
GstPadTemplate **template_p;
GST_DEBUG ("set target %s:%s on %s:%s", if (target) {
GST_DEBUG_PAD_NAME (target), GST_DEBUG_PAD_NAME (pad)); 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 */ /* clear old target */
if ((oldtarget = GST_PROXY_PAD_TARGET (pad))) { 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_PROXY_PAD_TARGET (pad) = NULL;
gst_object_unref (oldtarget);
} }
if (target) { if (target) {
/* set and ref new target if any */ /* set and ref new target if any */
GST_PROXY_PAD_TARGET (pad) = gst_object_ref (target); GST_PROXY_PAD_TARGET (pad) = gst_object_ref (target);
gst_pad_set_query_type_function (pad, /* Set new pad template */
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query_type)); template_p = &GST_PAD_PAD_TEMPLATE (pad);
gst_pad_set_event_function (pad, gst_object_replace ((GstObject **) template_p,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_event)); (GstObject *) GST_PAD_PAD_TEMPLATE (target));
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));
}
} }
return TRUE; return TRUE;
} }
@ -373,10 +352,18 @@ gst_proxy_pad_get_target (GstPad * pad)
return target; return target;
} }
static void static GstPad *
gst_proxy_pad_init (GstProxyPad * pad) 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 static void
@ -386,8 +373,13 @@ gst_proxy_pad_dispose (GObject * object)
GstPad **target_p; GstPad **target_p;
GST_PROXY_LOCK (pad); GST_PROXY_LOCK (pad);
/* remove and unref the target */
target_p = &GST_PROXY_PAD_TARGET (pad); target_p = &GST_PROXY_PAD_TARGET (pad);
gst_object_replace ((GstObject **) target_p, NULL); 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); GST_PROXY_UNLOCK (pad);
G_OBJECT_CLASS (gst_proxy_pad_parent_class)->dispose (object); 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); 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 #ifndef GST_DISABLE_LOADSAVE
/** /**
* gst_proxy_pad_save_thyself: * gst_proxy_pad_save_thyself:
@ -444,7 +460,6 @@ struct _GstGhostPad
GstProxyPad pad; GstProxyPad pad;
/* with PROXY_LOCK */ /* with PROXY_LOCK */
GstPad *internal;
gulong notify_id; gulong notify_id;
/*< private > */ /*< private > */
@ -462,9 +477,6 @@ struct _GstGhostPadClass
G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD); 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); 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 /* 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); 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); if (target) {
internal = GST_GHOST_PAD (pad)->internal; if (GST_PAD_IS_SRC (internal))
if (internal) gst_pad_link (internal, target);
gst_object_ref (internal); else
GST_PROXY_UNLOCK (pad); 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 static void
gst_ghost_pad_class_init (GstGhostPadClass * klass) gst_ghost_pad_class_init (GstGhostPadClass * klass)
{ {
GObjectClass *gobject_class = (GObjectClass *) klass; GObjectClass *gobject_class = (GObjectClass *) klass;
GstObjectClass *gstobject_class = (GstObjectClass *) klass;
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ghost_pad_dispose); 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 */ /* see gstghostpad design docs */
@ -508,7 +559,7 @@ gst_ghost_pad_internal_do_activate_push (GstPad * pad, gboolean active)
gboolean ret; gboolean ret;
if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) { 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) { if (parent) {
g_return_val_if_fail (GST_IS_GHOST_PAD (parent), FALSE); 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; ret = FALSE;
} }
} else { } else {
GstPad *parent = GST_PAD (gst_object_get_parent (GST_OBJECT (pad))); GstPad *parent = gst_proxy_pad_get_internal (pad);
if (parent) { if (parent) {
g_return_val_if_fail (GST_IS_GHOST_PAD (parent), FALSE); 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; gboolean ret;
if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) { 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) { if (internal) {
ret = gst_pad_activate_push (internal, active); ret = gst_pad_activate_push (internal, active);
@ -600,7 +651,7 @@ gst_ghost_pad_do_activate_pull (GstPad * pad, gboolean active)
ret = FALSE; ret = FALSE;
} }
} else { } else {
GstPad *internal = gst_ghost_pad_get_internal (pad); GstPad *internal = gst_proxy_pad_get_internal (pad);
if (internal) { if (internal) {
ret = gst_pad_activate_pull (internal, active); ret = gst_pad_activate_pull (internal, active);
@ -617,25 +668,13 @@ static GstPadLinkReturn
gst_ghost_pad_do_link (GstPad * pad, GstPad * peer) gst_ghost_pad_do_link (GstPad * pad, GstPad * peer)
{ {
GstPad *internal, *target; GstPad *internal, *target;
GstPadLinkReturn ret; GstPadLinkReturn ret = GST_PAD_LINK_OK;
target = gst_proxy_pad_get_target (pad); target = gst_proxy_pad_get_target (pad);
g_return_val_if_fail (target != NULL, GST_PAD_LINK_NOSCHED); g_return_val_if_fail (target != NULL, GST_PAD_LINK_NOSCHED);
/* proxy the peer into the bin */ internal = gst_proxy_pad_get_internal (pad);
internal = g_object_new (GST_TYPE_PROXY_PAD,
"name", NULL,
"direction", GST_PAD_DIRECTION (peer),
"template", GST_PAD_PAD_TEMPLATE (peer), NULL);
gst_proxy_pad_set_target (internal, peer); 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 we are a source pad, we should call the peer link function
* if the peer has one */ * if the peer has one */
@ -645,11 +684,7 @@ gst_ghost_pad_do_link (GstPad * pad, GstPad * peer)
} }
gst_object_unref (target); gst_object_unref (target);
gst_object_unref (internal);
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);
return ret; return ret;
} }
@ -658,17 +693,20 @@ static void
gst_ghost_pad_do_unlink (GstPad * pad) gst_ghost_pad_do_unlink (GstPad * pad)
{ {
GstPad *target = gst_proxy_pad_get_target (pad); GstPad *target = gst_proxy_pad_get_target (pad);
GstPad *internal = gst_proxy_pad_get_internal (pad);
g_return_if_fail (target != NULL); g_return_if_fail (target != NULL);
GST_DEBUG_OBJECT (pad, "unlinking ghostpad"); 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) if (target->unlinkfunc)
target->unlinkfunc (target); target->unlinkfunc (target);
gst_ghost_pad_set_internal (GST_GHOST_PAD (pad), NULL);
gst_object_unref (target); gst_object_unref (target);
gst_object_unref (internal);
} }
static void static void
@ -687,63 +725,6 @@ on_int_notify (GstPad * internal, GParamSpec * unused, GstGhostPad * pad)
gst_caps_unref (caps); 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 static void
gst_ghost_pad_init (GstGhostPad * pad) gst_ghost_pad_init (GstGhostPad * pad)
{ {
@ -756,7 +737,35 @@ gst_ghost_pad_init (GstGhostPad * pad)
static void static void
gst_ghost_pad_dispose (GObject * object) 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); 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) gst_ghost_pad_new_no_target (const gchar * name, GstPadDirection dir)
{ {
GstPad *ret; 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); ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name, "direction", dir, NULL);
gst_pad_set_activatepush_function (ret, /* Set directional padfunctions for ghostpad */
GST_DEBUG_FUNCPTR (gst_ghost_pad_do_activate_push)); 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_link_function (ret, GST_DEBUG_FUNCPTR (gst_ghost_pad_do_link));
gst_pad_set_unlink_function (ret, gst_pad_set_unlink_function (ret,
GST_DEBUG_FUNCPTR (gst_ghost_pad_do_unlink)); 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; return ret;
} }
@ -807,12 +885,12 @@ gst_ghost_pad_new (const gchar * name, GstPad * target)
{ {
GstPad *ret; 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_IS_PAD (target), NULL);
g_return_val_if_fail (!gst_pad_is_linked (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)))) { 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); gst_ghost_pad_set_target (GST_GHOST_PAD (ret), target);
} }
return ret; return ret;
@ -850,15 +928,15 @@ gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
{ {
GstPad *internal; GstPad *internal;
GstPad *oldtarget; GstPad *oldtarget;
GstObject *parent;
gboolean result; gboolean result;
g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE); g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
GST_PROXY_LOCK (gpad); 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_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget));
GST_DEBUG_PAD_NAME (newtarget), GST_DEBUG_PAD_NAME (gpad));
/* clear old target */ /* clear old target */
if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) { 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); result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget);
if (result && newtarget) { if (result && newtarget) {
/* and link to internal pad if we have one */ /* and link to internal pad if we are not unparent-ed */
if (internal) { if ((parent = gst_object_get_parent (GST_OBJECT (gpad)))) {
if (GST_PAD_IS_SRC (internal)) if (GST_PAD_IS_SRC (internal))
result = gst_pad_link (internal, newtarget); result = gst_pad_link (internal, newtarget);
else else
result = gst_pad_link (newtarget, internal); 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); GST_PROXY_UNLOCK (gpad);

View file

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

View file

@ -2783,19 +2783,10 @@ gulong
gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data) gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data)
{ {
gulong sigid; gulong sigid;
gboolean was_ghost = FALSE;
g_return_val_if_fail (GST_IS_PAD (pad), 0); g_return_val_if_fail (GST_IS_PAD (pad), 0);
g_return_val_if_fail (handler != NULL, 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); GST_OBJECT_LOCK (pad);
sigid = g_signal_connect (pad, "have-data", handler, data); sigid = g_signal_connect (pad, "have-data", handler, data);
GST_PAD_DO_EVENT_SIGNALS (pad)++; 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_PAD_DO_BUFFER_SIGNALS (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
GST_OBJECT_UNLOCK (pad); GST_OBJECT_UNLOCK (pad);
if (was_ghost) {
gst_object_unref (pad);
}
return sigid; return sigid;
} }
@ -2827,19 +2814,10 @@ gulong
gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data) gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data)
{ {
gulong sigid; gulong sigid;
gboolean was_ghost = FALSE;
g_return_val_if_fail (GST_IS_PAD (pad), 0); g_return_val_if_fail (GST_IS_PAD (pad), 0);
g_return_val_if_fail (handler != NULL, 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); GST_OBJECT_LOCK (pad);
sigid = g_signal_connect (pad, "have-data::event", handler, data); sigid = g_signal_connect (pad, "have-data::event", handler, data);
GST_PAD_DO_EVENT_SIGNALS (pad)++; 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_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
GST_OBJECT_UNLOCK (pad); GST_OBJECT_UNLOCK (pad);
if (was_ghost) {
gst_object_unref (pad);
}
return sigid; return sigid;
} }
@ -2869,19 +2843,10 @@ gulong
gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data) gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data)
{ {
gulong sigid; gulong sigid;
gboolean was_ghost = FALSE;
g_return_val_if_fail (GST_IS_PAD (pad), 0); g_return_val_if_fail (GST_IS_PAD (pad), 0);
g_return_val_if_fail (handler != NULL, 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); GST_OBJECT_LOCK (pad);
sigid = g_signal_connect (pad, "have-data::buffer", handler, data); sigid = g_signal_connect (pad, "have-data::buffer", handler, data);
GST_PAD_DO_BUFFER_SIGNALS (pad)++; 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_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
GST_OBJECT_UNLOCK (pad); GST_OBJECT_UNLOCK (pad);
if (was_ghost) {
gst_object_unref (pad);
}
return sigid; return sigid;
} }
@ -2906,19 +2867,9 @@ gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data)
void void
gst_pad_remove_data_probe (GstPad * pad, guint handler_id) 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 (GST_IS_PAD (pad));
g_return_if_fail (handler_id > 0); 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); GST_OBJECT_LOCK (pad);
g_signal_handler_disconnect (pad, handler_id); g_signal_handler_disconnect (pad, handler_id);
GST_PAD_DO_BUFFER_SIGNALS (pad)--; 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_PAD_DO_BUFFER_SIGNALS (pad));
GST_OBJECT_UNLOCK (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 void
gst_pad_remove_event_probe (GstPad * pad, guint handler_id) 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 (GST_IS_PAD (pad));
g_return_if_fail (handler_id > 0); 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); GST_OBJECT_LOCK (pad);
g_signal_handler_disconnect (pad, handler_id); g_signal_handler_disconnect (pad, handler_id);
GST_PAD_DO_EVENT_SIGNALS (pad)--; GST_PAD_DO_EVENT_SIGNALS (pad)--;
GST_DEBUG ("removed event probe from pad %s:%s, now %d event probes", 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_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
GST_OBJECT_UNLOCK (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 void
gst_pad_remove_buffer_probe (GstPad * pad, guint handler_id) 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 (GST_IS_PAD (pad));
g_return_if_fail (handler_id > 0); 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); GST_OBJECT_LOCK (pad);
g_signal_handler_disconnect (pad, handler_id); g_signal_handler_disconnect (pad, handler_id);
GST_PAD_DO_BUFFER_SIGNALS (pad)--; 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_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
GST_OBJECT_UNLOCK (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) while (GST_OBJECT_REFCOUNT_VALUE (fsrc) > 2)
THREAD_SWITCH (); THREAD_SWITCH ();
ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 2); /* gisrc */ ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 1);
ASSERT_OBJECT_REFCOUNT (gsink, "gsink", 1); ASSERT_OBJECT_REFCOUNT (gsink, "gsink", 1);
ASSERT_OBJECT_REFCOUNT (gsrc, "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 (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 */ ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 2); /* gsrc */
gst_object_unref (gsink); gst_object_unref (gsink);
ASSERT_OBJECT_REFCOUNT (isink, "isink", 1); ASSERT_OBJECT_REFCOUNT (isink, "isink", 1);
ASSERT_OBJECT_REFCOUNT (gisrc, "gisrc", 1); ASSERT_OBJECT_REFCOUNT (gisrc, "gisrc", 1);
ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 2); /* gisrc */ ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 1);
gst_object_unref (gisrc); gst_object_unref (gisrc);
ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 1); ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 1);
gst_object_unref (gsrc); gst_object_unref (gsrc);
ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 1); ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 1);
ASSERT_OBJECT_REFCOUNT (gisink, "gisink", 1); ASSERT_OBJECT_REFCOUNT (gisink, "gisink", 1);
ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 2); /* gisrc */ ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 1);
gst_object_unref (gisink); gst_object_unref (gisink);
ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 1); ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 1);