gst/adder/gstadder.*: Implement release_request_pad.
authorWim Taymans <wim.taymans@gmail.com>
Tue, 30 May 2006 16:07:50 +0000 (16:07 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Tue, 30 May 2006 16:07:50 +0000 (16:07 +0000)
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
gst/adder/gstadder.c
gst/adder/gstadder.h
tests/check/elements/adder.c

index f711f73..63216f9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 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):
        Fix build again.
 
index d5361ab..f8a9028 100644 (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)
 {
index 9b1aa82..38b4fea 100644 (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;
index bd701b9..b1a57d8 100644 (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);