*/
TFCore::~TFCore ()
{
+ gst_tensors_info_free (&inputTensorMeta);
+ gst_tensors_info_free (&outputTensorMeta);
}
/**
* @brief initialize the object with tensorflow model
* @return 0 if OK. non-zero if error.
- * -1 if the model is not loaded.
- * -2 if the initialization of input tensor is failed.
- * -3 if the initialization of output tensor is failed.
*/
int
TFCore::init (const GstTensorFilterProperties * prop)
{
- if (setTensorProp (&inputTensorMeta, &prop->input_meta)) {
- GST_ERROR ("Failed to initialize input tensor\n");
- return -2;
- }
- if (setTensorProp (&outputTensorMeta, &prop->output_meta)) {
- GST_ERROR ("Failed to initialize output tensor\n");
- return -3;
- }
- if (loadModel ()) {
- GST_ERROR ("Failed to load model\n");
- return -1;
- }
- return 0;
+ gst_tensors_info_copy (&inputTensorMeta, &prop->input_meta);
+ gst_tensors_info_copy (&outputTensorMeta, &prop->output_meta);
+
+ return loadModel ();
}
/**
}
}
char chars[] = "[]";
- for (unsigned int i = 0; i < strlen (chars); ++i)
+ for (unsigned int j = 0; j < strlen (chars); ++j)
{
shape_description.erase (
std::remove (
shape_description.begin (),
shape_description.end (),
- chars[i]
+ chars[j]
),
shape_description.end ()
);
}
DataType dtype = DT_INVALID;
+ char *tensor_name = inputTensorMeta.info[i].name;
+
if (node->attr ().count ("dtype")) {
dtype = node->attr ().at ("dtype").type ();
}
- if (strcmp (inputTensorMeta.info[i].name, node->name ().c_str ())) {
+ if (!tensor_name || strcmp (tensor_name, node->name ().c_str ())) {
GST_ERROR ("Input Tensor is not valid: the name of input tensor is different\n");
return -2;
}
}
/**
- * @brief extract and store the information of src tensors
- * @return 0 if OK. non-zero if error.
- */
-int
-TFCore::setTensorProp (GstTensorsInfo * dest, const GstTensorsInfo * src)
-{
- dest->num_tensors = src->num_tensors;
- memcpy (dest->info, src->info, sizeof (GstTensorInfo) * src->num_tensors);
- return 0;
-}
-
-/**
- * @brief return the number of Input Tensors.
- * @return the number of Input Tensors.
- */
-int
-TFCore::getInputTensorSize ()
-{
- return inputTensorMeta.num_tensors;
-}
-
-/**
- * @brief return the number of Output Tensors.
- * @return the number of Output Tensors
- */
-int
-TFCore::getOutputTensorSize ()
-{
- return outputTensorMeta.num_tensors;
-}
-
-/**
* @brief return the Dimension of Input Tensor.
* @param[out] info Structure for tensor info.
* @todo return whole array rather than index 0
int
TFCore::getInputTensorDim (GstTensorsInfo * info)
{
- info->num_tensors = inputTensorMeta.num_tensors;
- memcpy (info->info, inputTensorMeta.info,
- sizeof (GstTensorInfo) * inputTensorMeta.num_tensors);
+ gst_tensors_info_copy (info, &inputTensorMeta);
return 0;
}
int
TFCore::getOutputTensorDim (GstTensorsInfo * info)
{
- info->num_tensors = outputTensorMeta.num_tensors;
- memcpy (info->info, outputTensorMeta.info,
- sizeof (GstTensorInfo) * outputTensorMeta.num_tensors);
+ gst_tensors_info_copy (info, &outputTensorMeta);
return 0;
}
int
TFCore::run (const GstTensorMemory * input, GstTensorMemory * output)
{
+#if (DBG)
+ gint64 start_time = g_get_real_time ();
+#endif
+
std::vector <std::pair <string, Tensor>> input_feeds;
std::vector <string> output_tensor_names;
std::vector <Tensor> outputs;
}
for (int i = 0; i < outputTensorMeta.num_tensors; ++i) {
- output[i].type = getTensorTypeFromTF (outputs[i].dtype());
- output[i].size = tensor_element_size[output[i].type];
- for (int j = 0; j < NNS_TENSOR_RANK_LIMIT; ++j)
- output[i].size *= outputTensorMeta.info[i].dimension[j];
-
+ g_assert (output[i].type == getTensorTypeFromTF (outputs[i].dtype()));
array_len = output[i].size / tensor_element_size[output[i].type];
switch (output[i].type) {
}
}
+#if (DBG)
+ gint64 stop_time = g_get_real_time ();
+ g_message ("Invoke() is finished: %" G_GINT64_FORMAT,
+ (stop_time - start_time));
+#endif
+
return 0;
}
tf_core_init (void * tf, const GstTensorFilterProperties * prop)
{
TFCore *c = (TFCore *) tf;
- int ret = c->init (prop);
- return ret;
+ return c->init (prop);
}
/**
*/
TFLiteCore::~TFLiteCore ()
{
+ gst_tensors_info_free (&inputTensorMeta);
+ gst_tensors_info_free (&outputTensorMeta);
}
/**
}
/**
- * @brief return the number of Input Tensors.
- * @return the number of Input Tensors.
- */
-int
-TFLiteCore::getInputTensorSize ()
-{
- return inputTensorMeta.num_tensors;
-}
-
-/**
- * @brief return the number of Output Tensors.
- * @return the number of Output Tensors
- */
-int
-TFLiteCore::getOutputTensorSize ()
-{
- return outputTensorMeta.num_tensors;
-}
-
-/**
* @brief return the Dimension of Input Tensor.
* @param[out] info Structure for tensor info.
* @todo return whole array rather than index 0
int
TFLiteCore::getInputTensorDim (GstTensorsInfo * info)
{
- info->num_tensors = inputTensorMeta.num_tensors;
- memcpy (info->info, inputTensorMeta.info,
- sizeof (GstTensorInfo) * inputTensorMeta.num_tensors);
+ gst_tensors_info_copy (info, &inputTensorMeta);
return 0;
}
int
TFLiteCore::getOutputTensorDim (GstTensorsInfo * info)
{
- info->num_tensors = outputTensorMeta.num_tensors;
- memcpy (info->info, outputTensorMeta.info,
- sizeof (GstTensorInfo) * outputTensorMeta.num_tensors);
+ gst_tensors_info_copy (info, &outputTensorMeta);
return 0;
}
int tensor_idx;
TfLiteTensor *tensor_ptr;
- for (int i = 0; i < getOutputTensorSize (); ++i) {
+ for (int i = 0; i < outputTensorMeta.num_tensors; ++i) {
tensor_idx = interpreter->outputs ()[i];
tensor_ptr = interpreter->tensor (tensor_idx);
tensors_idx.push_back (tensor_idx);
}
- for (int i = 0; i < getInputTensorSize (); ++i) {
+ for (int i = 0; i < inputTensorMeta.num_tensors; ++i) {
tensor_idx = interpreter->inputs ()[i];
tensor_ptr = interpreter->tensor (tensor_idx);
tflite_core_init (void * tflite)
{
TFLiteCore *c = (TFLiteCore *) tflite;
- int ret = c->init ();
- return ret;
+ return c->init ();
}
/**
tflite_core_getInputDim (void * tflite, GstTensorsInfo * info)
{
TFLiteCore *c = (TFLiteCore *) tflite;
- int ret = c->getInputTensorDim (info);
- return ret;
+ return c->getInputTensorDim (info);
}
/**
tflite_core_getOutputDim (void * tflite, GstTensorsInfo * info)
{
TFLiteCore *c = (TFLiteCore *) tflite;
- int ret = c->getOutputTensorDim (info);
- return ret;
+ return c->getOutputTensorDim (info);
}
/**
#include <glib.h>
#include <string.h>
-#include <nnstreamer_subplugin.h>
#include "tensor_filter.h"
/**
static gboolean gst_tensor_filter_start (GstBaseTransform * trans);
static gboolean gst_tensor_filter_stop (GstBaseTransform * trans);
+static void gst_tensor_filter_compare_tensors (GstTensorsInfo * info1,
+ GstTensorsInfo * info2);
+
/**
* @brief Open nn framework.
*/
}
/**
- * @brief deallocate the name of each GstTensorInfo.
- * @param The GstTensorsInfo object
- */
-static void
-gst_tensor_filter_deallocate_tensor_name (GstTensorsInfo * info)
-{
- guint i;
- for (i = 0; i < info->num_tensors; ++i)
- g_free (info->info[i].name);
- gst_tensors_info_init (info);
-}
-
-/**
- * @brief Clear and reset data.
+ * @brief Function to finalize instance.
*/
static void
-gst_tensor_filter_reset (GstTensorFilter * self)
+gst_tensor_filter_finalize (GObject * object)
{
+ GstTensorFilter *self;
GstTensorFilterProperties *prop;
+ self = GST_TENSOR_FILTER (object);
prop = &self->prop;
gst_tensor_filter_close_fw (self);
g_free_const (prop->fwname);
- prop->fwname = NULL;
-
g_free_const (prop->model_file);
- prop->model_file = NULL;
-
g_free_const (prop->custom_properties);
- prop->custom_properties = NULL;
- prop->input_configured = FALSE;
- gst_tensor_filter_deallocate_tensor_name (&prop->input_meta);
-
- prop->output_configured = FALSE;
- gst_tensor_filter_deallocate_tensor_name (&prop->output_meta);
-
- self->configured = FALSE;
- gst_tensors_config_init (&self->in_config);
- gst_tensors_config_init (&self->out_config);
-}
-
-/**
- * @brief Function to finalize instance.
- */
-static void
-gst_tensor_filter_finalize (GObject * object)
-{
- GstTensorFilter *self;
-
- self = GST_TENSOR_FILTER (object);
+ gst_tensors_info_free (&prop->input_meta);
+ gst_tensors_info_free (&prop->output_meta);
- gst_tensor_filter_reset (self);
+ gst_tensors_info_free (&self->in_config.info);
+ gst_tensors_info_free (&self->out_config.info);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
gst_tensor_filter_load_tensor_info (GstTensorFilter * self)
{
GstTensorFilterProperties *prop;
+ GstTensorsInfo in_info, out_info;
int res;
prop = &self->prop;
- /**
- * supposed fixed in-tensor info if getInputDimension is defined.
- */
- if (!prop->input_configured) {
- GstTensorsInfo in_info;
+ gst_tensors_info_init (&in_info);
+ gst_tensors_info_init (&out_info);
- gst_tensors_info_init (&in_info);
+ /* supposed fixed in-tensor info if getInputDimension is defined. */
+ if (!prop->input_configured) {
gst_tensor_filter_call (self, res, getInputDimension, &in_info);
if (res == 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));
+ if (!gst_tensors_info_is_equal (&in_info, &prop->input_meta)) {
+ GST_ERROR_OBJECT (self, "The input tensor is not compatible.");
+ gst_tensor_filter_compare_tensors (&in_info, &prop->input_meta);
+ g_assert (0);
+ goto done;
+ }
+ } else {
+ gst_tensors_info_copy (&prop->input_meta, &in_info);
}
prop->input_configured = TRUE;
- prop->input_meta = in_info;
-
silent_debug_info (&in_info, "input tensor");
}
}
- /**
- * supposed fixed out-tensor info if getOutputDimension is defined.
- */
+ /* supposed fixed out-tensor info if getOutputDimension is defined. */
if (!prop->output_configured) {
- GstTensorsInfo out_info;
-
- gst_tensors_info_init (&out_info);
gst_tensor_filter_call (self, res, getOutputDimension, &out_info);
if (res == 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));
+ if (!gst_tensors_info_is_equal (&out_info, &prop->output_meta)) {
+ GST_ERROR_OBJECT (self, "The output tensor is not compatible.");
+ gst_tensor_filter_compare_tensors (&out_info, &prop->output_meta);
+ g_assert (0);
+ goto done;
+ }
+ } else {
+ gst_tensors_info_copy (&prop->output_meta, &out_info);
}
prop->output_configured = TRUE;
- prop->output_meta = out_info;
-
silent_debug_info (&out_info, "output tensor");
}
}
+
+done:
+ gst_tensors_info_free (&in_info);
+ gst_tensors_info_free (&out_info);
}
/**
* @brief Printout the comparison results of two tensors.
* @param[in] info1 The tensors to be shown on the left hand side
* @param[in] info2 The tensors to be shown on the right hand side
- * @return The newly allocated string for the printout. The caller must deallocate it.
* @todo If this is going to be used by other elements, move this to nnstreamer/tensor_common.
*/
-static gchar *
-_compare_tensors (GstTensorsInfo * info1, GstTensorsInfo * info2)
+static void
+gst_tensor_filter_compare_tensors (GstTensorsInfo * info1,
+ GstTensorsInfo * info2)
{
gchar null[] = "";
gchar *result = null;
g_free (line);
}
- if (result == null)
- return NULL;
- return result;
-}
-
-/**
- * @brief Copy GstTensorsInfo without the name of tensors.
- * @param[out] the destination object
- * @param[in] the source object
- */
-static void
-gst_tensor_filter_copy_info (GstTensorsInfo * dest, const GstTensorsInfo * src)
-{
- guint i;
-
- g_return_if_fail (dest != NULL && src != NULL);
-
- dest->num_tensors = src->num_tensors;
- for (i = 0; i < src->num_tensors; ++i) {
- memcpy (dest->info[i].dimension, src->info[i].dimension,
- sizeof (tensor_dim));
- dest->info[i].type = src->info[i].type;
+ if (result != null) {
+ /* print warning message */
+ g_warning ("Tensor info :\n%s", result);
+ g_free (result);
}
}
g_return_val_if_fail (incaps != NULL, FALSE);
prop = &self->prop;
+ gst_tensors_config_init (&in_config);
+ gst_tensors_config_init (&out_config);
/**
* GstTensorFilter has to parse the tensor dimension and type from NN model.
/** 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)) {
- gchar *str = _compare_tensors (&in_config.info, &prop->input_meta);
- /* print warning message */
- g_warning ("The input tensor is not compatible.\n%s", str);
- GST_ERROR_OBJECT (self, "The input tensor is not compatible.\n%s", str);
- g_free (str);
- return FALSE;
+ GST_ERROR_OBJECT (self, "The input tensor is not compatible.");
+ gst_tensor_filter_compare_tensors (&in_config.info, &prop->input_meta);
+ goto done;
}
+ } else {
+ gst_tensors_info_copy (&prop->input_meta, &in_config.info);
}
prop->input_configured = TRUE;
- gst_tensor_filter_copy_info (&prop->input_meta, &in_config.info);
/** call setInputDimension if output tensor is not configured */
if (!prop->output_configured) {
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)) {
- gchar *str = _compare_tensors (&out_info, &prop->output_meta);
- /* print warning message */
- g_warning ("The output tensor is not compatible.\n%s", str);
- GST_ERROR_OBJECT (self,
- "The output tensor is not compatible.\n%s", str);
- g_free (str);
- return FALSE;
+ if (!gst_tensors_info_is_equal (&out_info, &prop->output_meta)) {
+ GST_ERROR_OBJECT (self, "The output tensor is not compatible.");
+ gst_tensor_filter_compare_tensors (&out_info, &prop->output_meta);
+ gst_tensors_info_free (&out_info);
+ goto done;
}
+ } else {
+ gst_tensors_info_copy (&prop->output_meta, &out_info);
}
prop->output_configured = TRUE;
- gst_tensor_filter_copy_info (&prop->output_meta, &out_info);
-
silent_debug_info (&out_info, "output tensor");
}
+ gst_tensors_info_free (&out_info);
+
if (!prop->output_configured) {
GST_ERROR_OBJECT (self, "Failed to get output tensor info.\n");
g_assert (0);
- return FALSE;
+ goto done;
}
}
* GstTensorFilter cannot assure the framerate.
* Simply set the framerate of out-tensor from incaps.
*/
- out_config.info = prop->output_meta;
+ gst_tensors_info_copy (&out_config.info, &prop->output_meta);
out_config.rate_n = in_config.rate_n;
out_config.rate_d = in_config.rate_d;
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;
+ gst_tensors_info_copy (&self->in_config.info, &in_config.info);
+ self->in_config.rate_n = in_config.rate_n;
+ self->in_config.rate_d = in_config.rate_d;
+
+ gst_tensors_info_copy (&self->out_config.info, &out_config.info);
+ self->out_config.rate_n = out_config.rate_n;
+ self->out_config.rate_d = out_config.rate_d;
+
self->configured = TRUE;
}
}
+done:
+ gst_tensors_info_free (&in_config.info);
+ gst_tensors_info_free (&out_config.info);
return self->configured;
}
config.info = self->prop.output_meta;
result = gst_tensor_filter_caps_from_config (self, &config);
} else {
- GstTensorsInfo in_info;
-
/* check in-tensor info to call setInputDimension */
- in_info = config.info;
- if (gst_tensors_info_validate (&in_info)) {
+ if (gst_tensors_info_validate (&config.info)) {
+ GstTensorsInfo out_info;
int res = -1;
/* call setInputDimension with given input tensor */
- gst_tensor_filter_call (self, res, setInputDimension, &in_info,
- &config.info);
+ gst_tensors_info_init (&out_info);
+ gst_tensor_filter_call (self, res, setInputDimension, &config.info,
+ &out_info);
if (res == 0) {
+ config.info = out_info;
result = gst_tensor_filter_caps_from_config (self, &config);
} else {
GST_ERROR_OBJECT (self, "Cannot get the output tensor info.");
g_assert (0);
result = gst_caps_from_string (CAPS_STRING);
}
+
+ gst_tensors_info_free (&out_info);
} else {
/* we don't know the exact tensor info yet */
result = gst_caps_from_string (CAPS_STRING);