From 28cbbee0fb5b88a33592749646a0bb0141ab4aea Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 30 May 2006 16:07:50 +0000 Subject: [PATCH] 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. --- ChangeLog | 11 +++++ gst/adder/gstadder.c | 31 +++++++++++--- gst/adder/gstadder.h | 3 +- tests/check/elements/adder.c | 81 +++++++++++++++++++++++++++++++++++- 4 files changed, 118 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index f711f737b0..63216f9731 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2006-05-30 Wim Taymans + + * 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 * ext/ogg/gstoggdemux.c: (gst_ogg_chain_new_stream): diff --git a/gst/adder/gstadder.c b/gst/adder/gstadder.c index d5361ab4d6..f8a9028d2c 100644 --- a/gst/adder/gstadder.c +++ b/gst/adder/gstadder.c @@ -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) { diff --git a/gst/adder/gstadder.h b/gst/adder/gstadder.h index 9b1aa822be..38b4feaa7d 100644 --- a/gst/adder/gstadder.h +++ b/gst/adder/gstadder.h @@ -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; diff --git a/tests/check/elements/adder.c b/tests/check/elements/adder.c index bd701b973a..b1a57d8564 100644 --- a/tests/check/elements/adder.c +++ b/tests/check/elements/adder.c @@ -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);