mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-12 02:15:31 +00:00
Merge branch 'master' into 0.11
Conflicts: gst/gstghostpad.c
This commit is contained in:
commit
a1d82bec39
2 changed files with 80 additions and 165 deletions
|
@ -54,29 +54,18 @@
|
|||
|
||||
#define GST_PROXY_PAD_CAST(obj) ((GstProxyPad *)obj)
|
||||
#define GST_PROXY_PAD_PRIVATE(obj) (GST_PROXY_PAD_CAST (obj)->priv)
|
||||
#define GST_PROXY_PAD_TARGET(pad) (GST_PROXY_PAD_PRIVATE (pad)->target)
|
||||
#define GST_PROXY_PAD_TARGET(pad) (GST_PAD_PEER (GST_PROXY_PAD_INTERNAL (pad)))
|
||||
#define GST_PROXY_PAD_INTERNAL(pad) (GST_PROXY_PAD_PRIVATE (pad)->internal)
|
||||
#define GST_PROXY_PAD_RETARGET(pad) (GST_PROXY_PAD_PRIVATE (pad)->retarget)
|
||||
#define GST_PROXY_GET_LOCK(pad) (GST_PROXY_PAD_PRIVATE (pad)->proxy_lock)
|
||||
#define GST_PROXY_LOCK(pad) (g_mutex_lock (GST_PROXY_GET_LOCK (pad)))
|
||||
#define GST_PROXY_UNLOCK(pad) (g_mutex_unlock (GST_PROXY_GET_LOCK (pad)))
|
||||
|
||||
struct _GstProxyPadPrivate
|
||||
{
|
||||
/* with PROXY_LOCK */
|
||||
GMutex *proxy_lock;
|
||||
GstPad *target;
|
||||
GstPad *internal;
|
||||
gboolean retarget;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD);
|
||||
|
||||
static GstPad *gst_proxy_pad_get_target (GstPad * pad);
|
||||
|
||||
static void gst_proxy_pad_dispose (GObject * object);
|
||||
static void gst_proxy_pad_finalize (GObject * object);
|
||||
|
||||
/**
|
||||
* gst_proxy_pad_query_type_default:
|
||||
* @pad: a #GstPad.
|
||||
|
@ -433,62 +422,16 @@ no_target:
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_proxy_pad_set_target_unlocked (GstPad * pad, GstPad * target)
|
||||
{
|
||||
GstPad *oldtarget;
|
||||
|
||||
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)))
|
||||
goto wrong_direction;
|
||||
} else
|
||||
GST_LOG_OBJECT (pad, "clearing target");
|
||||
|
||||
/* clear old target */
|
||||
if ((oldtarget = GST_PROXY_PAD_TARGET (pad)))
|
||||
gst_object_unref (oldtarget);
|
||||
|
||||
/* set and ref new target if any */
|
||||
if (target)
|
||||
GST_PROXY_PAD_TARGET (pad) = gst_object_ref (target);
|
||||
else
|
||||
GST_PROXY_PAD_TARGET (pad) = NULL;
|
||||
|
||||
return TRUE;
|
||||
|
||||
/* ERRORS */
|
||||
wrong_direction:
|
||||
{
|
||||
GST_ERROR_OBJECT (pad,
|
||||
"target pad doesn't have the same direction as ourself");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_proxy_pad_set_target (GstPad * pad, GstPad * target)
|
||||
{
|
||||
gboolean result;
|
||||
|
||||
GST_PROXY_LOCK (pad);
|
||||
result = gst_proxy_pad_set_target_unlocked (pad, target);
|
||||
GST_PROXY_UNLOCK (pad);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GstPad *
|
||||
gst_proxy_pad_get_target (GstPad * pad)
|
||||
{
|
||||
GstPad *target;
|
||||
|
||||
GST_PROXY_LOCK (pad);
|
||||
GST_OBJECT_LOCK (pad);
|
||||
target = GST_PROXY_PAD_TARGET (pad);
|
||||
if (target)
|
||||
gst_object_ref (target);
|
||||
GST_PROXY_UNLOCK (pad);
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
|
||||
return target;
|
||||
}
|
||||
|
@ -514,11 +457,11 @@ gst_proxy_pad_get_internal (GstProxyPad * pad)
|
|||
|
||||
g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
|
||||
|
||||
GST_PROXY_LOCK (pad);
|
||||
GST_OBJECT_LOCK (pad);
|
||||
internal = GST_PROXY_PAD_INTERNAL (pad);
|
||||
if (internal)
|
||||
gst_object_ref (internal);
|
||||
GST_PROXY_UNLOCK (pad);
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
|
||||
return GST_PROXY_PAD_CAST (internal);
|
||||
}
|
||||
|
@ -534,31 +477,15 @@ gst_proxy_pad_get_internal (GstProxyPad * pad)
|
|||
void
|
||||
gst_proxy_pad_unlink_default (GstPad * pad)
|
||||
{
|
||||
GstPad *internal;
|
||||
|
||||
/* don't do anything if this unlink resulted from retargeting the pad
|
||||
* controlled by the ghostpad. We only want to invalidate the target pad when
|
||||
* the element suddenly unlinked with our internal pad. */
|
||||
if (GST_PROXY_PAD_RETARGET (pad))
|
||||
return;
|
||||
|
||||
internal = GST_PROXY_PAD_INTERNAL (pad);
|
||||
|
||||
/* nothing to do anymore */
|
||||
GST_DEBUG_OBJECT (pad, "pad is unlinked");
|
||||
|
||||
gst_proxy_pad_set_target (internal, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_proxy_pad_class_init (GstProxyPadClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GstProxyPadPrivate));
|
||||
|
||||
gobject_class->dispose = gst_proxy_pad_dispose;
|
||||
gobject_class->finalize = gst_proxy_pad_finalize;
|
||||
|
||||
/* Register common function pointer descriptions */
|
||||
GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_query_type_default);
|
||||
GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_event_default);
|
||||
|
@ -573,35 +500,6 @@ gst_proxy_pad_class_init (GstProxyPadClass * klass)
|
|||
GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_getrange_default);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_proxy_pad_dispose (GObject * object)
|
||||
{
|
||||
GstPad *pad = GST_PAD (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);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_proxy_pad_finalize (GObject * object)
|
||||
{
|
||||
GstProxyPad *pad = GST_PROXY_PAD (object);
|
||||
|
||||
g_mutex_free (GST_PROXY_GET_LOCK (pad));
|
||||
GST_PROXY_GET_LOCK (pad) = NULL;
|
||||
|
||||
G_OBJECT_CLASS (gst_proxy_pad_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_proxy_pad_init (GstProxyPad * ppad)
|
||||
{
|
||||
|
@ -609,7 +507,6 @@ gst_proxy_pad_init (GstProxyPad * ppad)
|
|||
|
||||
GST_PROXY_PAD_PRIVATE (ppad) = G_TYPE_INSTANCE_GET_PRIVATE (ppad,
|
||||
GST_TYPE_PROXY_PAD, GstProxyPadPrivate);
|
||||
GST_PROXY_GET_LOCK (pad) = g_mutex_new ();
|
||||
|
||||
gst_pad_set_query_type_function (pad, gst_proxy_pad_query_type_default);
|
||||
gst_pad_set_event_function (pad, gst_proxy_pad_event_default);
|
||||
|
@ -807,17 +704,12 @@ GstPadLinkReturn
|
|||
gst_ghost_pad_link_default (GstPad * pad, GstPad * peer)
|
||||
{
|
||||
GstPadLinkReturn ret;
|
||||
GstPad *internal;
|
||||
|
||||
g_return_val_if_fail (GST_IS_GHOST_PAD (pad), GST_PAD_LINK_REFUSED);
|
||||
g_return_val_if_fail (GST_IS_PAD (peer), GST_PAD_LINK_REFUSED);
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "linking ghostpad");
|
||||
|
||||
internal = GST_PROXY_PAD_INTERNAL (pad);
|
||||
if (!gst_proxy_pad_set_target (internal, peer))
|
||||
goto target_failed;
|
||||
|
||||
ret = GST_PAD_LINK_OK;
|
||||
/* if we are a source pad, we should call the peer link function
|
||||
* if the peer has one, see design docs. */
|
||||
|
@ -825,24 +717,10 @@ gst_ghost_pad_link_default (GstPad * pad, GstPad * peer)
|
|||
if (GST_PAD_LINKFUNC (peer)) {
|
||||
ret = GST_PAD_LINKFUNC (peer) (peer, pad);
|
||||
if (ret != GST_PAD_LINK_OK)
|
||||
goto link_failed;
|
||||
GST_DEBUG_OBJECT (pad, "linking failed");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
/* ERRORS */
|
||||
target_failed:
|
||||
{
|
||||
GST_DEBUG_OBJECT (pad, "setting target failed");
|
||||
return GST_PAD_LINK_REFUSED;
|
||||
}
|
||||
link_failed:
|
||||
{
|
||||
GST_DEBUG_OBJECT (pad, "linking failed");
|
||||
/* clear target again */
|
||||
gst_proxy_pad_set_target (internal, NULL);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -856,16 +734,9 @@ link_failed:
|
|||
void
|
||||
gst_ghost_pad_unlink_default (GstPad * pad)
|
||||
{
|
||||
GstPad *internal;
|
||||
|
||||
g_return_if_fail (GST_IS_GHOST_PAD (pad));
|
||||
|
||||
internal = GST_PROXY_PAD_INTERNAL (pad);
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "unlinking ghostpad");
|
||||
|
||||
/* The target of the internal pad is no longer valid */
|
||||
gst_proxy_pad_set_target (internal, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -919,7 +790,7 @@ gst_ghost_pad_dispose (GObject * object)
|
|||
gst_object_unref (peer);
|
||||
}
|
||||
|
||||
GST_PROXY_LOCK (pad);
|
||||
GST_OBJECT_LOCK (pad);
|
||||
internal = GST_PROXY_PAD_INTERNAL (pad);
|
||||
|
||||
gst_pad_set_activatepull_function (internal, NULL);
|
||||
|
@ -930,7 +801,7 @@ gst_ghost_pad_dispose (GObject * object)
|
|||
gst_object_unparent (GST_OBJECT_CAST (internal));
|
||||
GST_PROXY_PAD_INTERNAL (pad) = NULL;
|
||||
|
||||
GST_PROXY_UNLOCK (pad);
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
|
||||
G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object);
|
||||
}
|
||||
|
@ -1003,7 +874,7 @@ gst_ghost_pad_construct (GstGhostPad * gpad)
|
|||
gst_pad_set_getrange_function (internal, gst_proxy_pad_getrange_default);
|
||||
}
|
||||
|
||||
GST_PROXY_LOCK (pad);
|
||||
GST_OBJECT_LOCK (pad);
|
||||
|
||||
/* now make the ghostpad a parent of the internal pad */
|
||||
if (!gst_object_set_parent (GST_OBJECT_CAST (internal),
|
||||
|
@ -1027,7 +898,7 @@ gst_ghost_pad_construct (GstGhostPad * gpad)
|
|||
gst_pad_set_activatepush_function (internal,
|
||||
gst_ghost_pad_internal_activate_push_default);
|
||||
|
||||
GST_PROXY_UNLOCK (pad);
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
|
||||
GST_GHOST_PAD_PRIVATE (gpad)->constructed = TRUE;
|
||||
return TRUE;
|
||||
|
@ -1039,7 +910,7 @@ parent_failed:
|
|||
GST_DEBUG_PAD_NAME (internal));
|
||||
g_critical ("Could not set internal pad %s:%s",
|
||||
GST_DEBUG_PAD_NAME (internal));
|
||||
GST_PROXY_UNLOCK (pad);
|
||||
GST_OBJECT_UNLOCK (pad);
|
||||
gst_object_unref (internal);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1252,7 +1123,6 @@ gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
|
|||
{
|
||||
GstPad *internal;
|
||||
GstPad *oldtarget;
|
||||
gboolean result;
|
||||
GstPadLinkReturn lret;
|
||||
|
||||
g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
|
||||
|
@ -1269,24 +1139,20 @@ gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
|
|||
GST_DEBUG_OBJECT (gpad, "clearing target");
|
||||
|
||||
/* clear old target */
|
||||
GST_PROXY_LOCK (gpad);
|
||||
GST_OBJECT_LOCK (gpad);
|
||||
if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) {
|
||||
|
||||
GST_PROXY_PAD_RETARGET (internal) = TRUE;
|
||||
GST_OBJECT_UNLOCK (gpad);
|
||||
|
||||
/* unlink internal pad */
|
||||
if (GST_PAD_IS_SRC (internal))
|
||||
gst_pad_unlink (internal, oldtarget);
|
||||
else
|
||||
gst_pad_unlink (oldtarget, internal);
|
||||
|
||||
GST_PROXY_PAD_RETARGET (internal) = FALSE;
|
||||
} else {
|
||||
GST_OBJECT_UNLOCK (gpad);
|
||||
}
|
||||
|
||||
result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget);
|
||||
GST_PROXY_UNLOCK (gpad);
|
||||
|
||||
if (result && newtarget) {
|
||||
if (newtarget) {
|
||||
/* and link to internal pad without any checks */
|
||||
GST_DEBUG_OBJECT (gpad, "connecting internal pad to target");
|
||||
|
||||
|
@ -1301,17 +1167,13 @@ gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
|
|||
goto link_failed;
|
||||
}
|
||||
|
||||
return result;
|
||||
return TRUE;
|
||||
|
||||
/* ERRORS */
|
||||
link_failed:
|
||||
{
|
||||
GST_WARNING_OBJECT (gpad, "could not link internal and target, reason:%d",
|
||||
lret);
|
||||
/* and unset target again */
|
||||
GST_PROXY_LOCK (gpad);
|
||||
gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), NULL);
|
||||
GST_PROXY_UNLOCK (gpad);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,9 +106,8 @@ GST_START_TEST (test_remove2)
|
|||
ret = gst_pad_link (srcpad, sinkpad);
|
||||
GST_DEBUG ("linked srcpad and sinkpad");
|
||||
fail_unless (ret == GST_PAD_LINK_OK);
|
||||
/* the linking causes a proxypad to be created for srcpad,
|
||||
* to which sinkpad gets linked. This proxypad has a ref to srcpad */
|
||||
ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 3);
|
||||
/* Refcount should be unchanged, targets are now decuced using peer pad */
|
||||
ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 2);
|
||||
ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2);
|
||||
gst_object_unref (srcpad);
|
||||
gst_object_unref (sinkpad);
|
||||
|
@ -120,14 +119,14 @@ GST_START_TEST (test_remove2)
|
|||
/* pad is still linked to ghostpad */
|
||||
fail_if (!gst_pad_is_linked (srcpad));
|
||||
ASSERT_OBJECT_REFCOUNT (src, "src", 1);
|
||||
ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 3);
|
||||
ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 2);
|
||||
gst_object_unref (srcpad);
|
||||
ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 1);
|
||||
|
||||
/* cleanup */
|
||||
/* now unlink the pads */
|
||||
gst_pad_unlink (srcpad, sinkpad);
|
||||
ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1); /* proxy has dropped ref */
|
||||
ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1); /* we dropped our ref */
|
||||
ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 1);
|
||||
|
||||
ASSERT_OBJECT_REFCOUNT (src, "src", 1);
|
||||
|
@ -362,15 +361,15 @@ GST_START_TEST (test_ghost_pads)
|
|||
|
||||
/* all objects above have one refcount owned by us as well */
|
||||
|
||||
ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 3); /* parent and gisrc */
|
||||
ASSERT_OBJECT_REFCOUNT (fsrc, "fsrc", 2); /* parent */
|
||||
ASSERT_OBJECT_REFCOUNT (gsink, "gsink", 2); /* parent */
|
||||
ASSERT_OBJECT_REFCOUNT (gsrc, "gsrc", 2); /* parent */
|
||||
ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 3); /* parent and gisink */
|
||||
ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 2); /* parent */
|
||||
|
||||
ASSERT_OBJECT_REFCOUNT (gisrc, "gisrc", 2); /* parent */
|
||||
ASSERT_OBJECT_REFCOUNT (isink, "isink", 3); /* parent and gsink */
|
||||
ASSERT_OBJECT_REFCOUNT (isink, "isink", 2); /* parent */
|
||||
ASSERT_OBJECT_REFCOUNT (gisink, "gisink", 2); /* parent */
|
||||
ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 3); /* parent and gsrc */
|
||||
ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 2); /* parent */
|
||||
|
||||
ret = gst_element_set_state (b1, GST_STATE_PLAYING);
|
||||
ret = gst_element_get_state (b1, NULL, NULL, GST_CLOCK_TIME_NONE);
|
||||
|
@ -1055,6 +1054,59 @@ GST_START_TEST (test_ghost_pads_change_when_linked)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
/* test that setting a ghostpad proxy pad as ghostpad target automatically set
|
||||
* both ghostpad targets.
|
||||
*
|
||||
* fakesrc ! ( ) ! fakesink
|
||||
*/
|
||||
|
||||
GST_START_TEST (test_ghost_pads_internal_link)
|
||||
{
|
||||
GstElement *pipeline, *src, *bin, *sink;
|
||||
GstPad *sinkpad, *srcpad, *target;
|
||||
GstProxyPad *proxypad;
|
||||
|
||||
pipeline = gst_element_factory_make ("pipeline", NULL);
|
||||
bin = gst_element_factory_make ("bin", NULL);
|
||||
src = gst_element_factory_make ("fakesrc", NULL);
|
||||
sink = gst_element_factory_make ("fakesink", NULL);
|
||||
|
||||
gst_bin_add (GST_BIN (pipeline), src);
|
||||
gst_bin_add (GST_BIN (pipeline), bin);
|
||||
gst_bin_add (GST_BIN (pipeline), sink);
|
||||
|
||||
/* create the sink ghostpad */
|
||||
sinkpad = gst_ghost_pad_new_no_target ("sink", GST_PAD_SINK);
|
||||
proxypad = gst_proxy_pad_get_internal (GST_PROXY_PAD (sinkpad));
|
||||
gst_element_add_pad (bin, sinkpad);
|
||||
|
||||
/* create the src ghostpad and link it to sink proxypad */
|
||||
srcpad = gst_ghost_pad_new ("src", GST_PAD (proxypad));
|
||||
gst_object_unref (proxypad);
|
||||
gst_element_add_pad (bin, srcpad);
|
||||
|
||||
fail_unless (gst_element_link_many (src, bin, sink, NULL));
|
||||
|
||||
/* Check that both targets are set, and point to each other */
|
||||
target = gst_ghost_pad_get_target (GST_GHOST_PAD (sinkpad));
|
||||
fail_if (target == NULL);
|
||||
proxypad = gst_proxy_pad_get_internal (GST_PROXY_PAD (srcpad));
|
||||
fail_unless (target == GST_PAD (proxypad));
|
||||
gst_object_unref (target);
|
||||
gst_object_unref (proxypad);
|
||||
|
||||
target = gst_ghost_pad_get_target (GST_GHOST_PAD (srcpad));
|
||||
fail_if (target == NULL);
|
||||
proxypad = gst_proxy_pad_get_internal (GST_PROXY_PAD (sinkpad));
|
||||
fail_unless (target == GST_PAD (proxypad));
|
||||
gst_object_unref (target);
|
||||
gst_object_unref (proxypad);
|
||||
|
||||
/* clean up */
|
||||
gst_object_unref (pipeline);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
gst_ghost_pad_suite (void)
|
||||
|
@ -1079,6 +1131,7 @@ gst_ghost_pad_suite (void)
|
|||
tcase_add_test (tc_chain, test_ghost_pads_sink_link_unlink);
|
||||
tcase_add_test (tc_chain, test_ghost_pads_src_link_unlink);
|
||||
tcase_add_test (tc_chain, test_ghost_pads_change_when_linked);
|
||||
tcase_add_test (tc_chain, test_ghost_pads_internal_link);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue