From 474103f91afeccf13f0e0a8d995d9dfdfd8305ee Mon Sep 17 00:00:00 2001 From: Jaeyun Date: Thu, 20 Sep 2018 16:40:05 +0900 Subject: [PATCH] [Example/CustomFilter/Test] change custom passthrough filter 1. change custom passthrough example to support multi tensors 2. add simple stream testcases for multi tensors Signed-off-by: Jaeyun Jung --- ...mer_customfilter_example_passthrough_variable.c | 25 ++-- tests/nnstreamer_filter_custom/runTest.sh | 9 +- tests/nnstreamer_sink/unittest_sink.cpp | 159 +++++++++++++++++++-- 3 files changed, 174 insertions(+), 19 deletions(-) diff --git a/nnstreamer_example/custom_example_passthrough/nnstreamer_customfilter_example_passthrough_variable.c b/nnstreamer_example/custom_example_passthrough/nnstreamer_customfilter_example_passthrough_variable.c index c4afd25..febb352 100644 --- a/nnstreamer_example/custom_example_passthrough/nnstreamer_customfilter_example_passthrough_variable.c +++ b/nnstreamer_example/custom_example_passthrough/nnstreamer_customfilter_example_passthrough_variable.c @@ -32,6 +32,7 @@ static void * pt_init (const GstTensorFilterProperties * prop) { pt_data *data = (pt_data *) malloc (sizeof (pt_data)); + g_assert (data); data->id = 0; return data; @@ -55,17 +56,20 @@ static int set_inputDim (void *private_data, const GstTensorFilterProperties * prop, const GstTensorsInfo * in_info, GstTensorsInfo * out_info) { - int i; + int i, t; g_assert (in_info); g_assert (out_info); - out_info->num_tensors = 1; + out_info->num_tensors = in_info->num_tensors; - for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++) - out_info->info[0].dimension[i] = in_info->info[0].dimension[i]; + for (t = 0; t < in_info->num_tensors; t++) { + for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++) { + out_info->info[t].dimension[i] = in_info->info[t].dimension[i]; + } - out_info->info[0].type = in_info->info[0].type; + out_info->info[t].type = in_info->info[t].type; + } return 0; } @@ -79,16 +83,19 @@ pt_invoke (void *private_data, const GstTensorFilterProperties * prop, { pt_data *data = private_data; size_t size; + int t; g_assert (data); g_assert (input); g_assert (output); - size = get_tensor_element_count (prop->output_meta.info[0].dimension) * - tensor_element_size[prop->output_meta.info[0].type]; + for (t = 0; t < prop->output_meta.num_tensors; t++) { + size = get_tensor_element_count (prop->output_meta.info[t].dimension) * + tensor_element_size[prop->output_meta.info[t].type]; - g_assert (input[0].data != output[0].data); - memcpy (output[0].data, input[0].data, size); + g_assert (input[t].data != output[t].data); + memcpy (output[t].data, input[t].data, size); + } return 0; } diff --git a/tests/nnstreamer_filter_custom/runTest.sh b/tests/nnstreamer_filter_custom/runTest.sh index 055fbf1..4a42bf2 100755 --- a/tests/nnstreamer_filter_custom/runTest.sh +++ b/tests/nnstreamer_filter_custom/runTest.sh @@ -35,10 +35,15 @@ gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} videotestsrc num-buffers=1 ! video/ compareAll testcase03.direct.log testcase03.passthrough.log 3 -gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} videotestsrc num-buffers=1 ! video/x-raw,format=RGB,width=640,height=480,framerate=0/1 ! videoconvert ! video/x-raw, format=RGB ! tensor_converter ! tee name=t ! queue ! tensor_filter framework=\"custom\" model=\"${PATH_TO_MODEL_V}\" ! filesink location=\"testcase04.passthrough.log\" sync=true t. ! queue ! filesink location=\"testcase04.direct.log\" sync=true" 4 +# Test single tensor (other/tensor) +gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} videotestsrc num-buffers=1 ! video/x-raw,format=RGB,width=640,height=480,framerate=0/1 ! videoconvert ! video/x-raw, format=RGB ! tensor_converter ! tee name=t ! queue ! tensor_filter framework=\"custom\" model=\"${PATH_TO_MODEL_V}\" ! filesink location=\"testcase04.tensor.passthrough.log\" sync=true t. ! queue ! filesink location=\"testcase04.tensor.direct.log\" sync=true" 4-1 -compareAll testcase04.direct.log testcase04.passthrough.log 4 +compareAll testcase04.tensor.direct.log testcase04.tensor.passthrough.log 4-2 +# Test multi tensors with mux (other/tensors) +gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} tensor_mux name=mux ! tee name=t ! queue ! tensor_filter framework=\"custom\" model=\"${PATH_TO_MODEL_V}\" ! filesink location=\"testcase04.tensors.passthrough.log\" sync=true t. ! queue ! filesink location=\"testcase04.tensors.direct.log\" sync=true videotestsrc num-buffers=1 ! video/x-raw,format=RGB,width=160,height=120,framerate=0/1 ! tensor_converter ! mux.sink_0 videotestsrc num-buffers=1 ! video/x-raw,format=RGB,width=120,height=80,framerate=0/1 ! tensor_converter ! mux.sink_1 videotestsrc num-buffers=1 ! video/x-raw,format=RGB,width=64,height=48,framerate=0/1 ! tensor_converter ! mux.sink_2" 4-3 + +compareAll testcase04.tensors.direct.log testcase04.tensors.passthrough.log 4-4 # Test scaler (5, 6, 7) PATH_TO_MODEL_S="../../build/nnstreamer_example/custom_example_scaler/libnnstreamer_customfilter_scaler.so" diff --git a/tests/nnstreamer_sink/unittest_sink.cpp b/tests/nnstreamer_sink/unittest_sink.cpp index 471cfbd..f2a6f4a 100644 --- a/tests/nnstreamer_sink/unittest_sink.cpp +++ b/tests/nnstreamer_sink/unittest_sink.cpp @@ -67,11 +67,13 @@ typedef enum TEST_TYPE_TEXT, /**< pipeline for text */ TEST_TYPE_TEXT_3F, /**< pipeline for text 3 frames */ TEST_TYPE_TENSORS, /**< pipeline for tensors with tensor_mux */ + TEST_TYPE_CUSTOM_TENSOR, /**< pipeline for single tensor with passthrough custom filter */ + TEST_TYPE_CUSTOM_TENSORS, /**< pipeline for tensors with passthrough custom filter */ TEST_TYPE_NEGO_FAILED, /**< pipeline to test caps negotiation */ - TEST_TYPE_VIDEO_RGB_AGGR, /**< pipeline to test tensor-aggregator */ - TEST_TYPE_AUDIO_S16_AGGR, /**< pipeline to test tensor-aggregator */ - TEST_TYPE_AUDIO_U16_AGGR, /**< pipeline to test tensor-aggregator */ - TEST_TYPE_TYPECAST, /**< pipeline for typecast with tensor-transform */ + TEST_TYPE_VIDEO_RGB_AGGR, /**< pipeline to test tensor_aggregator */ + TEST_TYPE_AUDIO_S16_AGGR, /**< pipeline to test tensor_aggregator */ + TEST_TYPE_AUDIO_U16_AGGR, /**< pipeline to test tensor_aggregator */ + TEST_TYPE_TYPECAST, /**< pipeline for typecast with tensor_transform */ TEST_TYPE_UNKNOWN /**< unknonwn */ } TestType; @@ -187,7 +189,7 @@ _new_data_cb (GstElement * element, GstBuffer * buffer, gpointer user_data) } if (g_test_data.received_size != buf_size) { - _print_log ("invalid size, old[%d] new[%d]", g_test_data.received_size, + _print_log ("invalid size, old[%zd] new[%zd]", g_test_data.received_size, buf_size); g_assert (0); } @@ -442,9 +444,27 @@ _setup_pipeline (TestOption & option) g_strdup_printf ("tensor_mux name=mux ! tensor_sink name=test_sink " "videotestsrc num-buffers=%d ! video/x-raw,width=160,height=120,format=RGB,framerate=(fraction)30/1 ! tensor_converter ! mux.sink_0 " - "videotestsrc num-buffers=%d ! video/x-raw,width=160,height=120,format=RGB,framerate=(fraction)30/1 ! tensor_converter ! mux.sink_1 ", + "videotestsrc num-buffers=%d ! video/x-raw,width=160,height=120,format=RGB,framerate=(fraction)30/1 ! tensor_converter ! mux.sink_1", option.num_buffers, option.num_buffers); break; + case TEST_TYPE_CUSTOM_TENSOR: + /** video 160x120 RGB, passthrough custom filter */ + str_pipeline = + g_strdup_printf + ("videotestsrc num-buffers=%d ! videoconvert ! video/x-raw,width=160,height=120,format=RGB,framerate=(fraction)30/1 ! " + "tensor_converter ! tensor_filter framework=custom model=./nnstreamer_example/custom_example_passthrough/libnnstreamer_customfilter_passthrough_variable.so ! tensor_sink name=test_sink", + option.num_buffers); + break; + case TEST_TYPE_CUSTOM_TENSORS: + /** other/tensors with tensormux, passthrough custom filter */ + str_pipeline = + g_strdup_printf + ("tensor_mux name=mux ! tensor_filter framework=custom model=./nnstreamer_example/custom_example_passthrough/libnnstreamer_customfilter_passthrough_variable.so ! tensor_sink name=test_sink " + "videotestsrc num-buffers=%d ! video/x-raw,width=160,height=120,format=RGB,framerate=(fraction)30/1 ! tensor_converter ! mux.sink_0 " + "videotestsrc num-buffers=%d ! video/x-raw,width=120,height=80,format=RGB,framerate=(fraction)30/1 ! tensor_converter ! mux.sink_1 " + "videotestsrc num-buffers=%d ! video/x-raw,width=64,height=48,format=RGB,framerate=(fraction)30/1 ! tensor_converter ! mux.sink_2", + option.num_buffers, option.num_buffers, option.num_buffers); + break; case TEST_TYPE_NEGO_FAILED: /** caps negotiation failed */ str_pipeline = @@ -734,7 +754,7 @@ TEST (tensor_sink_test, caps_tensors) /** check received buffers */ EXPECT_EQ (g_test_data.received, num_buffers); EXPECT_EQ (g_test_data.mem_blocks, 2); - EXPECT_EQ (g_test_data.received_size, 115200); + EXPECT_EQ (g_test_data.received_size, 115200); /** 160 * 120 * 3 * 2 */ /** check caps name */ EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensors")); @@ -1118,7 +1138,7 @@ TEST (tensor_stream_test, audio_s8) /** * @brief Test for audio format U8, 100 frames from tensor_converter. */ -TEST (tensor_stream_test, audio_u8_100F) +TEST (tensor_stream_test, audio_u8_100f) { const guint num_buffers = 5; /** 5 * 500 frames */ TestOption option = { num_buffers, TEST_TYPE_AUDIO_U8_100F }; @@ -1314,6 +1334,129 @@ TEST (tensor_stream_test, text_utf8_3f) } /** + * @brief Test for other/tensor, passthrough custom filter. + */ +TEST (tensor_stream_test, custom_filter_tensor) +{ + const guint num_buffers = 5; + TestOption option = { num_buffers, TEST_TYPE_CUSTOM_TENSOR }; + + ASSERT_TRUE (_setup_pipeline (option)); + + gst_element_set_state (g_test_data.pipeline, GST_STATE_PLAYING); + g_main_loop_run (g_test_data.loop); + 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, 1); + EXPECT_EQ (g_test_data.received_size, 57600); + + /** check caps name */ + EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor")); + + /** check tensor config for video */ + EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config)); + EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_UINT8); + EXPECT_EQ (g_test_data.tensor_config.info.dimension[0], 3); + EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 160); + EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 120); + EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1); + EXPECT_EQ (g_test_data.tensor_config.rate_n, 30); + EXPECT_EQ (g_test_data.tensor_config.rate_d, 1); + + /** check caps and config for tensor */ + { + GstCaps *caps; + GstStructure *structure; + GstTensorConfig config; + + caps = gst_tensor_caps_from_config (&g_test_data.tensor_config); + structure = gst_caps_get_structure (caps, 0); + + EXPECT_TRUE (gst_tensor_config_from_structure (&config, structure)); + EXPECT_TRUE (gst_tensor_config_is_equal (&config, + &g_test_data.tensor_config)); + + gst_caps_unref (caps); + } + + _free_test_data (); +} + +/** + * @brief Test for other/tensors, passthrough custom filter. + */ +TEST (tensor_stream_test, custom_filter_tensors) +{ + const guint num_buffers = 5; + TestOption option = { num_buffers, TEST_TYPE_CUSTOM_TENSORS }; + + ASSERT_TRUE (_setup_pipeline (option)); + + gst_element_set_state (g_test_data.pipeline, GST_STATE_PLAYING); + g_main_loop_run (g_test_data.loop); + 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, 3); + EXPECT_EQ (g_test_data.received_size, 95616); /** 160 * 120 * 3 + 120 * 80 * 3 + 64 * 48 * 3 */ + + /** check caps name */ + EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensors")); + + /** check tensors config for video */ + EXPECT_TRUE (gst_tensors_config_validate (&g_test_data.tensors_config)); + EXPECT_EQ (g_test_data.tensors_config.info.num_tensors, 3); + + EXPECT_EQ (g_test_data.tensors_config.info.info[0].type, _NNS_UINT8); + EXPECT_EQ (g_test_data.tensors_config.info.info[0].dimension[0], 3); + EXPECT_EQ (g_test_data.tensors_config.info.info[0].dimension[1], 160); + EXPECT_EQ (g_test_data.tensors_config.info.info[0].dimension[2], 120); + EXPECT_EQ (g_test_data.tensors_config.info.info[0].dimension[3], 1); + + EXPECT_EQ (g_test_data.tensors_config.info.info[1].type, _NNS_UINT8); + EXPECT_EQ (g_test_data.tensors_config.info.info[1].dimension[0], 3); + EXPECT_EQ (g_test_data.tensors_config.info.info[1].dimension[1], 120); + EXPECT_EQ (g_test_data.tensors_config.info.info[1].dimension[2], 80); + EXPECT_EQ (g_test_data.tensors_config.info.info[1].dimension[3], 1); + + EXPECT_EQ (g_test_data.tensors_config.info.info[2].type, _NNS_UINT8); + EXPECT_EQ (g_test_data.tensors_config.info.info[2].dimension[0], 3); + EXPECT_EQ (g_test_data.tensors_config.info.info[2].dimension[1], 64); + EXPECT_EQ (g_test_data.tensors_config.info.info[2].dimension[2], 48); + EXPECT_EQ (g_test_data.tensors_config.info.info[2].dimension[3], 1); + + EXPECT_EQ (g_test_data.tensors_config.rate_n, 30); + EXPECT_EQ (g_test_data.tensors_config.rate_d, 1); + + /** check caps and config for tensors */ + { + GstCaps *caps; + GstStructure *structure; + GstTensorsConfig config; + + caps = gst_tensors_caps_from_config (&g_test_data.tensors_config); + structure = gst_caps_get_structure (caps, 0); + + EXPECT_TRUE (gst_tensors_config_from_structure (&config, structure)); + EXPECT_TRUE (gst_tensors_config_is_equal (&config, + &g_test_data.tensors_config)); + + gst_caps_unref (caps); + } + + _free_test_data (); +} + +/** * @brief Test for typecast to int32 using tensor_transform. */ TEST (tensor_stream_test, typecast_int32) -- 2.7.4