From: Edward Hervey Date: Tue, 11 Jul 2006 16:20:09 +0000 (+0000) Subject: gst/gstbin.c: (de)activate src pads before calling state_change on the childs. X-Git-Tag: RELEASE-0_10_9~9 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4f9d5adb40898114dfc7a0760259c0ce581fff58;p=platform%2Fupstream%2Fgstreamer.git 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 (!?!). --- diff --git a/ChangeLog b/ChangeLog index 9fdfe53..290471f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,49 @@ +2006-07-11 Edward Hervey + + * 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 * docs/gst/gstreamer-sections.txt: diff --git a/gst/gstbin.c b/gst/gstbin.c index 32c0d12..e7e4a4f 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -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; } /* diff --git a/gst/gstghostpad.c b/gst/gstghostpad.c index 89ab320..fc261eb 100644 --- a/gst/gstghostpad.c +++ b/gst/gstghostpad.c @@ -2,6 +2,7 @@ * Copyright (C) 1999,2000 Erik Walthinsen * 2000 Wim Taymans * 2005 Andy Wingo + * 2006 Edward Hervey * * 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; - - g_return_val_if_fail (target != NULL, NULL); + GList *res = 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; - - g_return_val_if_fail (target != 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)); + GstPad *internal = gst_proxy_pad_get_internal (pad); - result = gst_pad_alloc_buffer (peer, offset, size, caps, buf); - - gst_object_unref (peer); - } else { - result = GST_FLOW_NOT_LINKED; - } + g_return_val_if_fail (internal != NULL, 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; - - g_return_val_if_fail (target != NULL, FALSE); + gboolean res = 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); diff --git a/gst/gstpad.c b/gst/gstpad.c index e2ddda8..12e0306 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -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; diff --git a/gst/gstutils.c b/gst/gstutils.c index bbc749c..ac1bf33 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -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); - } } /** diff --git a/tests/check/gst/gstghostpad.c b/tests/check/gst/gstghostpad.c index 2ab4247..793dd35 100644 --- a/tests/check/gst/gstghostpad.c +++ b/tests/check/gst/gstghostpad.c @@ -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);