[Filter] change properties for one tensors to array
authorHyoungjooAhn <hello.ahn@samsung.com>
Thu, 9 Aug 2018 11:03:46 +0000 (20:03 +0900)
committer함명주/동작제어Lab(SR)/Principal Engineer/삼성전자 <myungjoo.ham@samsung.com>
Fri, 17 Aug 2018 06:34:27 +0000 (15:34 +0900)
for now, the first index(0) will be used before multi tensor environment

Signed-off-by: HyoungjooAhn <hello.ahn@samsung.com>
gst/tensor_filter/tensor_filter.c
gst/tensor_filter/tensor_filter.h
gst/tensor_filter/tensor_filter_custom.c
include/tensor_typedef.h
nnstreamer_example/custom_example_average/nnstreamer_customfilter_example_average.c
nnstreamer_example/custom_example_passthrough/nnstreamer_customfilter_example_passthrough_variable.c
nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler.c
nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler_allocator.c

index b9f1bf7..fa2fcc2 100644 (file)
@@ -236,6 +236,7 @@ gst_tensor_filter_class_init (GstTensor_FilterClass * g_class)
  * instantiate pads and add them to element
  * set pad calback functions
  * initialize instance structure
+ * @todo change the first index [0] of input/output Dimension & Type to loop for multi tensors
  */
 static void
 gst_tensor_filter_init (GstTensor_Filter * filter)
@@ -251,18 +252,18 @@ gst_tensor_filter_init (GstTensor_Filter * filter)
   prop->outputConfigured = _TFC_INIT;
   prop->modelFilename = NULL;
 
-  prop->inputDimension[0] = 1;  /* innermost */
-  prop->inputDimension[1] = 1;
-  prop->inputDimension[2] = 1;
-  prop->inputDimension[3] = 1;  /* out */
-  prop->inputType = _NNS_END;   /* not initialized */
+  prop->inputDimension[0][0] = 1;       /* innermost */
+  prop->inputDimension[0][1] = 1;
+  prop->inputDimension[0][2] = 1;
+  prop->inputDimension[0][3] = 1;       /* out */
+  prop->inputType[0] = _NNS_END;        /* not initialized */
   prop->inputCapNegotiated = FALSE;
 
-  prop->outputDimension[0] = 1; /* innermost */
-  prop->outputDimension[1] = 1;
-  prop->outputDimension[2] = 1;
-  prop->outputDimension[3] = 1; /* out */
-  prop->outputType = _NNS_END;  /* not initialized */
+  prop->outputDimension[0][0] = 1;      /* innermost */
+  prop->outputDimension[0][1] = 1;
+  prop->outputDimension[0][2] = 1;
+  prop->outputDimension[0][3] = 1;      /* out */
+  prop->outputType[0] = _NNS_END;       /* not initialized */
   prop->outputCapNegotiated = FALSE;
 
   prop->customProperties = NULL;
@@ -335,8 +336,8 @@ gst_tensor_filter_fix_caps (GstTensor_Filter * filter, gboolean isInput,
     GstCaps * fromCaps)
 {
   tensor_type *type = NULL, _type;
-  uint32_t *dimension;
-  tensor_dim dim;
+  uint32_t *dimension[NNS_TENSOR_SIZE_LIMIT];
+  tensor_dim dim[NNS_TENSOR_SIZE_LIMIT];
   GstTensor_Filter_CheckStatus configured = _TFC_INIT;
   GstTensor_Filter_Properties *prop = &filter->prop;
   GstCaps *tmp = NULL, *tmp2 = NULL, *staticcap = NULL, *resultCaps = NULL;
@@ -345,37 +346,44 @@ gst_tensor_filter_fix_caps (GstTensor_Filter * filter, gboolean isInput,
   staticcap = gst_static_caps_get (&rawcap);
 
   if (isInput == TRUE) {
-    type = &(prop->inputType);
-    dimension = prop->inputDimension;
+    type = prop->inputType;
+    int i;
+    for (i = 0; i < NNS_TENSOR_SIZE_LIMIT; i++) {
+      dimension[i] = prop->inputDimension[i];
+    }
     configured = prop->inputConfigured & _TFC_ALL;
   } else {
-    type = &(prop->outputType);
-    dimension = prop->outputDimension;
+    type = prop->outputType;
+    int i;
+    for (i = 0; i < NNS_TENSOR_SIZE_LIMIT; i++) {
+      dimension[i] = prop->outputDimension[i];
+    }
     configured = prop->outputConfigured & _TFC_ALL;
   }
 
   /* 2. configure caps based on type & dimension */
   if (configured == _TFC_ALL) {
-    rank = gst_tensor_filter_get_rank (dimension);
+    rank = gst_tensor_filter_get_rank (dimension[0]);
     tmp2 =
         gst_caps_new_simple ("other/tensor", "rank", G_TYPE_INT, rank, "type",
-        G_TYPE_STRING, tensor_element_typename[*type], "dim1", G_TYPE_INT,
-        dimension[0], "dim2", G_TYPE_INT, dimension[1], "dim3", G_TYPE_INT,
-        dimension[2], "dim4", G_TYPE_INT, dimension[3], NULL);
+        G_TYPE_STRING, tensor_element_typename[type[0]], "dim1", G_TYPE_INT,
+        dimension[0][0], "dim2", G_TYPE_INT, dimension[0][1], "dim3",
+        G_TYPE_INT, dimension[0][2], "dim4", G_TYPE_INT, dimension[0][3], NULL);
     tmp = gst_caps_intersect_full (staticcap, tmp2, GST_CAPS_INTERSECT_FIRST);
     gst_caps_unref (tmp2);
   } else if (configured == _TFC_DIMENSION) {
-    rank = gst_tensor_filter_get_rank (dimension);
+    rank = gst_tensor_filter_get_rank (dimension[0]);
     tmp2 =
         gst_caps_new_simple ("other/tensor", "rank", G_TYPE_INT, rank, "dim1",
-        G_TYPE_INT, dimension[0], "dim2", G_TYPE_INT, dimension[1], "dim3",
-        G_TYPE_INT, dimension[2], "dim4", G_TYPE_INT, dimension[3], NULL);
+        G_TYPE_INT, dimension[0][0], "dim2", G_TYPE_INT, dimension[0][1],
+        "dim3", G_TYPE_INT, dimension[0][2], "dim4", G_TYPE_INT,
+        dimension[0][3], NULL);
     tmp = gst_caps_intersect_full (staticcap, tmp2, GST_CAPS_INTERSECT_FIRST);
     gst_caps_unref (tmp2);
   } else if (configured == _TFC_TYPE) {
     tmp2 =
         gst_caps_new_simple ("other/tensor", "type", G_TYPE_STRING,
-        tensor_element_typename[*type], NULL);
+        tensor_element_typename[type[0]], NULL);
     tmp = gst_caps_intersect_full (staticcap, tmp2, GST_CAPS_INTERSECT_FIRST);
     gst_caps_unref (tmp2);
   } else {
@@ -413,8 +421,9 @@ gst_tensor_filter_fix_caps (GstTensor_Filter * filter, gboolean isInput,
   }
 
   /* 2-2. Extract effective dim info from tmp */
-  dimension = dim;
-  configured = gst_tensor_filter_generate_dim_from_cap (tmp, dimension, &_type);
+  dimension[0] = dim[0];
+  configured =
+      gst_tensor_filter_generate_dim_from_cap (tmp, dimension[0], &_type);
   configured &= _TFC_ALL;
   /* tmp is no more needed */
   gst_caps_unref (tmp);
@@ -431,8 +440,8 @@ gst_tensor_filter_fix_caps (GstTensor_Filter * filter, gboolean isInput,
       gst_tensor_filter_call (filter, ret, getOutputDimension, rdim, &rtype);
     /* 3-1-1-a. If inputdim is available but outputdim is not available */
     if (ret != 0 && configured == _TFC_ALL && prop->fw->setInputDimension) {
-      gst_tensor_filter_call (filter, ret, setInputDimension, dimension, _type,
-          rdim, &rtype);
+      gst_tensor_filter_call (filter, ret, setInputDimension, dimension[0],
+          _type, rdim, &rtype);
     }
     /* if ret == 0, either get or set has been successful. */
     if (ret != 0) {
@@ -536,12 +545,12 @@ gst_tensor_filter_set_property (GObject * object, guint prop_id,
       /* Once configures, it cannot be changed in runtime */
       {
         int rank = get_tensor_dimension (g_value_get_string (value),
-            prop->inputDimension);
+            prop->inputDimension[0]);
         g_assert (rank > 0 && rank <= NNS_TENSOR_RANK_LIMIT);
         prop->inputConfigured |= _TFC_DIMENSION;
         silent_debug ("Input Prop: %d:%d:%d:%d Rank %d\n",
-            prop->inputDimension[0], prop->inputDimension[1],
-            prop->inputDimension[2], prop->inputDimension[3], rank);
+            prop->inputDimension[0][0], prop->inputDimension[0][1],
+            prop->inputDimension[0][2], prop->inputDimension[0][3], rank);
       }
       break;
     case PROP_OUTPUT:
@@ -549,27 +558,27 @@ gst_tensor_filter_set_property (GObject * object, guint prop_id,
       /* Once configures, it cannot be changed in runtime */
       {
         int rank = get_tensor_dimension (g_value_get_string (value),
-            prop->outputDimension);
+            prop->outputDimension[0]);
         g_assert (rank > 0 && rank <= NNS_TENSOR_RANK_LIMIT);
         prop->outputConfigured |= _TFC_DIMENSION;
         silent_debug ("Output Prop: %d:%d:%d:%d Rank %d\n",
-            prop->outputDimension[0], prop->outputDimension[1],
-            prop->outputDimension[2], prop->outputDimension[3], rank);
+            prop->outputDimension[0][0], prop->outputDimension[0][1],
+            prop->outputDimension[0][2], prop->outputDimension[0][3], rank);
       }
       break;
     case PROP_INPUTTYPE:
-      g_assert (prop->inputType == _NNS_END && value);
+      g_assert (prop->inputType[0] == _NNS_END && value);
       /* Once configures, it cannot be changed in runtime */
-      prop->inputType = get_tensor_type (g_value_get_string (value));
+      prop->inputType[0] = get_tensor_type (g_value_get_string (value));
       prop->inputConfigured |= _TFC_TYPE;
-      g_assert (prop->inputType != _NNS_END);
+      g_assert (prop->inputType[0] != _NNS_END);
       break;
     case PROP_OUTPUTTYPE:
-      g_assert (prop->outputType == _NNS_END && value);
+      g_assert (prop->outputType[0] == _NNS_END && value);
       /* Once configures, it cannot be changed in runtime */
-      prop->outputType = get_tensor_type (g_value_get_string (value));
+      prop->outputType[0] = get_tensor_type (g_value_get_string (value));
       prop->outputConfigured |= _TFC_TYPE;
-      g_assert (prop->outputType != _NNS_END);
+      g_assert (prop->outputType[0] != _NNS_END);
       break;
     case PROP_CUSTOM:
       g_assert (prop->customProperties == NULL && value);
@@ -611,7 +620,7 @@ gst_tensor_filter_get_property (GObject * object, guint prop_id,
           g_array_sized_new (FALSE, FALSE, 4, NNS_TENSOR_RANK_LIMIT);
       int i;
       for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++)
-        g_array_append_val (input, filter->prop.inputDimension[i]);
+        g_array_append_val (input, filter->prop.inputDimension[0][i]);
       g_value_take_boxed (value, input);
       /* take function hands the object over from here so that we don't need to free it. */
     }
@@ -621,18 +630,18 @@ gst_tensor_filter_get_property (GObject * object, guint prop_id,
           g_array_sized_new (FALSE, FALSE, 4, NNS_TENSOR_RANK_LIMIT);
       int i;
       for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++)
-        g_array_append_val (output, filter->prop.outputDimension[i]);
+        g_array_append_val (output, filter->prop.outputDimension[0][i]);
       g_value_take_boxed (value, output);
       /* take function hands the object over from here so that we don't need to free it. */
     }
       break;
     case PROP_INPUTTYPE:
       g_value_set_string (value,
-          tensor_element_typename[filter->prop.inputType]);
+          tensor_element_typename[filter->prop.inputType[0]]);
       break;
     case PROP_OUTPUTTYPE:
       g_value_set_string (value,
-          tensor_element_typename[filter->prop.outputType]);
+          tensor_element_typename[filter->prop.outputType[0]]);
       break;
     case PROP_CUSTOM:
       g_value_set_string (value, filter->prop.customProperties);
@@ -722,8 +731,8 @@ gst_tensor_filter_transform (GstBaseTransform * trans,
   g_assert (outbuf);
 
   if (filter->prop.fw->allocate_in_invoke == FALSE) {
-    outBufSize = tensor_element_size[filter->prop.outputType] *
-        get_tensor_element_count (filter->prop.outputDimension);
+    outBufSize = tensor_element_size[filter->prop.outputType[0]] *
+        get_tensor_element_count (filter->prop.outputDimension[0]);
     if (gst_buffer_get_size (outbuf) < outBufSize) {
       /** @todo: write a routine to say aloud when this happens */
       gst_buffer_set_size (outbuf, outBufSize);
@@ -754,11 +763,11 @@ gst_tensor_filter_transform (GstBaseTransform * trans,
 
     /** @todo Performance: cache get_tensor_element_count * tensor_element_size */
     mem = gst_memory_new_wrapped (0, retoutptr,
-        get_tensor_element_count (filter->prop.outputDimension) *
-        tensor_element_size[filter->prop.outputType],
+        get_tensor_element_count (filter->prop.outputDimension[0]) *
+        tensor_element_size[filter->prop.outputType[0]],
         0,
-        get_tensor_element_count (filter->prop.outputDimension) *
-        tensor_element_size[filter->prop.outputType], NULL, NULL);
+        get_tensor_element_count (filter->prop.outputDimension[0]) *
+        tensor_element_size[filter->prop.outputType[0]], NULL, NULL);
     gst_buffer_insert_memory (outbuf, -1, mem);
   }
 
@@ -826,18 +835,18 @@ gst_tensor_filter_property_process (GstTensor_Filter * filter, gboolean fixate)
     gst_tensor_filter_call (filter, ret, getInputDimension, dim, &type);
     if (ret == 0) {
       if (prop->inputConfigured & _TFC_TYPE)
-        if (prop->inputType != type)
+        if (prop->inputType[0] != type)
           return -1;
       if (prop->inputConfigured & _TFC_DIMENSION)
         for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++)
-          if (prop->inputDimension[i] != dim[i])
+          if (prop->inputDimension[0][i] != dim[i])
             return -1;
       if (fixate && !(prop->inputConfigured & _TFC_TYPE)) {
-        prop->inputType = type;
+        prop->inputType[0] = type;
         prop->inputConfigured |= _TFC_TYPE;
       }
       if (fixate && !(prop->inputConfigured & _TFC_DIMENSION)) {
-        memcpy (prop->inputDimension, dim, sizeof (dim));
+        memcpy (prop->inputDimension[0], dim, sizeof (dim));
         prop->inputConfigured |= _TFC_DIMENSION;
       }
     }
@@ -847,18 +856,18 @@ gst_tensor_filter_property_process (GstTensor_Filter * filter, gboolean fixate)
     gst_tensor_filter_call (filter, ret, getOutputDimension, dim, &type);
     if (ret == 0) {
       if (prop->outputConfigured & _TFC_TYPE)
-        if (prop->outputType != type)
+        if (prop->outputType[0] != type)
           return -1;
       if (prop->outputConfigured & _TFC_DIMENSION)
         for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++)
-          if (prop->outputDimension[i] != dim[i])
+          if (prop->outputDimension[0][i] != dim[i])
             return -1;
       if (fixate && !(prop->outputConfigured & _TFC_TYPE)) {
-        prop->outputType = type;
+        prop->outputType[0] = type;
         prop->outputConfigured |= _TFC_TYPE;
       }
       if (fixate && !(prop->outputConfigured & _TFC_DIMENSION)) {
-        memcpy (prop->outputDimension, dim, sizeof (dim));
+        memcpy (prop->outputDimension[0], dim, sizeof (dim));
         prop->outputConfigured |= _TFC_DIMENSION;
       }
     }
@@ -869,8 +878,8 @@ gst_tensor_filter_property_process (GstTensor_Filter * filter, gboolean fixate)
     tensor_type itype, *cmptype;
     /* If filter's inputdimension is not clear, yet, we cannot proceed. try again later */
     if ((prop->inputConfigured & _TFC_ALL) == _TFC_ALL) {
-      cmpdim = &(prop->inputDimension);
-      cmptype = &(prop->inputType);
+      cmpdim = &(prop->inputDimension[0]);
+      cmptype = &(prop->inputType[0]);
     } else {
       if (fw->getInputDimension != NULL) {
         gst_tensor_filter_call (filter, ret, getInputDimension, idim, &itype);
@@ -890,22 +899,22 @@ gst_tensor_filter_property_process (GstTensor_Filter * filter, gboolean fixate)
       goto finalize;
 
     if (prop->outputConfigured & _TFC_TYPE) {
-      if (prop->outputType != type)
+      if (prop->outputType[0] != type)
         return -1;
     }
     if (prop->outputConfigured & _TFC_DIMENSION) {
       for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++) {
-        if (prop->outputDimension[i] != dim[i])
+        if (prop->outputDimension[0][i] != dim[i])
           return -1;
       }
     }
 
     if (fixate && !(prop->outputConfigured & _TFC_TYPE)) {
-      prop->outputType = type;
+      prop->outputType[0] = type;
       prop->outputConfigured |= _TFC_TYPE;
     }
     if (fixate && !(prop->outputConfigured & _TFC_DIMENSION)) {
-      memcpy (prop->outputDimension, dim, sizeof (dim));
+      memcpy (prop->outputDimension[0], dim, sizeof (dim));
       prop->outputConfigured |= _TFC_DIMENSION;
     }
   }
@@ -1023,12 +1032,12 @@ gst_tensor_caps_to_dimension (GstCaps * caps, gboolean input,
 {
   if (input) {
     prop->inputConfigured |=
-        gst_tensor_filter_generate_dim_from_cap (caps, prop->inputDimension,
-        &prop->inputType);
+        gst_tensor_filter_generate_dim_from_cap (caps, prop->inputDimension[0],
+        &prop->inputType[0]);
   } else {
     prop->outputConfigured |=
-        gst_tensor_filter_generate_dim_from_cap (caps, prop->outputDimension,
-        &prop->outputType);
+        gst_tensor_filter_generate_dim_from_cap (caps, prop->outputDimension[0],
+        &prop->outputType[0]);
   }
 }
 
@@ -1082,7 +1091,7 @@ gst_tensor_filter_fixate_caps (GstBaseTransform * trans,
       && (obj->prop.inputConfigured & _TFC_ALL) == _TFC_ALL) {
     int ret = 0;
     gst_tensor_filter_call (obj, ret, getInputDimension,
-        obj->prop.inputDimension, &obj->prop.inputType);
+        obj->prop.inputDimension[0], &obj->prop.inputType[0]);
     if (ret == 0) {
       obj->prop.inputConfigured |= _TFC_ALL;
     }
@@ -1091,7 +1100,7 @@ gst_tensor_filter_fixate_caps (GstBaseTransform * trans,
       && (obj->prop.outputConfigured & _TFC_ALL) == _TFC_ALL) {
     int ret = 0;
     gst_tensor_filter_call (obj, ret, getOutputDimension,
-        obj->prop.outputDimension, &obj->prop.outputType);
+        obj->prop.outputDimension[0], &obj->prop.outputType[0]);
     if (ret == 0) {
       obj->prop.outputConfigured |= _TFC_ALL;
     }
@@ -1112,8 +1121,8 @@ gst_tensor_filter_fixate_caps (GstBaseTransform * trans,
     if (fw->setInputDimension) {
       int ret = 0;
       gst_tensor_filter_call (obj, ret, setInputDimension,
-          obj->prop.inputDimension, obj->prop.inputType,
-          obj->prop.outputDimension, &obj->prop.outputType);
+          obj->prop.inputDimension[0], obj->prop.inputType[0],
+          obj->prop.outputDimension[0], &obj->prop.outputType[0]);
       obj->prop.outputConfigured |= _TFC_ALL;
       g_assert (ret == 0);
       return result;
index 44e9a5b..29fbd46 100644 (file)
@@ -36,7 +36,6 @@
 #include <tensor_common.h>
 
 G_BEGIN_DECLS
-
 /* #defines don't like whitespacey bits */
 #define GST_TYPE_TENSOR_FILTER \
   (gst_tensor_filter_get_type())
@@ -49,19 +48,18 @@ G_BEGIN_DECLS
 #define GST_IS_TENSOR_FILTER_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TENSOR_FILTER))
 #define GST_TENSOR_FILTER_CAST(obj)  ((GstTensor_Filter *)(obj))
-
 typedef struct _GstTensor_Filter GstTensor_Filter;
 
 typedef struct _GstTensor_FilterClass GstTensor_FilterClass;
 
-extern const charnnfw_names[];
+extern const char *nnfw_names[];
 
 /**
  * @brief Internal data structure for tensor_filter instances.
  */
 struct _GstTensor_Filter
 {
-  GstBaseTransform element;    /**< This is the parent object */
+  GstBaseTransform element;     /**< This is the parent object */
 
   void *privateData; /**< NNFW plugin's private data is stored here */
 
@@ -85,7 +83,7 @@ struct _GstTensor_Filter
  */
 struct _GstTensor_FilterClass
 {
-  GstBaseTransformClass parent_class;  /**< Inherits GstBaseTransformClass */
+  GstBaseTransformClass parent_class;   /**< Inherits GstBaseTransformClass */
 };
 
 /**
@@ -106,7 +104,8 @@ struct _GstTensor_Filter_Framework
   gboolean allow_in_place; /**< TRUE if InPlace transfer of input-to-output is allowed. Not supported in main, yet */
   gboolean allocate_in_invoke; /**< TRUE if invoke_NN is going to allocate outputptr by itself and return the address via outputptr. Do not change this value after cap negotiation is complete (or the stream has been started). */
 
-  uint8_t *(*invoke_NN)(const GstTensor_Filter *filter, void **private_data, const uint8_t *inputptr, uint8_t *outputptr);
+  uint8_t *(*invoke_NN) (const GstTensor_Filter * filter, void **private_data,
+      const uint8_t * inputptr, uint8_t * outputptr);
       /**< Mandatory callback. Invoke the given network model.
        *
        * @param[in] filter "this" pointer. Use this to read property values
@@ -116,7 +115,8 @@ struct _GstTensor_Filter_Framework
        * @return outputptr if allocate_in_invoke = 00 if OK. non-zero if error.
        */
 
-  int (*getInputDimension)(const GstTensor_Filter *filter, void **private_data, tensor_dim inputDimension, tensor_type *type);
+  int (*getInputDimension) (const GstTensor_Filter * filter,
+      void **private_data, tensor_dim inputDimension, tensor_type * type);
       /**< Optional. Set NULL if not supported. Get dimension of input tensor
        * If getInputDimension is NULL, setInputDimension must be defined.
        * If getInputDimension is defined, it is recommended to define getOutputDimension
@@ -125,9 +125,10 @@ struct _GstTensor_Filter_Framework
        * @param[in/out] private_data A subplugin may save its internal private data here. The subplugin is responsible for alloc/free of this pointer.
        * @param[out] inputDimension dimension of input tensor (return value)
        * @param[out] type type of input tensor element (return value)
-       * @return 0 if OK. non-zero if error.
+       * @return the size of input tensors
        */
-  int (*getOutputDimension)(const GstTensor_Filter *filter, void **private_data, tensor_dim outputDimension, tensor_type *type);
+  int (*getOutputDimension) (const GstTensor_Filter * filter,
+      void **private_data, tensor_dim outputDimension, tensor_type * type);
       /**< Optional. Set NULL if not supported. Get dimension of output tensor
        * If getInputDimension is NULL, setInputDimension must be defined.
        * If getInputDimension is defined, it is recommended to define getOutputDimension
@@ -136,9 +137,12 @@ struct _GstTensor_Filter_Framework
        * @param[in/out] private_data A subplugin may save its internal private data here. The subplugin is responsible for alloc/free of this pointer.
        * @param[out] outputDimension dimension of output tensor (return value)
        * @param[out] type type of output tensor element (return value)
-       * @return 0 if OK. non-zero if error.
+       * @return the size of output tensors
        */
-  int (*setInputDimension)(const GstTensor_Filter *filter, void **private_data, const tensor_dim inputDimension, const tensor_type inputType, tensor_dim outputDimension, tensor_type *outputType);
+  int (*setInputDimension) (const GstTensor_Filter * filter,
+      void **private_data, const tensor_dim inputDimension,
+      const tensor_type inputType, tensor_dim outputDimension,
+      tensor_type * outputType);
       /**< Optional. Set Null if not supported. Tensor_filter::main will
        * configure input dimension from pad-cap in run-time for the sub-plugin.
        * Then, the sub-plugin is required to return corresponding output dimension
@@ -157,13 +161,13 @@ struct _GstTensor_Filter_Framework
        * @return 0 if OK. non-zero if error.
        */
 
-  void (*open)(const GstTensor_Filter *filter, void **private_data);
+  void (*open) (const GstTensor_Filter * filter, void **private_data);
       /**< Optional. tensor_filter.c will call this before any of other callbacks and will call once before calling close
        *
        * @param[in] filter "this" pointer. Use this to read property values
        * @param[in/out] private_data A subplugin may save its internal private data here. The subplugin is responsible for alloc/free of this pointer. Normally, open() allocates memory for private_data.
        */
-  void (*close)(const GstTensor_Filter *filter, void **private_data);
+  void (*close) (const GstTensor_Filter * filter, void **private_data);
       /**< Optional. tensor_filter.c will not call other callbacks after calling close. Free-ing private_data is this function's responsibility. Set NULL after that.
        *
        * @param[in] filter "this" pointer. Use this to read property values
@@ -177,5 +181,4 @@ extern GstTensor_Filter_Framework NNS_support_custom;
 extern GstTensor_Filter_Framework *tensor_filter_supported[];
 
 G_END_DECLS
-
 #endif /* __GST_TENSOR_FILTER_H__ */
index ebb7085..10bc5fb 100644 (file)
@@ -32,6 +32,9 @@
 #include <glib.h>
 #include <dlfcn.h>
 
+/**
+ * @brief internal_data
+ */
 struct _internal_data
 {
   GstTensor_Filter *parent;
@@ -140,8 +143,9 @@ custom_invoke (const GstTensor_Filter * filter, void **private_data,
     size_t size;
     uint8_t *retptr = ptr->methods->allocate_invoke (ptr->customFW_private_data,
         &(filter->prop), inptr, &size);
-    g_assert (size == (get_tensor_element_count (filter->prop.outputDimension) *
-            tensor_element_size[filter->prop.outputType]));
+    g_assert (size ==
+        (get_tensor_element_count (filter->prop.outputDimension[0]) *
+            tensor_element_size[filter->prop.outputType[0]]));
     return retptr;
   } else {
     return NULL;
index dce3a0b..b616694 100644 (file)
@@ -30,6 +30,7 @@
 #define __GST_TENSOR_TYPEDEF_H__
 
 #define NNS_TENSOR_RANK_LIMIT  (4)
+#define NNS_TENSOR_SIZE_LIMIT  (16)
 #define NNS_TENSOR_DIM_NULL ({0, 0, 0, 0})
 /**
  * @brief Possible data element types of other/tensor.
@@ -122,12 +123,15 @@ typedef struct _GstTensor_Filter_Properties
   int fwClosed; /**< true IF close() is called or tried. Use int instead of gboolean because this is refered by custom plugins. */
   const char *modelFilename; /**< Filepath to the model file (as an argument for NNFW). char instead of gchar for non-glib custom plugins */
 
-  tensor_dim inputDimension; /**< The input tensor dimension */
-  tensor_type inputType; /**< The type for each element in the input tensor */
+  tensor_dim inputDimension[NNS_TENSOR_SIZE_LIMIT]; /**< The list of dimensions of each input tensors */
+  tensor_type inputType[NNS_TENSOR_SIZE_LIMIT]; /**< The list of types for each input tensors */
   int inputCapNegotiated; /**< @todo check if this is really needed */
-  tensor_dim outputDimension; /**< The output tensor dimension */
-  tensor_type outputType; /**< The type for each element in the output tensor */
+  int inputTensorSize; /**< The number of input tensors */
+
+  tensor_dim outputDimension[NNS_TENSOR_SIZE_LIMIT]; /**< The list of dimensions of each output tensors */
+  tensor_type outputType[NNS_TENSOR_SIZE_LIMIT];  /**< The list of types for each output tensors */
   int outputCapNegotiated; /**< @todo check if this is really needed */
+  int outputTensorSize; /**< The number of output tensors */
 
   const char *customProperties; /**< sub-plugin specific custom property values in string */
 } GstTensor_Filter_Properties;
index 7b3fcdb..fb77cd8 100644 (file)
@@ -12,6 +12,7 @@
  * This scales a tensor of [N][y][x][M] to [N][1][1][M]
  *
  * This heavliy suffers from overflows. Do not use this for real applications!!!!!!
+ * @bug                No known bugs except for NYI items
  */
 
 #include <stdlib.h>
 #include <assert.h>
 #include <tensor_filter_custom.h>
 
+/**
+ * @brief _pt_data
+ */
 typedef struct _pt_data
 {
   uint32_t id; /***< Just for testing */
 } pt_data;
 
+/**
+ * @brief pt_init
+ */
 static void *
 pt_init (const GstTensor_Filter_Properties * prop)
 {
@@ -34,6 +41,9 @@ pt_init (const GstTensor_Filter_Properties * prop)
   return data;
 }
 
+/**
+ * @brief pt_exit
+ */
 static void
 pt_exit (void *private_data, const GstTensor_Filter_Properties * prop)
 {
@@ -42,6 +52,9 @@ pt_exit (void *private_data, const GstTensor_Filter_Properties * prop)
   free (data);
 }
 
+/**
+ * @brief set_inputDim
+ */
 static int
 set_inputDim (void *private_data, const GstTensor_Filter_Properties * prop,
     const tensor_dim iDim, const tensor_type iType,
@@ -63,27 +76,33 @@ set_inputDim (void *private_data, const GstTensor_Filter_Properties * prop,
 }
 
 
+/**
+ * @brief do_avg
+ */
 #define do_avg(type, sumtype) do {\
-      sumtype *avg = (sumtype *) malloc(sizeof(sumtype) * prop->inputDimension[0]); \
+      sumtype *avg = (sumtype *) malloc(sizeof(sumtype) * prop->inputDimension[0][0]); \
       type *iptr = (type *) inptr; \
       type *optr = (type *) outptr; \
-      for (z = 0; z < prop->inputDimension[3]; z++) { \
-        for (y = 0; y < prop->inputDimension[0]; y++) \
+      for (z = 0; z < prop->inputDimension[0][3]; z++) { \
+        for (y = 0; y < prop->inputDimension[0][0]; y++) \
           avg[y] = 0; \
-        for (y = 0; y < prop->inputDimension[2]; y++) { \
-          for (x = 0; x < prop->inputDimension[1]; x++) { \
-            for (c = 0; c < prop->inputDimension[0]; c++) { \
+        for (y = 0; y < prop->inputDimension[0][2]; y++) { \
+          for (x = 0; x < prop->inputDimension[0][1]; x++) { \
+            for (c = 0; c < prop->inputDimension[0][0]; c++) { \
               avg[c] += *(iptr + c + x * ix + y * iy + z * iz); \
             } \
           } \
         } \
-        for (c = 0; c < prop->inputDimension[0]; c++) { \
-          *(optr + c + z * prop->inputDimension[0]) = (type) (avg[c] / xy); \
+        for (c = 0; c < prop->inputDimension[0][0]; c++) { \
+          *(optr + c + z * prop->inputDimension[0][0]) = (type) (avg[c] / xy); \
         } \
       } \
       free(avg); \
   } while (0)
 
+/**
+ * @brief pt_invoke
+ */
 static int
 pt_invoke (void *private_data, const GstTensor_Filter_Properties * prop,
     const uint8_t * inptr, uint8_t * outptr)
@@ -91,12 +110,12 @@ pt_invoke (void *private_data, const GstTensor_Filter_Properties * prop,
   pt_data *data = private_data;
   uint32_t c, x, y, z;
 
-  unsigned ix = prop->inputDimension[0];
-  unsigned iy = prop->inputDimension[0] * prop->inputDimension[1];
+  unsigned ix = prop->inputDimension[0][0];
+  unsigned iy = prop->inputDimension[0][0] * prop->inputDimension[0][1];
   unsigned iz =
-      prop->inputDimension[0] * prop->inputDimension[1] *
-      prop->inputDimension[2];
-  unsigned xy = prop->inputDimension[1] * prop->inputDimension[2];
+      prop->inputDimension[0][0] * prop->inputDimension[0][1] *
+      prop->inputDimension[0][2];
+  unsigned xy = prop->inputDimension[0][1] * prop->inputDimension[0][2];
 
   assert (data);
   assert (inptr);
@@ -105,11 +124,11 @@ pt_invoke (void *private_data, const GstTensor_Filter_Properties * prop,
   /* This assumes the limit is 4 */
   assert (NNS_TENSOR_RANK_LIMIT == 4);
 
-  assert (prop->inputDimension[0] == prop->outputDimension[0]);
-  assert (prop->inputDimension[3] == prop->outputDimension[3]);
-  assert (prop->inputType == prop->outputType);
+  assert (prop->inputDimension[0][0] == prop->outputDimension[0][0]);
+  assert (prop->inputDimension[0][3] == prop->outputDimension[0][3]);
+  assert (prop->inputType[0] == prop->outputType[0]);
 
-  switch (prop->inputType) {
+  switch (prop->inputType[0]) {
     case _NNS_INT8:
       do_avg (int8_t, int64_t);
       break;
index 1f931e6..63a9765 100644 (file)
@@ -8,6 +8,7 @@
  * @date       22 Jun 2018
  * @brief      Custom NNStreamer Filter Example 2. "Pass-Through with Variable Dimensions"
  * @author     MyungJoo Ham <myungjoo.ham@samsung.com>
+ * @bug                No known bugs except for NYI items
  */
 
 #include <stdlib.h>
 #include <tensor_filter_custom.h>
 #include <tensor_common.h>
 
+/**
+ * @brief _pt_data
+ */
 typedef struct _pt_data
 {
   uint32_t id; /***< Just for testing */
 } pt_data;
 
+/**
+ * @brief pt_init
+ */
 static void *
 pt_init (const GstTensor_Filter_Properties * prop)
 {
@@ -30,6 +37,9 @@ pt_init (const GstTensor_Filter_Properties * prop)
   return data;
 }
 
+/**
+ * @brief pt_exit
+ */
 static void
 pt_exit (void *private_data, const GstTensor_Filter_Properties * prop)
 {
@@ -38,6 +48,9 @@ pt_exit (void *private_data, const GstTensor_Filter_Properties * prop)
   free (data);
 }
 
+/**
+ * @brief set_inputDim
+ */
 static int
 set_inputDim (void *private_data, const GstTensor_Filter_Properties * prop,
     const tensor_dim iDim, const tensor_type iType,
@@ -52,6 +65,9 @@ set_inputDim (void *private_data, const GstTensor_Filter_Properties * prop,
   return 0;
 }
 
+/**
+ * @brief pt_invoke
+ */
 static int
 pt_invoke (void *private_data, const GstTensor_Filter_Properties * prop,
     const uint8_t * inptr, uint8_t * outptr)
@@ -63,8 +79,8 @@ pt_invoke (void *private_data, const GstTensor_Filter_Properties * prop,
   g_assert (inptr);
   g_assert (outptr);
 
-  size = get_tensor_element_count (prop->outputDimension) *
-      tensor_element_size[prop->outputType];
+  size = get_tensor_element_count (prop->outputDimension[0]) *
+      tensor_element_size[prop->outputType[0]];
 
   g_assert (inptr != outptr);
   memcpy (outptr, inptr, size);
index d4cbeb8..b76c097 100644 (file)
@@ -146,37 +146,37 @@ pt_invoke (void *private_data, const GstTensor_Filter_Properties * prop,
   /* This assumes the limit is 4 */
   assert (NNS_TENSOR_RANK_LIMIT == 4);
 
-  assert (prop->inputDimension[0] == prop->outputDimension[0]);
-  assert (prop->inputDimension[3] == prop->outputDimension[3]);
-  assert (prop->inputType == prop->outputType);
+  assert (prop->inputDimension[0][0] == prop->outputDimension[0][0]);
+  assert (prop->inputDimension[0][3] == prop->outputDimension[0][3]);
+  assert (prop->inputType[0] == prop->outputType[0]);
 
-  elementsize = tensor_element_size[prop->inputType];
+  elementsize = tensor_element_size[prop->inputType[0]];
 
-  ox = (data->new_x > 0) ? data->new_x : prop->outputDimension[1];
-  oy = (data->new_y > 0) ? data->new_y : prop->outputDimension[2];
+  ox = (data->new_x > 0) ? data->new_x : prop->outputDimension[0][1];
+  oy = (data->new_y > 0) ? data->new_y : prop->outputDimension[0][2];
 
-  oidx0 = prop->outputDimension[0];
-  oidx1 = oidx0 * prop->outputDimension[1];
-  oidx2 = oidx1 * prop->outputDimension[2];
+  oidx0 = prop->outputDimension[0][0];
+  oidx1 = oidx0 * prop->outputDimension[0][1];
+  oidx2 = oidx1 * prop->outputDimension[0][2];
 
-  iidx0 = prop->inputDimension[0];
-  iidx1 = iidx0 * prop->inputDimension[1];
-  iidx2 = iidx1 * prop->inputDimension[2];
+  iidx0 = prop->inputDimension[0][0];
+  iidx1 = iidx0 * prop->inputDimension[0][1];
+  iidx2 = iidx1 * prop->inputDimension[0][2];
 
-  for (z = 0; z < prop->inputDimension[3]; z++) {
+  for (z = 0; z < prop->inputDimension[0][3]; z++) {
     for (y = 0; y < oy; y++) {
       for (x = 0; x < ox; x++) {
         unsigned int c;
-        for (c = 0; c < prop->inputDimension[0]; c++) {
+        for (c = 0; c < prop->inputDimension[0][0]; c++) {
           int sz;
           /* Output[y'][x'] = Input[ y' * y / new-y ][ x' * x / new-x ]. Yeah This is Way too Simple. But this is just an example :D */
           unsigned ix, iy;
 
-          ix = x * prop->inputDimension[1] / ox;
-          iy = y * prop->inputDimension[2] / oy;
+          ix = x * prop->inputDimension[0][1] / ox;
+          iy = y * prop->inputDimension[0][2] / oy;
 
-          assert (ix >= 0 && iy >= 0 && ix < prop->inputDimension[1]
-              && iy < prop->inputDimension[2]);
+          assert (ix >= 0 && iy >= 0 && ix < prop->inputDimension[0][1]
+              && iy < prop->inputDimension[0][2]);
 
           /* outptr[z][y][x][c] = inptr[z][iy][ix][c]; */
           for (sz = 0; sz < elementsize; sz++)
index bdc0a96..b3b2bfc 100644 (file)
@@ -142,8 +142,8 @@ pt_allocate_invoke (void *private_data,
   uint32_t iidx0, iidx1, iidx2;
 
   *size =
-      get_tensor_element_count (prop->outputDimension) *
-      tensor_element_size[prop->outputType];
+      get_tensor_element_count (prop->outputDimension[0]) *
+      tensor_element_size[prop->outputType[0]];
   uint8_t *outptr = (uint8_t *) malloc (sizeof (uint8_t) * *size);
 
   assert (data);
@@ -153,36 +153,36 @@ pt_allocate_invoke (void *private_data,
   /* This assumes the limit is 4 */
   assert (NNS_TENSOR_RANK_LIMIT == 4);
 
-  assert (prop->inputDimension[0] == prop->outputDimension[0]);
-  assert (prop->inputDimension[3] == prop->outputDimension[3]);
-  assert (prop->inputType == prop->outputType);
+  assert (prop->inputDimension[0][0] == prop->outputDimension[0][0]);
+  assert (prop->inputDimension[0][3] == prop->outputDimension[0][3]);
+  assert (prop->inputType[0] == prop->outputType[0]);
 
-  elementsize = tensor_element_size[prop->inputType];
+  elementsize = tensor_element_size[prop->inputType[0]];
 
-  ox = (data->new_x > 0) ? data->new_x : prop->outputDimension[1];
-  oy = (data->new_y > 0) ? data->new_y : prop->outputDimension[2];
+  ox = (data->new_x > 0) ? data->new_x : prop->outputDimension[0][1];
+  oy = (data->new_y > 0) ? data->new_y : prop->outputDimension[0][2];
 
-  oidx0 = prop->outputDimension[0];
-  oidx1 = oidx0 * prop->outputDimension[1];
-  oidx2 = oidx1 * prop->outputDimension[2];
+  oidx0 = prop->outputDimension[0][0];
+  oidx1 = oidx0 * prop->outputDimension[0][1];
+  oidx2 = oidx1 * prop->outputDimension[0][2];
 
-  iidx0 = prop->inputDimension[0];
-  iidx1 = iidx0 * prop->inputDimension[1];
-  iidx2 = iidx1 * prop->inputDimension[2];
+  iidx0 = prop->inputDimension[0][0];
+  iidx1 = iidx0 * prop->inputDimension[0][1];
+  iidx2 = iidx1 * prop->inputDimension[0][2];
 
-  for (z = 0; z < prop->inputDimension[3]; z++) {
+  for (z = 0; z < prop->inputDimension[0][3]; z++) {
     for (y = 0; y < oy; y++) {
       for (x = 0; x < ox; x++) {
         unsigned int c;
-        for (c = 0; c < prop->inputDimension[0]; c++) {
+        for (c = 0; c < prop->inputDimension[0][0]; c++) {
           /* Output[y'][x'] = Input[ y' * y / new-y ][ x' * x / new-x ]. Yeah This is Way too Simple. But this is just an example :D */
           unsigned ix, iy, sz;
 
-          ix = x * prop->inputDimension[1] / ox;
-          iy = y * prop->inputDimension[2] / oy;
+          ix = x * prop->inputDimension[0][1] / ox;
+          iy = y * prop->inputDimension[0][2] / oy;
 
-          assert (ix >= 0 && iy >= 0 && ix < prop->inputDimension[1]
-              && iy < prop->inputDimension[2]);
+          assert (ix >= 0 && iy >= 0 && ix < prop->inputDimension[0][1]
+              && iy < prop->inputDimension[0][2]);
 
           /* outptr[z][y][x][c] = inptr[z][iy][ix][c]; */
           for (sz = 0; sz < elementsize; sz++)