[TensorMerge] Add Proper GstMemory Generation according to direction
authorjijoong.moon <jijoong.moon@samsung.com>
Mon, 15 Oct 2018 01:12:13 +0000 (10:12 +0900)
committerMyungJoo Ham <myungjoo.ham@gmail.com>
Wed, 17 Oct 2018 13:10:24 +0000 (22:10 +0900)
Add gst_tensor_merge_generate_mem function to generate output
GstMemory to push.
Now support linear mode and channel, width, height option.

Assume tensor a is aC:aW:aH:aB and b is bC:bW:bH:bB.
if the mode is linear and channel option,
the output tensor is generated by
  aC+bC:aW:aH:aB ( should be aH==bH, aW==bW and a.type==b.type ).
  That means,

   [[aB][aH][aW][aC,bC]]

if linear and width option,
  aC:aW+bW:aH,aB ( should be aC==bC, aH==bH and a.type==b.type ).

  [[aB][aH][aW,bW][aC]]

if linear and height option
  aC:aW:aH+bH,aB (should be aC==bC, aW==bW and a.type==b.type ).

  [[aB][aH,bH][aW][aC]]

Signed-off-by: jijoong.moon <jijoong.moon@samsung.com>
gst/tensor_merge/gsttensormerge.c
gst/tensor_merge/gsttensormerge.h
tests/nnstreamer_merge/generateTest.py [new file with mode: 0755]
tests/nnstreamer_merge/runTest.sh

index fbb3c2c..4c14183 100644 (file)
@@ -196,9 +196,10 @@ static const gchar *gst_tensor_merge_mode_string[] = {
 };
 
 static const gchar *gst_tensor_merge_linear_string[] = {
-  [LINEAR_WIDTH] = "width",
-  [LINEAR_HEIGHT] = "height",
-  [LINEAR_CHANNEL] = "channel",
+  [LINEAR_FIRST] = "0",
+  [LINEAR_SECOND] = "1",
+  [LINEAR_THIRD] = "2",
+  [LINEAR_FOURTH] = "3",
   [LINEAR_END] = NULL,
 };
 
@@ -371,52 +372,37 @@ gst_merge_tensors_config (GstTensorMerge * tensor_merge,
     GstTensorsConfig * configs, GstTensorConfig * config)
 {
   gboolean ret = FALSE;
+  int i, j;
+  tensor_dim dim;
+  tensor_type type;
+  type = configs->info.info[0].type;
+  memcpy (&dim, &configs->info.info[0].dimension, sizeof (tensor_dim));
+
+  for (i = 1; i < configs->info.num_tensors; i++) {
+    if (type != configs->info.info[i].type)
+      GST_ELEMENT_ERROR (tensor_merge, CORE, NEGOTIATION, (NULL), (NULL));
+  }
+
   switch (tensor_merge->mode) {
     case GTT_LINEAR:
     {
-      switch (tensor_merge->data_linear.direction) {
-          /* TODO : Currently we merge channel only. Have to extend W,H direction */
-        case LINEAR_CHANNEL:
-        {
-          int i, width, height, channel, batch;
-          tensor_type type;
-          type = configs->info.info[0].type;
-          batch = configs->info.info[0].dimension[3];
-          width = configs->info.info[0].dimension[1];
-          height = configs->info.info[0].dimension[2];
-          channel = configs->info.info[0].dimension[0];
-
-          for (i = 1; i < configs->info.num_tensors; i++) {
-            if (type != configs->info.info[i].type)
-              GST_ELEMENT_ERROR (tensor_merge, CORE, NEGOTIATION, (NULL),
-                  (NULL));
-            if (batch != configs->info.info[i].dimension[3])
-              GST_ELEMENT_ERROR (tensor_merge, CORE, NEGOTIATION, (NULL),
-                  (NULL));
-            if (width != configs->info.info[i].dimension[1])
-              GST_ELEMENT_ERROR (tensor_merge, CORE, NEGOTIATION, (NULL),
-                  (NULL));
-            if (height != configs->info.info[i].dimension[2])
+      int targetIdx = tensor_merge->data_linear.direction;
+      for (i = 1; i < configs->info.num_tensors; i++) {
+        for (j = 0; j < NNS_TENSOR_RANK_LIMIT; j++) {
+          if (j == targetIdx) {
+            dim[j] += configs->info.info[i].dimension[j];
+          } else {
+            if (dim[j] != configs->info.info[i].dimension[j])
               GST_ELEMENT_ERROR (tensor_merge, CORE, NEGOTIATION, (NULL),
                   (NULL));
-            channel += configs->info.info[i].dimension[0];
           }
-
-          config->info.type = type;
-          config->info.dimension[0] = width;
-          config->info.dimension[1] = height;
-          config->info.dimension[2] = channel;
-          config->info.dimension[3] = batch;
-          config->rate_d = configs->rate_d;
-          config->rate_n = configs->rate_n;
         }
-          ret = TRUE;
-          break;
-        case LINEAR_WIDTH:
-        case LINEAR_HEIGHT:
-        default:
-          ret = FALSE;
       }
+      config->info.type = type;
+      memcpy (&config->info.dimension, &dim, sizeof (tensor_dim));
+      config->rate_d = configs->rate_d;
+      config->rate_n = configs->rate_n;
+      ret = TRUE;
     }
       break;
     default:
@@ -472,16 +458,18 @@ gst_tensor_merge_collect_buffer (GstTensorMerge * tensor_merge,
 
     if (GST_IS_BUFFER (buf)) {
       if (GST_BUFFER_PTS_IS_VALID (buf)) {
-        pad->pts_timestamp =
-            gst_segment_to_running_time (&data->segment, GST_FORMAT_TIME,
-            GST_BUFFER_PTS (buf));
+        if (data->segment.format == GST_FORMAT_TIME)
+          pad->pts_timestamp =
+              gst_segment_to_running_time (&data->segment, GST_FORMAT_TIME,
+              GST_BUFFER_PTS (buf));
       } else {
         pad->pts_timestamp = GST_CLOCK_TIME_NONE;
       }
-      if (GST_BUFFER_DTS_IS_VALID (buf)) {
-        pad->dts_timestamp =
-            gst_segment_to_running_time (&data->segment, GST_FORMAT_TIME,
-            GST_BUFFER_DTS (buf));
+      if (buf && GST_BUFFER_DTS_IS_VALID (buf)) {
+        if (data->segment.format == GST_FORMAT_TIME)
+          pad->dts_timestamp =
+              gst_segment_to_running_time (&data->segment, GST_FORMAT_TIME,
+              GST_BUFFER_DTS (buf));
       } else {
         pad->dts_timestamp = GST_CLOCK_TIME_NONE;
       }
@@ -518,6 +506,146 @@ gst_tensor_merge_collect_buffer (GstTensorMerge * tensor_merge,
   return isEOS;
 }
 
+
+/**
+ * @brief Generate Output GstMemory
+ * @param tensor_merge tensor merger
+ * @param tensors_buf collected tensors buffer
+ * @param tensor_buf output tensor buffer
+ * @return boolean
+ */
+static GstFlowReturn
+gst_tensor_merge_generate_mem (GstTensorMerge * tensor_merge,
+    GstBuffer * tensors_buf, GstBuffer * tensor_buf)
+{
+  GstFlowReturn ret = GST_FLOW_OK;
+  GstMapInfo mInfo[NNS_TENSOR_SIZE_LIMIT];
+  GstMemory *mem[NNS_TENSOR_SIZE_LIMIT];
+  GstMapInfo outInfo;
+  GstMemory *outMem;
+  uint8_t *inptr, *outptr;
+  int num_mem = tensor_merge->tensors_config.info.num_tensors;
+  int i, j, k, l;
+  size_t outSize = 0;
+  tensor_dim dim;
+  tensor_type type;
+
+  memcpy (&dim, &tensor_merge->tensors_config.info.info[0].dimension,
+      sizeof (tensor_dim));
+  type = tensor_merge->tensors_config.info.info[0].type;
+
+  for (i = 0; i < num_mem; i++) {
+    mem[i] = gst_buffer_peek_memory (tensors_buf, i);
+    g_assert (gst_memory_map (mem[i], &mInfo[i], GST_MAP_READ));
+    outSize += mInfo[i].size;
+  }
+
+  outMem = gst_allocator_alloc (NULL, outSize, NULL);
+  g_assert (gst_memory_map (outMem, &outInfo, GST_MAP_WRITE));
+  outptr = outInfo.data;
+
+  switch (tensor_merge->mode) {
+    case GTT_LINEAR:
+    {
+      switch (tensor_merge->data_linear.direction) {
+        case LINEAR_FIRST:
+        {
+          for (l = 0; l < dim[3]; l++) {
+            for (i = 0; i < dim[2]; i++) {
+              for (j = 0; j < dim[1]; j++) {
+                for (k = 0; k < num_mem; k++) {
+                  size_t c =
+                      tensor_merge->tensors_config.info.info[k].dimension[0];
+                  size_t s = tensor_element_size[type] * c;
+                  inptr =
+                      mInfo[k].data + (l * dim[2] * dim[1] + i * dim[1] +
+                      j) * s;
+                  memcpy (outptr, inptr, s);
+                  outptr += s;
+                }
+              }
+            }
+
+          }
+          ret = TRUE;
+        }
+          break;
+        case LINEAR_SECOND:
+        {
+          for (l = 0; l < dim[3]; l++) {
+            for (i = 0; i < dim[2]; i++) {
+              for (k = 0; k < num_mem; k++) {
+                size_t c = 1;
+                for (j = 0; j < LINEAR_SECOND + 1; j++)
+                  c *= tensor_merge->tensors_config.info.info[k].dimension[j];
+
+                size_t s = tensor_element_size[type] * c;
+
+                inptr = mInfo[k].data + (l * dim[2] + i) * s;
+
+                memcpy (outptr, inptr, s);
+                outptr += s;
+              }
+            }
+          }
+          ret = TRUE;
+        }
+          break;
+        case LINEAR_THIRD:
+        {
+          for (l = 0; l < dim[3]; l++) {
+            for (k = 0; k < num_mem; k++) {
+              size_t c = 1;
+              for (j = 0; j < LINEAR_THIRD + 1; j++)
+                c *= tensor_merge->tensors_config.info.info[k].dimension[j];
+
+              size_t s = tensor_element_size[type] * c;
+
+              inptr = mInfo[k].data + l * s;
+
+              memcpy (outptr, inptr, s);
+              outptr += s;
+            }
+          }
+          ret = TRUE;
+        }
+          break;
+        case LINEAR_FOURTH:
+        {
+          for (k = 0; k < num_mem; k++) {
+            size_t c = 1;
+            for (j = 0; j < LINEAR_FOURTH + 1; j++)
+              c *= tensor_merge->tensors_config.info.info[k].dimension[j];
+
+            size_t s = tensor_element_size[type] * c;
+
+            inptr = mInfo[k].data;
+            memcpy (outptr, inptr, s);
+            outptr += s;
+          }
+
+          ret = TRUE;
+        }
+          break;
+        default:
+          ret = FALSE;
+      }
+    }
+      break;
+    default:
+      ret = FALSE;
+  }
+
+  gst_buffer_append_memory (tensor_buf, outMem);
+  gst_buffer_copy_into (tensor_buf, tensors_buf, GST_BUFFER_COPY_TIMESTAMPS, 0,
+      -1);
+  for (i = 0; i < num_mem; i++)
+    gst_memory_unmap (mem[i], &mInfo[i]);
+  gst_memory_unmap (outMem, &outInfo);
+
+  return ret;
+}
+
 /**
  * @brief Gst Collect Pads Function which is called once collect pads done.
  * @param pads GstCollectPads
@@ -530,7 +658,6 @@ gst_tensor_merge_collected (GstCollectPads * pads,
 {
   GstFlowReturn ret = GST_FLOW_OK;
   GstBuffer *tensors_buf, *tensor_buf;
-  GstMemory *mem;
   GstClockTime pts_time = GST_CLOCK_TIME_NONE;
   GstClockTime dts_time = GST_CLOCK_TIME_NONE;
   GstClockTime time = 0;
@@ -595,21 +722,15 @@ gst_tensor_merge_collected (GstCollectPads * pads,
     tensor_merge->need_segment = FALSE;
   }
 
-  /* TODO : Should handle Properly. This is just for the temperaly usage */
-  mem = gst_buffer_get_all_memory (tensors_buf);
-
   tensor_buf = gst_buffer_new ();
   g_assert (tensor_buf != NULL);
 
-  gst_buffer_append_memory (tensor_buf, mem);
-  gst_buffer_copy_into (tensor_buf, tensors_buf, GST_BUFFER_COPY_TIMESTAMPS, 0,
-      -1);
+  gst_tensor_merge_generate_mem (tensor_merge, tensors_buf, tensor_buf);
 
   ret = gst_pad_push (tensor_merge->srcpad, tensor_buf);
   if (ret != GST_FLOW_OK) {
     GST_WARNING_OBJECT (tensor_merge, "pushed outbuf, result = %s",
         gst_flow_get_name (ret));
-    /* fall-through, returns result */
   }
 beach:
   gst_buffer_unref (tensors_buf);
index 8608c6f..7c46e5c 100644 (file)
@@ -51,9 +51,10 @@ typedef enum
 
 typedef enum
 {
-  LINEAR_WIDTH = 0,
-  LINEAR_HEIGHT = 1,
-  LINEAR_CHANNEL = 2,
+  LINEAR_FIRST = 0,            /* CHANNEL */
+  LINEAR_SECOND = 1,           /* WIDTH */
+  LINEAR_THIRD = 2,            /* HEIGHT */
+  LINEAR_FOURTH = 3,           /* BATCH */
   LINEAR_END,
 } tensor_merge_linear_mode;
 
diff --git a/tests/nnstreamer_merge/generateTest.py b/tests/nnstreamer_merge/generateTest.py
new file mode 100755 (executable)
index 0000000..d3e2884
--- /dev/null
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+
+##
+# Copyright (C) 2018 Samsung Electronics
+# License: LGPL-2.1
+#
+# @file generateTest.py
+# @brief Generate golden test results for test cases
+# @author Jijoong Moon <jijoong.moon@samsung.com>
+
+import sys
+import os
+sys.path.append(os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
+from struct import pack
+import random
+
+import numpy as np
+
+def saveTestData(filename, width, height, channel, batch):
+    string = b''
+    data = []
+
+    for b in range(0,batch):
+        for h in range(0,height):
+            for w in range(0,width):
+                for c in range(0,channel):
+                    n = random.uniform(0.0, 10.0)
+                    string += pack('f', n)
+                    data.append(n)
+
+    with open(filename,'wb') as file:
+        file.write(string)
+    file.close()
+
+    return data
+
+#merge with channel direction
+ch = [3, 2, 4]
+width = 100
+height= 50
+batch= 1
+
+buf=[]
+
+buf.append(saveTestData("channel_00.dat", width, height, 3, batch))
+buf.append(saveTestData("channel_01.dat", width, height, 2, batch))
+buf.append(saveTestData("channel_02.dat", width, height, 4, batch))
+
+out = ''
+for b in range(0, batch):
+    for h in range(0,height):
+        for w in range(0,width):
+            for n in range(0,3):
+                for c in range(0,ch[n]):
+                    out += pack('f',buf[n][b*height*width*ch[n]+h*width*ch[n] + w * ch[n] + c])
+
+with open("channel.golden", 'wb') as file:
+    file.write(out)
+
+#merge with width direction
+width = [100, 200, 300]
+ch = 3
+height= 50
+batch= 1
+
+buf=[]
+
+buf.append(saveTestData("width_100.dat", width[0], height, ch, batch))
+buf.append(saveTestData("width_200.dat", width[1], height, ch, batch))
+buf.append(saveTestData("width_300.dat", width[2], height, ch, batch))
+
+out = ''
+
+for b in range(0, batch):
+    for h in range(0,height):
+        for n in range(0,3):
+            for w in range(0,width[n]):
+                for c in range(0,ch):
+                    out += pack('f',buf[n][b*height*width[n]*ch + h*width[n]*ch + w * ch + c])
+
+with open("width.golden", 'wb') as file:
+    file.write(out)
+
+#merge with width direction
+batch = [1, 2, 3]
+ch = 3
+height= 50
+width= 100
+
+buf=[]
+
+buf.append(saveTestData("batch_1.dat", width, height, ch, batch[0]))
+buf.append(saveTestData("batch_2.dat", width, height, ch, batch[1]))
+buf.append(saveTestData("batch_3.dat", width, height, ch, batch[2]))
+
+out = ''
+for n in range(0,3):
+    for b in range(0, batch[n]):
+        for h in range(0,height):
+            for w in range(0,width):
+                for c in range(0,ch):
+                    out += pack('f',buf[n][b*height*width*ch + h*width*ch + w * ch + c])
+
+with open("batch.golden", 'wb') as file:
+    file.write(out)
index ef92277..86ba819 100755 (executable)
@@ -8,36 +8,51 @@ then
 else
   echo "Test Case Generation Started"
   python ../nnstreamer_converter/generateGoldenTestResult.py 9
+  python generateTest.py
   sopath=$1
 fi
 convertBMP2PNG
 
-gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} --gst-debug=tensor_merge:5 tensor_merge name=merge mode=linear option=channel ! filesink location=testcase01_RGB_100x100.log filesrc location=testcase02_RGB_100x100.png ! pngdec ! videoscale ! imagefreeze ! videoconvert ! video/x-raw,format=RGB,width=100,height=100,framerate=0/1  ! tensor_converter ! merge.sink_0" 1
+gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} --gst-debug=tensor_merge:5 tensor_merge name=merge mode=linear option=2 ! filesink location=testcase01_RGB_100x100.log filesrc location=testcase02_RGB_100x100.png ! pngdec ! videoscale ! imagefreeze ! videoconvert ! video/x-raw,format=RGB,width=100,height=100,framerate=0/1  ! tensor_converter ! merge.sink_0" 1
 
 compareAllSizeLimit testcase01_RGB_100x100.golden testcase01_RGB_100x100.log 1
 
-gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} --gst-debug=tensor_merge:5 tensor_merge name=merge mode=linear option=channel ! filesink location=testcase02_RGB_100x100.log filesrc location=testcase02_RGB_100x100.png ! pngdec ! videoscale ! imagefreeze ! videoconvert ! video/x-raw,format=RGB,width=100,height=100,framerate=0/1  ! tensor_converter ! merge.sink_0 filesrc location=testcase02_RGB_100x100.png ! pngdec ! videoscale ! imagefreeze ! videoconvert ! video/x-raw,format=RGB,width=100,height=100,framerate=0/1  ! tensor_converter ! merge.sink_1" 2
+gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} --gst-debug=tensor_merge:5 tensor_merge name=merge mode=linear option=2 ! filesink location=testcase02_RGB_100x100.log filesrc location=testcase02_RGB_100x100.png ! pngdec ! videoscale ! imagefreeze ! videoconvert ! video/x-raw,format=RGB,width=100,height=100,framerate=0/1  ! tensor_converter ! merge.sink_0 filesrc location=testcase02_RGB_100x100.png ! pngdec ! videoscale ! imagefreeze ! videoconvert ! video/x-raw,format=RGB,width=100,height=100,framerate=0/1  ! tensor_converter ! merge.sink_1" 2
 
 compareAllSizeLimit testcase02_RGB_100x100.golden testcase02_RGB_100x100.log 2
 
-gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} --gst-debug=tensor_merge:5 tensor_merge name=merge mode=linear option=channel ! filesink location=testcase03_RGB_100x100.log filesrc location=testcase02_RGB_100x100.png ! pngdec ! videoscale ! imagefreeze ! videoconvert ! video/x-raw,format=RGB,width=100,height=100,framerate=0/1  ! tensor_converter ! merge.sink_0 filesrc location=testcase02_RGB_100x100.png ! pngdec ! videoscale ! imagefreeze ! videoconvert ! video/x-raw,format=RGB,width=100,height=100,framerate=0/1  ! tensor_converter ! merge.sink_1 filesrc location=testcase02_RGB_100x100.png ! pngdec ! videoscale ! imagefreeze ! videoconvert ! video/x-raw,format=RGB,width=100,height=100,framerate=0/1  ! tensor_converter ! merge.sink_2" 3
+gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} --gst-debug=tensor_merge:5 tensor_merge name=merge mode=linear option=2 ! filesink location=testcase03_RGB_100x100.log filesrc location=testcase02_RGB_100x100.png ! pngdec ! videoscale ! imagefreeze ! videoconvert ! video/x-raw,format=RGB,width=100,height=100,framerate=0/1  ! tensor_converter ! merge.sink_0 filesrc location=testcase02_RGB_100x100.png ! pngdec ! videoscale ! imagefreeze ! videoconvert ! video/x-raw,format=RGB,width=100,height=100,framerate=0/1  ! tensor_converter ! merge.sink_1 filesrc location=testcase02_RGB_100x100.png ! pngdec ! videoscale ! imagefreeze ! videoconvert ! video/x-raw,format=RGB,width=100,height=100,framerate=0/1  ! tensor_converter ! merge.sink_2" 3
 
 compareAllSizeLimit testcase03_RGB_100x100.golden testcase03_RGB_100x100.log 3
 
-gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} --gst-debug=tensor_merge:5 tensor_merge name=merge mode=linear option=channel ! filesink location=testcase01.log multifilesrc location=\"testsequence01_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_0" 4
+gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} --gst-debug=tensor_merge:5 tensor_merge name=merge mode=linear option=2 ! filesink location=testcase01.log multifilesrc location=\"testsequence01_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_0" 4
 
 compareAllSizeLimit testcase01.golden testcase01.log 4
 
-gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} --gst-debug=tensor_merge:5 tensor_merge name=merge mode=linear option=channel ! filesink location=testcase02.log multifilesrc location=\"testsequence02_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_0 multifilesrc location=\"testsequence02_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_1" 5
+gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} --gst-debug=tensor_merge:5 tensor_merge name=merge mode=linear option=2 ! filesink location=testcase02.log multifilesrc location=\"testsequence02_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_0 multifilesrc location=\"testsequence02_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_1" 5
 
 compareAllSizeLimit testcase02.golden testcase02.log 5
 
-gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} --gst-debug=tensor_merge:5 tensor_merge name=merge mode=linear option=channel ! filesink location=testcase03.log multifilesrc location=\"testsequence03_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_0 multifilesrc location=\"testsequence03_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_1 multifilesrc location=\"testsequence03_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_2" 6
+gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} --gst-debug=tensor_merge:5 tensor_merge name=merge mode=linear option=2 ! filesink location=testcase03.log multifilesrc location=\"testsequence03_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_0 multifilesrc location=\"testsequence03_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_1 multifilesrc location=\"testsequence03_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_2" 6
 
 compareAllSizeLimit testcase03.golden testcase03.log 6
 
-gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} --gst-debug=tensor_merge:5 tensor_merge name=merge mode=linear option=channel ! filesink location=testcase04.log multifilesrc location=\"testsequence04_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_0 multifilesrc location=\"testsequence04_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_1 multifilesrc location=\"testsequence04_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_2 multifilesrc location=\"testsequence04_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_3" 7
+gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} --gst-debug=tensor_merge:5 tensor_merge name=merge mode=linear option=2 ! filesink location=testcase04.log multifilesrc location=\"testsequence04_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_0 multifilesrc location=\"testsequence04_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_1 multifilesrc location=\"testsequence04_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_2 multifilesrc location=\"testsequence04_%1d.png\" index=0 caps=\"image/png, framerate=(fraction)30/1\" ! pngdec ! tensor_converter ! merge.sink_3" 7
 
 compareAllSizeLimit testcase03.golden testcase03.log 7
 
+
+gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} --gst-debug=tensor_merge:5 tensor_merge name=merge mode=linear option=0 ! filesink location=channel.log filesrc location=channel_00.dat blocksize=60000 num_buffers=1 ! application/octet-stream ! tensor_converter input-dim=3:50:100:1 input-type=float32 ! merge.sink_0 filesrc location=channel_01.dat blocksize=40000 num_buffers=1 ! application/octet-stream ! tensor_converter input-dim=2:50:100:1 input-type=float32 ! merge.sink_1 filesrc location=channel_02.dat blocksize=80000 num_buffers=1 ! application/octet-stream ! tensor_converter input-dim=4:50:100:1 input-type=float32 ! merge.sink_2" 8
+
+compareAllSizeLimit channel.golden channel.log 8
+
+gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} --gst-debug=tensor_merge:5 tensor_merge name=merge mode=linear option=1 ! filesink location=width.log filesrc location=width_100.dat blocksize=60000 num_buffers=1 ! application/octet-stream ! tensor_converter input-dim=3:100:50:1 input-type=float32 ! merge.sink_0 filesrc location=width_200.dat blocksize=120000 num_buffers=1 ! application/octet-stream ! tensor_converter input-dim=3:200:50:1 input-type=float32 ! merge.sink_1 filesrc location=width_300.dat blocksize=180000 num_buffers=1 ! application/octet-stream ! tensor_converter input-dim=3:300:50:1 input-type=float32 ! merge.sink_2" 9
+
+compareAllSizeLimit width.golden width.log 9
+
+gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} --gst-debug=tensor_merge:5 tensor_merge name=merge mode=linear option=3 ! filesink location=batch.log filesrc location=batch_1.dat blocksize=60000 num_buffers=1 ! application/octet-stream ! tensor_converter input-dim=3:100:50:1 input-type=float32 ! merge.sink_0 filesrc location=batch_2.dat blocksize=120000 num_buffers=1 ! application/octet-stream ! tensor_converter input-dim=3:100:50:2 input-type=float32 ! merge.sink_1 filesrc location=batch_3.dat blocksize=180000 num_buffers=1 ! application/octet-stream ! tensor_converter input-dim=3:100:50:3 input-type=float32 ! merge.sink_2" 10
+
+compareAllSizeLimit batch.golden batch.log 10
+
+
 report