summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 8efaf40)
raw | patch | inline | side by side (parent: 8efaf40)
author | Wim Taymans <wim.taymans@collabora.co.uk> | |
Mon, 16 Feb 2009 11:58:34 +0000 (12:58 +0100) | ||
committer | Wim Taymans <wim.taymans@collabora.co.uk> | |
Mon, 16 Feb 2009 11:58:34 +0000 (12:58 +0100) |
When the target pad disappears (because it was explicitly unlinked or the
element was removed/unreffed) make sure we receive a notify with the unlink
function on the proxy pad and clear the target. We use a simple flag to not do
this and cause deadlocks when the target was changed explicitly using the
ghostpad functions.
Update the unit test because we now unref the target sooner (and correctly).
element was removed/unreffed) make sure we receive a notify with the unlink
function on the proxy pad and clear the target. We use a simple flag to not do
this and cause deadlocks when the target was changed explicitly using the
ghostpad functions.
Update the unit test because we now unref the target sooner (and correctly).
gst/gstghostpad.c | patch | blob | history | |
tests/check/gst/gstghostpad.c | patch | blob | history |
diff --git a/gst/gstghostpad.c b/gst/gstghostpad.c
index 694f67371181125750106064ad8cede8f00987e2..89ac95e80447d81e97c180cbd40fc5a5bf66e694 100644 (file)
--- a/gst/gstghostpad.c
+++ b/gst/gstghostpad.c
#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_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)))
GMutex *proxy_lock;
GstPad *target;
GstPad *internal;
+ gboolean retarget;
};
G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD);
return target;
}
+static void
+gst_proxy_pad_do_unlink (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 suddently unlinked with our internal pad. */
+ if (GST_PROXY_PAD_RETARGET (pad))
+ return;
+
+ internal = GST_PROXY_PAD_INTERNAL (pad);
+
+ GST_DEBUG_OBJECT (pad, "pad is unlinked");
+
+ gst_proxy_pad_set_target (internal, NULL);
+}
+
static void
gst_proxy_pad_dispose (GObject * object)
{
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_fixatecaps));
gst_pad_set_setcaps_function (pad,
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_setcaps));
+ gst_pad_set_unlink_function (pad,
+ GST_DEBUG_FUNCPTR (gst_proxy_pad_do_unlink));
}
#ifndef GST_DISABLE_LOADSAVE
(gpointer) on_src_target_notify, gpad);
}
+ GST_PROXY_PAD_RETARGET (internal) = TRUE;
+
/* 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;
}
result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget);
index 25a0baa4e6dca6380c40f4cedca4075568395541..3db738019ef89a482c0ae73eb54a8f2dd16c9e20 100644 (file)
GST_END_TEST;
+
+
/* test if a ghost pad without a target can be linked and
* unlinked. An untargeted ghostpad has a default ANY caps unless there
* is a padtemplate that says something else.
GST_END_TEST;
+/* Test that removing the target of a ghostpad properly sets the target of the
+ * ghostpad to NULL */
+GST_START_TEST (test_remove_target)
+{
+ GstElement *b1, *b2, *src, *sink;
+
+ GstPad *sinkpad, *ghost, *target;
+
+ b1 = gst_element_factory_make ("pipeline", NULL);
+ b2 = gst_element_factory_make ("bin", NULL);
+ src = gst_element_factory_make ("fakesrc", NULL);
+ sink = gst_element_factory_make ("fakesink", NULL);
+ ASSERT_OBJECT_REFCOUNT (src, "src", 1);
+
+ fail_unless (gst_bin_add (GST_BIN (b2), sink));
+ fail_unless (gst_bin_add (GST_BIN (b1), src));
+ fail_unless (gst_bin_add (GST_BIN (b1), b2));
+ ASSERT_OBJECT_REFCOUNT (src, "src", 1);
+
+ sinkpad = gst_element_get_static_pad (sink, "sink");
+ gst_element_add_pad (b2, gst_ghost_pad_new ("sink", sinkpad));
+
+ ghost = gst_element_get_static_pad (b2, "sink");
+
+ target = gst_ghost_pad_get_target (GST_GHOST_PAD (ghost));
+ fail_unless (target == sinkpad);
+ gst_object_unref (target);
+ gst_object_unref (sinkpad);
+
+ gst_bin_remove (GST_BIN (b2), sink);
+
+ target = gst_ghost_pad_get_target (GST_GHOST_PAD (ghost));
+ fail_unless (target == NULL);
+
+ gst_object_unref (b1);
+}
+
+GST_END_TEST;
+
+
/* test if linking fails over different bins using a pipeline
* like this:
*
ASSERT_OBJECT_REFCOUNT (fsink, "fsink", 1);
ASSERT_OBJECT_REFCOUNT (gisrc, "gisrc", 2); /* gsink */
- ASSERT_OBJECT_REFCOUNT (isink, "isink", 2); /* gsink */
+ ASSERT_OBJECT_REFCOUNT (isink, "isink", 1); /* gsink */
ASSERT_OBJECT_REFCOUNT (gisink, "gisink", 2); /* gsrc */
- ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 2); /* gsrc */
+ ASSERT_OBJECT_REFCOUNT (isrc, "isrc", 1); /* gsrc */
gst_object_unref (gsink);
ASSERT_OBJECT_REFCOUNT (isink, "isink", 1);
gst_object_unref (src_template);
gst_object_unref (sink_template);
}
+
GST_END_TEST;
static gint linked_count1;
static gint unlinked_count2;
static GstPadLinkReturn
-pad_linked1 (GstPad *pad, GstPad *peer)
+pad_linked1 (GstPad * pad, GstPad * peer)
{
linked_count1++;
return GST_PAD_LINK_OK;
}
+
static void
-pad_unlinked1 (GstPad *pad)
+pad_unlinked1 (GstPad * pad)
{
unlinked_count1++;
}
+
static GstPadLinkReturn
-pad_linked2 (GstPad *pad, GstPad *peer)
+pad_linked2 (GstPad * pad, GstPad * peer)
{
linked_count2++;
return GST_PAD_LINK_OK;
}
+
static void
-pad_unlinked2 (GstPad *pad)
+pad_unlinked2 (GstPad * pad)
{
unlinked_count2++;
}
gst_object_unref (srctempl);
gst_object_unref (sinktempl);
}
+
GST_END_TEST;
GST_START_TEST (test_ghost_pads_src_link_unlink)
gst_object_unref (srctempl);
gst_object_unref (sinktempl);
}
+
GST_END_TEST;
static Suite *
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_remove1);
tcase_add_test (tc_chain, test_remove2);
+ tcase_add_test (tc_chain, test_remove_target);
tcase_add_test (tc_chain, test_link);
tcase_add_test (tc_chain, test_ghost_pads);
tcase_add_test (tc_chain, test_ghost_pads_bin);