refactor tensor-filter to support multi-tensors (other/tensors).
tf and tf-lte should be updated later for multi-tensors.
1. add common GstTensorsInfo in tensor-filter and parse from NN model
2. change NN framework properties
3. fix the bug in common functions for multi-tensors
4. remove space to get tensor dim and type in common function
Signed-off-by: Jaeyun Jung <jy1210.jung@samsung.com>
/** [size][frames] */
config->info.dimension[0] = GST_TENSOR_STRING_SIZE; /** fixed size of string */
- config->info.dimension[1] = 1; /** Supposed 1 frame in tensor,, change this if tensor contains N frames */
+ config->info.dimension[1] = 1; /** Supposed 1 frame in tensor, change this if tensor contains N frames */
config->info.dimension[2] = 1;
config->info.dimension[3] = 1;
const GstStructure * structure)
{
const gchar *name;
- guint i, j;
+ guint i;
g_return_val_if_fail (config != NULL, FALSE);
gst_tensors_config_init (config);
const gchar *dims_string;
const gchar *types_string;
- gst_structure_get_uint (structure, "num_tensors",
- &config->info.num_tensors);
+ gst_structure_get_int (structure, "num_tensors",
+ (gint *) (&config->info.num_tensors));
gst_structure_get_fraction (structure, "framerate", &config->rate_n,
&config->rate_d);
/* parse dimensions */
dims_string = gst_structure_get_string (structure, "dimensions");
if (dims_string) {
- gchar **str_dim, **str_dims;
- gint num_dim, num_dims;
- guint64 val;
+ gchar **str_dims;
+ gint num_dims;
str_dims = g_strsplit (dims_string, ",", -1);
num_dims = g_strv_length (str_dims);
}
for (i = 0; i < num_dims; i++) {
- str_dim = g_strsplit (str_dims[i], ":", NNS_TENSOR_RANK_LIMIT);
- num_dim = g_strv_length (str_dim);
-
- for (j = 0; j < num_dim; j++) {
- val = g_ascii_strtoull (str_dim[j], NULL, 10);
- config->info.info[i].dimension[j] = (uint32_t) val;
- }
-
- for (; j < NNS_TENSOR_RANK_LIMIT; j++) {
- config->info.info[i].dimension[j] = 1;
- }
-
- g_strfreev (str_dim);
+ get_tensor_dimension (str_dims[i], config->info.info[i].dimension);
}
g_strfreev (str_dims);
gchar **str_types;
gint num_types;
- str_types = g_strsplit (dims_string, ",", -1);
+ str_types = g_strsplit (types_string, ",", -1);
num_types = g_strv_length (str_types);
if (config->info.num_tensors != num_types) {
if (config->info.num_tensors > 0) {
GString *dimensions = g_string_new (NULL);
GString *types = g_string_new (NULL);
+ gchar *dim_str;
/** dimensions and types */
for (i = 0; i < config->info.num_tensors; i++) {
- /**
- * @note supposed dimension with rank 4 (NNS_TENSOR_RANK_LIMIT)
- */
- gchar *dim_string = g_strdup_printf ("%d:%d:%d:%d",
- config->info.info[i].dimension[0], config->info.info[i].dimension[1],
- config->info.info[i].dimension[2], config->info.info[i].dimension[3]);
-
- dimensions = g_string_append (dimensions, dim_string);
- types =
- g_string_append (types,
+ dim_str = get_tensor_dimension_string (config->info.info[i].dimension);
+
+ g_string_append (dimensions, dim_str);
+ g_string_append (types,
tensor_element_typename[config->info.info[i].type]);
if (i < config->info.num_tensors - 1) {
- dimensions = g_string_append (dimensions, ",");
- types = g_string_append (types, ",");
+ g_string_append (dimensions, ",");
+ g_string_append (types, ",");
}
- g_free (dim_string);
+ g_free (dim_str);
}
gst_caps_set_simple (caps, "num_tensors", G_TYPE_INT,
get_tensor_type (const gchar * typestr)
{
int len;
+ gchar *type_string;
+ tensor_type type = _NNS_END;
+
+ g_return_val_if_fail (typestr != NULL, _NNS_END);
+
+ /** remove spaces */
+ type_string = g_strdup (typestr);
+ g_strstrip (type_string);
- if (!typestr)
- return _NNS_END;
- len = strlen (typestr);
+ len = strlen (type_string);
- if (typestr[0] == 'u' || typestr[0] == 'U') {
+ if (type_string[0] == 'u' || type_string[0] == 'U') {
/**
* Let's believe the developer and the following three letters are "int"
* (case insensitive)
*/
if (len == 6) { /* uint16, uint32 */
- if (typestr[4] == '1' && typestr[5] == '6')
- return _NNS_UINT16;
- else if (typestr[4] == '3' && typestr[5] == '2')
- return _NNS_UINT32;
- else if (typestr[4] == '6' && typestr[5] == '4')
- return _NNS_UINT64;
+ if (type_string[4] == '1' && type_string[5] == '6')
+ type = _NNS_UINT16;
+ else if (type_string[4] == '3' && type_string[5] == '2')
+ type = _NNS_UINT32;
+ else if (type_string[4] == '6' && type_string[5] == '4')
+ type = _NNS_UINT64;
} else if (len == 5) { /* uint8 */
- if (typestr[4] == '8')
- return _NNS_UINT8;
+ if (type_string[4] == '8')
+ type = _NNS_UINT8;
}
- } else if (typestr[0] == 'i' || typestr[0] == 'I') {
+ } else if (type_string[0] == 'i' || type_string[0] == 'I') {
/**
* Let's believe the developer and the following two letters are "nt"
* (case insensitive)
*/
if (len == 5) { /* int16, int32 */
- if (typestr[3] == '1' && typestr[4] == '6')
- return _NNS_INT16;
- else if (typestr[3] == '3' && typestr[4] == '2')
- return _NNS_INT32;
- else if (typestr[3] == '6' && typestr[4] == '4')
- return _NNS_INT64;
+ if (type_string[3] == '1' && type_string[4] == '6')
+ type = _NNS_INT16;
+ else if (type_string[3] == '3' && type_string[4] == '2')
+ type = _NNS_INT32;
+ else if (type_string[3] == '6' && type_string[4] == '4')
+ type = _NNS_INT64;
} else if (len == 4) { /* int8 */
- if (typestr[3] == '8')
- return _NNS_INT8;
+ if (type_string[3] == '8')
+ type = _NNS_INT8;
}
- return _NNS_END;
- } else if (typestr[0] == 'f' || typestr[0] == 'F') {
+ } else if (type_string[0] == 'f' || type_string[0] == 'F') {
/* Let's assume that the following 4 letters are "loat" */
if (len == 7) {
- if (typestr[5] == '6' && typestr[6] == '4')
- return _NNS_FLOAT64;
- else if (typestr[5] == '3' && typestr[6] == '2')
- return _NNS_FLOAT32;
+ if (type_string[5] == '6' && type_string[6] == '4')
+ type = _NNS_FLOAT64;
+ else if (type_string[5] == '3' && type_string[6] == '2')
+ type = _NNS_FLOAT32;
}
}
- return _NNS_END;
+ g_free (type_string);
+ return type;
}
/**
/**
* @brief Parse tensor dimension parameter string
* @return The Rank. 0 if error.
- * @param param The parameter string in the format of d1:d2:d3:d4, d1:d2:d3, d1:d2, or d1, where dN is a positive integer and d1 is the innermost dimension; i.e., dim[d4][d3][d2][d1];
+ * @param dimstr The dimension string in the format of d1:d2:d3:d4, d1:d2:d3, d1:d2, or d1, where dN is a positive integer and d1 is the innermost dimension; i.e., dim[d4][d3][d2][d1];
+ * @param dim dimension to be filled.
*/
int
-get_tensor_dimension (const gchar * param,
- uint32_t dim[NNS_TENSOR_SIZE_LIMIT][NNS_TENSOR_RANK_LIMIT])
+get_tensor_dimension (const gchar * dimstr, tensor_dim dim)
{
- int i, j = 0;
+ int rank = 0;
guint64 val;
- gchar **_strv = g_strsplit (param, ",./", -1);
- gint num_tensor = g_strv_length (_strv);
+ gchar **strv;
+ gchar *dim_string;
+ gint i, num_dims;
- for (i = 0; i < num_tensor; i++) {
- gchar **strv = g_strsplit (_strv[i], ":", NNS_TENSOR_RANK_LIMIT);
+ g_return_val_if_fail (dimstr != NULL, 0);
- g_assert (strv != NULL);
+ /** remove spaces */
+ dim_string = g_strdup (dimstr);
+ g_strstrip (dim_string);
- for (j = 0; j < NNS_TENSOR_RANK_LIMIT; j++) {
- if (strv[j] == NULL)
- break;
- val = g_ascii_strtoull (strv[j], NULL, 10);
- dim[i][j] = val;
- }
- for (; j < NNS_TENSOR_RANK_LIMIT; j++)
- dim[i][j] = 1;
- g_strfreev (strv);
+ strv = g_strsplit (dim_string, ":", NNS_TENSOR_RANK_LIMIT);
+ num_dims = g_strv_length (strv);
+
+ for (i = 0; i < num_dims; i++) {
+ g_strstrip (strv[i]);
+ if (strv[i] == NULL || strlen (strv[i]) == 0)
+ break;
+
+ val = g_ascii_strtoull (strv[i], NULL, 10);
+ dim[i] = (uint32_t) val;
+ rank = i + 1;
}
- g_strfreev (_strv);
+ for (; i < NNS_TENSOR_RANK_LIMIT; i++)
+ dim[i] = 1;
+
+ g_strfreev (strv);
+ g_free (dim_string);
+ return rank;
+}
+
+/**
+ * @brief Get dimension string from given tensor dimension.
+ * @param dim tensor dimension
+ * @return Formatted string of given dimension (d1:d2:d3:d4).
+ * @note The returned value should be freed with g_free()
+ */
+gchar *
+get_tensor_dimension_string (const tensor_dim dim)
+{
+ gint i;
+ GString *dim_str;
+
+ dim_str = g_string_new (NULL);
+
+ for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++) {
+ g_string_append_printf (dim_str, "%d", dim[i]);
- return num_tensor;
+ if (i < NNS_TENSOR_RANK_LIMIT - 1) {
+ g_string_append (dim_str, ":");
+ }
+ }
+
+ return g_string_free (dim_str, FALSE);
}
/**
}
/**
- * @brief internal static function to trim the front.
- */
-static const gchar *
-ftrim (const gchar * str)
-{
- if (!str)
- return str;
- while (*str && (*str == ' ' || *str == '\t')) {
- str++;
- }
- return str;
-}
-
-/**
- * @brief Extract other/tensors dim/type from GstStructure
- */
-int
-get_tensors_from_structure (const GstStructure * str,
- GstTensor_TensorsMeta * meta, int *framerate_num, int *framerate_denom)
-{
- int num = 0;
- const gchar *strval;
- gint fn = 0, fd = 0;
- gchar **strv;
- int counter = 0;
-
- if (!gst_structure_has_name (str, "other/tensors"))
- return 0;
-
- if (gst_structure_get_int (str, "num_tensors", (int *) &num)) {
- if (num > 16 || num < 1)
- num = 0;
- }
- if (0 == num)
- return 0;
-
- meta->num_tensors = num;
-
- if (gst_structure_get_fraction (str, "framerate", &fn, &fd)) {
- if (framerate_num)
- *framerate_num = fn;
- if (framerate_denom)
- *framerate_denom = fd;
- }
-
- strval = gst_structure_get_string (str, "dimensions");
-
- counter = get_tensor_dimension (strval, meta->dims);
-
- if (counter != num) {
- err_print
- ("The number of dimensions does not match the number of tensors.\n");
- return 0;
- }
-
- strval = gst_structure_get_string (str, "types");
- strv = g_strsplit (strval, ",", -1);
- counter = 0;
- while (strv[counter]) {
- if (counter >= num) {
- err_print ("The number of types does not match the number of tensors.\n");
- return 0;
- }
- meta->types[counter] = get_tensor_type (ftrim (strv[counter]));
- if (meta->types[counter] >= _NNS_END)
- return 0;
- counter++;
- }
- if (counter != num) {
- err_print ("The number of types does not match the number of tensors.\n");
- return 0;
- }
- g_strfreev (strv);
- return num;
-}
-
-/**
* @brief Get tensor dimension/type from GstCaps
*/
GstTensor_Filter_CheckStatus
* SECTION:element-tensor_filter
*
* A filter that converts media stream to tensor stream for NN frameworks.
- * The output is always in the format of other/tensor
+ * The output is always in the format of other/tensor or other/tensors.
*
* <refsect2>
* <title>Example launch line</title>
#include "tensor_filter.h"
-GstTensor_Filter_Framework *tensor_filter_supported[] = {
+/**
+ * @brief Macro for debug mode.
+ */
+#ifndef DBG
+#define DBG (!self->silent)
+#endif
+
+/**
+ * @brief Macro for debug message.
+ */
+#define silent_debug(...) \
+ debug_print (DBG, __VA_ARGS__)
+
+#define silent_debug_caps(caps,msg) do {\
+ if (DBG) { \
+ if (caps) { \
+ GstStructure *caps_s; \
+ gchar *caps_s_string; \
+ guint caps_size, caps_idx; \
+ caps_size = gst_caps_get_size (caps);\
+ for (caps_idx = 0; caps_idx < caps_size; caps_idx++) { \
+ caps_s = gst_caps_get_structure (caps, caps_idx); \
+ caps_s_string = gst_structure_to_string (caps_s); \
+ debug_print (TRUE, msg " = %s\n", caps_s_string); \
+ g_free (caps_s_string); \
+ } \
+ } \
+ } \
+} while (0)
+
+GstTensorFilterFramework *tensor_filter_supported[] = {
[_T_F_UNDEFINED] = NULL,
[_T_F_CUSTOM] = &NNS_support_custom,
GST_DEBUG_CATEGORY_STATIC (gst_tensor_filter_debug);
#define GST_CAT_DEFAULT gst_tensor_filter_debug
-/* Filter signals and args */
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
-
+/**
+ * @brief GstTensorFilter properties.
+ */
enum
{
PROP_0,
};
/**
+ * @brief Default caps string for both sink and source pad.
+ */
+#define CAPS_STRING GST_TENSOR_CAP_DEFAULT "; " GST_TENSORS_CAP_DEFAULT
+
+/**
* @brief The capabilities of the inputs
*/
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_TENSOR_CAP_DEFAULT));
+ GST_STATIC_CAPS (CAPS_STRING));
/**
* @brief The capabilities of the outputs
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_TENSOR_CAP_DEFAULT));
+ GST_STATIC_CAPS (CAPS_STRING));
#define gst_tensor_filter_parent_class parent_class
-G_DEFINE_TYPE (GstTensor_Filter, gst_tensor_filter, GST_TYPE_BASE_TRANSFORM);
+G_DEFINE_TYPE (GstTensorFilter, gst_tensor_filter, GST_TYPE_BASE_TRANSFORM);
+/* GObject vmethod implementations */
static void gst_tensor_filter_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_tensor_filter_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
-/* GstBaseTransformer vmethod implementations */
+/* GstBaseTransform vmethod implementations */
static GstFlowReturn gst_tensor_filter_transform (GstBaseTransform * trans,
GstBuffer * inbuf, GstBuffer * outbuf);
static GstFlowReturn gst_tensor_filter_transform_ip (GstBaseTransform * trans,
GstCaps * othercaps, gsize * othersize);
static gboolean gst_tensor_filter_start (GstBaseTransform * trans);
static gboolean gst_tensor_filter_stop (GstBaseTransform * trans);
-/* GObject vmethod implementations */
+
+/**
+ * @brief Invoke callbacks of filter->prop.fw. Guarantees calling open for the first call.
+ */
+#define gst_tensor_filter_call(filter,ret,funcname,...) do { \
+ if (filter->prop.fw_opened == FALSE) { \
+ if (filter->prop.fw->open != NULL) \
+ filter->prop.fw->open (filter, &filter->privateData); \
+ filter->prop.fw_opened = TRUE; \
+ } \
+ ret = filter->prop.fw->funcname (filter, &filter->privateData, __VA_ARGS__); \
+ } while(0)
+
+/**
+ * @brief Close nn framework.
+ */
+#define gst_tensor_filter_close(filter) do { \
+ g_assert (filter->prop.fw_opened); \
+ if (filter->prop.fw->close) \
+ filter->prop.fw->close (filter, &filter->privateData); \
+ filter->prop.fw_opened = FALSE; \
+ } while (0)
/**
* @brief initialize the tensor_filter's class
*/
static void
-gst_tensor_filter_class_init (GstTensor_FilterClass * g_class)
+gst_tensor_filter_class_init (GstTensorFilterClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstBaseTransformClass *trans_class;
- GstTensor_FilterClass *klass;
- klass = (GstTensor_FilterClass *) g_class;
trans_class = (GstBaseTransformClass *) klass;
gstelement_class = (GstElementClass *) trans_class;
gobject_class = (GObjectClass *) gstelement_class;
gobject_class->get_property = gst_tensor_filter_get_property;
g_object_class_install_property (gobject_class, PROP_SILENT,
- g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?",
- FALSE, G_PARAM_READWRITE));
+ g_param_spec_boolean ("silent", "Silent", "Produce verbose output",
+ FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_FRAMEWORK,
g_param_spec_string ("framework", "Framework",
- "Neural network framework ?", "", G_PARAM_READWRITE));
+ "Neural network framework", "",
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_MODEL,
g_param_spec_string ("model", "Model filepath",
- "Filepath to the model file ?", "", G_PARAM_READWRITE));
+ "File path to the model file", "",
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_INPUT,
g_param_spec_string ("input", "Input dimension",
"Input tensor dimension from inner array, upto 4 dimensions ?", "",
- G_PARAM_READWRITE));
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_INPUTTYPE,
g_param_spec_string ("inputtype", "Input tensor element type",
- "Type of each element of the input tensor ?", "uint8",
- G_PARAM_READWRITE));
+ "Type of each element of the input tensor ?", "",
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_OUTPUT,
g_param_spec_string ("output", "Output dimension",
"Output tensor dimension from inner array, upto 4 dimensions ?", "",
- G_PARAM_READWRITE));
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_OUTPUTTYPE,
g_param_spec_string ("outputtype", "Output tensor element type",
- "Type of each element of the output tensor ?", "uint8",
- G_PARAM_READWRITE));
+ "Type of each element of the output tensor ?", "",
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_CUSTOM,
g_param_spec_string ("custom", "Custom properties for subplugins",
- "Custom properties for subplugins ?", "", G_PARAM_READWRITE));
+ "Custom properties for subplugins ?", "",
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gst_element_class_set_details_simple (gstelement_class,
"Tensor_Filter",
- "NN Frameworks (e.g., tensorflow) as Media Filters",
+ "Converter/Filter/Tensor",
"Handles NN Frameworks (e.g., tensorflow) as Media Filters with other/tensor type stream",
"MyungJoo Ham <myungjoo.ham@samsung.com>");
* 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)
+gst_tensor_filter_init (GstTensorFilter * self)
{
- int i;
- GstTensor_Filter_Properties *prop = &filter->prop;
+ GstTensorFilterProperties *prop;
- prop->silent = TRUE;
+ prop = &self->prop;
+
+ /* init NNFW properties */
prop->nnfw = _T_F_UNDEFINED;
prop->fw = NULL;
- prop->fwOpened = FALSE;
- prop->fwClosed = FALSE;
- prop->inputConfigured = _TFC_INIT;
- prop->outputConfigured = _TFC_INIT;
- prop->modelFilename = NULL;
-
- for (i = 0; i < NNS_TENSOR_SIZE_LIMIT; i++) {
- prop->inputMeta.dims[i][0] = 1; /* innermost */
- prop->inputMeta.dims[i][1] = 1;
- prop->inputMeta.dims[i][2] = 1;
- prop->inputMeta.dims[i][3] = 1; /* out */
- prop->inputMeta.types[i] = _NNS_END; /* not initialized */
-
- prop->outputMeta.dims[i][0] = 1; /* innermost */
- prop->outputMeta.dims[i][1] = 1;
- prop->outputMeta.dims[i][2] = 1;
- prop->outputMeta.dims[i][3] = 1; /* out */
- prop->outputMeta.types[i] = _NNS_END; /* not initialized */
- }
-
- prop->inputCapNegotiated = FALSE;
- prop->outputCapNegotiated = FALSE;
-
- prop->customProperties = NULL;
- filter->privateData = NULL; /* mark not initialized. */
+ prop->fw_opened = FALSE;
+ prop->input_configured = FALSE;
+ prop->output_configured = FALSE;
+ prop->model_file = NULL;
+ prop->custom_properties = NULL;
+ gst_tensors_info_init (&prop->input_meta);
+ gst_tensors_info_init (&prop->output_meta);
+
+ /* init internal properties */
+ self->privateData = NULL;
+ self->silent = TRUE;
+ self->configured = FALSE;
+ gst_tensors_config_init (&self->in_config);
+ gst_tensors_config_init (&self->out_config);
}
-#define silent_debug(...) debug_print (!prop->silent, __VA_ARGS__)
-
-/**
- * @brief Invoke callbacks of filter->prop.fw. Gurantees calling open for the first call.
- */
-#define gst_tensor_filter_call(filter, ret, funcname, ...) do { \
- if (filter->prop.fwOpened == FALSE) { \
- if (filter->prop.fw->open != NULL) \
- filter->prop.fw->open(filter, &filter->privateData); \
- filter->prop.fwOpened = TRUE; \
- } \
- g_assert(filter->prop.fwClosed != TRUE); \
- ret = filter->prop.fw->funcname(filter, &filter->privateData, __VA_ARGS__); \
- } while(0)
-
-/** @todo Call this where appropriate */
-#define gst_tensor_filter_close(filter) \
- do { \
- g_assert(filter->prop.fwClosed != TRUE); \
- g_assert(filter->prop.fwOpened == TRUE); \
- if (filter->prop.fw->close) \
- filter->prop.fw->close(filter, &filter->privateData); \
- filter->prop.fw->fwClosed = TRUE; \
- } while (0);
-
-static GstTensor_Filter_CheckStatus
-gst_tensor_filter_generate_dim_from_cap (GstCaps * caps, const tensor_dim dim,
- tensor_type * type);
/**
- * @brief Find caps based on i/o configuration or from the 'other' cap
- * @param filter "this" object
- * @param isInput TRUE if the "source" is input(sinkpad) and "target" is output(srcpad0
- * @param fromCaps The "source" cap given
- * @return The "target" cap from "source" cap.
- *
- * We need both type and dimension to do this.
- * This is supposed to be used by set_properties, restrting pad-caps before attaching input/output elements
- *
- * @todo Looks like this is buggy!!!
+ * @brief Calculate output buffer size.
+ * @param self "this" pointer
+ * @param index index of output tensors (if index < 0, the size of all output tensors will be returned.)
+ * @return output buffer size
*/
-static GstCaps *
-gst_tensor_filter_fix_caps (GstTensor_Filter * filter, gboolean isInput,
- GstCaps * fromCaps)
+static gsize
+gst_tensor_filter_out_size (GstTensorFilter * self, gint index)
{
- tensor_type *type = NULL, _type[NNS_TENSOR_SIZE_LIMIT];
- const 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;
- GstStaticCaps rawcap = GST_STATIC_CAPS (GST_TENSOR_CAP_DEFAULT);
- staticcap = gst_static_caps_get (&rawcap);
-
- if (isInput == TRUE) {
- type = prop->inputMeta.types;
- int i;
- for (i = 0; i < NNS_TENSOR_SIZE_LIMIT; i++) {
- dimension[i] = prop->inputMeta.dims[i];
- }
- configured = prop->inputConfigured & _TFC_ALL;
- } else {
- type = prop->outputMeta.types;
- int i;
- for (i = 0; i < NNS_TENSOR_SIZE_LIMIT; i++) {
- dimension[i] = prop->outputMeta.dims[i];
- }
- configured = prop->outputConfigured & _TFC_ALL;
- }
-
- /* 2. configure caps based on type & dimension */
- if (configured == _TFC_ALL) {
- tmp2 =
- gst_caps_new_simple ("other/tensor", "type",
- 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) {
- tmp2 =
- gst_caps_new_simple ("other/tensor", "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_TYPE) {
- tmp2 =
- gst_caps_new_simple ("other/tensor", "type", G_TYPE_STRING,
- tensor_element_typename[type[0]], NULL);
- tmp = gst_caps_intersect_full (staticcap, tmp2, GST_CAPS_INTERSECT_FIRST);
- gst_caps_unref (tmp2);
- } else {
- /* knows nothing. This happens.. */
- tmp2 = gst_caps_new_any ();
- tmp = gst_caps_intersect_full (staticcap, tmp2, GST_CAPS_INTERSECT_FIRST);
- gst_caps_unref (tmp2);
- }
+ GstTensorsInfo *info;
+ guint i;
+ gsize out_size = 0;
- if (fromCaps) {
- gchar *str;
- if (prop->silent == FALSE) {
- str = gst_caps_to_string (fromCaps);
- debug_print (TRUE, "fromCaps: %s\n", str);
- g_free (str);
+ g_assert (self->configured);
- str = gst_caps_to_string (tmp);
- debug_print (TRUE, "filter: %s\n", str);
- g_free (str);
- }
- tmp2 = gst_caps_intersect_full (fromCaps, tmp, GST_CAPS_INTERSECT_FIRST);
- gst_caps_unref (tmp);
- tmp = tmp2;
- if (prop->silent == FALSE) {
- str = gst_caps_to_string (tmp);
- debug_print (TRUE, "filtered fromCaps: %s\n", str);
- g_free (str);
- }
- } else {
- if (prop->silent == FALSE) {
- gchar *str = gst_caps_to_string (tmp);
- debug_print (TRUE, "not filtered fromCaps: %s\n", str);
- g_free (str);
- }
- }
-
- /* 2-2. Extract effective dim info from tmp */
- dimension[0] = dim[0];
- configured =
- gst_tensor_filter_generate_dim_from_cap (tmp, dimension[0], &_type[0]);
- configured &= _TFC_ALL;
- /* tmp is no more needed */
- gst_caps_unref (tmp);
-
- /* 3. Calculate resultcap from fromcap. */
- if (isInput == TRUE) {
- /* result == srcpad (output) */
- GstTensor_TensorsMeta outputMeta;
- int ret = -1;
-
- /* 3-1-1. Try get output dim for srcpad */
- if (prop->fw->getOutputDimension) {
- gst_tensor_filter_call (filter, ret, getOutputDimension, &outputMeta);
- }
- /* 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[0],
- _type[0], outputMeta.dims[0], &outputMeta.types[0]);
- }
- /* if ret == 0, either get or set has been successful. */
- if (ret != 0) {
- /* We do not have enough info for dimension */
- /* knows nothing. This happens.. */
- tmp = gst_caps_new_any ();
- resultCaps =
- gst_caps_intersect_full (staticcap, tmp, GST_CAPS_INTERSECT_FIRST);
- gst_caps_unref (tmp);
- }
+ info = &self->out_config.info;
- /* 3-1.2. Configure resultCap from rdim/rtype */
- if (resultCaps == NULL) {
- resultCaps =
- gst_caps_new_simple ("other/tensor", "type",
- G_TYPE_STRING, tensor_element_typename[outputMeta.types[0]], "dim1",
- G_TYPE_INT, outputMeta.dims[0][0], "dim2", G_TYPE_INT,
- outputMeta.dims[0][1], "dim3", G_TYPE_INT, outputMeta.dims[0][2],
- "dim4", G_TYPE_INT, outputMeta.dims[0][3], NULL);
+ if (index < 0) {
+ /** calculate all output tensors */
+ for (i = 0; i < info->num_tensors; i++) {
+ out_size +=
+ get_tensor_element_count (info->info[i].dimension) *
+ tensor_element_size[info->info[i].type];
}
} else {
- /* result == sinkpad (input) */
- GstTensor_TensorsMeta meta;
- int ret = -1;
+ g_assert (index < info->num_tensors);
- /* 3-1-1. Try get output dim for srcpad */
- if (prop->fw->getInputDimension) {
- gst_tensor_filter_call (filter, ret, getInputDimension, &meta);
- }
- if (ret != 0) {
- /* We do not have output->input dimension conversion. */
- /* knows nothing. This happens.. */
- tmp = gst_caps_new_any ();
- resultCaps =
- gst_caps_intersect_full (staticcap, tmp, GST_CAPS_INTERSECT_FIRST);
- gst_caps_unref (tmp);
- }
-
- /* 3-1.2. Configure resultCap from rdim/rtype */
- if (resultCaps == NULL) {
- resultCaps =
- gst_caps_new_simple ("other/tensor",
- "type", G_TYPE_STRING, tensor_element_typename[meta.types[0]], "dim1",
- G_TYPE_INT, meta.dims[0][0], "dim2", G_TYPE_INT, meta.dims[0][1],
- "dim3", G_TYPE_INT, meta.dims[0][2], "dim4", G_TYPE_INT,
- meta.dims[0][3], NULL);
- }
+ out_size =
+ get_tensor_element_count (info->info[index].dimension) *
+ tensor_element_size[info->info[index].type];
}
- /** @todo 5. Verify with get_input/output_dimension callbacks! */
- gst_caps_unref (staticcap);
-
- return resultCaps;
+ return out_size;
}
/**
- * @brief @todo fill this in
+ * @brief Setter for tensor_filter properties.
*/
static void
gst_tensor_filter_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
- GstTensor_Filter *filter = GST_TENSOR_FILTER (object);
- GstTensor_Filter_Properties *prop = &filter->prop;
- GstTensor_Filter_Framework *fw = prop->fw;
+ GstTensorFilter *self;
+ GstTensorFilterProperties *prop;
+
+ self = GST_TENSOR_FILTER (object);
+ prop = &self->prop;
- silent_debug ("Setting property. for Prop %d.\n", prop_id);
+ silent_debug ("Setting property for prop %d.\n", prop_id);
switch (prop_id) {
case PROP_SILENT:
- prop->silent = g_value_get_boolean (value);
- silent_debug ("Debug mode on (silent off)\n");
+ self->silent = g_value_get_boolean (value);
+ silent_debug ("Debug mode = %d", self->silent);
break;
case PROP_FRAMEWORK:
g_assert (prop->nnfw == _T_F_UNDEFINED && value);
g_assert (prop->nnfw != _T_F_UNDEFINED);
g_assert (tensor_filter_supported[prop->nnfw] != NULL);
prop->fw = tensor_filter_supported[prop->nnfw];
- fw = prop->fw;
g_assert (prop->fw != NULL);
/* See if mandatory methods are filled in */
- g_assert (fw->invoke_NN);
- g_assert ((fw->getInputDimension && fw->getOutputDimension)
- || fw->setInputDimension);
+ g_assert (prop->fw->invoke_NN);
+ g_assert ((prop->fw->getInputDimension && prop->fw->getOutputDimension)
+ || prop->fw->setInputDimension);
break;
case PROP_MODEL:
- g_assert (prop->modelFilename == NULL && value);
+ g_assert (prop->model_file == NULL && value);
/* Once configures, it cannot be changed in runtime */
- prop->modelFilename = g_value_dup_string (value);
- silent_debug ("Model = %s\n", prop->modelFilename);
- g_assert (g_file_test (prop->modelFilename,
- G_FILE_TEST_IS_REGULAR) == TRUE);
+ prop->model_file = g_value_dup_string (value);
+ silent_debug ("Model = %s\n", prop->model_file);
+ g_assert (g_file_test (prop->model_file, G_FILE_TEST_IS_REGULAR));
break;
case PROP_INPUT:
- g_assert (!(prop->inputConfigured & _TFC_DIMENSION) && value);
+ g_assert (!prop->input_configured && value);
/* Once configures, it cannot be changed in runtime */
{
- int i;
- prop->inputMeta.num_tensors =
- get_tensor_dimension (g_value_get_string (value),
- prop->inputMeta.dims);
- for (i = 0; i < prop->inputMeta.num_tensors; i++) {
+ int i, rank;
+ gchar **str_dims;
+
+ str_dims = g_strsplit (g_value_get_string (value), ",", -1);
+ prop->input_meta.num_tensors = g_strv_length (str_dims);
+
+ for (i = 0; i < prop->input_meta.num_tensors; i++) {
+ rank =
+ get_tensor_dimension (str_dims[i],
+ prop->input_meta.info[i].dimension);
+ g_assert (rank > 0);
+
silent_debug ("Input Prop: %d:%d:%d:%d Rank %d\n",
- prop->inputMeta.dims[i][0], prop->inputMeta.dims[i][1],
- prop->inputMeta.dims[i][2], prop->inputMeta.dims[i][3],
- prop->inputMeta.ranks[i]);
+ prop->input_meta.info[i].dimension[0],
+ prop->input_meta.info[i].dimension[1],
+ prop->input_meta.info[i].dimension[2],
+ prop->input_meta.info[i].dimension[3], rank);
}
- prop->inputConfigured |= _TFC_DIMENSION;
+
+ g_strfreev (str_dims);
}
break;
case PROP_OUTPUT:
- g_assert (!(prop->outputConfigured & _TFC_DIMENSION) && value);
+ g_assert (!prop->output_configured && value);
/* Once configures, it cannot be changed in runtime */
{
- int i;
- prop->outputMeta.num_tensors =
- get_tensor_dimension (g_value_get_string (value),
- prop->outputMeta.dims);
- for (i = 0; i < prop->outputMeta.num_tensors; i++) {
+ int i, rank;
+ gchar **str_dims;
+
+ str_dims = g_strsplit (g_value_get_string (value), ",", -1);
+ prop->output_meta.num_tensors = g_strv_length (str_dims);
+
+ for (i = 0; i < prop->output_meta.num_tensors; i++) {
+ rank =
+ get_tensor_dimension (str_dims[i],
+ prop->output_meta.info[i].dimension);
+ g_assert (rank > 0);
+
silent_debug ("Output Prop: %d:%d:%d:%d Rank %d\n",
- prop->outputMeta.dims[i][0], prop->outputMeta.dims[i][1],
- prop->outputMeta.dims[i][2], prop->outputMeta.dims[i][3],
- prop->outputMeta.ranks[i]);
+ prop->output_meta.info[i].dimension[0],
+ prop->output_meta.info[i].dimension[1],
+ prop->output_meta.info[i].dimension[2],
+ prop->output_meta.info[i].dimension[3], rank);
}
- prop->outputConfigured |= _TFC_DIMENSION;
+
+ g_strfreev (str_dims);
}
break;
case PROP_INPUTTYPE:
- g_assert (prop->inputMeta.types[0] == _NNS_END && value);
+ g_assert (!prop->input_configured && value);
/* Once configures, it cannot be changed in runtime */
- prop->inputMeta.types[0] = get_tensor_type (g_value_get_string (value));
- prop->inputConfigured |= _TFC_TYPE;
- g_assert (prop->inputMeta.types[0] != _NNS_END);
+ {
+ int i;
+ gchar **str_types;
+
+ str_types = g_strsplit (g_value_get_string (value), ",", -1);
+ prop->input_meta.num_tensors = g_strv_length (str_types);
+
+ for (i = 0; i < prop->input_meta.num_tensors; i++) {
+ prop->input_meta.info[i].type = get_tensor_type (str_types[i]);
+ g_assert (prop->input_meta.info[i].type != _NNS_END);
+ }
+
+ g_strfreev (str_types);
+ }
break;
case PROP_OUTPUTTYPE:
- g_assert (prop->outputMeta.types[0] == _NNS_END && value);
+ g_assert (!prop->output_configured && value);
/* Once configures, it cannot be changed in runtime */
- prop->outputMeta.types[0] = get_tensor_type (g_value_get_string (value));
- prop->outputConfigured |= _TFC_TYPE;
- g_assert (prop->outputMeta.types[0] != _NNS_END);
+ {
+ int i;
+ gchar **str_types;
+
+ str_types = g_strsplit (g_value_get_string (value), ",", -1);
+ prop->output_meta.num_tensors = g_strv_length (str_types);
+
+ for (i = 0; i < prop->output_meta.num_tensors; i++) {
+ prop->output_meta.info[i].type = get_tensor_type (str_types[i]);
+ g_assert (prop->output_meta.info[i].type != _NNS_END);
+ }
+
+ g_strfreev (str_types);
+ }
break;
case PROP_CUSTOM:
- g_assert (prop->customProperties == NULL && value);
+ g_assert (prop->custom_properties == NULL && value);
/* Once configures, it cannot be changed in runtime */
- prop->customProperties = g_value_dup_string (value);
- if (prop->silent == FALSE)
- g_printerr ("Custom Option = %s\n", prop->customProperties);
+ prop->custom_properties = g_value_dup_string (value);
+ silent_debug ("Custom Option = %s\n", prop->custom_properties);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
/**
- * @brief @todo fill this in
+ * @brief Getter for tensor_filter properties.
*/
static void
gst_tensor_filter_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
- GstTensor_Filter *filter = GST_TENSOR_FILTER (object);
+ GstTensorFilter *self;
+ GstTensorFilterProperties *prop;
- debug_print (!filter->prop.silent, "Getting property. for Prop %d.\n",
- prop_id);
+ self = GST_TENSOR_FILTER (object);
+ prop = &self->prop;
+
+ silent_debug ("Getting property for prop %d.\n", prop_id);
switch (prop_id) {
case PROP_SILENT:
- g_value_set_boolean (value, filter->prop.silent);
+ g_value_set_boolean (value, self->silent);
break;
case PROP_FRAMEWORK:
- g_value_set_string (value, nnfw_names[filter->prop.nnfw]);
+ g_value_set_string (value, nnfw_names[prop->nnfw]);
break;
case PROP_MODEL:
- g_value_set_string (value, filter->prop.modelFilename);
+ g_value_set_string (value, prop->model_file);
break;
- case PROP_INPUT:{
- GArray *input =
- 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.inputMeta.dims[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. */
- }
+ case PROP_INPUT:
+ if (prop->input_meta.num_tensors > 0) {
+ GString *dimensions = g_string_new (NULL);
+ gchar *dim_str;
+ int i;
+
+ for (i = 0; i < prop->input_meta.num_tensors; i++) {
+ dim_str =
+ get_tensor_dimension_string (prop->input_meta.info[i].dimension);
+ g_string_append (dimensions, dim_str);
+
+ if (i < prop->input_meta.num_tensors - 1) {
+ g_string_append (dimensions, ",");
+ }
+
+ g_free (dim_str);
+ }
+
+ g_value_set_string (value, dimensions->str);
+ g_string_free (dimensions, TRUE);
+ } else {
+ g_value_set_string (value, "");
+ }
break;
- case PROP_OUTPUT:{
- GArray *output =
- 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.outputMeta.dims[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. */
- }
+ case PROP_OUTPUT:
+ if (prop->output_meta.num_tensors > 0) {
+ GString *dimensions = g_string_new (NULL);
+ gchar *dim_str;
+ int i;
+
+ for (i = 0; i < prop->output_meta.num_tensors; i++) {
+ dim_str =
+ get_tensor_dimension_string (prop->output_meta.info[i].dimension);
+ g_string_append (dimensions, dim_str);
+
+ if (i < prop->output_meta.num_tensors - 1) {
+ g_string_append (dimensions, ",");
+ }
+
+ g_free (dim_str);
+ }
+
+ g_value_set_string (value, dimensions->str);
+ g_string_free (dimensions, TRUE);
+ } else {
+ g_value_set_string (value, "");
+ }
break;
case PROP_INPUTTYPE:
- g_value_set_string (value,
- tensor_element_typename[filter->prop.inputMeta.types[0]]);
+ if (prop->input_meta.num_tensors > 0) {
+ GString *types = g_string_new (NULL);
+ int i;
+
+ for (i = 0; i < prop->input_meta.num_tensors; i++) {
+ g_string_append (types,
+ tensor_element_typename[prop->input_meta.info[i].type]);
+
+ if (i < prop->input_meta.num_tensors - 1) {
+ g_string_append (types, ",");
+ }
+ }
+
+ g_value_set_string (value, types->str);
+ g_string_free (types, TRUE);
+ } else {
+ g_value_set_string (value, "");
+ }
break;
case PROP_OUTPUTTYPE:
- g_value_set_string (value,
- tensor_element_typename[filter->prop.outputMeta.types[0]]);
+ if (prop->output_meta.num_tensors > 0) {
+ GString *types = g_string_new (NULL);
+ int i;
+
+ for (i = 0; i < prop->output_meta.num_tensors; i++) {
+ g_string_append (types,
+ tensor_element_typename[prop->output_meta.info[i].type]);
+
+ if (i < prop->output_meta.num_tensors - 1) {
+ g_string_append (types, ",");
+ }
+ }
+
+ g_value_set_string (value, types->str);
+ g_string_free (types, TRUE);
+ } else {
+ g_value_set_string (value, "");
+ }
break;
case PROP_CUSTOM:
- g_value_set_string (value, filter->prop.customProperties);
+ g_value_set_string (value, prop->custom_properties);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
-/******************************************************************
- * GstElement vmethod implementations
- */
-
-/**
- * @brief entry point to initialize the plug-in
- * initialize the plug-in itself
- * register the element factories and other features
- */
-static gboolean
-tensor_filter_init (GstPlugin * tensor_filter)
-{
- /**
- * debug category for fltering log messages
- *
- * exchange the string 'Template tensor_filter' with your description
- */
- GST_DEBUG_CATEGORY_INIT (gst_tensor_filter_debug, "tensor_filter",
- 0, "Template tensor_filter");
-
- return gst_element_register (tensor_filter, "tensor_filter", GST_RANK_NONE,
- GST_TYPE_TENSOR_FILTER);
-}
-
-/**
- * PACKAGE: this is usually set by autotools depending on some _INIT macro
- * in configure.ac and then written into and defined in config.h, but we can
- * just set it ourselves here in case someone doesn't use autotools to
- * compile this code. GST_PLUGIN_DEFINE needs PACKAGE to be defined.
- */
-#ifndef PACKAGE
-#define PACKAGE "tensor_filter"
-#endif
-
/**
- * gstreamer looks for this structure to register tensor_filters
- *
- * exchange the string 'Template tensor_filter' with your tensor_filter description
- */
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- tensor_filter,
- "tensor_filter",
- tensor_filter_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/");
-
-/**
- * @brief @todo fill this in
+ * @brief non-ip transform. required vmethod of GstBaseTransform.
*/
static GstFlowReturn
gst_tensor_filter_transform (GstBaseTransform * trans,
GstBuffer * inbuf, GstBuffer * outbuf)
{
- GstTensor_Filter *filter = GST_TENSOR_FILTER_CAST (trans);
- size_t outBufSize;
+ GstTensorFilter *self;
+ gsize outBufSize;
uint8_t *inptr, *outptr;
uint8_t *retoutptr;
GstMapInfo inInfo, outInfo;
- if (G_UNLIKELY (filter->prop.inputCapNegotiated == FALSE
- || filter->prop.outputCapNegotiated == FALSE))
+ self = GST_TENSOR_FILTER_CAST (trans);
+
+ if (G_UNLIKELY (!self->configured))
goto unknown_format;
- if (G_UNLIKELY (!filter->prop.fw))
+ if (G_UNLIKELY (!self->prop.fw))
goto unknown_framework;
- if (G_UNLIKELY (!filter->prop.modelFilename))
+ if (G_UNLIKELY (!self->prop.model_file))
goto unknown_model;
- if (G_UNLIKELY (!filter->prop.fw->invoke_NN))
+ if (G_UNLIKELY (!self->prop.fw->invoke_NN))
goto unknown_invoke;
/* 0. Check all properties and inbuf size. */
- debug_print (!filter->prop.silent, "Invoking %s with %s model\n",
- filter->prop.fw->name, filter->prop.modelFilename);
-
- g_assert ((filter->prop.inputConfigured & _TFC_ALL) == _TFC_ALL &&
- (filter->prop.outputConfigured & _TFC_ALL) == _TFC_ALL);
+ silent_debug ("Invoking %s with %s model\n", self->prop.fw->name,
+ self->prop.model_file);
/* 1. Allocate outbuf if allocate_in_invoke is FALSE */
g_assert (outbuf);
- if (filter->prop.fw->allocate_in_invoke == FALSE) {
- outBufSize = tensor_element_size[filter->prop.outputMeta.types[0]] *
- get_tensor_element_count (filter->prop.outputMeta.dims[0]);
+ outBufSize = gst_tensor_filter_out_size (self, -1);
+
+ if (self->prop.fw->allocate_in_invoke == FALSE) {
if (gst_buffer_get_size (outbuf) < outBufSize) {
/** @todo: write a routine to say aloud when this happens */
gst_buffer_set_size (outbuf, outBufSize);
}
- debug_print (!filter->prop.silent, "outbuf = %lu / expected = %lu\n",
+ silent_debug ("outbuf = %lu / expected = %lu\n",
gst_buffer_get_size (outbuf), outBufSize);
g_assert (gst_buffer_get_size (outbuf) >= outBufSize);
inptr = inInfo.data;
outptr = outInfo.data;
- gst_tensor_filter_call (filter, retoutptr, invoke_NN, inptr, outptr);
+ gst_tensor_filter_call (self, retoutptr, invoke_NN, inptr, outptr);
g_assert (outptr == retoutptr);
gst_buffer_unmap (inbuf, &inInfo);
g_assert (gst_buffer_get_size (outbuf) == 0);
inptr = inInfo.data;
- gst_tensor_filter_call (filter, retoutptr, invoke_NN, inptr, NULL);
+ gst_tensor_filter_call (self, retoutptr, invoke_NN, inptr, NULL);
gst_buffer_unmap (inbuf, &inInfo);
- /** @todo Performance: cache get_tensor_element_count * tensor_element_size */
- mem = gst_memory_new_wrapped (0, retoutptr,
- get_tensor_element_count (filter->prop.outputMeta.dims[0]) *
- tensor_element_size[filter->prop.outputMeta.types[0]],
- 0,
- get_tensor_element_count (filter->prop.outputMeta.dims[0]) *
- tensor_element_size[filter->prop.outputMeta.types[0]], NULL, NULL);
+ mem =
+ gst_memory_new_wrapped (0, retoutptr, outBufSize, 0, outBufSize, NULL,
+ NULL);
gst_buffer_insert_memory (outbuf, -1, mem);
}
/* 3. Return result! */
return GST_FLOW_OK;
unknown_format:
- GST_ELEMENT_ERROR (filter, CORE, NOT_IMPLEMENTED, (NULL), ("unknown format"));
+ GST_ELEMENT_ERROR (self, CORE, NOT_IMPLEMENTED, (NULL), ("unknown format"));
return GST_FLOW_NOT_NEGOTIATED;
unknown_framework:
- GST_ELEMENT_ERROR (filter, CORE, NOT_IMPLEMENTED, (NULL),
+ GST_ELEMENT_ERROR (self, CORE, NOT_IMPLEMENTED, (NULL),
("framework not configured"));
return GST_FLOW_ERROR;
unknown_model:
- GST_ELEMENT_ERROR (filter, CORE, NOT_IMPLEMENTED, (NULL),
+ GST_ELEMENT_ERROR (self, CORE, NOT_IMPLEMENTED, (NULL),
("model filepath not configured"));
return GST_FLOW_ERROR;
unknown_invoke:
- GST_ELEMENT_ERROR (filter, CORE, NOT_IMPLEMENTED, (NULL),
+ GST_ELEMENT_ERROR (self, CORE, NOT_IMPLEMENTED, (NULL),
("invoke function is not defined"));
return GST_FLOW_ERROR;
}
/**
- * @brief @todo fill this in
+ * @brief in-place transform. required vmethod of GstBaseTransform.
*/
static GstFlowReturn
gst_tensor_filter_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
/** @todo 1. Resize buf if output is larger than input */
/** @todo 2. Call the filter-subplugin callback, "invoke" */
/** @todo 3. Return result! */
- g_assert (1 == 0);
+ g_assert (0);
return GST_FLOW_ERROR;
}
-
/**
- * @brief process property values, call get/set I/O dim. (internal static function)
- * If set-prop configured dimension, verify the dimension with fw callbacks
- * Otherwise, configure dimension with fw callbacks.
- *
- * @param filter "this" pointer
- * @param fixate TRUE if we may fixate property values.
- * @return 1: OK and all set. 0: Try again later. -1: cannot proceed. fatal ERROR.
+ * @brief Load tensor info from NN model.
+ * (both input and output tensor)
*/
-static int
-gst_tensor_filter_property_process (GstTensor_Filter * filter, gboolean fixate)
+static void
+gst_tensor_filter_load_tensor_info (GstTensorFilter * self)
{
- GstTensor_Filter_Framework *fw = filter->prop.fw;
- GstTensor_Filter_Properties *prop = &filter->prop;
- int ret;
- GstTensor_TensorsMeta meta;
- int i, tensor_idx;
-
- /* Ensure the subplugin is contacted first before checking the XOR assert */
- if (!prop->fwOpened && fw->open)
- fw->open (filter, &filter->privateData);
- prop->fwOpened = TRUE;
-
- if (fw->getInputDimension != NULL) {
- gst_tensor_filter_call (filter, ret, getInputDimension, &meta);
- if (ret == 0) {
- for (tensor_idx = 0; tensor_idx < meta.num_tensors; tensor_idx++) {
- if (prop->inputConfigured & _TFC_TYPE)
- if (prop->inputMeta.types[tensor_idx] != meta.types[tensor_idx]) {
- return -1;
- }
- if (prop->inputConfigured & _TFC_DIMENSION)
- for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++)
- if (prop->inputMeta.dims[tensor_idx][i] != meta.dims[tensor_idx][i]) {
- return -1;
- }
- if (fixate && !(prop->inputConfigured & _TFC_TYPE)) {
- prop->inputMeta.types[tensor_idx] = meta.types[tensor_idx];
- prop->inputConfigured |= _TFC_TYPE;
- }
- if (fixate && !(prop->inputConfigured & _TFC_DIMENSION)) {
- memcpy (prop->inputMeta.dims[tensor_idx], meta.dims[tensor_idx],
- sizeof (meta.dims[tensor_idx]));
- prop->inputConfigured |= _TFC_DIMENSION;
+ GstTensorFilterProperties *prop;
+ int res;
+
+ prop = &self->prop;
+
+ /**
+ * supposed fixed in-tensor info if getInputDimension is defined.
+ */
+ if (!prop->input_configured) {
+ if (prop->fw->getInputDimension) {
+ GstTensorsInfo in_info;
+
+ gst_tensors_info_init (&in_info);
+ gst_tensor_filter_call (self, res, getInputDimension, &in_info);
+
+ if (res == 0) {
+ g_assert (in_info.num_tensors > 0);
+
+ /** if set-property called and already has info, verify it! */
+ if (prop->input_meta.num_tensors > 0) {
+ g_assert (gst_tensors_info_is_equal (&prop->input_meta, &in_info));
}
+
+ prop->input_configured = TRUE;
+ self->in_config.info = prop->input_meta = in_info;
}
}
}
- if (fw->getOutputDimension != NULL) {
- gst_tensor_filter_call (filter, ret, getOutputDimension, &meta);
- if (ret == 0) {
- for (tensor_idx = 0; tensor_idx < meta.num_tensors; tensor_idx++) {
- if (prop->outputConfigured & _TFC_TYPE)
- if (prop->outputMeta.types[tensor_idx] != meta.types[tensor_idx]) {
- return -1;
- }
- if (prop->outputConfigured & _TFC_DIMENSION)
- for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++)
- if (prop->outputMeta.dims[tensor_idx][i] !=
- meta.dims[tensor_idx][i]) {
- return -1;
- }
- if (fixate && !(prop->outputConfigured & _TFC_TYPE)) {
- prop->outputMeta.types[tensor_idx] = meta.types[tensor_idx];
- prop->outputConfigured |= _TFC_TYPE;
- }
- if (fixate && !(prop->outputConfigured & _TFC_DIMENSION)) {
- memcpy (prop->outputMeta.dims[tensor_idx], meta.dims[tensor_idx],
- sizeof (meta.dims[tensor_idx]));
- prop->outputConfigured |= _TFC_DIMENSION;
+ /**
+ * supposed fixed out-tensor info if getOutputDimension is defined.
+ */
+ if (!prop->output_configured) {
+ if (prop->fw->getOutputDimension) {
+ GstTensorsInfo out_info;
+
+ gst_tensors_info_init (&out_info);
+ gst_tensor_filter_call (self, res, getOutputDimension, &out_info);
+
+ if (res == 0) {
+ g_assert (out_info.num_tensors > 0);
+
+ /** if set-property called and already has info, verify it! */
+ if (prop->output_meta.num_tensors > 0) {
+ g_assert (gst_tensors_info_is_equal (&prop->output_meta, &out_info));
}
+
+ prop->output_configured = TRUE;
+ self->out_config.info = prop->output_meta = out_info;
}
}
}
+}
- if (fw->setInputDimension != NULL) {
- GstTensor_TensorsMeta *cmpMeta;
- /* If filter's inputdimension is not clear, yet, we cannot proceed. try again later */
- if ((prop->inputConfigured & _TFC_ALL) == _TFC_ALL) {
- cmpMeta = &meta;
- memcpy (meta.dims[0], prop->outputMeta.dims[0], sizeof (meta.dims[0]));
- meta.types[0] = prop->outputMeta.types[0];
- } else {
- if (fw->getOutputDimension != NULL) {
- gst_tensor_filter_call (filter, ret, getInputDimension, &meta);
- if (ret != 0)
- goto finalize;
- cmpMeta = &meta;
- } else {
- /* Nothing to do here */
- goto finalize;
- }
- }
+/**
+ * @brief Configure input and output tensor info from incaps.
+ * @param self "this" pointer
+ * @param incaps received caps for sink pad
+ * @return TRUE if fully configured
+ */
+static gboolean
+gst_tensor_filter_configure_tensor (GstTensorFilter * self,
+ const GstCaps * incaps)
+{
+ GstTensorFilterProperties *prop;
+ GstStructure *structure;
+ GstTensorsConfig in_config, out_config;
- gst_tensor_filter_call (filter, ret, setInputDimension, cmpMeta->dims[0],
- cmpMeta->types[0], meta.dims[0], &meta.types[0]);
- if (ret != 0)
- goto finalize;
+ g_return_val_if_fail (incaps != NULL, FALSE);
- if (prop->outputConfigured & _TFC_TYPE) {
- if (prop->outputMeta.types[0] != meta.types[0]) {
- return -1;
+ prop = &self->prop;
+
+ /**
+ * GstTensorFilter has to parse the tensor dimension and type from NN model.
+ * 1. Call functions getInputDimension and getOutputDimension to get the dimension and type.
+ * 2. If these functions are not defined, call setInputDimension with parsed info from caps.
+ * 3. If set-prop configured dimension, verify the dimension with fw callbacks.
+ */
+ gst_tensor_filter_load_tensor_info (self);
+
+ structure = gst_caps_get_structure (incaps, 0);
+ gst_tensors_config_from_structure (&in_config, structure);
+
+ /**
+ * Check configuration from caps.
+ * If true, fully configured tensor info from caps.
+ */
+ if (gst_tensors_config_validate (&in_config)) {
+ /** if set-property called and already has info, verify it! */
+ if (prop->input_meta.num_tensors > 0) {
+ if (!gst_tensors_info_is_equal (&in_config.info, &prop->input_meta)) {
+ g_assert (0);
+ return FALSE;
}
}
- if (prop->outputConfigured & _TFC_DIMENSION) {
- for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++) {
- if (prop->outputMeta.dims[0][i] != meta.dims[0][i]) {
- return -1;
+
+ prop->input_configured = TRUE;
+ self->in_config.info = prop->input_meta = in_config.info;
+
+ /** call setInputDimension if output tensor is not configured */
+ if (!prop->output_configured) {
+ if (prop->fw->setInputDimension) {
+ GstTensorsInfo out_info;
+ int res;
+
+ gst_tensors_info_init (&out_info);
+ gst_tensor_filter_call (self, res, setInputDimension, &in_config.info,
+ &out_info);
+
+ if (res == 0) {
+ /** if set-property called and already has info, verify it! */
+ if (prop->output_meta.num_tensors > 0) {
+ if (!gst_tensors_info_is_equal (&prop->output_meta, &out_info)) {
+ g_assert (0);
+ return FALSE;
+ }
+ }
+
+ prop->output_configured = TRUE;
+ self->out_config.info = prop->output_meta = out_info;
}
}
- }
- if (fixate && !(prop->outputConfigured & _TFC_TYPE)) {
- prop->outputMeta.types[0] = meta.types[0];
- prop->outputConfigured |= _TFC_TYPE;
+ if (!prop->output_configured) {
+ err_print ("Failed to get output tensor info.\n");
+ g_assert (0);
+ return FALSE;
+ }
}
- if (fixate && !(prop->outputConfigured & _TFC_DIMENSION)) {
- memcpy (prop->outputMeta.dims[0], meta.dims[0], sizeof (meta.dims[0]));
- prop->outputConfigured |= _TFC_DIMENSION;
+
+ /**
+ * @todo how can we update the framerate?
+ * GstTensorFilter cannot assure the framerate.
+ * Simply set the framerate of out-tensor from incaps.
+ */
+ out_config.info = prop->output_meta;
+ out_config.rate_n = in_config.rate_n;
+ out_config.rate_d = in_config.rate_d;
+
+ if (self->configured) {
+ /** already configured, compare to old. */
+ g_assert (gst_tensors_config_is_equal (&self->in_config, &in_config));
+ g_assert (gst_tensors_config_is_equal (&self->out_config, &out_config));
+ } else {
+ self->in_config = in_config;
+ self->out_config = out_config;
+ self->configured = TRUE;
}
}
-finalize:
- if ((prop->inputConfigured & _TFC_ALL) == _TFC_ALL &&
- (prop->outputConfigured & _TFC_ALL) == _TFC_ALL)
- return 1;
- else
- return 0;
-
- return -1; /* Code cannot reach here */
+ return self->configured;
}
+/**
+ * @brief Get caps for given config.
+ * @param self "this" pointer
+ * @param config tensor config info
+ */
+static GstCaps *
+gst_tensor_filter_caps_from_config (GstTensorFilter * self,
+ GstTensorsConfig * config)
+{
+ GstCaps *caps;
+
+ g_return_val_if_fail (config != NULL, NULL);
+
+ if (config->info.num_tensors < 2) {
+ GstTensorConfig c;
+
+ /**
+ * supposed other/tensor if the number of tensor is less than 2.
+ */
+ c.info = config->info.info[0];
+ c.rate_n = config->rate_n;
+ c.rate_d = config->rate_d;
+
+ caps = gst_tensor_caps_from_config (&c);
+ } else {
+ caps = gst_tensors_caps_from_config (config);
+ }
+
+ return caps;
+}
/**
* @brief configure tensor-srcpad cap from "proposed" cap.
gst_tensor_filter_transform_caps (GstBaseTransform * trans,
GstPadDirection direction, GstCaps * caps, GstCaps * filter)
{
- GstTensor_Filter *obj = GST_TENSOR_FILTER_CAST (trans);
- int check = gst_tensor_filter_property_process (obj, FALSE);
+ GstTensorFilter *self;
+ GstCaps *result;
- g_assert (check >= 0);
+ self = GST_TENSOR_FILTER_CAST (trans);
- if (direction == GST_PAD_SINK) {
- /* caps: sink pad. get src pad info */
- obj->prop.outputCapNegotiated = TRUE;
+ silent_debug ("Direction = %d\n", direction);
+ silent_debug_caps (caps, "from");
+ silent_debug_caps (filter, "filter");
- /** @todo 1. Check caps w/ getInputDimension && saved input dimension */
- /** @todo 2. Check returning-caps w/ getOutputDimension && saved output dimension */
+ /**
+ * GstTensorFilter has to parse the tensor dimension and type from NN model.
+ * In this stage, in-caps is not fixed yet.
+ * So, just call getInputDimension and getOutputDimension to get the tensor info.
+ * If these functions are not defined, we have to call setInputDimension in set_caps(), and then it will fully configure the tensor info.
+ */
+ gst_tensor_filter_load_tensor_info (self);
- return gst_tensor_filter_fix_caps (obj, TRUE, caps);
+ if (direction == GST_PAD_SINK) {
+ /* caps: sink pad. get src pad info */
+ if (self->prop.output_configured) {
+ /** fixed tensor info */
+ result = gst_tensor_filter_caps_from_config (self, &self->out_config);
+ } else {
+ /** we don't know the exact tensor info yet */
+ result = gst_caps_from_string (CAPS_STRING);
+ }
} else {
/* caps: src pad. get sink pad info */
- obj->prop.inputCapNegotiated = TRUE;
-
- /** @todo 1. Check caps w/ getOutputDimension && saved output dimension */
- /** @todo 2. Check returning-caps w/ getInputDimension && saved input dimension */
- return gst_tensor_filter_fix_caps (obj, FALSE, caps);
+ if (self->prop.input_configured) {
+ /** fixed tensor info */
+ result = gst_tensor_filter_caps_from_config (self, &self->in_config);
+ } else {
+ /** we don't know the exact tensor info yet */
+ result = gst_caps_from_string (CAPS_STRING);
+ }
}
- /* Cannot reach here. */
- return NULL;
-}
-
-/**
- * @brief Try to generate dim/type from caps (internal static function)
- * @return _TFC_TYPE is on if type determined. _TFC_DIMENSION is on if dim determined
- * @param filter "this" pointer
- * @param caps the caps to be analyzed (padcap)
- * @param[out] dim tensor dimension derived from caps
- * @param[out] type tensor type derived from caps
- */
-static GstTensor_Filter_CheckStatus
-gst_tensor_filter_generate_dim_from_cap (GstCaps * caps, const tensor_dim dim,
- tensor_type * type)
-{
- unsigned int i, capsize;
- const GstStructure *str;
- GstTensor_Filter_CheckStatus ret = _TFC_INIT;
- const gchar *strval;
-
- if (!caps) {
- return _TFC_INIT;
- }
+ if (filter) {
+ GstCaps *intersection;
- capsize = gst_caps_get_size (caps);
+ intersection =
+ gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);
- for (i = 0; i < capsize; i++) {
- str = gst_caps_get_structure (caps, i);
- if (gst_structure_get_int (str, "dim1", (int *) &dim[0]) &&
- gst_structure_get_int (str, "dim2", (int *) &dim[1]) &&
- gst_structure_get_int (str, "dim3", (int *) &dim[2]) &&
- gst_structure_get_int (str, "dim4", (int *) &dim[3])) {
- ret |= _TFC_DIMENSION;
- }
- strval = gst_structure_get_string (str, "type");
- if (strval) {
- *type = get_tensor_type (strval);
- g_assert (*type != _NNS_END);
- ret |= _TFC_TYPE;
- }
+ gst_caps_unref (result);
+ result = intersection;
}
- return ret;
-}
-
-/**
- * @brief Read pad-cap and return dimension/type info
- * @return _TFC_TYPE is on if type determined. _TFC_DIMENSION is on if dim determined
- * @param[in] caps The pad cap
- * @param[in] input TRUE if input. FALSE if output.
- * @param[out] dim Tensor dimension
- @ @param[out[ type Tensor element type
- */
-static void
-gst_tensor_caps_to_dimension (GstCaps * caps, gboolean input,
- GstTensor_Filter_Properties * prop)
-{
- if (input) {
- prop->inputConfigured |=
- gst_tensor_filter_generate_dim_from_cap (caps, prop->inputMeta.dims[0],
- &prop->inputMeta.types[0]);
- } else {
- prop->outputConfigured |=
- gst_tensor_filter_generate_dim_from_cap (caps, prop->outputMeta.dims[0],
- &prop->outputMeta.types[0]);
- }
+ silent_debug_caps (result, "to");
+ return result;
}
/**
- * @brief @todo fill this in
+ * @brief fixate caps. required vmethod of GstBaseTransform.
*/
static GstCaps *
gst_tensor_filter_fixate_caps (GstBaseTransform * trans,
GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
{
- GstCaps *supposed =
- gst_tensor_filter_transform_caps (trans, direction, caps, NULL);
- GstCaps *result = gst_caps_intersect (othercaps, supposed);
- GstTensor_Filter *obj = GST_TENSOR_FILTER_CAST (trans);
- GstTensor_Filter_Framework *fw = obj->prop.fw;
- GstCaps *sinkpadcap, *srcpadcap;
- int check = gst_tensor_filter_property_process (obj, TRUE);
- GstTensor_TensorsMeta meta;
+ GstTensorFilter *self;
+ GstTensorsConfig in_config, out_config;
+ GstStructure *structure;
+ GstCaps *supposed;
+ GstCaps *result;
- gst_caps_unref (supposed);
- g_assert (check >= 0);
+ self = GST_TENSOR_FILTER_CAST (trans);
- g_assert (!gst_caps_is_empty (result));
- gst_caps_unref (othercaps);
+ silent_debug ("fixate_caps, direction = %d\n", direction);
+ silent_debug_caps (caps, "caps");
+ silent_debug_caps (othercaps, "othercaps");
- result = gst_caps_make_writable (result);
- result = gst_caps_fixate (result);
+ gst_tensors_config_init (&in_config);
+ gst_tensors_config_init (&out_config);
- if (direction == GST_PAD_SINK) {
- if (gst_caps_is_subset (caps, result)) {
- gst_caps_replace (&result, caps);
- }
- obj->prop.inputCapNegotiated = TRUE;
- sinkpadcap = caps;
- srcpadcap = result;
+ gst_tensor_filter_load_tensor_info (self);
+
+ /**
+ * Get input tensor info from caps.
+ * @todo Do we need to verify configured info from caps?
+ * If getInputDimension is defined and gets exact tensor info from NN model, we can use it.
+ */
+ structure = gst_caps_get_structure (caps, 0);
+ gst_tensors_config_from_structure (&in_config, structure);
+
+ /** output tensor info */
+ if (self->prop.output_configured) {
+ /** fixed tensor info */
+ out_config.info = self->prop.output_meta;
} else {
- obj->prop.outputCapNegotiated = TRUE;
- sinkpadcap = result;
- srcpadcap = caps;
- }
+ int res = -1;
- if ((obj->prop.inputConfigured & _TFC_ALL) == _TFC_ALL &&
- (obj->prop.outputConfigured & _TFC_ALL) == _TFC_ALL)
- return result;
-
- debug_print (!obj->prop.silent, "Nego (%s) / i %d / o %d\n",
- (direction == GST_PAD_SINK) ? "sink" : "src",
- obj->prop.inputCapNegotiated, obj->prop.outputCapNegotiated);
-
- /* Before moving on, use if getInputDim/getOutputDim is available. */
- if (fw->getInputDimension
- && (obj->prop.inputConfigured & _TFC_ALL) == _TFC_ALL) {
- int ret = 0;
- int tensor_idx;
- gst_tensor_filter_call (obj, ret, getInputDimension, &meta);
- for (tensor_idx = 0; tensor_idx < meta.num_tensors; tensor_idx++) {
- memcpy (obj->prop.inputMeta.dims[tensor_idx], meta.dims[tensor_idx],
- sizeof (meta.dims[tensor_idx]));
- obj->prop.inputMeta.types[tensor_idx] = meta.types[tensor_idx];
+ /** call setInputDimension with given input tensor */
+ gst_tensor_filter_call (self, res, setInputDimension, &in_config.info,
+ &out_config.info);
- }
- if (ret == 0) {
- obj->prop.inputConfigured |= _TFC_ALL;
+ if (res != 0) {
+ silent_debug ("Cannot get the output tensor info.");
}
}
- if (fw->getOutputDimension
- && (obj->prop.outputConfigured & _TFC_ALL) == _TFC_ALL) {
- int ret = 0;
- int tensor_idx;
- gst_tensor_filter_call (obj, ret, getOutputDimension, &meta);
- for (tensor_idx = 0; tensor_idx < meta.num_tensors; tensor_idx++) {
- memcpy (obj->prop.outputMeta.dims[tensor_idx], meta.dims[tensor_idx],
- sizeof (meta.dims[tensor_idx]));
- obj->prop.outputMeta.types[tensor_idx] = meta.types[tensor_idx];
- }
- if (ret == 0) {
- obj->prop.outputConfigured |= _TFC_ALL;
- }
- }
- if ((obj->prop.inputConfigured & _TFC_ALL) == _TFC_ALL &&
- (obj->prop.outputConfigured & _TFC_ALL) == _TFC_ALL) {
- return result;
- }
- gst_tensor_caps_to_dimension (sinkpadcap, TRUE, &obj->prop);
- gst_tensor_caps_to_dimension (srcpadcap, FALSE, &obj->prop);
-
- if ((obj->prop.inputConfigured & _TFC_ALL) == _TFC_ALL &&
- (obj->prop.outputConfigured & _TFC_ALL) == _TFC_ALL)
- return result;
-
- if ((obj->prop.inputConfigured & _TFC_ALL) == _TFC_ALL) {
- if (fw->setInputDimension) {
- int ret = 0;
- gst_tensor_filter_call (obj, ret, setInputDimension,
- obj->prop.inputMeta.dims[0], obj->prop.inputMeta.types[0],
- obj->prop.outputMeta.dims[0], &obj->prop.outputMeta.types[0]);
- obj->prop.outputConfigured |= _TFC_ALL;
- g_assert (ret == 0);
- return result;
- }
- }
+ out_config.rate_n = in_config.rate_n;
+ out_config.rate_d = in_config.rate_d;
- /**
- * @todo ARCH-Decision required; are we going to (and do we need to)
- * support setOutputDimention (and get InputDim accordingly?)
- *
- * If not, we have done with it and emit error here if we still don't have
- * capabilities fixed.
- *
- * In this case, result should be re-calculated because
- * gst_tensor_filter_transform_caps () cannot do reverse transform.
- */
+ supposed = gst_tensor_filter_caps_from_config (self, &out_config);
- if (!obj->prop.silent) {
- gchar *str = gst_caps_to_string (caps);
- debug_print (TRUE, "Caps(%s) %s\n",
- (direction == GST_PAD_SINK) ? "input/sink" : "output/src", str);
- g_free (str);
- str = gst_caps_to_string (result);
- debug_print (TRUE, "Caps(%s) %s\n",
- (direction == GST_PAD_SINK) ? "Op-input/sink" : "Op-output/src", str);
- g_free (str);
- }
+ result = gst_caps_intersect (othercaps, supposed);
+ gst_caps_unref (supposed);
- g_assert (0); /* Not Supported (configure input from output dimension) */
+ result = gst_caps_make_writable (result);
+ result = gst_caps_fixate (result);
+
+ silent_debug_caps (result, "result");
return result;
}
/**
- * @brief @todo fill this in
+ * @brief set caps. required vmethod of GstBaseTransform.
*/
static gboolean
gst_tensor_filter_set_caps (GstBaseTransform * trans,
GstCaps * incaps, GstCaps * outcaps)
{
- GstTensor_Filter *filter = GST_TENSOR_FILTER_CAST (trans);
- int check = gst_tensor_filter_property_process (filter, TRUE);
- tensor_dim dim;
- tensor_type type;
- gboolean result;
+ GstTensorFilter *self;
+ GstStructure *structure;
+ GstTensorsConfig config;
- g_assert (check >= 0);
+ self = GST_TENSOR_FILTER_CAST (trans);
- result = gst_tensor_filter_generate_dim_from_cap (incaps, dim, &type);
- /** @todo Configure filter-dim from caps if filter-dim is not configured, yet */
- if ((filter->prop.inputConfigured & _TFC_ALL) != _TFC_ALL) {
- /* we may set if result == TRUE */
- g_assert (FALSE); /* NYI */
+ silent_debug_caps (incaps, "incaps");
+ silent_debug_caps (outcaps, "outcaps");
- g_assert (result == TRUE);
+ if (!gst_tensor_filter_configure_tensor (self, incaps)) {
+ silent_debug ("Failed to configure tensor.");
+ return FALSE;
}
- /** @todo Check consistencyu between dim/type with filter->input* */
- result = gst_tensor_filter_generate_dim_from_cap (outcaps, dim, &type);
- /** @todo Configure filter-dim from caps if filter-dim is not configured, yet */
- if ((filter->prop.outputConfigured & _TFC_ALL) != _TFC_ALL) {
- /* we may set if result == TRUE */
- g_assert (FALSE); /* NYI */
+ if (!gst_tensors_config_validate (&self->in_config)) {
+ silent_debug ("Failed to validate input tensor.");
+ return FALSE;
+ }
- g_assert (result == TRUE);
+ if (!gst_tensors_config_validate (&self->out_config)) {
+ silent_debug ("Failed to validate output tensor.");
+ return FALSE;
+ }
+
+ /** compare output tensor */
+ structure = gst_caps_get_structure (outcaps, 0);
+ gst_tensors_config_from_structure (&config, structure);
+
+ if (!gst_tensors_config_is_equal (&self->out_config, &config)) {
+ silent_debug ("Invalid outcaps.");
+ return FALSE;
}
- /** @todo Check consistencyu between dim/type with filter->output* */
return TRUE;
}
GstPadDirection direction, GstCaps * caps, gsize size,
GstCaps * othercaps, gsize * othersize)
{
- GstTensor_Filter *filter = GST_TENSOR_FILTER_CAST (trans);
- const GstCaps *srccap = (direction == GST_PAD_SINK) ? othercaps : caps;
- tensor_dim dim;
- tensor_type type;
- GstTensor_Filter_CheckStatus ret =
- get_tensor_from_padcap (srccap, dim, &type, NULL, NULL);
-
- if (filter->prop.fw->allocate_in_invoke == TRUE) {
- *othersize = 0; /* Do not allocate outbuf. invoke_NN will allocate! */
- return TRUE;
- }
+ GstTensorFilter *self;
- g_assert ((ret & _TFC_ALL) == _TFC_ALL);
-
- if (!filter->prop.silent) {
- debug_print (TRUE, "transform_size, direction = %s\n",
- (direction == GST_PAD_SINK) ? "sink" : "src");
- GstStructure *structure = gst_caps_get_structure (caps, 0);
- gchar *str = gst_structure_to_string (structure);
- debug_print (TRUE, "cap = %s\n", str);
- g_free (str);
- structure = gst_caps_get_structure (othercaps, 0);
- str = gst_structure_to_string (structure);
- debug_print (TRUE, "othercap = %s\n", str);
- g_free (str);
- }
+ self = GST_TENSOR_FILTER_CAST (trans);
- *othersize = get_tensor_element_count (dim) * tensor_element_size[type];
+ g_assert (self->configured);
+ if (self->prop.fw->allocate_in_invoke == TRUE) {
+ /* Do not allocate outbuf. invoke_NN will allocate! */
+ *othersize = 0;
+ return TRUE;
+ }
+
+ *othersize = gst_tensor_filter_out_size (self, -1);
return TRUE;
}
static gboolean
gst_tensor_filter_start (GstBaseTransform * trans)
{
- GstTensor_Filter *filter = GST_TENSOR_FILTER_CAST (trans);
- GstTensor_Filter_Framework *fw = filter->prop.fw;
- GstTensor_Filter_Properties *prop = &filter->prop;
+ GstTensorFilter *self;
+ GstTensorFilterProperties *prop;
- if (!prop->fwOpened && fw->open)
- fw->open (filter, &filter->privateData);
- prop->fwOpened = TRUE;
+ self = GST_TENSOR_FILTER_CAST (trans);
+ prop = &self->prop;
- g_assert (prop->fwClosed == FALSE);
+ if (!prop->fw_opened && prop->fw->open) {
+ prop->fw->open (self, &self->privateData);
+ }
+ prop->fw_opened = TRUE;
return TRUE;
}
static gboolean
gst_tensor_filter_stop (GstBaseTransform * trans)
{
- GstTensor_Filter *filter = GST_TENSOR_FILTER_CAST (trans);
- GstTensor_Filter_Framework *fw = filter->prop.fw;
- GstTensor_Filter_Properties *prop = &filter->prop;
+ GstTensorFilter *self;
+ GstTensorFilterProperties *prop;
- g_assert (prop->fwOpened == TRUE);
+ self = GST_TENSOR_FILTER_CAST (trans);
+ prop = &self->prop;
- if (fw->close)
- fw->close (filter, &filter->privateData);
- prop->fwClosed = TRUE;
+ gst_tensor_filter_close (self);
- if (prop->modelFilename) {
- g_free ((void *) prop->modelFilename);
- prop->modelFilename = NULL;
+ if (prop->model_file) {
+ g_free ((void *) prop->model_file);
+ prop->model_file = NULL;
}
- if (prop->customProperties) {
- g_free ((void *) prop->customProperties);
- prop->customProperties = NULL;
+ if (prop->custom_properties) {
+ g_free ((void *) prop->custom_properties);
+ prop->custom_properties = NULL;
}
return TRUE;
}
+
+/**
+ * @brief entry point to initialize the plug-in
+ * initialize the plug-in itself
+ * register the element factories and other features
+ */
+static gboolean
+gst_tensor_filter_plugin_init (GstPlugin * plugin)
+{
+ /**
+ * debug category for filtering log messages
+ */
+ GST_DEBUG_CATEGORY_INIT (gst_tensor_filter_debug, "tensor_filter",
+ 0, "tensor_filter element");
+
+ return gst_element_register (plugin, "tensor_filter", GST_RANK_NONE,
+ GST_TYPE_TENSOR_FILTER);
+}
+
+/**
+ * @brief Definition for identifying tensor_filter plugin.
+ *
+ * PACKAGE: this is usually set by autotools depending on some _INIT macro
+ * in configure.ac and then written into and defined in config.h, but we can
+ * just set it ourselves here in case someone doesn't use autotools to
+ * compile this code. GST_PLUGIN_DEFINE needs PACKAGE to be defined.
+ */
+#ifndef PACKAGE
+#define PACKAGE "tensor_filter"
+#endif
+
+/**
+ * @brief Macro to define the entry point of the plugin.
+ * gstreamer looks for this structure to register tensor_filter.
+ */
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ tensor_filter,
+ "GStreamer plugin to use general neural network frameworks as filters",
+ gst_tensor_filter_plugin_init, VERSION, "LGPL", "GStreamer",
+ "http://gstreamer.net/");
#include <tensor_common.h>
G_BEGIN_DECLS
-/* #defines don't like whitespacey bits */
+
#define GST_TYPE_TENSOR_FILTER \
(gst_tensor_filter_get_type())
#define GST_TENSOR_FILTER(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TENSOR_FILTER,GstTensor_Filter))
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TENSOR_FILTER,GstTensorFilter))
#define GST_TENSOR_FILTER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TENSOR_FILTER,GstTensor_FilterClass))
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TENSOR_FILTER,GstTensorFilterClass))
#define GST_IS_TENSOR_FILTER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TENSOR_FILTER))
#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;
+#define GST_TENSOR_FILTER_CAST(obj) ((GstTensorFilter *)(obj))
-typedef struct _GstTensor_FilterClass GstTensor_FilterClass;
+typedef struct _GstTensorFilter GstTensorFilter;
+typedef struct _GstTensorFilterClass GstTensorFilterClass;
extern const char *nnfw_names[];
/**
* @brief Internal data structure for tensor_filter instances.
*/
-struct _GstTensor_Filter
+struct _GstTensorFilter
{
GstBaseTransform element; /**< This is the parent object */
void *privateData; /**< NNFW plugin's private data is stored here */
+ GstTensorFilterProperties prop; /**< NNFW plugin's properties */
- GstTensor_Filter_Properties prop;
+ /** internal properties for tensor-filter */
+ int silent; /**< Verbose mode if FALSE. int instead of gboolean for non-glib custom plugins */
+ gboolean configured; /**< True if already successfully configured tensor metadata */
+ GstTensorsConfig in_config; /**< input tensor info */
+ GstTensorsConfig out_config; /**< output tensor info */
};
-/** @brief Location of GstTensor_Filter from privateData
- * @param p the "privateData" pointer of GstTensor_Filter
- * @return the pointer to GstTensor_Filter containing p as privateData
+/**
+ * @brief Location of GstTensorFilter from privateData
+ * @param p the "privateData" pointer of GstTensorFilter
+ * @return the pointer to GstTensorFilter containing p as privateData
*/
-#define GstTensor_Filter_of_privateData(p) ({ \
+#define GstTensorFilter_of_privateData(p) ({ \
const void **__mptr = (const void **)(p); \
- (GstTensor_Filter *)( (char *)__mptr - offsetof(GstTensor_Filter, privateData) );})
+ (GstTensorFilter *)( (char *)__mptr - offsetof(GstTensorFilter, privateData) );})
/**
- * @brief GstTensor_FilterClass inherits GstBaseTransformClass.
+ * @brief GstTensorFilterClass inherits GstBaseTransformClass.
*
* Referring another child (sibiling), GstVideoFilter (abstract class) and
* its child (concrete class) GstVideoConverter.
- * Note that GstTensor_FilterClass is a concrete class; thus we need to look at both.
+ * Note that GstTensorFilterClass is a concrete class; thus we need to look at both.
*/
-struct _GstTensor_FilterClass
+struct _GstTensorFilterClass
{
GstBaseTransformClass parent_class; /**< Inherits GstBaseTransformClass */
};
* filter Filter properties. Read Only
* private_data Subplugin's private data. Set this (*private_data = XXX) if you want to change filter->private_data
*/
-struct _GstTensor_Filter_Framework
+struct _GstTensorFilterFramework
{
gchar *name; /**< Name of the neural network framework, searchable by FRAMEWORK property */
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,
+ uint8_t *(*invoke_NN) (const GstTensorFilter * filter, void **private_data,
const uint8_t * inputptr, uint8_t * outputptr);
/**< Mandatory callback. Invoke the given network model.
*
* @return outputptr if allocate_in_invoke = 00 if OK. non-zero if error.
*/
- int (*getInputDimension) (const GstTensor_Filter * filter,
- void **private_data, GstTensor_TensorsMeta * meta);
+ int (*getInputDimension) (const GstTensorFilter * filter,
+ void **private_data, GstTensorsInfo * info);
/**< 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
*
* @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.
- * @param[out] inputDimension dimension of input tensor (return value)
- * @param[out] type type of input tensor element (return value)
+ * @param[out] info structure of tensor info (return value)
* @return the size of input tensors
*/
- int (*getOutputDimension) (const GstTensor_Filter * filter,
- void **private_data, GstTensor_TensorsMeta * meta);
+
+ int (*getOutputDimension) (const GstTensorFilter * filter,
+ void **private_data, GstTensorsInfo * info);
/**< 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
*
* @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.
- * @param[out] outputDimension dimension of output tensor (return value)
- * @param[out] type type of output tensor element (return value)
+ * @param[out] info structure of tensor info (return value)
* @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 GstTensorFilter * filter,
+ void **private_data, const GstTensorsInfo * in_info,
+ GstTensorsInfo * out_info);
/**< 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
*
* @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.
- * @param[in] inputDimension dimension of input tensor
- * @param[in] inputType type of input tensor element
- * @param[out] outputDimension dimension of output tensor (return value)
- * @param[out] outputType type of output tensor element (return value)
+ * @param[in] in_info structure of input tensor info
+ * @param[out] out_info structure of output tensor info (return value)
* @return 0 if OK. non-zero if error.
*/
- void (*open) (const GstTensor_Filter * filter, void **private_data);
+ void (*open) (const GstTensorFilter * 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 GstTensorFilter * 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
*/
};
-extern GstTensor_Filter_Framework NNS_support_tensorflow_lite;
-extern GstTensor_Filter_Framework NNS_support_tensorflow;
-extern GstTensor_Filter_Framework NNS_support_custom;
+extern GstTensorFilterFramework NNS_support_tensorflow_lite;
+extern GstTensorFilterFramework NNS_support_tensorflow;
+extern GstTensorFilterFramework NNS_support_custom;
-extern GstTensor_Filter_Framework *tensor_filter_supported[];
+extern GstTensorFilterFramework *tensor_filter_supported[];
G_END_DECLS
+
#endif /* __GST_TENSOR_FILTER_H__ */
* @bug No known bugs except for NYI items
*
* This is the per-NN-framework plugin (custom) for tensor_filter.
- * Fill in "GstTensor_Filter_Framework" for tensor_filter.h/c
+ * Fill in "GstTensorFilterFramework" for tensor_filter.h/c
*
*/
*/
struct _internal_data
{
- GstTensor_Filter *parent;
+ GstTensorFilter *parent;
void *handle;
NNStreamer_custom_class *methods;
* @return 0 if successfully loaded. 1 if skipped (already loaded). -1 if error
*/
static int
-custom_loadlib (const GstTensor_Filter * filter, void **private_data)
+custom_loadlib (const GstTensorFilter * filter, void **private_data)
{
internal_data *ptr;
char *dlsym_error;
if (filter->privateData != NULL) {
- /** @todo : Check the integrity of filter->data and filter->modelFilename, nnfw */
+ /** @todo : Check the integrity of filter->data and filter->model_file, nnfw */
return 1;
}
ptr = g_new0 (internal_data, 1); /* Fill Zero! */
*private_data = ptr;
g_assert (*private_data == filter->privateData);
- ptr->parent = GstTensor_Filter_of_privateData (private_data);
+ ptr->parent = GstTensorFilter_of_privateData (private_data);
/* Load .so if this is the first time for this instance. */
- ptr->handle = dlopen (filter->prop.modelFilename, RTLD_NOW);
+ ptr->handle = dlopen (filter->prop.model_file, RTLD_NOW);
if (!ptr->handle) {
g_free (ptr);
*private_data = NULL;
}
/**
- * @brief The open callback for GstTensor_Filter_Framework. Called before anything else
+ * @brief The open callback for GstTensorFilterFramework. Called before anything else
*/
static void
-custom_open (const GstTensor_Filter * filter, void **private_data)
+custom_open (const GstTensorFilter * filter, void **private_data)
{
int retval = custom_loadlib (filter, private_data);
internal_data *ptr;
}
/**
- * @brief The mandatory callback for GstTensor_Filter_Framework
+ * @brief The mandatory callback for GstTensorFilterFramework
* @param filter The parent object
* @param[in] inptr The input tensor
* @param[out] outptr The output tensor
*/
static uint8_t *
-custom_invoke (const GstTensor_Filter * filter, void **private_data,
+custom_invoke (const GstTensorFilter * filter, void **private_data,
const uint8_t * inptr, uint8_t * outptr)
{
int retval = custom_loadlib (filter, private_data);
uint8_t *retptr = ptr->methods->allocate_invoke (ptr->customFW_private_data,
&(filter->prop), inptr, &size);
g_assert (size ==
- (get_tensor_element_count (filter->prop.outputMeta.dims[0]) *
- tensor_element_size[filter->prop.outputMeta.types[0]]));
+ (get_tensor_element_count (filter->prop.output_meta.info[0].dimension) *
+ tensor_element_size[filter->prop.output_meta.info[0].type]));
return retptr;
} else {
return NULL;
}
/**
- * @brief The optional callback for GstTensor_Filter_Framework
+ * @brief The optional callback for GstTensorFilterFramework
*/
static int
-custom_getInputDim (const GstTensor_Filter * filter, void **private_data,
- GstTensor_TensorsMeta * meta)
+custom_getInputDim (const GstTensorFilter * filter, void **private_data,
+ GstTensorsInfo * info)
{
int retval = custom_loadlib (filter, private_data);
internal_data *ptr;
}
return ptr->methods->getInputDim (ptr->customFW_private_data, &(filter->prop),
- meta);
+ info);
}
/**
- * @brief The optional callback for GstTensor_Filter_Framework
+ * @brief The optional callback for GstTensorFilterFramework
*/
static int
-custom_getOutputDim (const GstTensor_Filter * filter, void **private_data,
- GstTensor_TensorsMeta * meta)
+custom_getOutputDim (const GstTensorFilter * filter, void **private_data,
+ GstTensorsInfo * info)
{
int retval = custom_loadlib (filter, private_data);
internal_data *ptr;
}
return ptr->methods->getOutputDim (ptr->customFW_private_data,
- &(filter->prop), meta);
+ &(filter->prop), info);
}
/**
- * @brief The set-input-dim callback for GstTensor_Filter_Framework
+ * @brief The set-input-dim callback for GstTensorFilterFramework
*/
static int
-custom_setInputDim (const GstTensor_Filter * filter, void **private_data,
- const tensor_dim iDimension, const tensor_type iType,
- tensor_dim oDimension, tensor_type * oType)
+custom_setInputDim (const GstTensorFilter * filter, void **private_data,
+ const GstTensorsInfo * in_info, GstTensorsInfo * out_info)
{
int retval = custom_loadlib (filter, private_data);
internal_data *ptr;
return -1;
return ptr->methods->setInputDim (ptr->customFW_private_data,
- &(filter->prop), iDimension, iType, oDimension, oType);
+ &(filter->prop), in_info, out_info);
}
/**
* @brief Free privateData and move on.
*/
static void
-custom_close (const GstTensor_Filter * filter, void **private_data)
+custom_close (const GstTensorFilter * filter, void **private_data)
{
internal_data *ptr = *private_data;
g_assert (filter->privateData == NULL);
}
-GstTensor_Filter_Framework NNS_support_custom = {
+GstTensorFilterFramework NNS_support_custom = {
.name = "custom",
.allow_in_place = FALSE, /* custom cannot support in-place (outptr == inptr). */
.allocate_in_invoke = FALSE, /* Let tensor_flow allocate output buffers */
* @bug No known bugs except for NYI items
*
* This is the per-NN-framework plugin (tensorflow) for tensor_filter.
- * Fill in "GstTensor_Filter_Framework" for tensor_filter.h/c
+ * Fill in "GstTensorFilterFramework" for tensor_filter.h/c
*
*/
* @return 0 if successfully loaded. 1 if skipped (already loaded). -1 if error
*/
static int
-tf_loadModelFile (const GstTensor_Filter * filter, void **private_data)
+tf_loadModelFile (const GstTensorFilter * filter, void **private_data)
{
tf_data *tf;
if (filter->privateData != NULL) {
- /** @todo : Check the integrity of filter->data and filter->modelFilename, nnfw */
+ /** @todo : Check the integrity of filter->data and filter->model_file, nnfw */
return 1;
}
tf = g_new0 (tf_data, 1); /** initialize tf Fill Zero! */
*private_data = tf;
- tf->tf_private_data = tf_core_new (filter->prop.modelFilename);
+ tf->tf_private_data = tf_core_new (filter->prop.model_file);
if (tf->tf_private_data) {
return 0;
} else {
}
/**
- * @brief The open callback for GstTensor_Filter_Framework. Called before anything else
+ * @brief The open callback for GstTensorFilterFramework. Called before anything else
* @param filter : tensor_filter instance
* @param private_data : tensorflow lite plugin's private data
*/
static void
-tf_open (const GstTensor_Filter * filter, void **private_data)
+tf_open (const GstTensorFilter * filter, void **private_data)
{
int retval = tf_loadModelFile (filter, private_data);
g_assert (retval == 0); /** This must be called only once */
}
/**
- * @brief The mandatory callback for GstTensor_Filter_Framework
+ * @brief The mandatory callback for GstTensorFilterFramework
* @param[in] inptr The input tensor
* @param[out] outptr The output tensor
*/
static uint8_t *
-tf_invoke (const GstTensor_Filter * filter, void **private_data,
+tf_invoke (const GstTensorFilter * filter, void **private_data,
const uint8_t * inptr, uint8_t * outptr)
{
int retval;
}
/**
- * @brief The optional callback for GstTensor_Filter_Framework
+ * @brief The optional callback for GstTensorFilterFramework
*/
static int
-tf_getInputDim (const GstTensor_Filter * filter, void **private_data,
- GstTensor_TensorsMeta * meta)
+tf_getInputDim (const GstTensorFilter * filter, void **private_data,
+ GstTensorsInfo * info)
{
int temp_idx = 0;
tf_data *tf;
else
temp_idx = 0;
g_assert (filter->privateData && *private_data == filter->privateData);
- return tf_core_getInputDim (tf->tf_private_data, meta->dims[0],
- &meta->types[0], &meta->num_tensors);
+ return tf_core_getInputDim (tf->tf_private_data, info);
}
/**
- * @brief The optional callback for GstTensor_Filter_Framework
+ * @brief The optional callback for GstTensorFilterFramework
*/
static int
-tf_getOutputDim (const GstTensor_Filter * filter, void **private_data,
- GstTensor_TensorsMeta * meta)
+tf_getOutputDim (const GstTensorFilter * filter, void **private_data,
+ GstTensorsInfo * info)
{
int temp_idx = 0;
tf_data *tf;
else
temp_idx = 0;
g_assert (filter->privateData && *private_data == filter->privateData);
- return tf_core_getOutputDim (tf->tf_private_data, meta->dims[0],
- &meta->types[0], &meta->num_tensors);
+ return tf_core_getOutputDim (tf->tf_private_data, info);
}
/**
- * @brief The set-input-dim callback for GstTensor_Filter_Framework
+ * @brief The set-input-dim callback for GstTensorFilterFramework
*/
static int
-tf_setInputDim (const GstTensor_Filter * filter, void **private_data,
- const tensor_dim iDimension, const tensor_type iType,
- tensor_dim oDimension, tensor_type * oType)
+tf_setInputDim (const GstTensorFilter * filter, void **private_data,
+ const GstTensorsInfo * in_info, GstTensorsInfo * out_info)
{
/** @todo call tflite core apis */
return 0; /** NYI */
* @brief Free privateData and move on.
*/
static void
-tf_close (const GstTensor_Filter * filter, void **private_data)
+tf_close (const GstTensorFilter * filter, void **private_data)
{
tf_data *tf;
tf = *private_data;
g_assert (filter->privateData == NULL);
}
-GstTensor_Filter_Framework NNS_support_tensorflow = {
+GstTensorFilterFramework NNS_support_tensorflow = {
.name = "tensorflow",
.allow_in_place = FALSE, /** @todo: support this to optimize performance later. */
.allocate_in_invoke = TRUE,
/**
* @brief return the Dimension of Input Tensor.
- * @param idx : the index of the input tensor
- * @param[out] dim : the array of the input tensor
- * @param[out] type : the data type of the input tensor
+ * @param[out] info Structure for tensor info.
* @return 0 if OK. non-zero if error.
*/
int
-TFCore::getInputTensorDim (tensor_dim dim, tensor_type * type,
- unsigned int *num_tensors)
+TFCore::getInputTensorDim (GstTensorsInfo * info)
{
- int ret = getTensorDim (dim, type);
- return ret;
+ /**
+ * @todo fill here
+ */
+ return 0;
}
/**
* @brief return the Dimension of Output Tensor.
- * @param idx : the index of the output tensor
- * @param[out] dim : the array of the output tensor
- * @param[out] type : the data type of the output tensor
+ * @param[out] info Structure for tensor info.
* @return 0 if OK. non-zero if error.
*/
int
-TFCore::getOutputTensorDim (tensor_dim dim, tensor_type * type,
- unsigned int *num_tensors)
+TFCore::getOutputTensorDim (GstTensorsInfo * info)
{
- int ret = getTensorDim (dim, type);
- return ret;
+ /**
+ * @todo fill here
+ */
+ return 0;
}
/**
/**
* @brief get the Dimension of Input Tensor of model
- * @param tf : the class object
- * @param idx : the index of the input tensor
- * @param[out] dim : the array of the input tensor
- * @param[out] type : the data type of the input tensor
+ * @param tf the class object
+ * @param[out] info Structure for tensor info.
* @return 0 if OK. non-zero if error.
*/
int
-tf_core_getInputDim (void *tf, tensor_dim dim, tensor_type * type,
- unsigned int *num_tensors)
+tf_core_getInputDim (void *tf, GstTensorsInfo * info)
{
TFCore *c = (TFCore *) tf;
- return c->getInputTensorDim (dim, type, num_tensors);
+ return c->getInputTensorDim (info);
}
/**
* @brief get the Dimension of Output Tensor of model
- * @param tf : the class object
- * @param idx : the index of the output tensor
- * @param[out] dim : the array of the output tensor
- * @param[out] type : the data type of the output tensor
+ * @param tf the class object
+ * @param[out] info Structure for tensor info.
* @return 0 if OK. non-zero if error.
*/
int
-tf_core_getOutputDim (void *tf, tensor_dim dim, tensor_type * type,
- unsigned int *num_tensors)
+tf_core_getOutputDim (void *tf, GstTensorsInfo * info)
{
TFCore *c = (TFCore *) tf;
- return c->getOutputTensorDim (dim, type, num_tensors);
+ return c->getOutputTensorDim (info);
}
/**
* @bug No known bugs except for NYI items
*
* This is the per-NN-framework plugin (tensorflow-lite) for tensor_filter.
- * Fill in "GstTensor_Filter_Framework" for tensor_filter.h/c
+ * Fill in "GstTensorFilterFramework" for tensor_filter.h/c
*
*/
* @return 0 if successfully loaded. 1 if skipped (already loaded). -1 if error
*/
static int
-tflite_loadModelFile (const GstTensor_Filter * filter, void **private_data)
+tflite_loadModelFile (const GstTensorFilter * filter, void **private_data)
{
tflite_data *tf;
if (filter->privateData != NULL) {
- /** @todo : Check the integrity of filter->data and filter->modelFilename, nnfw */
+ /** @todo : Check the integrity of filter->data and filter->model_file, nnfw */
return 1;
}
tf = g_new0 (tflite_data, 1); /** initialize tf Fill Zero! */
*private_data = tf;
- tf->tflite_private_data = tflite_core_new (filter->prop.modelFilename);
+ tf->tflite_private_data = tflite_core_new (filter->prop.model_file);
if (tf->tflite_private_data) {
return 0;
} else {
}
/**
- * @brief The open callback for GstTensor_Filter_Framework. Called before anything else
+ * @brief The open callback for GstTensorFilterFramework. Called before anything else
* @param filter : tensor_filter instance
* @param private_data : tensorflow lite plugin's private data
*/
static void
-tflite_open (const GstTensor_Filter * filter, void **private_data)
+tflite_open (const GstTensorFilter * filter, void **private_data)
{
int retval = tflite_loadModelFile (filter, private_data);
g_assert (retval == 0); /** This must be called only once */
}
/**
- * @brief The mandatory callback for GstTensor_Filter_Framework
+ * @brief The mandatory callback for GstTensorFilterFramework
* @param[in] inptr The input tensor
* @param[out] outptr The output tensor
*/
static uint8_t *
-tflite_invoke (const GstTensor_Filter * filter, void **private_data,
+tflite_invoke (const GstTensorFilter * filter, void **private_data,
const uint8_t * inptr, uint8_t * outptr)
{
int retval;
}
/**
- * @brief The optional callback for GstTensor_Filter_Framework
+ * @brief The optional callback for GstTensorFilterFramework
*/
static int
-tflite_getInputDim (const GstTensor_Filter * filter, void **private_data,
- GstTensor_TensorsMeta * meta)
+tflite_getInputDim (const GstTensorFilter * filter, void **private_data,
+ GstTensorsInfo * info)
{
tflite_data *tf;
tf = *private_data;
g_assert (filter->privateData && *private_data == filter->privateData);
- int ret = tflite_core_getInputDim (tf->tflite_private_data, meta);
+ int ret = tflite_core_getInputDim (tf->tflite_private_data, info);
return ret;
}
/**
- * @brief The optional callback for GstTensor_Filter_Framework
+ * @brief The optional callback for GstTensorFilterFramework
*/
static int
-tflite_getOutputDim (const GstTensor_Filter * filter, void **private_data,
- GstTensor_TensorsMeta * meta)
+tflite_getOutputDim (const GstTensorFilter * filter, void **private_data,
+ GstTensorsInfo * info)
{
tflite_data *tf;
tf = *private_data;
g_assert (filter->privateData && *private_data == filter->privateData);
- int ret = tflite_core_getOutputDim (tf->tflite_private_data, meta);
+ int ret = tflite_core_getOutputDim (tf->tflite_private_data, info);
return ret;
}
/**
- * @brief The set-input-dim callback for GstTensor_Filter_Framework
+ * @brief The set-input-dim callback for GstTensorFilterFramework
*/
static int
-tflite_setInputDim (const GstTensor_Filter * filter, void **private_data,
- const tensor_dim iDimension, const tensor_type iType,
- tensor_dim oDimension, tensor_type * oType)
+tflite_setInputDim (const GstTensorFilter * filter, void **private_data,
+ const GstTensorsInfo * in_info, GstTensorsInfo * out_info)
{
/** @todo call tflite core apis */
return 0; /** NYI */
* @brief Free privateData and move on.
*/
static void
-tflite_close (const GstTensor_Filter * filter, void **private_data)
+tflite_close (const GstTensorFilter * filter, void **private_data)
{
tflite_data *tf;
tf = *private_data;
g_assert (filter->privateData == NULL);
}
-GstTensor_Filter_Framework NNS_support_tensorflow_lite = {
+GstTensorFilterFramework NNS_support_tensorflow_lite = {
.name = "tensorflow-lite",
.allow_in_place = FALSE, /** @todo: support this to optimize performance later. */
.allocate_in_invoke = TRUE,
* @param tfType : the defined type of Tensorflow Lite
* @return the enum of defined _NNS_TYPE
*/
-_nns_tensor_type TFLiteCore::getTensorType (TfLiteType tfType)
+_nns_tensor_type
+TFLiteCore::getTensorType (TfLiteType tfType)
{
switch (tfType) {
case kTfLiteFloat32:
inputTensorMeta.num_tensors = input_idx_list.size ();
for (int i = 0; i < inputTensorMeta.num_tensors; i++) {
- inputTensorMeta.ranks[i] = NNS_TENSOR_RANK_LIMIT;
-
- if (getTensorDim (input_idx_list[i], inputTensorMeta.dims[i],
- &inputTensorMeta.ranks[i])) {
+ if (getTensorDim (input_idx_list[i], inputTensorMeta.info[i].dimension)) {
return -1;
}
- inputTensorMeta.types[i] =
+ inputTensorMeta.info[i].type =
getTensorType (interpreter->tensor (input_idx_list[i])->type);
#if (DBG)
_print_log ("inputTensorMeta[%d] >> type:%d, dim[%d:%d:%d:%d], rank: %d",
- i, inputTensorMeta.types[i], inputTensorMeta.dims[i][0],
- inputTensorMeta.dims[i][1], inputTensorMeta.dims[i][2],
- inputTensorMeta.dims[i][3], inputTensorMeta.ranks[i]);
+ i, inputTensorMeta.info[i].type, inputTensorMeta.info[i].dimension[0],
+ inputTensorMeta.info[i].dimension[1],
+ inputTensorMeta.info[i].dimension[2],
+ inputTensorMeta.info[i].dimension[3]);
#endif
}
return 0;
outputTensorMeta.num_tensors = output_idx_list.size ();
for (int i = 0; i < outputTensorMeta.num_tensors; i++) {
- outputTensorMeta.ranks[i] = NNS_TENSOR_RANK_LIMIT;
-
- if (getTensorDim (output_idx_list[i], outputTensorMeta.dims[i],
- &outputTensorMeta.ranks[i])) {
+ if (getTensorDim (output_idx_list[i], outputTensorMeta.info[i].dimension)) {
return -1;
}
- outputTensorMeta.types[i] =
+ outputTensorMeta.info[i].type =
getTensorType (interpreter->tensor (output_idx_list[i])->type);
#if (DBG)
_print_log ("outputTensorMeta[%d] >> type:%d, dim[%d:%d:%d:%d], rank: %d",
- i, outputTensorMeta.types[i], outputTensorMeta.dims[i][0],
- outputTensorMeta.dims[i][1], outputTensorMeta.dims[i][2],
- outputTensorMeta.dims[i][3], outputTensorMeta.ranks[i]);
+ i, outputTensorMeta.info[i].type, outputTensorMeta.info[i].dimension[0],
+ outputTensorMeta.info[i].dimension[1],
+ outputTensorMeta.info[i].dimension[2],
+ outputTensorMeta.info[i].dimension[3]);
#endif
}
return 0;
* @brief return the Dimension of Tensor.
* @param tensor_idx : the real index of model of the tensor
* @param[out] dim : the array of the tensor
- * @param[out] rank : the rank of the tensor
* @return 0 if OK. non-zero if error.
*/
int
-TFLiteCore::getTensorDim (int tensor_idx, tensor_dim dim, int *rank)
+TFLiteCore::getTensorDim (int tensor_idx, tensor_dim dim)
{
int len = interpreter->tensor (tensor_idx)->dims->size;
- *rank = len;
g_assert (len <= NNS_TENSOR_RANK_LIMIT);
/* the order of dimension is reversed at CAPS negotiation */
/**
* @brief return the Dimension of Input Tensor.
- * @param[out] dim : the array of the input tensors
- * @param[out] type : the data type of the input tensors
- * @todo : return whole array rather than index 0
+ * @param[out] info Structure for tensor info.
+ * @todo return whole array rather than index 0
* @return 0 if OK. non-zero if error.
*/
int
-TFLiteCore::getInputTensorDim (GstTensor_TensorsMeta * meta)
+TFLiteCore::getInputTensorDim (GstTensorsInfo * info)
{
- for (int i = 0; i < inputTensorMeta.num_tensors; i++) {
- memcpy (meta->dims[i], inputTensorMeta.dims[i], sizeof (meta->dims[i]));
- meta->types[i] = inputTensorMeta.types[i];
- meta->ranks[i] = inputTensorMeta.ranks[i];
- }
- meta->num_tensors = inputTensorMeta.num_tensors;
+ info->num_tensors = inputTensorMeta.num_tensors;
+ memcpy (info->info, inputTensorMeta.info,
+ sizeof (GstTensorInfo) * inputTensorMeta.num_tensors);
return 0;
}
/**
* @brief return the Dimension of Tensor.
- * @param[out] dim : the array of the tensors
- * @param[out] type : the data type of the tensors
- * @todo : return whole array rather than index 0
+ * @param[out] info Structure for tensor info.
+ * @todo return whole array rather than index 0
* @return 0 if OK. non-zero if error.
*/
int
-TFLiteCore::getOutputTensorDim (GstTensor_TensorsMeta * meta)
+TFLiteCore::getOutputTensorDim (GstTensorsInfo * info)
{
- for (int i = 0; i < outputTensorMeta.num_tensors; i++) {
- memcpy (meta->dims, outputTensorMeta.dims[i], sizeof (meta->dims[i]));
- meta->types[i] = outputTensorMeta.types[i];
- meta->ranks[i] = outputTensorMeta.ranks[i];
- }
- meta->num_tensors = outputTensorMeta.num_tensors;
+ info->num_tensors = outputTensorMeta.num_tensors;
+ memcpy (info->info, outputTensorMeta.info,
+ sizeof (GstTensorInfo) * outputTensorMeta.num_tensors);
return 0;
}
int sizeOfArray = NNS_TENSOR_RANK_LIMIT;
for (int i = 0; i < sizeOfArray; i++) {
- output_number_of_pixels *= inputTensorMeta.dims[0][i];
+ output_number_of_pixels *= inputTensorMeta.info[0].dimension[i];
}
for (int i = 0; i < getInputTensorSize (); i++) {
inputTensors[0] = inptr;
for (int j = 0; j < output_number_of_pixels; j++) {
- if (inputTensorMeta.types[i] == _NNS_FLOAT32) {
+ if (inputTensorMeta.info[i].type == _NNS_FLOAT32) {
(interpreter->typed_tensor < float >(input))[j] =
((float) inputTensors[i][j] - 127.5f) / 127.5f;
- } else if (inputTensorMeta.types[i] == _NNS_UINT8) {
+ } else if (inputTensorMeta.info[i].type == _NNS_UINT8) {
(interpreter->typed_tensor < uint8_t > (input))[j] = inputTensors[i][j];
}
}
for (int i = 0; i < outputTensorMeta.num_tensors; i++) {
- if (outputTensorMeta.types[i] == _NNS_FLOAT32) {
+ if (outputTensorMeta.info[i].type == _NNS_FLOAT32) {
outputTensors[i] =
(uint8_t *) interpreter->typed_output_tensor < float >(i);
- } else if (outputTensorMeta.types[i] == _NNS_UINT8) {
+ } else if (outputTensorMeta.info[i].type == _NNS_UINT8) {
outputTensors[i] = interpreter->typed_output_tensor < uint8_t > (i);
}
}
/**
* @brief get the Dimension of Input Tensor of model
* @param tflite : the class object
- * @param[out] dim : the array of the input tensor
- * @param[out] type : the data type of the input tensor
+ * @param[out] info Structure for tensor info.
* @return 0 if OK. non-zero if error.
*/
int
-tflite_core_getInputDim (void *tflite, GstTensor_TensorsMeta * meta)
+tflite_core_getInputDim (void *tflite, GstTensorsInfo * info)
{
TFLiteCore *c = (TFLiteCore *) tflite;
- int ret = c->getInputTensorDim (meta);
+ int ret = c->getInputTensorDim (info);
return ret;
}
/**
* @brief get the Dimension of Output Tensor of model
* @param tflite : the class object
- * @param[out] dim : the array of the output tensor
- * @param[out] type : the data type of the output tensor
+ * @param[out] info Structure for tensor info.
* @return 0 if OK. non-zero if error.
*/
int
-tflite_core_getOutputDim (void *tflite, GstTensor_TensorsMeta * meta)
+tflite_core_getOutputDim (void *tflite, GstTensorsInfo * info)
{
TFLiteCore *c = (TFLiteCore *) tflite;
- int ret = c->getOutputTensorDim (meta);
+ int ret = c->getOutputTensorDim (info);
return ret;
}
/**
* @brief Parse tensor dimension parameter string
- * @return The Rank.
- * @param param The parameter string in the format of d1:d2:d3:d4, d1:d2:d3, d1:d2, or d1, where dN is a positive integer and d1 is the innermost dimension; i.e., dim[d4][d3][d2][d1];
+ * @return The Rank. 0 if error.
+ * @param dimstr The dimension string in the format of d1:d2:d3:d4, d1:d2:d3, d1:d2, or d1, where dN is a positive integer and d1 is the innermost dimension; i.e., dim[d4][d3][d2][d1];
+ * @param dim dimension to be filled.
*/
-extern int get_tensor_dimension (const gchar * param,
- uint32_t dim[NNS_TENSOR_SIZE_LIMIT][NNS_TENSOR_RANK_LIMIT]);
+extern int get_tensor_dimension (const gchar * dimstr, tensor_dim dim);
+
+/**
+ * @brief Get dimension string from given tensor dimension.
+ * @param dim tensor dimension
+ * @return Formatted string of given dimension (d1:d2:d3:d4).
+ * @note The returned value should be freed with g_free()
+ */
+extern gchar *get_tensor_dimension_string (const tensor_dim dim);
/**
* @brief Count the number of elemnts of a tensor
tensor_type * type, int *framerate_num, int *framerate_denum);
/**
- * @brief Read GstStructure, return corresponding tensor-dim/type. (other/tensor)
- * @return The number of tensors.
- * @param[in] str the GstStructure to be interpreted.
- * @param[out] meta An allocated but filled with Null meta, to be used as output.
- * @param[out] framerate_num Numerator of framerate. Set null to not use this.
- * @param[out] framerate_denum Denumerator of framerate. Set null to not use this.
- */
-extern int
-get_tensors_from_structure (const GstStructure * str,
- GstTensor_TensorsMeta * meta, int *framerate_num, int *framerate_denum);
-
-/**
* @brief Make str(xyz) ==> "xyz" with macro expansion
*/
#define str(s) xstr(s)
* @param[in] prop Tensor_Filter's property values. Do not change its values.
* @return The returned pointer will be passed to other functions as "private_data".
*/
-typedef void *(*NNS_custom_init_func)(const GstTensor_Filter_Properties *prop);
+typedef void *(*NNS_custom_init_func) (const GstTensorFilterProperties * prop);
/**
* @brief A function that is called after calling other functions, when it's ready to close.
* @param[in] private_data If you have allocated *private_data at init, free it here.
* @param[in] prop Tensor_Filter's property values. Do not change its values.
*/
-typedef void (*NNS_custom_exit_func)(void *private_data, const GstTensor_Filter_Properties *prop);
+typedef void (*NNS_custom_exit_func) (void *private_data,
+ const GstTensorFilterProperties * prop);
/**
* @brief Get input tensor type.
* @param[in] private_data The pointer returned by NNStreamer_custom_init.
* @param[in] prop Tensor_Filter's property values. Do not change its values.
- * @param[out] inputDimension uint32_t[NNS_TENSOR_RANK_LIMIT] (tensor_dim)
- * @param[out] type Type of each element in the input tensor
+ * @param[out] info Structure for tensor info.
*/
typedef int (*NNS_custom_get_input_dimension) (void *private_data,
- const GstTensor_Filter_Properties * prop, GstTensor_TensorsMeta * meta);
+ const GstTensorFilterProperties * prop, GstTensorsInfo * info);
/**
* @brief Get output tensor type.
* @param[in] private_data The pointer returned by NNStreamer_custom_init.
* @param[in] prop Tensor_Filter's property values. Do not change its values.
- * @param[out] outputDimension uint32_t[NNS_TENSOR_RANK_LIMIT] (tensor_dim)
- * @param[out] type Type of each element in the output tensor
+ * @param[out] info Structure for tensor info.
*/
typedef int (*NNS_custom_get_output_dimension) (void *private_data,
- const GstTensor_Filter_Properties * prop, GstTensor_TensorsMeta * meta);
+ const GstTensorFilterProperties * prop, GstTensorsInfo * info);
/**
* @brief Set input dim by framework. Let custom plutin set output dim accordingly.
* @param[in] private_data The pointer returned by NNStreamer_custom_init
* @param[in] prop Tensor_Filter's property values. Do not change its values.
- * @param[in] inputDimension Input dimension designated by the gstreamer framework. Note that this is not a fixed value and gstreamer may try different values during pad-cap negotiations.
- * @param[in] inputType Input element type designated by the gstreamer framework.
- * @param[out] outputDimension Output dimension according to the inputDimension/type.
- * @param[out] outputType Output element type according to the inputDimension/type.
+ * @param[in] in_info Input tensor info designated by the gstreamer framework. Note that this is not a fixed value and gstreamer may try different values during pad-cap negotiations.
+ * @param[out] out_info Output tensor info according to the input tensor info.
*
* @caution Do not fix internal values based on this call. Gstreamer may call
* this function repeatedly with different values during pad-cap negotiations.
* Fix values when invoke is finally called.
*/
-typedef int (*NNS_custom_set_input_dimension)(void *private_data, const GstTensor_Filter_Properties *prop,
- const tensor_dim inputDimension, const tensor_type inputType,
- tensor_dim outputDimension, tensor_type *outputType);
+typedef int (*NNS_custom_set_input_dimension) (void *private_data,
+ const GstTensorFilterProperties * prop, const GstTensorsInfo * in_info, GstTensorsInfo * out_info);
/**
* @brief Invoke the "main function". Without allocating output buffer. (fill in the given output buffer)
* @param[in] private_data The pointer returned by NNStreamer_custom_init.
* @param[in] prop Tensor_Filter's property values. Do not change its values.
- * @param[in] inputPtr pointer to input tensor, size = dim1 x dim2 x dim3 x dim4 x typesize, allocated by caller
- * @param[out] outputPtr pointer to output tensor, size = dim1 x dim2 x dim3 x dim4 x typesize, allocated by caller
+ * @param[in] inptr pointer to input tensor, size = dim1 x dim2 x dim3 x dim4 x typesize, allocated by caller
+ * @param[out] outptr pointer to output tensor, size = dim1 x dim2 x dim3 x dim4 x typesize, allocated by caller
* @return 0 if success
*/
-typedef int (*NNS_custom_invoke)(void *private_data, const GstTensor_Filter_Properties *prop,
- const uint8_t *inputPtr, uint8_t *outputPtr);
+typedef int (*NNS_custom_invoke) (void *private_data,
+ const GstTensorFilterProperties * prop, const uint8_t * inptr, uint8_t * outptr);
/**
* @brief Invoke the "main function". Without allocating output buffer. (fill in the given output buffer)
* @param[in] private_data The pointer returned by NNStreamer_custom_init.
* @param[in] prop Tensor_Filter's property values. Do not change its values.
- * @param[in] inputPtr pointer to input tensor, size = dim1 x dim2 x dim3 x dim4 x typesize, allocated by caller
+ * @param[in] inptr pointer to input tensor, size = dim1 x dim2 x dim3 x dim4 x typesize, allocated by caller
* @param[out] size The allocated size.
* @return The output buffer allocated in the invoke function
*/
-typedef uint8_t * (*NNS_custom_allocate_invoke)(void *private_data, const GstTensor_Filter_Properties *prop,
- const uint8_t *inputPtr, size_t *size);
+typedef uint8_t *(*NNS_custom_allocate_invoke) (void *private_data,
+ const GstTensorFilterProperties * prop, const uint8_t * inptr, size_t * size);
/**
* @brief Custom Filter Class
*
* Note that exery function pointer is MANDATORY!
*/
-struct _NNStreamer_custom_class {
+struct _NNStreamer_custom_class
+{
int allocate_outbuf_in_invoke; /**< Set non-zero if invoke function is to allocate output buffer. Note that the allocated outbuf size MUST be consistent with output tensor dimension & type */
NNS_custom_init_func initfunc; /**< called before any other callbacks from tensor_filter_custom.c */
NNS_custom_exit_func exitfunc; /**< will not call other callbacks after this call */
double get_ms (struct timeval t);
int getInputTensorSize ();
int getOutputTensorSize ();
- int getInputTensorDim (tensor_dim dim, tensor_type * type,
- unsigned int *num_tensors);
- int getOutputTensorDim (tensor_dim dim, tensor_type * type,
- unsigned int *num_tensors);
+ int getInputTensorDim (GstTensorsInfo * info);
+ int getOutputTensorDim (GstTensorsInfo * info);
int getInputTensorDimSize ();
int getOutputTensorDimSize ();
int invoke (uint8_t * inptr, uint8_t ** outptr);
extern void *tf_core_new (const char *_model_path);
extern void tf_core_delete (void *tf);
extern const char *tf_core_getModelPath (void *tf);
- extern int tf_core_getInputDim (void *tf, tensor_dim dim,
- tensor_type * type, unsigned int *num_tensors);
- extern int tf_core_getOutputDim (void *tf, tensor_dim dim,
- tensor_type * type, unsigned int *num_tensors);
+ extern int tf_core_getInputDim (void *tf, GstTensorsInfo * info);
+ extern int tf_core_getOutputDim (void *tf, GstTensorsInfo * info);
extern int tf_core_getInputSize (void *tf);
extern int tf_core_getOutputSize (void *tf);
extern int tf_core_invoke (void *tf, uint8_t * inptr, uint8_t ** outptr);
int setOutputTensorProp ();
int getInputTensorSize ();
int getOutputTensorSize ();
- int getInputTensorDim (GstTensor_TensorsMeta * meta);
- int getOutputTensorDim (GstTensor_TensorsMeta * meta);
+ int getInputTensorDim (GstTensorsInfo * info);
+ int getOutputTensorDim (GstTensorsInfo * info);
int invoke (uint8_t * inptr, uint8_t ** outptr);
private:
tensors inputTensors; /**< The list of input tensors */
tensors outputTensors; /**< The list of output tensors */
- GstTensor_TensorsMeta inputTensorMeta; /**< The meta of input tensors */
- GstTensor_TensorsMeta outputTensorMeta; /**< The meta of input tensors */
+ GstTensorsInfo inputTensorMeta; /**< The meta of input tensors */
+ GstTensorsInfo outputTensorMeta; /**< The meta of input tensors */
std::unique_ptr < tflite::Interpreter > interpreter;
std::unique_ptr < tflite::FlatBufferModel > model;
double get_ms (struct timeval t);
_nns_tensor_type getTensorType (TfLiteType tfType);
- int getTensorDim (int tensor_idx, tensor_dim dim, int *rank);
+ int getTensorDim (int tensor_idx, tensor_dim dim);
};
/**
extern void tflite_core_delete (void *tflite);
extern const char *tflite_core_getModelPath (void *tflite);
extern int tflite_core_getInputDim (void *tflite,
- GstTensor_TensorsMeta * meta);
+ GstTensorsInfo * info);
extern int tflite_core_getOutputDim (void *tflite,
- GstTensor_TensorsMeta * meta);
+ GstTensorsInfo * info);
extern int tflite_core_getOutputSize (void *tflite);
extern int tflite_core_getInputSize (void *tflite);
extern int tflite_core_invoke (void *tflite, uint8_t * inptr,
_T_F_NNFW_END,
} nnfw_type;
-struct _GstTensor_Filter_Framework;
-typedef struct _GstTensor_Filter_Framework GstTensor_Filter_Framework;
+struct _GstTensorFilterFramework;
+typedef struct _GstTensorFilterFramework GstTensorFilterFramework;
typedef enum {
_TFC_INIT = 0,
typedef uint8_t *tensors[NNS_TENSOR_SIZE_LIMIT]; /**< Array of tensors */
/**
- * @brief Internal meta data exchange format for a other/tensors instance
- * @todo replace this to GstTensorsInfo
- */
-typedef struct
-{
- unsigned int num_tensors; /**< The number of tensors */
- tensor_dim dims[NNS_TENSOR_SIZE_LIMIT]; /**< The list of dimensions of each tensors */
- tensor_type types[NNS_TENSOR_SIZE_LIMIT]; /**< The list of types for each tensors */
- int ranks[NNS_TENSOR_SIZE_LIMIT]; /**< The list of types for each tensors */
-} GstTensor_TensorsMeta;
-
-/**
* @brief Internal data structure for tensor info.
*/
typedef struct
} GstTensorsInfo;
/**
- * @brief Tensor_Filter's properties (internal data structure)
+ * @brief Tensor_Filter's properties for NN framework (internal data structure)
*
* Because custom filters of tensor_filter may need to access internal data
* of Tensor_Filter, we define this data structure here.
*/
-typedef struct _GstTensor_Filter_Properties
+typedef struct _GstTensorFilterProperties
{
- int silent; /**< Verbose mode if FALSE. int instead of gboolean for non-glib custom plugins */
- GstTensor_Filter_CheckStatus inputConfigured; /**< input dimension status */
- GstTensor_Filter_CheckStatus outputConfigured; /**< output dimension status */
nnfw_type nnfw; /**< The enum value of corresponding NNFW. _T_F_UNDEFINED if not configured */
- GstTensor_Filter_Framework *fw; /**< The implementation core of the NNFW. NULL if not configured */
- int fwOpened; /**< true IF open() is called or tried. Use int instead of gboolean because this is refered by custom plugins. */
- 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 */
+ GstTensorFilterFramework *fw; /**< The implementation core of the NNFW. NULL if not configured */
+ int fw_opened; /**< TRUE IF open() is called or tried. Use int instead of gboolean because this is refered by custom plugins. */
+ const char *model_file; /**< Filepath to the model file (as an argument for NNFW). char instead of gchar for non-glib custom plugins */
- int inputCapNegotiated; /**< @todo check if this is really needed */
- GstTensor_TensorsMeta inputMeta;
+ int input_configured; /**< TRUE if input tensor is configured. Use int instead of gboolean because this is refered by custom plugins. */
+ GstTensorsInfo input_meta; /**< configured input tensor info */
- int outputCapNegotiated; /**< @todo check if this is really needed */
- GstTensor_TensorsMeta outputMeta;
+ int output_configured; /**< TRUE if output tensor is configured. Use int instead of gboolean because this is refered by custom plugins. */
+ GstTensorsInfo output_meta; /**< configured output tensor info */
- const char *customProperties; /**< sub-plugin specific custom property values in string */
-} GstTensor_Filter_Properties;
+ const char *custom_properties; /**< sub-plugin specific custom property values in string */
+} GstTensorFilterProperties;
#endif /*__GST_TENSOR_TYPEDEF_H__*/
* @brief pt_init
*/
static void *
-pt_init (const GstTensor_Filter_Properties * prop)
+pt_init (const GstTensorFilterProperties * prop)
{
pt_data *data = (pt_data *) malloc (sizeof (pt_data));
* @brief pt_exit
*/
static void
-pt_exit (void *private_data, const GstTensor_Filter_Properties * prop)
+pt_exit (void *private_data, const GstTensorFilterProperties * prop)
{
pt_data *data = private_data;
assert (data);
* @brief set_inputDim
*/
static int
-set_inputDim (void *private_data, const GstTensor_Filter_Properties * prop,
- const tensor_dim iDim, const tensor_type iType,
- tensor_dim oDim, tensor_type * oType)
+set_inputDim (void *private_data, const GstTensorFilterProperties * prop,
+ const GstTensorsInfo * in_info, GstTensorsInfo * out_info)
{
int i;
pt_data *data = private_data;
+
assert (data);
+ assert (in_info);
+ assert (out_info);
+
+ out_info->num_tensors = 1;
for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++)
- oDim[i] = iDim[i];
+ out_info->info[0].dimension[i] = in_info->info[0].dimension[i];
- /* Update [1] and [2] oDim with new-x, new-y */
- oDim[1] = 1;
- oDim[2] = 1;
+ /* Update output dimension [1] and [2] with new-x, new-y */
+ out_info->info[0].dimension[1] = 1;
+ out_info->info[0].dimension[2] = 1;
- *oType = iType;
+ out_info->info[0].type = in_info->info[0].type;
return 0;
}
* @brief do_avg
*/
#define do_avg(type, sumtype) do {\
- sumtype *avg = (sumtype *) malloc(sizeof(sumtype) * prop->inputMeta.dims[0][0]); \
+ sumtype *avg = (sumtype *) malloc(sizeof(sumtype) * prop->input_meta.info[0].dimension[0]); \
type *iptr = (type *) inptr; \
type *optr = (type *) outptr; \
- for (z = 0; z < prop->inputMeta.dims[0][3]; z++) { \
- for (y = 0; y < prop->inputMeta.dims[0][0]; y++) \
+ for (z = 0; z < prop->input_meta.info[0].dimension[3]; z++) { \
+ for (y = 0; y < prop->input_meta.info[0].dimension[0]; y++) \
avg[y] = 0; \
- for (y = 0; y < prop->inputMeta.dims[0][2]; y++) { \
- for (x = 0; x < prop->inputMeta.dims[0][1]; x++) { \
- for (c = 0; c < prop->inputMeta.dims[0][0]; c++) { \
+ for (y = 0; y < prop->input_meta.info[0].dimension[2]; y++) { \
+ for (x = 0; x < prop->input_meta.info[0].dimension[1]; x++) { \
+ for (c = 0; c < prop->input_meta.info[0].dimension[0]; c++) { \
avg[c] += *(iptr + c + x * ix + y * iy + z * iz); \
} \
} \
} \
- for (c = 0; c < prop->inputMeta.dims[0][0]; c++) { \
- *(optr + c + z * prop->inputMeta.dims[0][0]) = (type) (avg[c] / xy); \
+ for (c = 0; c < prop->input_meta.info[0].dimension[0]; c++) { \
+ *(optr + c + z * prop->input_meta.info[0].dimension[0]) = (type) (avg[c] / xy); \
} \
} \
free(avg); \
* @brief pt_invoke
*/
static int
-pt_invoke (void *private_data, const GstTensor_Filter_Properties * prop,
+pt_invoke (void *private_data, const GstTensorFilterProperties * prop,
const uint8_t * inptr, uint8_t * outptr)
{
pt_data *data = private_data;
uint32_t c, x, y, z;
- unsigned ix = prop->inputMeta.dims[0][0];
- unsigned iy = prop->inputMeta.dims[0][0] * prop->inputMeta.dims[0][1];
- unsigned iz =
- prop->inputMeta.dims[0][0] * prop->inputMeta.dims[0][1] *
- prop->inputMeta.dims[0][2];
- unsigned xy = prop->inputMeta.dims[0][1] * prop->inputMeta.dims[0][2];
+ uint32_t ix = prop->input_meta.info[0].dimension[0];
+ uint32_t iy =
+ prop->input_meta.info[0].dimension[0] *
+ prop->input_meta.info[0].dimension[1];
+ uint32_t iz =
+ prop->input_meta.info[0].dimension[0] *
+ prop->input_meta.info[0].dimension[1] *
+ prop->input_meta.info[0].dimension[2];
+ uint32_t xy =
+ prop->input_meta.info[0].dimension[1] *
+ prop->input_meta.info[0].dimension[2];
assert (data);
assert (inptr);
/* This assumes the limit is 4 */
assert (NNS_TENSOR_RANK_LIMIT == 4);
- assert (prop->inputMeta.dims[0][0] == prop->outputMeta.dims[0][0]);
- assert (prop->inputMeta.dims[0][3] == prop->outputMeta.dims[0][3]);
- assert (prop->inputMeta.types[0] == prop->outputMeta.types[0]);
+ assert (prop->input_meta.info[0].dimension[0] ==
+ prop->output_meta.info[0].dimension[0]);
+ assert (prop->input_meta.info[0].dimension[3] ==
+ prop->output_meta.info[0].dimension[3]);
+ assert (prop->input_meta.info[0].type == prop->output_meta.info[0].type);
- switch (prop->inputMeta.types[0]) {
+ switch (prop->input_meta.info[0].type) {
case _NNS_INT8:
do_avg (int8_t, int64_t);
break;
* @brief _pt_data
*/
static void *
-pt_init (const GstTensor_Filter_Properties * prop)
+pt_init (const GstTensorFilterProperties * prop)
{
pt_data *data = (pt_data *) malloc (sizeof (pt_data));
int i;
* @brief _pt_data
*/
static void
-pt_exit (void *private_data, const GstTensor_Filter_Properties * prop)
+pt_exit (void *private_data, const GstTensorFilterProperties * prop)
{
pt_data *data = private_data;
g_assert (data);
* @brief _pt_data
*/
static int
-get_inputDim (void *private_data, const GstTensor_Filter_Properties * prop,
- GstTensor_TensorsMeta * meta)
+get_inputDim (void *private_data, const GstTensorFilterProperties * prop,
+ GstTensorsInfo * info)
{
pt_data *data = private_data;
int i;
g_assert (data);
g_assert (NNS_TENSOR_RANK_LIMIT >= 3);
- meta->dims[0][0] = D1;
- meta->dims[0][1] = D2;
- meta->dims[0][2] = D3;
+
+ info->info[0].dimension[0] = D1;
+ info->info[0].dimension[1] = D2;
+ info->info[0].dimension[2] = D3;
for (i = 3; i < NNS_TENSOR_RANK_LIMIT; i++)
- meta->dims[0][i] = 1;
- meta->types[0] = _NNS_UINT8;
- meta->num_tensors = 1;
+ info->info[0].dimension[i] = 1;
+ info->info[0].type = _NNS_UINT8;
+ info->num_tensors = 1;
return 0;
}
* @brief _pt_data
*/
static int
-get_outputDim (void *private_data, const GstTensor_Filter_Properties * prop,
- GstTensor_TensorsMeta * meta)
+get_outputDim (void *private_data, const GstTensorFilterProperties * prop,
+ GstTensorsInfo * info)
{
pt_data *data = private_data;
int i;
g_assert (data);
g_assert (NNS_TENSOR_RANK_LIMIT >= 3);
- meta->dims[0][0] = D1;
- meta->dims[0][1] = D2;
- meta->dims[0][2] = D3;
+
+ info->info[0].dimension[0] = D1;
+ info->info[0].dimension[1] = D2;
+ info->info[0].dimension[2] = D3;
for (i = 3; i < NNS_TENSOR_RANK_LIMIT; i++)
- meta->dims[0][i] = 1;
- meta->types[0] = _NNS_UINT8;
- meta->num_tensors = 1;
+ info->info[0].dimension[i] = 1;
+ info->info[0].type = _NNS_UINT8;
+ info->num_tensors = 1;
return 0;
}
* @brief _pt_data
*/
static int
-pt_invoke (void *private_data, const GstTensor_Filter_Properties * prop,
+pt_invoke (void *private_data, const GstTensorFilterProperties * prop,
const uint8_t * inptr, uint8_t * outptr)
{
pt_data *data = private_data;
* @brief pt_init
*/
static void *
-pt_init (const GstTensor_Filter_Properties * prop)
+pt_init (const GstTensorFilterProperties * prop)
{
pt_data *data = (pt_data *) malloc (sizeof (pt_data));
* @brief pt_exit
*/
static void
-pt_exit (void *private_data, const GstTensor_Filter_Properties * prop)
+pt_exit (void *private_data, const GstTensorFilterProperties * prop)
{
pt_data *data = private_data;
g_assert (data);
* @brief set_inputDim
*/
static int
-set_inputDim (void *private_data, const GstTensor_Filter_Properties * prop,
- const tensor_dim iDim, const tensor_type iType,
- tensor_dim oDim, tensor_type * oType)
+set_inputDim (void *private_data, const GstTensorFilterProperties * prop,
+ const GstTensorsInfo * in_info, GstTensorsInfo * out_info)
{
int i;
+ g_assert (in_info);
+ g_assert (out_info);
+
+ out_info->num_tensors = 1;
+
for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++)
- oDim[i] = iDim[i];
- *oType = iType;
+ out_info->info[0].dimension[i] = in_info->info[0].dimension[i];
+
+ out_info->info[0].type = in_info->info[0].type;
return 0;
}
* @brief pt_invoke
*/
static int
-pt_invoke (void *private_data, const GstTensor_Filter_Properties * prop,
+pt_invoke (void *private_data, const GstTensorFilterProperties * prop,
const uint8_t * inptr, uint8_t * outptr)
{
pt_data *data = private_data;
g_assert (inptr);
g_assert (outptr);
- size = get_tensor_element_count (prop->outputMeta.dims[0]) *
- tensor_element_size[prop->outputMeta.types[0]];
+ size = get_tensor_element_count (prop->output_meta.info[0].dimension) *
+ tensor_element_size[prop->output_meta.info[0].type];
g_assert (inptr != outptr);
memcpy (outptr, inptr, size);
* @brief tensor_filter_custom::NNS_custom_init_func
*/
static void *
-pt_init (const GstTensor_Filter_Properties * prop)
+pt_init (const GstTensorFilterProperties * prop)
{
pt_data *data = (pt_data *) malloc (sizeof (pt_data));
- if (prop->customProperties && strlen (prop->customProperties) > 0)
- data->property = _strdup (prop->customProperties);
+ if (prop->custom_properties && strlen (prop->custom_properties) > 0)
+ data->property = _strdup (prop->custom_properties);
else
data->property = NULL;
data->new_x = 0;
* @brief tensor_filter_custom::NNS_custom_exit_func
*/
static void
-pt_exit (void *private_data, const GstTensor_Filter_Properties * prop)
+pt_exit (void *private_data, const GstTensorFilterProperties * prop)
{
pt_data *data = private_data;
assert (data);
* @brief tensor_filter_custom::NNS_custom_set_input_dimension
*/
static int
-set_inputDim (void *private_data, const GstTensor_Filter_Properties * prop,
- const tensor_dim iDim, const tensor_type iType,
- tensor_dim oDim, tensor_type * oType)
+set_inputDim (void *private_data, const GstTensorFilterProperties * prop,
+ const GstTensorsInfo * in_info, GstTensorsInfo * out_info)
{
int i;
pt_data *data = private_data;
+
assert (data);
+ assert (in_info);
+ assert (out_info);
+
+ out_info->num_tensors = 1;
for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++)
- oDim[i] = iDim[i];
+ out_info->info[0].dimension[i] = in_info->info[0].dimension[i];
/* Update [1] and [2] oDim with new-x, new-y */
if (data->new_x > 0)
- oDim[1] = data->new_x;
+ out_info->info[0].dimension[1] = data->new_x;
if (data->new_y > 0)
- oDim[2] = data->new_y;
+ out_info->info[0].dimension[2] = data->new_y;
- *oType = iType;
+ out_info->info[0].type = in_info->info[0].type;
return 0;
}
* @brief tensor_filter_custom::NNS_custom_invoke
*/
static int
-pt_invoke (void *private_data, const GstTensor_Filter_Properties * prop,
+pt_invoke (void *private_data, const GstTensorFilterProperties * prop,
const uint8_t * inptr, uint8_t * outptr)
{
pt_data *data = private_data;
/* This assumes the limit is 4 */
assert (NNS_TENSOR_RANK_LIMIT == 4);
- assert (prop->inputMeta.dims[0][0] == prop->outputMeta.dims[0][0]);
- assert (prop->inputMeta.dims[0][3] == prop->outputMeta.dims[0][3]);
- assert (prop->inputMeta.types[0] == prop->outputMeta.types[0]);
+ assert (prop->input_meta.info[0].dimension[0] ==
+ prop->output_meta.info[0].dimension[0]);
+ assert (prop->input_meta.info[0].dimension[3] ==
+ prop->output_meta.info[0].dimension[3]);
+ assert (prop->input_meta.info[0].type == prop->output_meta.info[0].type);
- elementsize = tensor_element_size[prop->inputMeta.types[0]];
+ elementsize = tensor_element_size[prop->input_meta.info[0].type];
- ox = (data->new_x > 0) ? data->new_x : prop->outputMeta.dims[0][1];
- oy = (data->new_y > 0) ? data->new_y : prop->outputMeta.dims[0][2];
+ ox = (data->new_x > 0) ? data->new_x : prop->output_meta.info[0].dimension[1];
+ oy = (data->new_y > 0) ? data->new_y : prop->output_meta.info[0].dimension[2];
- oidx0 = prop->outputMeta.dims[0][0];
- oidx1 = oidx0 * prop->outputMeta.dims[0][1];
- oidx2 = oidx1 * prop->outputMeta.dims[0][2];
+ oidx0 = prop->output_meta.info[0].dimension[0];
+ oidx1 = oidx0 * prop->output_meta.info[0].dimension[1];
+ oidx2 = oidx1 * prop->output_meta.info[0].dimension[2];
- iidx0 = prop->inputMeta.dims[0][0];
- iidx1 = iidx0 * prop->inputMeta.dims[0][1];
- iidx2 = iidx1 * prop->inputMeta.dims[0][2];
+ iidx0 = prop->input_meta.info[0].dimension[0];
+ iidx1 = iidx0 * prop->input_meta.info[0].dimension[1];
+ iidx2 = iidx1 * prop->input_meta.info[0].dimension[2];
- for (z = 0; z < prop->inputMeta.dims[0][3]; z++) {
+ for (z = 0; z < prop->input_meta.info[0].dimension[3]; z++) {
for (y = 0; y < oy; y++) {
for (x = 0; x < ox; x++) {
unsigned int c;
- for (c = 0; c < prop->inputMeta.dims[0][0]; c++) {
+ for (c = 0; c < prop->input_meta.info[0].dimension[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->inputMeta.dims[0][1] / ox;
- iy = y * prop->inputMeta.dims[0][2] / oy;
+ ix = x * prop->input_meta.info[0].dimension[1] / ox;
+ iy = y * prop->input_meta.info[0].dimension[2] / oy;
- assert (ix >= 0 && iy >= 0 && ix < prop->inputMeta.dims[0][1]
- && iy < prop->inputMeta.dims[0][2]);
+ assert (ix >= 0 && iy >= 0
+ && ix < prop->input_meta.info[0].dimension[1]
+ && iy < prop->input_meta.info[0].dimension[2]);
/* outptr[z][y][x][c] = inptr[z][iy][ix][c]; */
for (sz = 0; sz < elementsize; sz++)
* @brief init callback of tensor_filter custom
*/
static void *
-pt_init (const GstTensor_Filter_Properties * prop)
+pt_init (const GstTensorFilterProperties * prop)
{
pt_data *data = (pt_data *) malloc (sizeof (pt_data));
- if (prop->customProperties && strlen (prop->customProperties) > 0)
- data->property = _strdup (prop->customProperties);
+ if (prop->custom_properties && strlen (prop->custom_properties) > 0)
+ data->property = _strdup (prop->custom_properties);
else
data->property = NULL;
data->new_x = 0;
* @brief exit callback of tensor_filter custom
*/
static void
-pt_exit (void *private_data, const GstTensor_Filter_Properties * prop)
+pt_exit (void *private_data, const GstTensorFilterProperties * prop)
{
pt_data *data = private_data;
assert (data);
* @brief setInputDimension callback of tensor_filter custom
*/
static int
-set_inputDim (void *private_data, const GstTensor_Filter_Properties * prop,
- const tensor_dim iDim, const tensor_type iType,
- tensor_dim oDim, tensor_type * oType)
+set_inputDim (void *private_data, const GstTensorFilterProperties * prop,
+ const GstTensorsInfo * in_info, GstTensorsInfo * out_info)
{
int i;
pt_data *data = private_data;
+
assert (data);
+ assert (in_info);
+ assert (out_info);
+
+ out_info->num_tensors = 1;
for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++)
- oDim[i] = iDim[i];
+ out_info->info[0].dimension[i] = in_info->info[0].dimension[i];
- /* Update [1] and [2] oDim with new-x, new-y */
+ /* Update output dimension [1] and [2] with new-x, new-y */
if (data->new_x > 0)
- oDim[1] = data->new_x;
+ out_info->info[0].dimension[1] = data->new_x;
if (data->new_y > 0)
- oDim[2] = data->new_y;
+ out_info->info[0].dimension[2] = data->new_y;
- *oType = iType;
+ out_info->info[0].type = in_info->info[0].type;
return 0;
}
*/
static uint8_t *
pt_allocate_invoke (void *private_data,
- const GstTensor_Filter_Properties * prop, const uint8_t * inptr,
+ const GstTensorFilterProperties * prop, const uint8_t * inptr,
size_t * size)
{
pt_data *data = private_data;
uint32_t iidx0, iidx1, iidx2;
*size =
- get_tensor_element_count (prop->outputMeta.dims[0]) *
- tensor_element_size[prop->outputMeta.types[0]];
+ get_tensor_element_count (prop->output_meta.info[0].dimension) *
+ tensor_element_size[prop->output_meta.info[0].type];
uint8_t *outptr = (uint8_t *) malloc (sizeof (uint8_t) * *size);
assert (data);
/* This assumes the limit is 4 */
assert (NNS_TENSOR_RANK_LIMIT == 4);
- assert (prop->inputMeta.dims[0][0] == prop->outputMeta.dims[0][0]);
- assert (prop->inputMeta.dims[0][3] == prop->outputMeta.dims[0][3]);
- assert (prop->inputMeta.types[0] == prop->outputMeta.types[0]);
+ assert (prop->input_meta.info[0].dimension[0] ==
+ prop->output_meta.info[0].dimension[0]);
+ assert (prop->input_meta.info[0].dimension[3] ==
+ prop->output_meta.info[0].dimension[3]);
+ assert (prop->input_meta.info[0].type == prop->output_meta.info[0].type);
- elementsize = tensor_element_size[prop->inputMeta.types[0]];
+ elementsize = tensor_element_size[prop->input_meta.info[0].type];
- ox = (data->new_x > 0) ? data->new_x : prop->outputMeta.dims[0][1];
- oy = (data->new_y > 0) ? data->new_y : prop->outputMeta.dims[0][2];
+ ox = (data->new_x > 0) ? data->new_x : prop->output_meta.info[0].dimension[1];
+ oy = (data->new_y > 0) ? data->new_y : prop->output_meta.info[0].dimension[2];
- oidx0 = prop->outputMeta.dims[0][0];
- oidx1 = oidx0 * prop->outputMeta.dims[0][1];
- oidx2 = oidx1 * prop->outputMeta.dims[0][2];
+ oidx0 = prop->output_meta.info[0].dimension[0];
+ oidx1 = oidx0 * prop->output_meta.info[0].dimension[1];
+ oidx2 = oidx1 * prop->output_meta.info[0].dimension[2];
- iidx0 = prop->inputMeta.dims[0][0];
- iidx1 = iidx0 * prop->inputMeta.dims[0][1];
- iidx2 = iidx1 * prop->inputMeta.dims[0][2];
+ iidx0 = prop->input_meta.info[0].dimension[0];
+ iidx1 = iidx0 * prop->input_meta.info[0].dimension[1];
+ iidx2 = iidx1 * prop->input_meta.info[0].dimension[2];
- for (z = 0; z < prop->inputMeta.dims[0][3]; z++) {
+ for (z = 0; z < prop->input_meta.info[0].dimension[3]; z++) {
for (y = 0; y < oy; y++) {
for (x = 0; x < ox; x++) {
unsigned int c;
- for (c = 0; c < prop->inputMeta.dims[0][0]; c++) {
+ for (c = 0; c < prop->input_meta.info[0].dimension[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->inputMeta.dims[0][1] / ox;
- iy = y * prop->inputMeta.dims[0][2] / oy;
+ ix = x * prop->input_meta.info[0].dimension[1] / ox;
+ iy = y * prop->input_meta.info[0].dimension[2] / oy;
- assert (ix >= 0 && iy >= 0 && ix < prop->inputMeta.dims[0][1]
- && iy < prop->inputMeta.dims[0][2]);
+ assert (ix >= 0 && iy >= 0
+ && ix < prop->input_meta.info[0].dimension[1]
+ && iy < prop->input_meta.info[0].dimension[2]);
/* outptr[z][y][x][c] = inptr[z][iy][ix][c]; */
for (sz = 0; sz < elementsize; sz++)
*/
TEST (common_get_tensor_dimension, case1)
{
- uint32_t dim[NNS_TENSOR_SIZE_LIMIT][NNS_TENSOR_RANK_LIMIT];
- int num_tensors = get_tensor_dimension ("345:123:433:177", dim);
- EXPECT_EQ (num_tensors, 1);
- EXPECT_EQ (dim[0][0], 345);
- EXPECT_EQ (dim[0][1], 123);
- EXPECT_EQ (dim[0][2], 433);
- EXPECT_EQ (dim[0][3], 177);
+ tensor_dim dim;
+ int rank = get_tensor_dimension ("345:123:433:177", dim);
+ EXPECT_EQ (rank, 4);
+ EXPECT_EQ (dim[0], 345);
+ EXPECT_EQ (dim[1], 123);
+ EXPECT_EQ (dim[2], 433);
+ EXPECT_EQ (dim[3], 177);
}
/**
*/
TEST (common_get_tensor_dimension, case2)
{
- uint32_t dim[NNS_TENSOR_SIZE_LIMIT][NNS_TENSOR_RANK_LIMIT];
- int num_tensors = get_tensor_dimension ("345:123:433", dim);
- EXPECT_EQ (num_tensors, 1);
- EXPECT_EQ (dim[0][0], 345);
- EXPECT_EQ (dim[0][1], 123);
- EXPECT_EQ (dim[0][2], 433);
- EXPECT_EQ (dim[0][3], 1);
+ tensor_dim dim;
+ int rank = get_tensor_dimension ("345:123:433", dim);
+ EXPECT_EQ (rank, 3);
+ EXPECT_EQ (dim[0], 345);
+ EXPECT_EQ (dim[1], 123);
+ EXPECT_EQ (dim[2], 433);
+ EXPECT_EQ (dim[3], 1);
}
/**
*/
TEST (common_get_tensor_dimension, case3)
{
- uint32_t dim[NNS_TENSOR_SIZE_LIMIT][NNS_TENSOR_RANK_LIMIT];
- int num_tensors = get_tensor_dimension ("345:123", dim);
- EXPECT_EQ (num_tensors, 1);
- EXPECT_EQ (dim[0][0], 345);
- EXPECT_EQ (dim[0][1], 123);
- EXPECT_EQ (dim[0][2], 1);
- EXPECT_EQ (dim[0][3], 1);
+ tensor_dim dim;
+ int rank = get_tensor_dimension ("345:123", dim);
+ EXPECT_EQ (rank, 2);
+ EXPECT_EQ (dim[0], 345);
+ EXPECT_EQ (dim[1], 123);
+ EXPECT_EQ (dim[2], 1);
+ EXPECT_EQ (dim[3], 1);
}
/**
*/
TEST (common_get_tensor_dimension, case4)
{
- uint32_t dim[NNS_TENSOR_SIZE_LIMIT][NNS_TENSOR_RANK_LIMIT];
- int num_tensors = get_tensor_dimension ("345", dim);
- EXPECT_EQ (num_tensors, 1);
- EXPECT_EQ (dim[0][0], 345);
- EXPECT_EQ (dim[0][1], 1);
- EXPECT_EQ (dim[0][2], 1);
- EXPECT_EQ (dim[0][3], 1);
+ tensor_dim dim;
+ int rank = get_tensor_dimension ("345", dim);
+ EXPECT_EQ (rank, 1);
+ EXPECT_EQ (dim[0], 345);
+ EXPECT_EQ (dim[1], 1);
+ EXPECT_EQ (dim[2], 1);
+ EXPECT_EQ (dim[3], 1);
}
/**
gboolean start; /**< stream started */
gboolean end; /**< eos reached */
gchar *caps_name; /**< negotiated caps name */
- GstTensorConfig config; /**< tensor config from negotiated caps */
+ GstTensorConfig tensor_config; /**< tensor config from negotiated caps */
+ GstTensorsConfig tensors_config; /**< tensors config from negotiated caps */
} TestData;
/**
_print_log ("pts %" GST_TIME_FORMAT, GST_TIME_ARGS (pts));
_print_log ("dts %" GST_TIME_FORMAT, GST_TIME_ARGS (dts));
+ _print_log ("number of memory blocks %d", gst_buffer_n_memory (buffer));
}
if (g_test_data.caps_name == NULL) {
_print_log ("caps name [%s]", g_test_data.caps_name);
if (g_str_equal (g_test_data.caps_name, "other/tensor")) {
- if (!gst_tensor_config_from_structure (&g_test_data.config, structure)) {
- _print_log ("failed to get config from caps");
+ if (!gst_tensor_config_from_structure (&g_test_data.tensor_config,
+ structure)) {
+ _print_log ("failed to get tensor config from caps");
+ }
+ } else if (g_str_equal (g_test_data.caps_name, "other/tensors")) {
+ if (!gst_tensors_config_from_structure (&g_test_data.tensors_config,
+ structure)) {
+ _print_log ("failed to get tensors config from caps");
}
}
g_test_data.caps_name = NULL;
g_test_data.tc_type = option.test_type;
g_test_data.t_type = option.t_type;
- gst_tensor_config_init (&g_test_data.config);
+ gst_tensor_config_init (&g_test_data.tensor_config);
+ gst_tensors_config_init (&g_test_data.tensors_config);
_print_log ("option num_buffers[%d] test_type[%d]",
option.num_buffers, option.test_type);
{
const guint num_buffers = 5;
TestOption option = { num_buffers, TEST_TYPE_TENSORS };
+ guint i;
ASSERT_TRUE (_setup_pipeline (option));
/** check caps name */
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensors"));
+ /** check tensors config for video */
+ EXPECT_TRUE (gst_tensors_config_validate (&g_test_data.tensors_config));
+ EXPECT_EQ (g_test_data.tensors_config.info.num_tensors, 2);
+
+ for (i = 0; i < g_test_data.tensors_config.info.num_tensors; i++) {
+ EXPECT_EQ (g_test_data.tensors_config.info.info[i].type, _NNS_UINT8);
+ EXPECT_EQ (g_test_data.tensors_config.info.info[i].dimension[0], 3);
+ EXPECT_EQ (g_test_data.tensors_config.info.info[i].dimension[1], 160);
+ EXPECT_EQ (g_test_data.tensors_config.info.info[i].dimension[2], 120);
+ EXPECT_EQ (g_test_data.tensors_config.info.info[i].dimension[3], 1);
+ }
+
+ EXPECT_EQ (g_test_data.tensors_config.rate_n, 30);
+ EXPECT_EQ (g_test_data.tensors_config.rate_d, 1);
+
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for video */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, _NNS_UINT8);
- EXPECT_EQ (g_test_data.config.info.dimension[0], 3);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 160);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 120);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 30);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_UINT8);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0], 3);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 160);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 120);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 30);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for video */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, _NNS_UINT8);
- EXPECT_EQ (g_test_data.config.info.dimension[0], 3);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 162);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 120);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 30);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_UINT8);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0], 3);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 162);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 120);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 30);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for video */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, _NNS_UINT8);
- EXPECT_EQ (g_test_data.config.info.dimension[0], 3);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 160);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 120);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 3);
- EXPECT_EQ (g_test_data.config.rate_n, 30);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_UINT8);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0], 3);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 160);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 120);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 3);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 30);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for video */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, _NNS_UINT8);
- EXPECT_EQ (g_test_data.config.info.dimension[0], 4);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 160);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 120);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 30);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_UINT8);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0], 4);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 160);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 120);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 30);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for video */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, _NNS_UINT8);
- EXPECT_EQ (g_test_data.config.info.dimension[0], 4);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 160);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 120);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 2);
- EXPECT_EQ (g_test_data.config.rate_n, 30);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_UINT8);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0], 4);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 160);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 120);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 2);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 30);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for video */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, _NNS_UINT8);
- EXPECT_EQ (g_test_data.config.info.dimension[0], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 160);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 120);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 30);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_UINT8);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 160);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 120);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 30);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for video */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, _NNS_UINT8);
- EXPECT_EQ (g_test_data.config.info.dimension[0], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 162);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 120);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 30);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_UINT8);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 162);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 120);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 30);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for video */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, _NNS_UINT8);
- EXPECT_EQ (g_test_data.config.info.dimension[0], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 162);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 120);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 3);
- EXPECT_EQ (g_test_data.config.rate_n, 30);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_UINT8);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 162);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 120);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 3);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 30);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for audio */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, _NNS_INT8);
- EXPECT_EQ (g_test_data.config.info.dimension[0], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 500);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 16000);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_INT8);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 500);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 16000);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for audio */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, _NNS_UINT8);
- EXPECT_EQ (g_test_data.config.info.dimension[0], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 100);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 16000);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_UINT8);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 100);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 16000);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for audio */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, _NNS_INT16);
- EXPECT_EQ (g_test_data.config.info.dimension[0], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 500);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 16000);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_INT16);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 500);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 16000);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for audio */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, _NNS_UINT16);
- EXPECT_EQ (g_test_data.config.info.dimension[0], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 1000);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 16000);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_UINT16);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 1000);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 16000);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for text */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, _NNS_INT8);
- EXPECT_EQ (g_test_data.config.info.dimension[0], GST_TENSOR_STRING_SIZE);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 0);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_INT8);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0],
+ GST_TENSOR_STRING_SIZE);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 0);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for text */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, _NNS_INT8);
- EXPECT_EQ (g_test_data.config.info.dimension[0], GST_TENSOR_STRING_SIZE);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 3);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 0);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_INT8);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0],
+ GST_TENSOR_STRING_SIZE);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 3);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 0);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for text */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, t_type);
- EXPECT_EQ (g_test_data.config.info.dimension[0], GST_TENSOR_STRING_SIZE);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 0);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, t_type);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0],
+ GST_TENSOR_STRING_SIZE);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 0);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for text */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, t_type);
- EXPECT_EQ (g_test_data.config.info.dimension[0], GST_TENSOR_STRING_SIZE);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 0);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, t_type);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0],
+ GST_TENSOR_STRING_SIZE);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 0);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for text */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, t_type);
- EXPECT_EQ (g_test_data.config.info.dimension[0], GST_TENSOR_STRING_SIZE);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 0);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, t_type);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0],
+ GST_TENSOR_STRING_SIZE);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 0);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for text */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, t_type);
- EXPECT_EQ (g_test_data.config.info.dimension[0], GST_TENSOR_STRING_SIZE);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 0);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, t_type);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0],
+ GST_TENSOR_STRING_SIZE);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 0);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for text */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, t_type);
- EXPECT_EQ (g_test_data.config.info.dimension[0], GST_TENSOR_STRING_SIZE);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 0);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, t_type);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0],
+ GST_TENSOR_STRING_SIZE);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 0);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for text */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, t_type);
- EXPECT_EQ (g_test_data.config.info.dimension[0], GST_TENSOR_STRING_SIZE);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 0);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, t_type);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0],
+ GST_TENSOR_STRING_SIZE);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 0);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for text */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, t_type);
- EXPECT_EQ (g_test_data.config.info.dimension[0], GST_TENSOR_STRING_SIZE);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 0);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, t_type);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0],
+ GST_TENSOR_STRING_SIZE);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 0);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for text */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, t_type);
- EXPECT_EQ (g_test_data.config.info.dimension[0], GST_TENSOR_STRING_SIZE);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 0);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, t_type);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0],
+ GST_TENSOR_STRING_SIZE);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 0);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for video */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, _NNS_UINT8);
- EXPECT_EQ (g_test_data.config.info.dimension[0], 3);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 160);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 120);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 10);
- EXPECT_EQ (g_test_data.config.rate_n, 30);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_UINT8);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0], 3);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 160);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 120);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 10);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 30);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for audio */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, _NNS_INT16);
- EXPECT_EQ (g_test_data.config.info.dimension[0], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 2000);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 16000);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_INT16);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 2000);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 16000);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}
EXPECT_TRUE (g_str_equal (g_test_data.caps_name, "other/tensor"));
/** check tensor config for audio */
- EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.config));
- EXPECT_EQ (g_test_data.config.info.type, _NNS_UINT16);
- EXPECT_EQ (g_test_data.config.info.dimension[0], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[1], 100);
- EXPECT_EQ (g_test_data.config.info.dimension[2], 1);
- EXPECT_EQ (g_test_data.config.info.dimension[3], 1);
- EXPECT_EQ (g_test_data.config.rate_n, 16000);
- EXPECT_EQ (g_test_data.config.rate_d, 1);
+ EXPECT_TRUE (gst_tensor_config_validate (&g_test_data.tensor_config));
+ EXPECT_EQ (g_test_data.tensor_config.info.type, _NNS_UINT16);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[0], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[1], 100);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[2], 1);
+ EXPECT_EQ (g_test_data.tensor_config.info.dimension[3], 1);
+ EXPECT_EQ (g_test_data.tensor_config.rate_n, 16000);
+ EXPECT_EQ (g_test_data.tensor_config.rate_d, 1);
_free_test_data ();
}