nle: Check seeking on deeply nested composition
authorThibault Saunier <tsaunier@igalia.com>
Wed, 3 Jul 2019 14:10:42 +0000 (10:10 -0400)
committerThibault Saunier <tsaunier@igalia.com>
Fri, 5 Jul 2019 22:30:41 +0000 (18:30 -0400)
tests/check/nle/nlecomposition.c

index 17508d2..71c9099 100644 (file)
@@ -439,21 +439,32 @@ GST_START_TEST (test_simple_audiomixer)
 GST_END_TEST;
 
 static GstElement *
-create_nested_source ()
+create_nested_source (gint nesting_depth)
 {
-  GstElement *source, *nested_source, *nested_comp;
+  gint i;
+  GstElement *source, *nested_comp, *bin;
 
   source = videotest_nle_src ("source", 0, 2 * GST_SECOND, 2, 2);
-  nested_comp =
-      gst_element_factory_make_or_warn ("nlecomposition", "nested_comp");
-  nle_composition_add (GST_BIN (nested_comp), source);
+  for (i = 0; i < nesting_depth; i++) {
+    gchar *name = g_strdup_printf ("nested_comp%d", i);
+    gchar *desc = g_strdup_printf ("nlecomposition name=%s ! queue", name);
+    bin = gst_parse_bin_from_description (desc, TRUE, NULL);
+    nested_comp = gst_bin_get_by_name (GST_BIN (bin), name);
+    g_free (name);
+    g_free (desc);
+
+    nle_composition_add (GST_BIN (nested_comp), source);
+    gst_object_unref (nested_comp);
+
+    name = g_strdup_printf ("nested_src%d", i);
+    source = gst_element_factory_make_or_warn ("nlesource", name);
+    g_free (name);
+    g_object_set (source, "start", 0, "duration", 2 * GST_SECOND, NULL);
+    gst_bin_add (GST_BIN (source), bin);
+  }
 
-  nested_source =
-      gst_element_factory_make_or_warn ("nlesource", "nested_source");
-  g_object_set (nested_source, "start", 0, "duration", 2 * GST_SECOND, NULL);
-  gst_bin_add (GST_BIN (nested_source), nested_comp);
 
-  return nested_source;
+  return source;
 }
 
 GST_START_TEST (test_seek_on_nested)
@@ -476,7 +487,7 @@ GST_START_TEST (test_seek_on_nested)
 
   gst_element_link (comp, sink);
 
-  nested_source = create_nested_source ();
+  nested_source = create_nested_source (1);
   srcpad = gst_element_get_static_pad (nested_source, "src");
   gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM,
       (GstPadProbeCallback) on_source1_pad_event_cb, NULL, NULL);
@@ -571,7 +582,7 @@ GST_START_TEST (test_error_in_nested_timeline)
 
   gst_element_link (comp, sink);
 
-  nested_source = create_nested_source ();
+  nested_source = create_nested_source (1);
   srcpad = gst_element_get_static_pad (nested_source, "src");
   gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM,
       (GstPadProbeCallback) on_source1_pad_event_cb, NULL, NULL);
@@ -637,6 +648,105 @@ GST_START_TEST (test_error_in_nested_timeline)
 
 GST_END_TEST;
 
+GST_START_TEST (test_nest_deep)
+{
+  GstBus *bus;
+  GstPad *srcpad;
+  GstElement *pipeline, *comp, *nested_source, *sink;
+  GstMessage *message;
+  gboolean carry_on, ret = FALSE;
+  GstClockTime position;
+
+  ges_init ();
+
+  pipeline = gst_pipeline_new ("test_pipeline");
+  comp = gst_element_factory_make_or_warn ("nlecomposition", NULL);
+
+  gst_element_set_state (comp, GST_STATE_READY);
+  sink = gst_element_factory_make_or_warn ("fakesink", "sink");
+  gst_bin_add_many (GST_BIN (pipeline), comp, sink, NULL);
+
+  gst_element_link (comp, sink);
+
+  nested_source = create_nested_source (2);
+  srcpad = gst_element_get_static_pad (nested_source, "src");
+  gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM,
+      (GstPadProbeCallback) on_source1_pad_event_cb, NULL, NULL);
+  gst_object_unref (srcpad);
+
+  /* Add nested source */
+  nle_composition_add (GST_BIN (comp), nested_source);
+  commit_and_wait (comp, &ret);
+  check_start_stop_duration (comp, 0, 2 * GST_SECOND, 2 * GST_SECOND);
+
+  bus = gst_element_get_bus (GST_ELEMENT (pipeline));
+
+  fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
+          GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE);
+
+  GST_DEBUG ("Let's poll the bus");
+
+  carry_on = TRUE;
+  while (carry_on) {
+    message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 10);
+    GST_DEBUG_BIN_TO_DOT_FILE (GST_BIN (pipeline),
+        GST_DEBUG_GRAPH_SHOW_ALL, "nothing");
+    if (message) {
+      switch (GST_MESSAGE_TYPE (message)) {
+        case GST_MESSAGE_ASYNC_DONE:
+        {
+          carry_on = FALSE;
+          GST_DEBUG ("Pipeline reached PAUSED, stopping polling");
+          break;
+        }
+        case GST_MESSAGE_EOS:
+        {
+          GST_WARNING ("Saw EOS");
+
+          fail_if (TRUE);
+        }
+        case GST_MESSAGE_ERROR:
+          GST_DEBUG_BIN_TO_DOT_FILE (GST_BIN (pipeline),
+              GST_DEBUG_GRAPH_SHOW_ALL, "error");
+          fail_error_message (message);
+        default:
+          break;
+      }
+      gst_mini_object_unref (GST_MINI_OBJECT (message));
+    }
+  }
+
+  gst_element_seek_simple (pipeline,
+      GST_FORMAT_TIME,
+      GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, 1 * GST_SECOND);
+
+  message = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
+      GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_ERROR);
+  gst_mini_object_unref (GST_MINI_OBJECT (message));
+
+  ret =
+      gst_element_query_position (GST_ELEMENT (pipeline), GST_FORMAT_TIME,
+      (gint64 *) & position);
+  fail_unless_equals_uint64 (position, 1 * GST_SECOND);
+
+  GST_DEBUG ("Setting pipeline to NULL");
+
+  fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
+          GST_STATE_NULL) == GST_STATE_CHANGE_FAILURE);
+
+  GST_DEBUG ("Resetted pipeline to NULL");
+
+  ASSERT_OBJECT_REFCOUNT_BETWEEN (pipeline, "main pipeline", 1, 2);
+  gst_check_objects_destroyed_on_unref (pipeline, comp, nested_source, NULL);
+  ASSERT_OBJECT_REFCOUNT_BETWEEN (bus, "main bus", 1, 2);
+  gst_object_unref (bus);
+
+  ges_deinit ();
+}
+
+GST_END_TEST;
+
+
 
 static Suite *
 gnonlin_suite (void)
@@ -651,6 +761,7 @@ gnonlin_suite (void)
   tcase_add_test (tc_chain, test_remove_last_object);
   tcase_add_test (tc_chain, test_seek_on_nested);
   tcase_add_test (tc_chain, test_error_in_nested_timeline);
+  tcase_add_test (tc_chain, test_nest_deep);
 
   tcase_add_test (tc_chain, test_dispose_on_commit);