From cade400b27a065daf1c40452e9bfed6c38a474a8 Mon Sep 17 00:00:00 2001 From: HyoungjooAhn Date: Thu, 9 Aug 2018 20:03:46 +0900 Subject: [PATCH] [Filter] change properties for one tensors to array for now, the first index(0) will be used before multi tensor environment Signed-off-by: HyoungjooAhn --- gst/tensor_filter/tensor_filter.c | 153 +++++++++++---------- gst/tensor_filter/tensor_filter.h | 31 +++-- gst/tensor_filter/tensor_filter_custom.c | 8 +- include/tensor_typedef.h | 12 +- .../nnstreamer_customfilter_example_average.c | 53 ++++--- ...mer_customfilter_example_passthrough_variable.c | 20 ++- .../nnstreamer_customfilter_example_scaler.c | 36 ++--- ...treamer_customfilter_example_scaler_allocator.c | 40 +++--- 8 files changed, 204 insertions(+), 149 deletions(-) diff --git a/gst/tensor_filter/tensor_filter.c b/gst/tensor_filter/tensor_filter.c index b9f1bf7..fa2fcc2 100644 --- a/gst/tensor_filter/tensor_filter.c +++ b/gst/tensor_filter/tensor_filter.c @@ -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; diff --git a/gst/tensor_filter/tensor_filter.h b/gst/tensor_filter/tensor_filter.h index 44e9a5b..29fbd46 100644 --- a/gst/tensor_filter/tensor_filter.h +++ b/gst/tensor_filter/tensor_filter.h @@ -36,7 +36,6 @@ #include 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 char* nnfw_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__ */ diff --git a/gst/tensor_filter/tensor_filter_custom.c b/gst/tensor_filter/tensor_filter_custom.c index ebb7085..10bc5fb 100644 --- a/gst/tensor_filter/tensor_filter_custom.c +++ b/gst/tensor_filter/tensor_filter_custom.c @@ -32,6 +32,9 @@ #include #include +/** + * @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; diff --git a/include/tensor_typedef.h b/include/tensor_typedef.h index dce3a0b..b616694 100644 --- a/include/tensor_typedef.h +++ b/include/tensor_typedef.h @@ -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; diff --git a/nnstreamer_example/custom_example_average/nnstreamer_customfilter_example_average.c b/nnstreamer_example/custom_example_average/nnstreamer_customfilter_example_average.c index 7b3fcdb..fb77cd8 100644 --- a/nnstreamer_example/custom_example_average/nnstreamer_customfilter_example_average.c +++ b/nnstreamer_example/custom_example_average/nnstreamer_customfilter_example_average.c @@ -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 @@ -20,11 +21,17 @@ #include #include +/** + * @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; 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 1f931e6..63a9765 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 @@ -8,6 +8,7 @@ * @date 22 Jun 2018 * @brief Custom NNStreamer Filter Example 2. "Pass-Through with Variable Dimensions" * @author MyungJoo Ham + * @bug No known bugs except for NYI items */ #include @@ -16,11 +17,17 @@ #include #include +/** + * @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); diff --git a/nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler.c b/nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler.c index d4cbeb8..b76c097 100644 --- a/nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler.c +++ b/nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler.c @@ -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++) diff --git a/nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler_allocator.c b/nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler_allocator.c index bdc0a96..b3b2bfc 100644 --- a/nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler_allocator.c +++ b/nnstreamer_example/custom_example_scaler/nnstreamer_customfilter_example_scaler_allocator.c @@ -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++) -- 2.7.4