adder: use collectpads clipping function
authorWim Taymans <wim.taymans@collabora.co.uk>
Thu, 24 Dec 2009 15:30:23 +0000 (16:30 +0100)
committerWim Taymans <wim@metal.(none)>
Thu, 24 Dec 2009 15:30:23 +0000 (16:30 +0100)
Install a clipping function in the collectpads and use the audio clipping helper
function to perform clipping to the segment boundaries.

Fixes #590265

gst/adder/Makefile.am
gst/adder/gstadder.c
tests/check/elements/adder.c

index cf4005d..7ec0a40 100644 (file)
@@ -1,10 +1,12 @@
 plugin_LTLIBRARIES = libgstadder.la
 
 libgstadder_la_SOURCES = gstadder.c
-libgstadder_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
+libgstadder_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
 #$(LIBOIL_CFLAGS)
 libgstadder_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-libgstadder_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS)
+libgstadder_la_LIBADD =  \
+                $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \
+                $(GST_BASE_LIBS) $(GST_LIBS)
 #$(LIBOIL_LIBS)
 libgstadder_la_LIBTOOLFLAGS = --tag=disable-static
 
index af0e472..4fe9739 100644 (file)
@@ -136,6 +136,8 @@ static void gst_adder_release_pad (GstElement * element, GstPad * pad);
 static GstStateChangeReturn gst_adder_change_state (GstElement * element,
     GstStateChange transition);
 
+static GstBuffer *gst_adder_do_clip (GstCollectPads * pads,
+    GstCollectData * data, GstBuffer * buffer, gpointer user_data);
 static GstFlowReturn gst_adder_collected (GstCollectPads * pads,
     gpointer user_data);
 
@@ -780,7 +782,7 @@ gst_adder_sink_event (GstPad * pad, GstEvent * event)
     case GST_EVENT_FLUSH_STOP:
       /* we received a flush-stop. The collect_event function will push the
        * event past our element. We simply forward all flush-stop events, even
-       * when no flush-stop was pendingk, this is required because collectpads
+       * when no flush-stop was pending, this is required because collectpads
        * does not provide an API to handle-but-not-forward the flush-stop.
        * We unset the pending flush-stop flag so that we don't send anymore
        * flush-stop from the collect function later.
@@ -882,6 +884,8 @@ gst_adder_init (GstAdder * adder)
   adder->collect = gst_collect_pads_new ();
   gst_collect_pads_set_function (adder->collect,
       GST_DEBUG_FUNCPTR (gst_adder_collected), adder);
+  gst_collect_pads_set_clip_function (adder->collect,
+      GST_DEBUG_FUNCPTR (gst_adder_do_clip), adder);
 }
 
 static void
@@ -1023,6 +1027,18 @@ gst_adder_release_pad (GstElement * element, GstPad * pad)
   gst_element_remove_pad (element, pad);
 }
 
+static GstBuffer *
+gst_adder_do_clip (GstCollectPads * pads, GstCollectData * data,
+    GstBuffer * buffer, gpointer user_data)
+{
+  GstAdder *adder = GST_ADDER (user_data);
+
+  buffer = gst_audio_buffer_clip (buffer, &data->segment, adder->rate,
+      adder->bps);
+
+  return buffer;
+}
+
 static GstFlowReturn
 gst_adder_collected (GstCollectPads * pads, gpointer user_data)
 {
index 243e3b6..db0e79a 100644 (file)
@@ -732,6 +732,116 @@ GST_START_TEST (test_remove_pad)
 GST_END_TEST;
 
 
+static GstBuffer *handoff_buffer = NULL;
+static void
+handoff_buffer_cb (GstElement * fakesink, GstBuffer * buffer, GstPad * pad,
+    gpointer user_data)
+{
+  GST_DEBUG ("got buffer %p", buffer);
+  gst_buffer_replace (&handoff_buffer, buffer);
+}
+
+/* check if clipping works as expected */
+GST_START_TEST (test_clip)
+{
+  GstElement *bin, *adder, *sink;
+  GstBus *bus;
+  GstPad *sinkpad;
+  gboolean res;
+  GstFlowReturn ret;
+  GstEvent *event;
+  GstBuffer *buffer;
+  GstCaps *caps;
+
+  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);
+
+  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);
+
+  /* just an adder and a fakesink */
+  adder = gst_element_factory_make ("adder", "adder");
+  sink = gst_element_factory_make ("fakesink", "sink");
+  g_object_set (sink, "signal-handoffs", TRUE, NULL);
+  g_signal_connect (sink, "handoff", (GCallback) handoff_buffer_cb, NULL);
+  gst_bin_add_many (GST_BIN (bin), adder, sink, NULL);
+
+  res = gst_element_link (adder, sink);
+  fail_unless (res == TRUE, NULL);
+
+  /* set to playing */
+  res = gst_element_set_state (bin, GST_STATE_PLAYING);
+  fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL);
+
+  /* create an unconnected sinkpad in adder, should also automatically activate
+   * the pad */
+  sinkpad = gst_element_get_request_pad (adder, "sink%d");
+  fail_if (sinkpad == NULL, NULL);
+
+  /* send segment to adder */
+  event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
+      GST_SECOND, 2 * GST_SECOND, 0);
+  gst_pad_send_event (sinkpad, event);
+
+  caps = gst_caps_new_simple ("audio/x-raw-int",
+      "rate", G_TYPE_INT, 44100,
+      "channels", G_TYPE_INT, 2,
+      "endianness", G_TYPE_INT, G_BYTE_ORDER,
+      "width", G_TYPE_INT, 16,
+      "depth", G_TYPE_INT, 16, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+
+  /* should be clipped and ok */
+  buffer = gst_buffer_new_and_alloc (44100);
+  GST_BUFFER_TIMESTAMP (buffer) = 0;
+  GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
+  gst_buffer_set_caps (buffer, caps);
+  GST_DEBUG ("pushing buffer %p", buffer);
+  ret = gst_pad_chain (sinkpad, buffer);
+  fail_unless (ret == GST_FLOW_OK);
+  fail_unless (handoff_buffer == NULL);
+
+  /* should be partially clipped */
+  buffer = gst_buffer_new_and_alloc (44100);
+  GST_BUFFER_TIMESTAMP (buffer) = 900 * GST_MSECOND;
+  GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
+  gst_buffer_set_caps (buffer, caps);
+  GST_DEBUG ("pushing buffer %p", buffer);
+  ret = gst_pad_chain (sinkpad, buffer);
+  fail_unless (ret == GST_FLOW_OK);
+  fail_unless (handoff_buffer != NULL);
+  gst_buffer_replace (&handoff_buffer, NULL);
+
+  /* should not be clipped */
+  buffer = gst_buffer_new_and_alloc (44100);
+  GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND;
+  GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
+  gst_buffer_set_caps (buffer, caps);
+  GST_DEBUG ("pushing buffer %p", buffer);
+  ret = gst_pad_chain (sinkpad, buffer);
+  fail_unless (ret == GST_FLOW_OK);
+  fail_unless (handoff_buffer != NULL);
+  gst_buffer_replace (&handoff_buffer, NULL);
+
+  /* should be clipped and ok */
+  buffer = gst_buffer_new_and_alloc (44100);
+  GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND;
+  GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND;
+  gst_buffer_set_caps (buffer, caps);
+  GST_DEBUG ("pushing buffer %p", buffer);
+  ret = gst_pad_chain (sinkpad, buffer);
+  fail_unless (ret == GST_FLOW_OK);
+  fail_unless (handoff_buffer == NULL);
+
+
+}
+
+GST_END_TEST;
+
 static Suite *
 adder_suite (void)
 {
@@ -745,6 +855,7 @@ adder_suite (void)
   tcase_add_test (tc_chain, test_live_seeking);
   tcase_add_test (tc_chain, test_add_pad);
   tcase_add_test (tc_chain, test_remove_pad);
+  tcase_add_test (tc_chain, test_clip);
 
   /* Use a longer timeout */
 #ifdef HAVE_VALGRIND