[Test] testcase to convert multi tensors
authorJaeyun <jy1210.jung@samsung.com>
Fri, 10 Jul 2020 05:35:44 +0000 (14:35 +0900)
committerMyungJoo Ham <myungjoo.ham@samsung.com>
Wed, 29 Jul 2020 08:06:05 +0000 (17:06 +0900)
add new testcases to convert byte stream to multi tensors.

Signed-off-by: Jaeyun <jy1210.jung@samsung.com>
tests/nnstreamer_plugins/unittest_plugins.cc
tests/nnstreamer_sink/unittest_sink.cc

index eac0e2d..9d31a70 100644 (file)
@@ -1756,6 +1756,454 @@ TEST (test_tensor_aggregator, aggregate_5)
   gst_harness_teardown (h);
 }
 
+/**
+ * @brief Test for tensor_converter (bytes to multi tensors)
+ */
+TEST (test_tensor_converter, bytes_to_multi_1)
+{
+  GstHarness *h;
+  GstBuffer *in_buf, *out_buf;
+  GstTensorsConfig config;
+  GstCaps *caps;
+  GstMemory *mem;
+  GstMapInfo info;
+  guint i;
+  gsize data_size;
+
+  h = gst_harness_new ("tensor_converter");
+
+  g_object_set (h->element, "input-dim", "3:4:2:2,3:4:2:2",
+      "input-type", "int32,int32", NULL);
+
+  /* in/out caps and tensors info */
+  caps = gst_caps_from_string ("application/octet-stream");
+  gst_harness_set_src_caps (h, caps);
+
+  gst_tensors_config_init (&config);
+  config.rate_n = 0;
+  config.rate_d = 1;
+  config.info.num_tensors = 2;
+
+  config.info.info[0].type = _NNS_INT32;
+  gst_tensor_parse_dimension ("3:4:2:2", config.info.info[0].dimension);
+  config.info.info[1].type = _NNS_INT32;
+  gst_tensor_parse_dimension ("3:4:2:2", config.info.info[1].dimension);
+
+  data_size = gst_tensors_info_get_size (&config.info, -1);
+
+  /* push buffers */
+  in_buf = gst_harness_create_buffer (h, data_size);
+
+  mem = gst_buffer_peek_memory (in_buf, 0);
+  ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_WRITE));
+
+  memcpy (info.data, aggr_test_frames, data_size);
+
+  gst_memory_unmap (mem, &info);
+
+  EXPECT_EQ (gst_harness_push (h, in_buf), GST_FLOW_OK);
+
+  /* get output buffer */
+  out_buf = gst_harness_pull (h);
+
+  ASSERT_TRUE (out_buf != NULL);
+  ASSERT_EQ (gst_buffer_n_memory (out_buf), 2U);
+  ASSERT_EQ (gst_buffer_get_size (out_buf), data_size);
+
+  /* 1st tensor */
+  mem = gst_buffer_peek_memory (out_buf, 0);
+  ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_READ));
+  for (i = 0; i < 48; i++)
+    EXPECT_EQ (((gint *) info.data)[i], aggr_test_frames[0][i]);
+  gst_memory_unmap (mem, &info);
+
+  /* 2nd tensor */
+  mem = gst_buffer_peek_memory (out_buf, 1);
+  ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_READ));
+  for (i = 0; i < 48; i++)
+    EXPECT_EQ (((gint *) info.data)[i], aggr_test_frames[1][i]);
+  gst_memory_unmap (mem, &info);
+
+  gst_buffer_unref (out_buf);
+
+  EXPECT_EQ (gst_harness_buffers_received (h), 1U);
+  gst_harness_teardown (h);
+}
+
+/**
+ * @brief Test for tensor_converter (bytes to multi tensors)
+ */
+TEST (test_tensor_converter, bytes_to_multi_2)
+{
+  GstHarness *h;
+  GstBuffer *in_buf, *out_buf;
+  GstTensorsConfig config;
+  GstCaps *caps;
+  GstMemory *mem;
+  GstMapInfo info;
+  guint i;
+  gsize data_size;
+
+  h = gst_harness_new ("tensor_converter");
+
+  g_object_set (h->element, "input-dim", "3:4:2:1,3:4:2:1,3:4:2:1,3:4:2:1",
+      "input-type", "int32,int32,int32,int32", NULL);
+
+  /* in/out caps and tensors info */
+  caps = gst_caps_from_string ("application/octet-stream");
+  gst_harness_set_src_caps (h, caps);
+
+  gst_tensors_config_init (&config);
+  config.rate_n = 0;
+  config.rate_d = 1;
+  config.info.num_tensors = 4;
+
+  config.info.info[0].type = _NNS_INT32;
+  gst_tensor_parse_dimension ("3:4:2:1", config.info.info[0].dimension);
+  config.info.info[1].type = _NNS_INT32;
+  gst_tensor_parse_dimension ("3:4:2:1", config.info.info[1].dimension);
+  config.info.info[2].type = _NNS_INT32;
+  gst_tensor_parse_dimension ("3:4:2:1", config.info.info[2].dimension);
+  config.info.info[3].type = _NNS_INT32;
+  gst_tensor_parse_dimension ("3:4:2:1", config.info.info[3].dimension);
+
+  data_size = gst_tensors_info_get_size (&config.info, -1);
+
+  /* push buffers */
+  in_buf = gst_harness_create_buffer (h, data_size);
+
+  mem = gst_buffer_peek_memory (in_buf, 0);
+  ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_WRITE));
+
+  memcpy (info.data, aggr_test_frames, data_size);
+
+  gst_memory_unmap (mem, &info);
+
+  EXPECT_EQ (gst_harness_push (h, in_buf), GST_FLOW_OK);
+
+  /* get output buffer */
+  out_buf = gst_harness_pull (h);
+
+  ASSERT_TRUE (out_buf != NULL);
+  ASSERT_EQ (gst_buffer_n_memory (out_buf), 4U);
+  ASSERT_EQ (gst_buffer_get_size (out_buf), data_size);
+
+  /* 1st tensor */
+  mem = gst_buffer_peek_memory (out_buf, 0);
+  ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_READ));
+  for (i = 0; i < 24; i++)
+    EXPECT_EQ (((gint *) info.data)[i], aggr_test_frames[0][i]);
+  gst_memory_unmap (mem, &info);
+
+  /* 2nd tensor */
+  mem = gst_buffer_peek_memory (out_buf, 1);
+  ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_READ));
+  for (i = 24; i < 48; i++)
+    EXPECT_EQ (((gint *) info.data)[i - 24], aggr_test_frames[0][i]);
+  gst_memory_unmap (mem, &info);
+
+  /* 3rd tensor */
+  mem = gst_buffer_peek_memory (out_buf, 2);
+  ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_READ));
+  for (i = 0; i < 24; i++)
+    EXPECT_EQ (((gint *) info.data)[i], aggr_test_frames[1][i]);
+  gst_memory_unmap (mem, &info);
+
+  /* 4th tensor */
+  mem = gst_buffer_peek_memory (out_buf, 3);
+  ASSERT_TRUE (gst_memory_map (mem, &info, GST_MAP_READ));
+  for (i = 24; i < 48; i++)
+    EXPECT_EQ (((gint *) info.data)[i - 24], aggr_test_frames[1][i]);
+  gst_memory_unmap (mem, &info);
+
+  gst_buffer_unref (out_buf);
+
+  EXPECT_EQ (gst_harness_buffers_received (h), 1U);
+  gst_harness_teardown (h);
+}
+
+/**
+ * @brief Test for tensor_converter (bytes to multi tensors)
+ */
+TEST (test_tensor_converter, bytes_to_multi_invalid_dim_01_n)
+{
+  GstHarness *h;
+  GstBuffer *in_buf;
+  GstTensorsConfig config;
+  GstCaps *caps;
+  gsize data_size;
+
+  h = gst_harness_new ("tensor_converter");
+
+  g_object_set (h->element, "input-dim", "2:2:2:2",
+      "input-type", "int32,uint64", NULL);
+
+  /* in/out caps and tensors info */
+  caps = gst_caps_from_string ("application/octet-stream");
+  gst_harness_set_src_caps (h, caps);
+
+  gst_tensors_config_init (&config);
+  config.rate_n = 0;
+  config.rate_d = 1;
+  config.info.num_tensors = 2;
+
+  config.info.info[0].type = _NNS_INT32;
+  gst_tensor_parse_dimension ("2:2:2:2", config.info.info[0].dimension);
+  config.info.info[1].type = _NNS_UINT64;
+  gst_tensor_parse_dimension ("2:2:2:2", config.info.info[1].dimension);
+
+  data_size = gst_tensors_info_get_size (&config.info, -1);
+
+  /* push buffers */
+  in_buf = gst_harness_create_buffer (h, data_size);
+  EXPECT_DEATH (gst_harness_push (h, in_buf), "");
+
+  EXPECT_EQ (gst_harness_buffers_received (h), 0U);
+  gst_harness_teardown (h);
+}
+
+/**
+ * @brief Test for tensor_converter (bytes to multi tensors)
+ */
+TEST (test_tensor_converter, bytes_to_multi_invalid_dim_02_n)
+{
+  GstHarness *h;
+  GstBuffer *in_buf;
+  GstTensorsConfig config;
+  GstCaps *caps;
+  gsize data_size;
+
+  h = gst_harness_new ("tensor_converter");
+
+  g_object_set (h->element, "input-dim", "2:2:2:2,2:0:1",
+      "input-type", "int32,float32", NULL);
+
+  /* in/out caps and tensors info */
+  caps = gst_caps_from_string ("application/octet-stream");
+  gst_harness_set_src_caps (h, caps);
+
+  gst_tensors_config_init (&config);
+  config.rate_n = 0;
+  config.rate_d = 1;
+  config.info.num_tensors = 2;
+
+  config.info.info[0].type = _NNS_INT32;
+  gst_tensor_parse_dimension ("2:2:2:2", config.info.info[0].dimension);
+  config.info.info[1].type = _NNS_FLOAT32;
+  gst_tensor_parse_dimension ("2:2:1:1", config.info.info[1].dimension);
+
+  data_size = gst_tensors_info_get_size (&config.info, -1);
+
+  /* push buffers */
+  in_buf = gst_harness_create_buffer (h, data_size);
+  EXPECT_DEATH (gst_harness_push (h, in_buf), "");
+
+  EXPECT_EQ (gst_harness_buffers_received (h), 0U);
+  gst_harness_teardown (h);
+}
+
+/**
+ * @brief Test for tensor_converter (bytes to multi tensors)
+ */
+TEST (test_tensor_converter, bytes_to_multi_invalid_type_01_n)
+{
+  GstHarness *h;
+  GstBuffer *in_buf;
+  GstTensorsConfig config;
+  GstCaps *caps;
+  gsize data_size;
+
+  h = gst_harness_new ("tensor_converter");
+
+  g_object_set (h->element, "input-type", "int64",
+      "input-dim", "2:2:2:2,2:2:2:2", NULL);
+
+  /* in/out caps and tensors info */
+  caps = gst_caps_from_string ("application/octet-stream");
+  gst_harness_set_src_caps (h, caps);
+
+  gst_tensors_config_init (&config);
+  config.rate_n = 0;
+  config.rate_d = 1;
+  config.info.num_tensors = 2;
+
+  config.info.info[0].type = _NNS_INT64;
+  gst_tensor_parse_dimension ("2:2:2:2", config.info.info[0].dimension);
+  config.info.info[1].type = _NNS_UINT64;
+  gst_tensor_parse_dimension ("2:2:2:2", config.info.info[1].dimension);
+
+  data_size = gst_tensors_info_get_size (&config.info, -1);
+
+  /* push buffers */
+  in_buf = gst_harness_create_buffer (h, data_size);
+  EXPECT_DEATH (gst_harness_push (h, in_buf), "");
+
+  EXPECT_EQ (gst_harness_buffers_received (h), 0U);
+  gst_harness_teardown (h);
+}
+
+/**
+ * @brief Test for tensor_converter (bytes to multi tensors)
+ */
+TEST (test_tensor_converter, bytes_to_multi_invalid_type_02_n)
+{
+  GstHarness *h;
+  GstBuffer *in_buf;
+  GstTensorsConfig config;
+  GstCaps *caps;
+  gsize data_size;
+
+  h = gst_harness_new ("tensor_converter");
+
+  g_object_set (h->element, "input-dim", "2:2:2:2,2:2:1:1",
+      "input-type", "int16,invalid", NULL);
+
+  /* in/out caps and tensors info */
+  caps = gst_caps_from_string ("application/octet-stream");
+  gst_harness_set_src_caps (h, caps);
+
+  gst_tensors_config_init (&config);
+  config.rate_n = 0;
+  config.rate_d = 1;
+  config.info.num_tensors = 2;
+
+  config.info.info[0].type = _NNS_INT16;
+  gst_tensor_parse_dimension ("2:2:2:2", config.info.info[0].dimension);
+  config.info.info[1].type = _NNS_INT16;
+  gst_tensor_parse_dimension ("2:2:1:1", config.info.info[1].dimension);
+
+  data_size = gst_tensors_info_get_size (&config.info, -1);
+
+  /* push buffers */
+  in_buf = gst_harness_create_buffer (h, data_size);
+  EXPECT_DEATH (gst_harness_push (h, in_buf), "");
+
+  EXPECT_EQ (gst_harness_buffers_received (h), 0U);
+  gst_harness_teardown (h);
+}
+
+/**
+ * @brief Test for tensor_converter (bytes to multi tensors)
+ */
+TEST (test_tensor_converter, bytes_to_multi_invalid_type_03_n)
+{
+  GstHarness *h;
+  GstBuffer *in_buf;
+  GstTensorsConfig config;
+  GstCaps *caps;
+  gsize data_size;
+
+  h = gst_harness_new ("tensor_converter");
+
+  g_object_set (h->element, "input-dim", "1:1:1:1,2:1:1:1,3",
+      "input-type", "int16,uint16", NULL);
+
+  /* in/out caps and tensors info */
+  caps = gst_caps_from_string ("application/octet-stream");
+  gst_harness_set_src_caps (h, caps);
+
+  gst_tensors_config_init (&config);
+  config.rate_n = 0;
+  config.rate_d = 1;
+  config.info.num_tensors = 3;
+
+  config.info.info[0].type = _NNS_INT16;
+  gst_tensor_parse_dimension ("1:1:1:1", config.info.info[0].dimension);
+  config.info.info[1].type = _NNS_UINT16;
+  gst_tensor_parse_dimension ("2:1:1:1", config.info.info[1].dimension);
+  config.info.info[1].type = _NNS_UINT8;
+  gst_tensor_parse_dimension ("3:1:1:1", config.info.info[1].dimension);
+
+  data_size = gst_tensors_info_get_size (&config.info, -1);
+
+  /* push buffers */
+  in_buf = gst_harness_create_buffer (h, data_size);
+  EXPECT_DEATH (gst_harness_push (h, in_buf), "");
+
+  EXPECT_EQ (gst_harness_buffers_received (h), 0U);
+  gst_harness_teardown (h);
+}
+
+/**
+ * @brief Test for tensor_converter (bytes to multi tensors)
+ */
+TEST (test_tensor_converter, bytes_to_multi_invalid_size_n)
+{
+  GstHarness *h;
+  GstBuffer *in_buf;
+  GstTensorsConfig config;
+  GstCaps *caps;
+  gsize data_size;
+
+  h = gst_harness_new ("tensor_converter");
+
+  g_object_set (h->element, "input-dim", "2:2:2:2,1:1:1:1",
+      "input-type", "float32,float64", NULL);
+
+  /* in/out caps and tensors info */
+  caps = gst_caps_from_string ("application/octet-stream");
+  gst_harness_set_src_caps (h, caps);
+
+  gst_tensors_config_init (&config);
+  config.rate_n = 0;
+  config.rate_d = 1;
+  config.info.num_tensors = 2;
+
+  config.info.info[0].type = _NNS_FLOAT32;
+  gst_tensor_parse_dimension ("2:2:2:2", config.info.info[0].dimension);
+  config.info.info[1].type = _NNS_FLOAT64;
+  gst_tensor_parse_dimension ("2:2:1:1", config.info.info[1].dimension);
+
+  data_size = gst_tensors_info_get_size (&config.info, -1);
+
+  /* push buffers */
+  in_buf = gst_harness_create_buffer (h, data_size);
+  EXPECT_DEATH (gst_harness_push (h, in_buf), "");
+
+  EXPECT_EQ (gst_harness_buffers_received (h), 0U);
+  gst_harness_teardown (h);
+}
+
+/**
+ * @brief Test for tensor_converter (bytes to multi tensors)
+ */
+TEST (test_tensor_converter, bytes_to_multi_invalid_frames_n)
+{
+  GstHarness *h;
+  GstBuffer *in_buf;
+  GstTensorsConfig config;
+  GstCaps *caps;
+  gsize data_size;
+
+  h = gst_harness_new ("tensor_converter");
+
+  g_object_set (h->element, "input-dim", "2:2:2:2,1:1:1:1",
+      "input-type", "float32,float64", "frames-per-tensor", "2", NULL);
+
+  /* in/out caps and tensors info */
+  caps = gst_caps_from_string ("application/octet-stream");
+  gst_harness_set_src_caps (h, caps);
+
+  gst_tensors_config_init (&config);
+  config.rate_n = 0;
+  config.rate_d = 1;
+  config.info.num_tensors = 2;
+
+  config.info.info[0].type = _NNS_FLOAT32;
+  gst_tensor_parse_dimension ("2:2:2:2", config.info.info[0].dimension);
+  config.info.info[1].type = _NNS_FLOAT64;
+  gst_tensor_parse_dimension ("1:1:1:1", config.info.info[1].dimension);
+
+  data_size = gst_tensors_info_get_size (&config.info, -1);
+
+  /* push buffers */
+  in_buf = gst_harness_create_buffer (h, data_size);
+  EXPECT_DEATH (gst_harness_push (h, in_buf), "");
+
+  EXPECT_EQ (gst_harness_buffers_received (h), 0U);
+  gst_harness_teardown (h);
+}
+
 #ifdef HAVE_ORC
 #include "transform-orc.h"
 
index 830b667..8ada9f0 100644 (file)
@@ -93,6 +93,7 @@ typedef enum
   TEST_TYPE_OCTET_VALID_TS, /**< pipeline for octet stream, valid timestamp */
   TEST_TYPE_OCTET_INVALID_TS, /**< pipeline for octet stream, invalid timestamp */
   TEST_TYPE_OCTET_2F, /**< pipeline for octet stream, 2 frames */
+  TEST_TYPE_OCTET_MULTI_TENSORS, /**< pipeline for octet stream, byte array to multi tensors */
   TEST_TYPE_TENSORS, /**< pipeline for tensors with tensor_mux */
   TEST_TYPE_TENSORS_MIX_1, /**< pipeline for tensors with tensor_mux, tensor_demux */
   TEST_TYPE_TENSORS_MIX_2, /**< pipeline for tensors with tensor_mux, tensor_demux pick 0,2 */
@@ -714,6 +715,13 @@ _setup_pipeline (TestOption & option)
           ("appsrc name=appsrc caps=application/octet-stream,framerate=(fraction)10/1 ! "
           "tensor_converter name=convert input-dim=1:5 input-type=int8 ! tensor_sink name=test_sink");
       break;
+    case TEST_TYPE_OCTET_MULTI_TENSORS:
+      /** byte stream, byte array to multi tensors */
+      str_pipeline =
+          g_strdup_printf
+          ("appsrc name=appsrc caps=application/octet-stream,framerate=(fraction)10/1 ! "
+          "tensor_converter name=convert input-dim=2,2 input-type=int32,int8 ! tensor_sink name=test_sink");
+      break;
     case TEST_TYPE_TENSORS:
       /** other/tensors with tensor_mux */
       str_pipeline =
@@ -2939,6 +2947,85 @@ TEST (tensor_stream_test, octet_2f)
 }
 
 /**
+ * @brief Test for octet stream.
+ */
+TEST (tensor_stream_test, octet_multi_tensors)
+{
+  const guint num_buffers = 10;
+  TestOption option = { num_buffers, TEST_TYPE_OCTET_MULTI_TENSORS };
+  GstElement *convert;
+  gchar *prop_str;
+  guint prop_uint;
+  guint timeout_id;
+
+  ASSERT_TRUE (_setup_pipeline (option));
+
+  /* tensor_converter properties */
+  convert = gst_bin_get_by_name (GST_BIN (g_test_data.pipeline), "convert");
+  ASSERT_TRUE (convert != NULL);
+
+  g_object_get (convert, "input-dim", &prop_str, NULL);
+  EXPECT_STREQ (prop_str, "2:1:1:1,2:1:1:1");
+  g_free (prop_str);
+
+  g_object_get (convert, "input-type", &prop_str, NULL);
+  EXPECT_STREQ (prop_str, "int32,int8");
+  g_free (prop_str);
+
+  g_object_get (convert, "frames-per-tensor", &prop_uint, NULL);
+  EXPECT_EQ (prop_uint, 1U);
+
+  gst_object_unref (convert);
+
+  gst_element_set_state (g_test_data.pipeline, GST_STATE_PLAYING);
+
+  g_timeout_add (100, _test_src_push_timer_cb, GINT_TO_POINTER (TRUE));
+
+  timeout_id = g_timeout_add (5000, _test_src_eos_timer_cb, g_test_data.loop);
+  g_main_loop_run (g_test_data.loop);
+  g_source_remove (timeout_id);
+
+  EXPECT_TRUE (_wait_pipeline_process_buffers (num_buffers));
+  gst_element_set_state (g_test_data.pipeline, GST_STATE_NULL);
+
+  /** check eos message */
+  EXPECT_EQ (g_test_data.status, TEST_EOS);
+
+  /** check received buffers */
+  EXPECT_EQ (g_test_data.received, num_buffers);
+  EXPECT_EQ (g_test_data.mem_blocks, 2U);
+  EXPECT_EQ (g_test_data.received_size, 10U);
+
+  /** check caps name */
+  EXPECT_STREQ (g_test_data.caps_name, "other/tensors");
+
+  /** check timestamp */
+  EXPECT_FALSE (g_test_data.invalid_timestamp);
+
+  /** check tensor config for multi tensors */
+  EXPECT_TRUE (gst_tensors_config_validate (&g_test_data.tensors_config));
+  EXPECT_EQ (g_test_data.tensors_config.info.num_tensors, 2U);
+
+  EXPECT_EQ (g_test_data.tensors_config.info.info[0].type, _NNS_INT32);
+  EXPECT_EQ (g_test_data.tensors_config.info.info[0].dimension[0], 2U);
+  EXPECT_EQ (g_test_data.tensors_config.info.info[0].dimension[1], 1U);
+  EXPECT_EQ (g_test_data.tensors_config.info.info[0].dimension[2], 1U);
+  EXPECT_EQ (g_test_data.tensors_config.info.info[0].dimension[3], 1U);
+
+  EXPECT_EQ (g_test_data.tensors_config.info.info[1].type, _NNS_INT8);
+  EXPECT_EQ (g_test_data.tensors_config.info.info[1].dimension[0], 2U);
+  EXPECT_EQ (g_test_data.tensors_config.info.info[1].dimension[1], 1U);
+  EXPECT_EQ (g_test_data.tensors_config.info.info[1].dimension[2], 1U);
+  EXPECT_EQ (g_test_data.tensors_config.info.info[1].dimension[3], 1U);
+
+  EXPECT_EQ (g_test_data.tensors_config.rate_n, 10);
+  EXPECT_EQ (g_test_data.tensors_config.rate_d, 1);
+
+  EXPECT_FALSE (g_test_data.test_failed);
+  _free_test_data ();
+}
+
+/**
  * @brief Test for other/tensor, passthrough custom filter.
  */
 TEST (tensor_stream_test, custom_filter_tensor)