gst/adder/gstadder.*: Implement release_request_pad.

Original commit message from CVS:
* gst/adder/gstadder.c: (gst_adder_class_init), (gst_adder_init),
(gst_adder_request_new_pad), (gst_adder_release_pad):
* gst/adder/gstadder.h:
Implement release_request_pad.
Make padcounter atomic.
* tests/check/elements/adder.c: (GST_START_TEST), (adder_suite):
Added check for release_pad in adder.
This commit is contained in:
Wim Taymans 2006-05-30 16:07:50 +00:00
parent 81286de66f
commit 28cbbee0fb
4 changed files with 118 additions and 8 deletions

View file

@ -1,3 +1,14 @@
2006-05-30 Wim Taymans <wim@fluendo.com>
* gst/adder/gstadder.c: (gst_adder_class_init), (gst_adder_init),
(gst_adder_request_new_pad), (gst_adder_release_pad):
* gst/adder/gstadder.h:
Implement release_request_pad.
Make padcounter atomic.
* tests/check/elements/adder.c: (GST_START_TEST), (adder_suite):
Added check for release_pad in adder.
2006-05-30 Wim Taymans <wim@fluendo.com>
* ext/ogg/gstoggdemux.c: (gst_ogg_chain_new_stream):

View file

@ -101,6 +101,8 @@ static gboolean gst_adder_sink_event (GstPad * pad, GstEvent * event);
static GstPad *gst_adder_request_new_pad (GstElement * element,
GstPadTemplate * temp, const gchar * unused);
static void gst_adder_release_pad (GstElement * element, GstPad * pad);
static GstStateChangeReturn gst_adder_change_state (GstElement * element,
GstStateChange transition);
@ -510,6 +512,7 @@ gst_adder_class_init (GstAdderClass * klass)
parent_class = g_type_class_peek_parent (klass);
gstelement_class->request_new_pad = gst_adder_request_new_pad;
gstelement_class->release_pad = gst_adder_release_pad;
gstelement_class->change_state = gst_adder_change_state;
}
@ -532,7 +535,7 @@ gst_adder_init (GstAdder * adder)
gst_element_add_pad (GST_ELEMENT (adder), adder->srcpad);
adder->format = GST_ADDER_FORMAT_UNSET;
adder->numpads = 0;
adder->padcount = 0;
adder->func = NULL;
/* keep track of the sinkpads requested */
@ -559,16 +562,19 @@ gst_adder_request_new_pad (GstElement * element, GstPadTemplate * templ,
gchar *name;
GstAdder *adder;
GstPad *newpad;
g_return_val_if_fail (GST_IS_ADDER (element), NULL);
gint padcount;
if (templ->direction != GST_PAD_SINK)
goto not_sink;
adder = GST_ADDER (element);
name = g_strdup_printf ("sink%d", adder->numpads);
/* increment pad counter */
padcount = g_atomic_int_exchange_and_add (&adder->padcount, 1);
name = g_strdup_printf ("sink%d", padcount);
newpad = gst_pad_new_from_template (templ, name);
GST_DEBUG_OBJECT (adder, "request new pad %s", name);
g_free (name);
gst_pad_set_getcaps_function (newpad,
@ -582,11 +588,10 @@ gst_adder_request_new_pad (GstElement * element, GstPadTemplate * templ,
adder->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad);
gst_pad_set_event_function (newpad, GST_DEBUG_FUNCPTR (gst_adder_sink_event));
/* takes ownership of the pad */
if (!gst_element_add_pad (GST_ELEMENT (adder), newpad))
goto could_not_add;
adder->numpads++;
return newpad;
/* errors */
@ -597,12 +602,26 @@ not_sink:
}
could_not_add:
{
GST_DEBUG_OBJECT (adder, "could not add pad");
gst_collect_pads_remove_pad (adder->collect, newpad);
gst_object_unref (newpad);
return NULL;
}
}
static void
gst_adder_release_pad (GstElement * element, GstPad * pad)
{
GstAdder *adder;
adder = GST_ADDER (element);
GST_DEBUG_OBJECT (adder, "release pad %s:%s", GST_DEBUG_PAD_NAME (pad));
gst_collect_pads_remove_pad (adder->collect, pad);
gst_element_remove_pad (element, pad);
}
static GstFlowReturn
gst_adder_collected (GstCollectPads * pads, gpointer user_data)
{

View file

@ -52,7 +52,8 @@ struct _GstAdder {
GstPad *srcpad;
GstCollectPads *collect;
gint numpads;
/* pad counter, used for creating unique request pads */
gint padcount;
/* the next are valid for both int and float */
GstAdderFormat format;

View file

@ -287,7 +287,7 @@ GST_START_TEST (test_play_twice)
GST_END_TEST;
/* check if adding and removing pads work as expected */
/* check if adding pads work as expected */
GST_START_TEST (test_add_pad)
{
GstElement *bin, *src1, *src2, *adder, *sink;
@ -363,6 +363,84 @@ GST_START_TEST (test_add_pad)
GST_END_TEST;
/* check if removing pads work as expected */
GST_START_TEST (test_remove_pad)
{
GstElement *bin, *src, *adder, *sink;
GstBus *bus;
GstPad *pad;
gboolean res;
GST_INFO ("preparing test");
/* build pipeline */
bin = gst_pipeline_new ("pipeline");
bus = gst_element_get_bus (bin);
gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
src = gst_element_factory_make ("audiotestsrc", "src");
g_object_set (src, "num-buffers", 4, NULL);
g_object_set (src, "wave", 4, NULL);
adder = gst_element_factory_make ("adder", "adder");
sink = gst_element_factory_make ("fakesink", "sink");
gst_bin_add_many (GST_BIN (bin), src, adder, sink, NULL);
res = gst_element_link (src, adder);
fail_unless (res == TRUE, NULL);
res = gst_element_link (adder, sink);
fail_unless (res == TRUE, NULL);
/* create an unconnected sinkpad in adder */
pad = gst_element_get_request_pad (adder, "sink%d");
fail_if (pad == NULL, NULL);
main_loop = g_main_loop_new (NULL, FALSE);
g_signal_connect (bus, "message::segment-done", (GCallback) message_received,
bin);
g_signal_connect (bus, "message::error", (GCallback) message_received, bin);
g_signal_connect (bus, "message::warning", (GCallback) message_received, bin);
g_signal_connect (bus, "message::eos", (GCallback) message_received, bin);
GST_INFO ("starting test");
/* prepare playing, this will not preroll as adder is waiting
* on the unconnected sinkpad. */
res = gst_element_set_state (bin, GST_STATE_PAUSED);
fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL);
/* wait for completion for one second, will return ASYNC */
res = gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, GST_SECOND);
fail_unless (res == GST_STATE_CHANGE_ASYNC, NULL);
/* get rid of the pad now, adder should stop waiting on it and
* continue the preroll */
gst_element_release_request_pad (adder, pad);
gst_object_unref (pad);
/* wait for completion, should work now */
res =
gst_element_get_state (GST_ELEMENT (bin), NULL, NULL,
GST_CLOCK_TIME_NONE);
fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL);
/* now play all */
res = gst_element_set_state (bin, GST_STATE_PLAYING);
fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL);
g_main_loop_run (main_loop);
res = gst_element_set_state (bin, GST_STATE_NULL);
fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL);
/* cleanup */
g_main_loop_unref (main_loop);
gst_object_unref (G_OBJECT (bus));
gst_object_unref (G_OBJECT (bin));
}
GST_END_TEST;
Suite *
adder_suite (void)
{
@ -373,6 +451,7 @@ adder_suite (void)
tcase_add_test (tc_chain, test_event);
tcase_add_test (tc_chain, test_play_twice);
tcase_add_test (tc_chain, test_add_pad);
tcase_add_test (tc_chain, test_remove_pad);
/* Use a longer timeout */
tcase_set_timeout (tc_chain, 6);