mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-04 22:48:54 +00:00
Clear target when the target pad disappears
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).
This commit is contained in:
parent
8efaf40013
commit
26f368f7e7
2 changed files with 81 additions and 6 deletions
|
@ -56,6 +56,7 @@
|
|||
#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)))
|
||||
|
@ -66,6 +67,7 @@ struct _GstProxyPadPrivate
|
|||
GMutex *proxy_lock;
|
||||
GstPad *target;
|
||||
GstPad *internal;
|
||||
gboolean retarget;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD);
|
||||
|
@ -371,6 +373,24 @@ gst_proxy_pad_get_target (GstPad * 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)
|
||||
{
|
||||
|
@ -426,6 +446,8 @@ gst_proxy_pad_init (GstProxyPad * ppad)
|
|||
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
|
||||
|
@ -1119,11 +1141,15 @@ gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
|
|||
(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);
|
||||
|
|
|
@ -148,6 +148,8 @@ GST_START_TEST (test_remove2)
|
|||
|
||||
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.
|
||||
|
@ -214,6 +216,46 @@ GST_START_TEST (test_ghost_pads_notarget)
|
|||
|
||||
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:
|
||||
*
|
||||
|
@ -357,9 +399,9 @@ GST_START_TEST (test_ghost_pads)
|
|||
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);
|
||||
|
@ -763,6 +805,7 @@ GST_START_TEST (test_ghost_pads_forward_setcaps)
|
|||
gst_object_unref (src_template);
|
||||
gst_object_unref (sink_template);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static gint linked_count1;
|
||||
|
@ -771,26 +814,29 @@ static gint linked_count2;
|
|||
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++;
|
||||
}
|
||||
|
@ -863,6 +909,7 @@ GST_START_TEST (test_ghost_pads_sink_link_unlink)
|
|||
gst_object_unref (srctempl);
|
||||
gst_object_unref (sinktempl);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_ghost_pads_src_link_unlink)
|
||||
|
@ -965,6 +1012,7 @@ GST_START_TEST (test_ghost_pads_src_link_unlink)
|
|||
gst_object_unref (srctempl);
|
||||
gst_object_unref (sinktempl);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
|
@ -977,6 +1025,7 @@ gst_ghost_pad_suite (void)
|
|||
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);
|
||||
|
|
Loading…
Reference in a new issue