context: use context on buffers instead of caps
[platform/upstream/gstreamer.git] / tests / check / elements / tee.c
index bc017dd..b07dba6 100644 (file)
@@ -116,7 +116,7 @@ GST_START_TEST (test_stress)
 {
   GstElement *pipeline;
   GstElement *tee;
-  gchar *desc;
+  const gchar *desc;
   GstBus *bus;
   GstMessage *msg;
   gint i;
@@ -166,10 +166,6 @@ GST_START_TEST (test_stress)
 
 GST_END_TEST;
 
-static GstFlowReturn
-final_sinkpad_bufferalloc (GstPad * pad, guint64 offset, guint size,
-    GstCaps * caps, GstBuffer ** buf);
-
 typedef struct
 {
   GstElement *tee;
@@ -184,7 +180,7 @@ typedef struct
   gboolean bufferalloc_blocked;
 } BufferAllocHarness;
 
-void
+static void
 buffer_alloc_harness_setup (BufferAllocHarness * h, gint countdown)
 {
   h->tee = gst_check_setup_element ("tee");
@@ -210,8 +206,6 @@ buffer_alloc_harness_setup (BufferAllocHarness * h, gint countdown)
 
   h->final_sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
   fail_if (h->final_sinkpad == NULL);
-  gst_pad_set_bufferalloc_function (h->final_sinkpad,
-      final_sinkpad_bufferalloc);
   fail_unless (gst_pad_set_caps (h->final_sinkpad, h->caps) == TRUE);
   fail_unless (gst_pad_set_active (h->final_sinkpad, TRUE) == TRUE);
   g_object_set_qdata (G_OBJECT (h->final_sinkpad),
@@ -223,10 +217,11 @@ buffer_alloc_harness_setup (BufferAllocHarness * h, gint countdown)
       GST_PAD_LINK_OK);
 }
 
-void
+static void
 buffer_alloc_harness_teardown (BufferAllocHarness * h)
 {
-  g_thread_join (h->app_thread);
+  if (h->app_thread)
+    g_thread_join (h->app_thread);
 
   gst_pad_set_active (h->final_sinkpad, FALSE);
   gst_object_unref (h->final_sinkpad);
@@ -238,6 +233,7 @@ buffer_alloc_harness_teardown (BufferAllocHarness * h)
   gst_check_teardown_element (h->tee);
 }
 
+#if 0
 static gpointer
 app_thread_func (gpointer data)
 {
@@ -261,7 +257,9 @@ app_thread_func (gpointer data)
 
   return NULL;
 }
+#endif
 
+#if 0
 static GstFlowReturn
 final_sinkpad_bufferalloc (GstPad * pad, guint64 offset, guint size,
     GstCaps * caps, GstBuffer ** buf)
@@ -304,20 +302,16 @@ final_sinkpad_bufferalloc (GstPad * pad, guint64 offset, guint size,
 
   return GST_FLOW_OK;
 }
+#endif
 
 /* Simulate an app releasing the pad while the first alloc_buffer() is in
  * progress. */
 GST_START_TEST (test_release_while_buffer_alloc)
 {
   BufferAllocHarness h;
-  GstBuffer *buf;
 
   buffer_alloc_harness_setup (&h, 1);
 
-  fail_unless_equals_int (gst_pad_alloc_buffer (h.start_srcpad, 0, 1, h.caps,
-          &buf), GST_FLOW_OK);
-  gst_buffer_unref (buf);
-
   buffer_alloc_harness_teardown (&h);
 }
 
@@ -328,19 +322,251 @@ GST_END_TEST;
 GST_START_TEST (test_release_while_second_buffer_alloc)
 {
   BufferAllocHarness h;
-  GstBuffer *buf;
 
   buffer_alloc_harness_setup (&h, 2);
 
-  fail_unless_equals_int (gst_pad_alloc_buffer (h.start_srcpad, 0, 1, h.caps,
-          &buf), GST_FLOW_OK);
-  gst_buffer_unref (buf);
+  buffer_alloc_harness_teardown (&h);
+}
+
+GST_END_TEST;
 
-  fail_unless_equals_int (gst_pad_alloc_buffer (h.start_srcpad, 0, 1, h.caps,
-          &buf), GST_FLOW_OK);
-  gst_buffer_unref (buf);
+/* Check the internal pads of tee */
+GST_START_TEST (test_internal_links)
+{
+  GstElement *tee;
+  GstPad *sinkpad, *srcpad1, *srcpad2;
+  GstIterator *it;
+  GstIteratorResult res;
+  gpointer val1, val2;
 
-  buffer_alloc_harness_teardown (&h);
+  tee = gst_check_setup_element ("tee");
+
+  sinkpad = gst_element_get_static_pad (tee, "sink");
+  fail_unless (sinkpad != NULL);
+  it = gst_pad_iterate_internal_links (sinkpad);
+  fail_unless (it != NULL);
+
+  /* iterator should not return anything */
+  val1 = NULL;
+  res = gst_iterator_next (it, &val1);
+  fail_unless (res == GST_ITERATOR_DONE);
+  fail_unless (val1 == NULL);
+
+  srcpad1 = gst_element_get_request_pad (tee, "src%d");
+  fail_unless (srcpad1 != NULL);
+
+  /* iterator should resync */
+  res = gst_iterator_next (it, &val1);
+  fail_unless (res == GST_ITERATOR_RESYNC);
+  fail_unless (val1 == NULL);
+  gst_iterator_resync (it);
+
+  /* we should get something now */
+  res = gst_iterator_next (it, &val1);
+  fail_unless (res == GST_ITERATOR_OK);
+  fail_unless (GST_PAD_CAST (val1) == srcpad1);
+
+  gst_object_unref (val1);
+
+  val1 = NULL;
+  res = gst_iterator_next (it, &val1);
+  fail_unless (res == GST_ITERATOR_DONE);
+  fail_unless (val1 == NULL);
+
+  srcpad2 = gst_element_get_request_pad (tee, "src%d");
+  fail_unless (srcpad2 != NULL);
+
+  /* iterator should resync */
+  res = gst_iterator_next (it, &val1);
+  fail_unless (res == GST_ITERATOR_RESYNC);
+  fail_unless (val1 == NULL);
+  gst_iterator_resync (it);
+
+  /* we should get one of the 2 pads now */
+  res = gst_iterator_next (it, &val1);
+  fail_unless (res == GST_ITERATOR_OK);
+  fail_unless (GST_PAD_CAST (val1) == srcpad1
+      || GST_PAD_CAST (val1) == srcpad2);
+
+  /* and the other */
+  res = gst_iterator_next (it, &val2);
+  fail_unless (res == GST_ITERATOR_OK);
+  fail_unless (GST_PAD_CAST (val2) == srcpad1
+      || GST_PAD_CAST (val2) == srcpad2);
+  fail_unless (val1 != val2);
+  gst_object_unref (val1);
+  gst_object_unref (val2);
+
+  val1 = NULL;
+  res = gst_iterator_next (it, &val1);
+  fail_unless (res == GST_ITERATOR_DONE);
+  fail_unless (val1 == NULL);
+
+  gst_iterator_free (it);
+
+  /* get an iterator for the other direction */
+  it = gst_pad_iterate_internal_links (srcpad1);
+  fail_unless (it != NULL);
+
+  res = gst_iterator_next (it, &val1);
+  fail_unless (res == GST_ITERATOR_OK);
+  fail_unless (GST_PAD_CAST (val1) == sinkpad);
+  gst_object_unref (val1);
+
+  res = gst_iterator_next (it, &val1);
+  fail_unless (res == GST_ITERATOR_DONE);
+  gst_iterator_free (it);
+
+  it = gst_pad_iterate_internal_links (srcpad2);
+  fail_unless (it != NULL);
+
+  res = gst_iterator_next (it, &val1);
+  fail_unless (res == GST_ITERATOR_OK);
+  fail_unless (GST_PAD_CAST (val1) == sinkpad);
+  gst_object_unref (val1);
+
+  res = gst_iterator_next (it, &val1);
+  fail_unless (res == GST_ITERATOR_DONE);
+
+  gst_iterator_free (it);
+  gst_object_unref (srcpad1);
+  gst_object_unref (srcpad2);
+  gst_object_unref (sinkpad);
+  gst_object_unref (tee);
+}
+
+GST_END_TEST;
+
+static GstFlowReturn
+_fake_chain (GstPad * pad, GstBuffer * buffer)
+{
+  gst_buffer_unref (buffer);
+  return GST_FLOW_OK;
+}
+
+static GstFlowReturn
+_fake_chain_error (GstPad * pad, GstBuffer * buffer)
+{
+  gst_buffer_unref (buffer);
+  return GST_FLOW_ERROR;
+}
+
+GST_START_TEST (test_flow_aggregation)
+{
+  GstPad *mysrc, *mysink1, *mysink2;
+  GstPad *teesink, *teesrc1, *teesrc2;
+  GstElement *tee;
+  GstBuffer *buffer;
+  GstCaps *caps;
+
+  caps = gst_caps_new_simple ("test/test", NULL);
+
+  tee = gst_element_factory_make ("tee", NULL);
+  fail_unless (tee != NULL);
+  teesink = gst_element_get_static_pad (tee, "sink");
+  fail_unless (teesink != NULL);
+  teesrc1 = gst_element_get_request_pad (tee, "src%d");
+  fail_unless (teesrc1 != NULL);
+  teesrc2 = gst_element_get_request_pad (tee, "src%d");
+  fail_unless (teesrc2 != NULL);
+
+  mysink1 = gst_pad_new ("mysink1", GST_PAD_SINK);
+  gst_pad_set_caps (mysink1, caps);
+  mysink2 = gst_pad_new ("mysink2", GST_PAD_SINK);
+  gst_pad_set_caps (mysink2, caps);
+  mysrc = gst_pad_new ("mysrc", GST_PAD_SRC);
+  gst_pad_set_caps (mysrc, caps);
+
+  gst_pad_set_chain_function (mysink1, _fake_chain);
+  gst_pad_set_active (mysink1, TRUE);
+  gst_pad_set_chain_function (mysink2, _fake_chain);
+  gst_pad_set_active (mysink2, TRUE);
+
+  fail_unless (gst_pad_link (mysrc, teesink) == GST_PAD_LINK_OK);
+  fail_unless (gst_pad_link (teesrc1, mysink1) == GST_PAD_LINK_OK);
+  fail_unless (gst_pad_link (teesrc2, mysink2) == GST_PAD_LINK_OK);
+
+  fail_unless (gst_element_set_state (tee,
+          GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
+
+  buffer = gst_buffer_new ();
+  //gst_buffer_set_caps (buffer, caps);
+
+  /* First check if everything works in normal state */
+  fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK);
+
+  /* One pad being in wrong state must result in wrong state */
+  gst_pad_set_active (mysink2, FALSE);
+  fail_unless (gst_pad_push (mysrc,
+          gst_buffer_ref (buffer)) == GST_FLOW_WRONG_STATE);
+
+  gst_pad_set_active (mysink1, FALSE);
+  gst_pad_set_active (mysink2, TRUE);
+  fail_unless (gst_pad_push (mysrc,
+          gst_buffer_ref (buffer)) == GST_FLOW_WRONG_STATE);
+
+  gst_pad_set_active (mysink2, FALSE);
+  fail_unless (gst_pad_push (mysrc,
+          gst_buffer_ref (buffer)) == GST_FLOW_WRONG_STATE);
+
+  /* Test if everything still works in normal state */
+  gst_pad_set_active (mysink1, TRUE);
+  gst_pad_set_active (mysink2, TRUE);
+  fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK);
+
+  /* One unlinked pad must return OK, two unlinked pads must return NOT_LINKED */
+  fail_unless (gst_pad_unlink (teesrc1, mysink1) == TRUE);
+  fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK);
+
+  fail_unless (gst_pad_link (teesrc1, mysink1) == GST_PAD_LINK_OK);
+  fail_unless (gst_pad_unlink (teesrc2, mysink2) == TRUE);
+  fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK);
+
+  fail_unless (gst_pad_unlink (teesrc1, mysink1) == TRUE);
+  fail_unless (gst_pad_push (mysrc,
+          gst_buffer_ref (buffer)) == GST_FLOW_NOT_LINKED);
+
+  /* Test if everything still works in normal state */
+  fail_unless (gst_pad_link (teesrc1, mysink1) == GST_PAD_LINK_OK);
+  fail_unless (gst_pad_link (teesrc2, mysink2) == GST_PAD_LINK_OK);
+  fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK);
+
+  /* One pad returning ERROR should result in ERROR */
+  gst_pad_set_chain_function (mysink1, _fake_chain_error);
+  fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_ERROR);
+
+  gst_pad_set_chain_function (mysink1, _fake_chain);
+  gst_pad_set_chain_function (mysink2, _fake_chain_error);
+  fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_ERROR);
+
+  gst_pad_set_chain_function (mysink1, _fake_chain_error);
+  fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_ERROR);
+
+  /* And now everything still needs to work */
+  gst_pad_set_chain_function (mysink1, _fake_chain);
+  gst_pad_set_chain_function (mysink2, _fake_chain);
+  fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK);
+
+  fail_unless (gst_element_set_state (tee,
+          GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
+
+  fail_unless (gst_pad_unlink (mysrc, teesink) == TRUE);
+  fail_unless (gst_pad_unlink (teesrc1, mysink1) == TRUE);
+  fail_unless (gst_pad_unlink (teesrc2, mysink2) == TRUE);
+
+
+  gst_object_unref (teesink);
+  gst_object_unref (teesrc1);
+  gst_object_unref (teesrc2);
+  gst_element_release_request_pad (tee, teesrc1);
+  gst_element_release_request_pad (tee, teesrc2);
+  gst_object_unref (tee);
+
+  gst_object_unref (mysink1);
+  gst_object_unref (mysink2);
+  gst_object_unref (mysrc);
+  gst_caps_unref (caps);
+  gst_buffer_unref (buffer);
 }
 
 GST_END_TEST;
@@ -351,11 +577,16 @@ tee_suite (void)
   Suite *s = suite_create ("tee");
   TCase *tc_chain = tcase_create ("general");
 
+  /* Set the timeout to a much larger time - 3 minutes */
+  tcase_set_timeout (tc_chain, 180);
+
   suite_add_tcase (s, tc_chain);
   tcase_add_test (tc_chain, test_num_buffers);
   tcase_add_test (tc_chain, test_stress);
   tcase_add_test (tc_chain, test_release_while_buffer_alloc);
   tcase_add_test (tc_chain, test_release_while_second_buffer_alloc);
+  tcase_add_test (tc_chain, test_internal_links);
+  tcase_add_test (tc_chain, test_flow_aggregation);
 
   return s;
 }