mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 08:46:40 +00:00
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:
parent
c687975a3c
commit
4f9d5adb40
6 changed files with 456 additions and 322 deletions
46
ChangeLog
46
ChangeLog
|
@ -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:
|
||||
|
|
97
gst/gstbin.c
97
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
|
29
gst/gstpad.c
29
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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue