Add common functions for tensor-filter and filter-single.
1. add struct for common property
2. reduce duplicated code of tensor-filter
Signed-off-by: Jaeyun Jung <jy1210.jung@samsung.com>
#include <stdint.h>
#include <glib-object.h>
-#include <nnstreamer/nnstreamer_subplugin.h>
-#include <nnstreamer/nnstreamer_plugin_api_filter.h>
+#include <nnstreamer/tensor_filter/tensor_filter_common.h>
G_BEGIN_DECLS
#define G_TYPE_TENSOR_FILTER_SINGLE \
{
GObject element; /**< This is the parent object */
- void *privateData; /**< NNFW plugin's private data is stored here */
- GstTensorFilterProperties prop; /**< NNFW plugin's properties */
- const GstTensorFilterFramework *fw; /**< The implementation core of the NNFW. NULL if not configured */
-
- /* internal properties for tensor_filter_single */
- gboolean silent; /**< Verbose mode if FALSE. int instead of gboolean for non-glib custom plugins */
- gboolean started; /**< filter has been started */
- GstTensorsConfig in_config; /**< input tensor info */
- GstTensorsConfig out_config; /**< output tensor info */
+ GstTensorFilterPrivate priv; /**< Internal properties for tensor-filter */
};
/**
#include <glib.h>
#include <string.h>
-#include <nnstreamer/nnstreamer_plugin_api.h>
-#include <nnstreamer/tensor_typedef.h>
-#include <nnstreamer/tensor_filter/tensor_filter_common.h>
-
#include "tensor_filter_single.h"
/**
* @brief Macro for debug mode.
*/
#ifndef DBG
-#define DBG (!self->silent)
+#define DBG (!priv->silent)
#endif
#define silent_debug_info(i,msg) do { \
static void
g_tensor_filter_single_init (GTensorFilterSingle * self)
{
- GstTensorFilterProperties *prop;
+ GstTensorFilterPrivate *priv;
- prop = &self->prop;
-
- /* init NNFW properties */
- prop->fwname = NULL;
- 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->fw = NULL;
- self->privateData = NULL;
- self->silent = TRUE;
- self->started = FALSE;
- gst_tensors_config_init (&self->in_config);
- gst_tensors_config_init (&self->out_config);
+ priv = &self->priv;
+
+ gst_tensor_filter_common_init_property (priv);
}
/**
static void
g_tensor_filter_single_finalize (GObject * object)
{
- gboolean status;
GTensorFilterSingle *self;
- GstTensorFilterProperties *prop;
+ GstTensorFilterPrivate *priv;
self = G_TENSOR_FILTER_SINGLE (object);
+ priv = &self->priv;
/** stop if not already stopped */
- if (self->started == TRUE) {
- status = g_tensor_filter_single_stop (self);
- g_debug ("Tensor filter single stop status: %d", status);
+ if (priv->configured == TRUE) {
+ g_tensor_filter_single_stop (self);
}
- prop = &self->prop;
-
- g_free_const (prop->fwname);
- g_free_const (prop->model_file);
- g_free_const (prop->custom_properties);
-
- gst_tensors_info_free (&prop->input_meta);
- gst_tensors_info_free (&prop->output_meta);
-
- gst_tensors_info_free (&self->in_config.info);
- gst_tensors_info_free (&self->out_config.info);
+ gst_tensor_filter_common_free_property (priv);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
const GValue * value, GParamSpec * pspec)
{
GTensorFilterSingle *self;
- GstTensorFilterProperties *prop;
+ GstTensorFilterPrivate *priv;
self = G_TENSOR_FILTER_SINGLE (object);
- prop = &self->prop;
+ priv = &self->priv;
g_debug ("Setting property for prop %d.\n", prop_id);
- switch (prop_id) {
- case PROP_SILENT:
- self->silent = g_value_get_boolean (value);
- g_debug ("Debug mode = %d", self->silent);
- break;
- case PROP_FRAMEWORK:
- {
- const gchar *fw_name = g_value_get_string (value);
- const GstTensorFilterFramework *fw;
-
- if (self->fw != NULL) {
- /* close old framework */
- g_tensor_filter_single_stop (self);
- }
-
- g_debug ("Framework = %s\n", fw_name);
-
- fw = nnstreamer_filter_find (fw_name);
-
- /* See if mandatory methods are filled in */
- if (nnstreamer_filter_validate (fw)) {
- self->fw = fw;
- prop->fwname = g_strdup (fw_name);
- } else {
- g_warning ("Cannot identify the given neural network framework, %s\n",
- fw_name);
- }
- break;
- }
- case PROP_MODEL:
- {
- const gchar *model_files = g_value_get_string (value);
- guint model_num;
-
- if (prop->model_file) {
- g_tensor_filter_single_stop (self);
- g_free_const (prop->model_file);
- prop->model_file = NULL;
- }
-
- if (prop->model_file_sub) {
- g_tensor_filter_single_stop (self);
- g_free_const (prop->model_file_sub);
- prop->model_file_sub = NULL;
- }
-
- /* Once configures, it cannot be changed in runtime */
- g_assert (model_files);
- model_num = gst_tensor_filter_parse_modelpaths_string (prop, model_files);
- if (model_num == 1) {
- g_debug ("Model = %s\n", prop->model_file);
- if (!g_file_test (prop->model_file, G_FILE_TEST_IS_REGULAR))
- g_critical ("Cannot find the model file: %s\n", prop->model_file);
- } else if (model_num == 2) {
- g_debug ("Init Model = %s\n", prop->model_file_sub);
- g_debug ("Pred Model = %s\n", prop->model_file);
- if (!g_file_test (prop->model_file_sub, G_FILE_TEST_IS_REGULAR))
- g_critical ("Cannot find the init model file: %s\n",
- prop->model_file_sub);
- if (!g_file_test (prop->model_file, G_FILE_TEST_IS_REGULAR))
- g_critical ("Cannot find the pred model file: %s\n",
- prop->model_file);
- } else if (model_num > 2) {
- /** @todo if the new NN framework requires more than 2 model files, this area will be implemented */
- g_critical
- ("There is no NN framework that requires model files more than 2. Current Input model files are :%d\n",
- model_num);
- } else {
- g_critical ("Set model file path first\n");
- }
- break;
- }
- case PROP_INPUT:
- g_assert (!prop->input_configured && value);
- /* Once configures, it cannot be changed in runtime */
- {
- guint num_dims;
-
- num_dims = gst_tensors_info_parse_dimensions_string (&prop->input_meta,
- g_value_get_string (value));
-
- if (prop->input_meta.num_tensors > 0 &&
- prop->input_meta.num_tensors != num_dims) {
- g_warning
- ("Invalid input-dim, given param does not match with old value.");
- }
-
- prop->input_meta.num_tensors = num_dims;
- }
- break;
- case PROP_OUTPUT:
- g_assert (!prop->output_configured && value);
- /* Once configures, it cannot be changed in runtime */
- {
- guint num_dims;
-
- num_dims = gst_tensors_info_parse_dimensions_string (&prop->output_meta,
- g_value_get_string (value));
-
- if (prop->output_meta.num_tensors > 0 &&
- prop->output_meta.num_tensors != num_dims) {
- g_warning
- ("Invalid output-dim, given param does not match with old value.");
- }
-
- prop->output_meta.num_tensors = num_dims;
- }
- break;
- case PROP_INPUTTYPE:
- g_assert (!prop->input_configured && value);
- /* Once configures, it cannot be changed in runtime */
- {
- guint num_types;
-
- num_types = gst_tensors_info_parse_types_string (&prop->input_meta,
- g_value_get_string (value));
-
- if (prop->input_meta.num_tensors > 0 &&
- prop->input_meta.num_tensors != num_types) {
- g_warning
- ("Invalid input-type, given param does not match with old value.");
- }
-
- prop->input_meta.num_tensors = num_types;
- }
- break;
- case PROP_OUTPUTTYPE:
- g_assert (!prop->output_configured && value);
- /* Once configures, it cannot be changed in runtime */
- {
- guint num_types;
-
- num_types = gst_tensors_info_parse_types_string (&prop->output_meta,
- g_value_get_string (value));
-
- if (prop->output_meta.num_tensors > 0 &&
- prop->output_meta.num_tensors != num_types) {
- g_warning
- ("Invalid output-type, given param does not match with old value.");
- }
-
- prop->output_meta.num_tensors = num_types;
- }
- break;
- case PROP_INPUTNAME:
- /* INPUTNAME is required by tensorflow to designate the order of tensors */
- g_assert (!prop->input_configured && value);
- /* Once configures, it cannot be changed in runtime */
- {
- guint num_names;
-
- num_names = gst_tensors_info_parse_names_string (&prop->input_meta,
- g_value_get_string (value));
-
- if (prop->input_meta.num_tensors > 0 &&
- prop->input_meta.num_tensors != num_names) {
- g_warning
- ("Invalid input-name, given param does not match with old value.");
- }
-
- prop->input_meta.num_tensors = num_names;
- }
- break;
- case PROP_OUTPUTNAME:
- /* OUTPUTNAME is required by tensorflow to designate the order of tensors */
- g_assert (!prop->output_configured && value);
- /* Once configures, it cannot be changed in runtime */
- {
- guint num_names;
-
- num_names = gst_tensors_info_parse_names_string (&prop->output_meta,
- g_value_get_string (value));
-
- if (prop->output_meta.num_tensors > 0 &&
- prop->output_meta.num_tensors != num_names) {
- g_warning
- ("Invalid output-name, given param does not match with old value.");
- }
-
- prop->output_meta.num_tensors = num_names;
- }
- break;
- case PROP_CUSTOM:
- /* In case updated custom properties in runtime! */
- g_free_const (prop->custom_properties);
- prop->custom_properties = g_value_dup_string (value);
- g_debug ("Custom Option = %s\n", prop->custom_properties);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
+ if (!gst_tensor_filter_common_set_property (priv, prop_id, value, pspec))
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
/**
GValue * value, GParamSpec * pspec)
{
GTensorFilterSingle *self;
- GstTensorFilterProperties *prop;
+ GstTensorFilterPrivate *priv;
self = G_TENSOR_FILTER_SINGLE (object);
- prop = &self->prop;
+ priv = &self->priv;
g_debug ("Getting property for prop %d.\n", prop_id);
- switch (prop_id) {
- case PROP_SILENT:
- g_value_set_boolean (value, self->silent);
- break;
- default:
- if (!gst_tensor_filter_common_get_property (prop, prop_id, value, pspec))
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
+ if (!gst_tensor_filter_common_get_property (priv, prop_id, value, pspec))
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
/**
static gboolean
g_tensor_filter_input_configured (GTensorFilterSingle * self)
{
- if (self->prop.input_configured)
- return TRUE;
- else
- return FALSE;
+ GstTensorFilterPrivate *priv;
+
+ priv = &self->priv;
+
+ return priv->prop.input_configured;
}
/**
static gboolean
g_tensor_filter_output_configured (GTensorFilterSingle * self)
{
- if (self->prop.output_configured)
- return TRUE;
- else
- return FALSE;
+ GstTensorFilterPrivate *priv;
+
+ priv = &self->priv;
+
+ return priv->prop.output_configured;
}
/**
static void
g_tensor_filter_load_tensor_info (GTensorFilterSingle * self)
{
+ GstTensorFilterPrivate *priv;
GstTensorFilterProperties *prop;
GstTensorsInfo in_info, out_info;
int res = -1;
- prop = &self->prop;
+ priv = &self->priv;
+ prop = &priv->prop;
gst_tensors_info_init (&in_info);
gst_tensors_info_init (&out_info);
/* supposed fixed in-tensor info if getInputDimension is defined. */
if (!prop->input_configured) {
res = -1;
- if (self->prop.fw_opened && self->fw && self->fw->getInputDimension) {
- res = self->fw->getInputDimension
- (&self->prop, &self->privateData, &in_info);
+ if (priv->prop.fw_opened && priv->fw && priv->fw->getInputDimension) {
+ res = priv->fw->getInputDimension
+ (&priv->prop, &priv->privateData, &in_info);
}
if (res == 0) {
/* supposed fixed out-tensor info if getOutputDimension is defined. */
if (!prop->output_configured) {
res = -1;
- if (self->prop.fw_opened && self->fw && self->fw->getOutputDimension) {
- res = self->fw->getOutputDimension
- (&self->prop, &self->privateData, &out_info);
+ if (priv->prop.fw_opened && priv->fw && priv->fw->getOutputDimension) {
+ res = priv->fw->getOutputDimension
+ (&priv->prop, &priv->privateData, &out_info);
}
if (res == 0) {
static gboolean
g_tensor_filter_single_start (GTensorFilterSingle * self)
{
+ GstTensorFilterPrivate *priv;
+
+ priv = &self->priv;
+
/** open framework, load model */
- if (self->fw == NULL)
+ if (priv->fw == NULL)
return FALSE;
- if (self->prop.fw_opened == FALSE && self->fw) {
- if (self->fw->open != NULL) {
- if (self->fw->open (&self->prop, &self->privateData) == 0)
- self->prop.fw_opened = TRUE;
- } else {
- self->prop.fw_opened = TRUE;
- }
- }
+ gst_tensor_filter_common_open_fw (priv);
- if (self->prop.fw_opened == FALSE)
+ if (priv->prop.fw_opened == FALSE)
return FALSE;
g_tensor_filter_load_tensor_info (self);
static gboolean
g_tensor_filter_single_stop (GTensorFilterSingle * self)
{
+ GstTensorFilterPrivate *priv;
+
+ priv = &self->priv;
+
/** close framework, unload model */
- if (self->prop.fw_opened) {
- if (self->fw && self->fw->close) {
- self->fw->close (&self->prop, &self->privateData);
- }
- self->prop.fw_opened = FALSE;
- g_free_const (self->prop.fwname);
- self->prop.fwname = NULL;
- self->fw = NULL;
- self->privateData = NULL;
- }
+ gst_tensor_filter_common_close_fw (priv);
return TRUE;
}
g_tensor_filter_single_invoke (GTensorFilterSingle * self,
GstTensorMemory * input, GstTensorMemory * output)
{
- gboolean status;
- int i;
+ GstTensorFilterPrivate *priv;
+ guint i;
+
+ priv = &self->priv;
- if (G_UNLIKELY (!self->fw) || G_UNLIKELY (!self->fw->invoke_NN))
+ if (G_UNLIKELY (!priv->fw) || G_UNLIKELY (!priv->fw->invoke_NN))
return FALSE;
- if (G_UNLIKELY (!self->fw->run_without_model) &&
- G_UNLIKELY (!self->prop.model_file))
+ if (G_UNLIKELY (!priv->fw->run_without_model) &&
+ G_UNLIKELY (!priv->prop.model_file))
return FALSE;
/** start if not already started */
- if (self->started == FALSE) {
- status = g_tensor_filter_single_start (self);
- if (status == FALSE) {
- return status;
+ if (priv->configured == FALSE) {
+ if (!g_tensor_filter_single_start (self)) {
+ return FALSE;
}
- self->started = TRUE;
+ priv->configured = TRUE;
}
/** Setup output buffer */
- for (i = 0; i < self->prop.output_meta.num_tensors; i++) {
+ for (i = 0; i < priv->prop.output_meta.num_tensors; i++) {
/* allocate memory if allocate_in_invoke is FALSE */
- if (self->fw->allocate_in_invoke == FALSE) {
+ if (priv->fw->allocate_in_invoke == FALSE) {
output[i].data = g_malloc (output[i].size);
if (!output[i].data)
goto error;
}
}
- if (self->fw->invoke_NN (&self->prop, &self->privateData, input, output) == 0)
+ if (priv->fw->invoke_NN (&priv->prop, &priv->privateData, input, output) == 0)
return TRUE;
error:
- if (self->fw->allocate_in_invoke == FALSE)
- for (i = 0; i < self->prop.output_meta.num_tensors; i++)
+ if (priv->fw->allocate_in_invoke == FALSE)
+ for (i = 0; i < priv->prop.output_meta.num_tensors; i++)
g_free (output[i].data);
return FALSE;
}
#include <config.h>
#endif
-#include <gst/gstinfo.h>
-#include <gst/gst.h>
-#include <glib.h>
#include <string.h>
#include "tensor_filter.h"
-#include "tensor_filter_common.h"
/**
* @brief Macro for debug mode.
*/
#ifndef DBG
-#define DBG (!self->silent)
+#define DBG (!priv->silent)
#endif
/**
} \
} while (0)
-#define REGEX_NNAPI_OPTION "(^(true|false)$|^(true|false)([:]?(cpu|gpu|npu)))"
-
GST_DEBUG_CATEGORY_STATIC (gst_tensor_filter_debug);
#define GST_CAT_DEFAULT gst_tensor_filter_debug
static gboolean gst_tensor_filter_start (GstBaseTransform * trans);
static gboolean gst_tensor_filter_stop (GstBaseTransform * trans);
-
-/**
- * @brief Open nn framework.
- */
-#define gst_tensor_filter_open_fw(filter) do { \
- if (filter->prop.fw_opened == FALSE && filter->fw) { \
- if (filter->fw->open != NULL) {\
- if (filter->fw->open (&filter->prop, &filter->privateData) == 0) \
- filter->prop.fw_opened = TRUE; \
- } else {\
- filter->prop.fw_opened = TRUE; \
- } \
- } \
- } while (0)
-
-/**
- * @brief Close nn framework.
- */
-#define gst_tensor_filter_close_fw(filter) do { \
- if (filter->prop.fw_opened) { \
- if (filter->fw && filter->fw->close) \
- filter->fw->close (&filter->prop, &filter->privateData); \
- filter->prop.fw_opened = FALSE; \
- g_free_const (filter->prop.fwname); \
- filter->prop.fwname = NULL; \
- filter->fw = NULL; \
- filter->privateData = NULL; \
- } \
- } while (0)
-
/**
* @brief Invoke callbacks of nn framework. Guarantees calling open for the first call.
*/
-#define gst_tensor_filter_call(filter,ret,funcname,...) do { \
- gst_tensor_filter_open_fw (filter); \
+#define gst_tensor_filter_call(priv,ret,funcname,...) do { \
+ gst_tensor_filter_common_open_fw (priv); \
ret = -1; \
- if (filter->prop.fw_opened && filter->fw && filter->fw->funcname) { \
- ret = filter->fw->funcname (&filter->prop, &filter->privateData, __VA_ARGS__); \
+ if (priv->prop.fw_opened && priv->fw && priv->fw->funcname) { \
+ ret = priv->fw->funcname (&priv->prop, &priv->privateData, __VA_ARGS__); \
} \
} while (0)
static void
gst_tensor_filter_init (GstTensorFilter * self)
{
- GstTensorFilterProperties *prop;
+ GstTensorFilterPrivate *priv;
+
+ priv = &self->priv;
- prop = &self->prop;
-
- /* init NNFW properties */
- prop->fwname = NULL;
- prop->fw_opened = FALSE;
- prop->input_configured = FALSE;
- prop->output_configured = FALSE;
- prop->model_file = NULL;
- prop->nnapi = NULL;
- prop->custom_properties = NULL;
- gst_tensors_info_init (&prop->input_meta);
- gst_tensors_info_init (&prop->output_meta);
-
- /* init internal properties */
- self->fw = NULL;
- self->privateData = NULL;
- self->silent = TRUE;
- self->configured = FALSE;
- gst_tensors_config_init (&self->in_config);
- gst_tensors_config_init (&self->out_config);
+ gst_tensor_filter_common_init_property (priv);
}
/**
gst_tensor_filter_finalize (GObject * object)
{
GstTensorFilter *self;
- GstTensorFilterProperties *prop;
+ GstTensorFilterPrivate *priv;
self = GST_TENSOR_FILTER (object);
- prop = &self->prop;
+ priv = &self->priv;
- gst_tensor_filter_close_fw (self);
-
- g_free_const (prop->fwname);
- g_free_const (prop->model_file);
- g_free_const (prop->custom_properties);
-
- gst_tensors_info_free (&prop->input_meta);
- gst_tensors_info_free (&prop->output_meta);
-
- gst_tensors_info_free (&self->in_config.info);
- gst_tensors_info_free (&self->out_config.info);
+ gst_tensor_filter_common_close_fw (priv);
+ gst_tensor_filter_common_free_property (priv);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static gsize
gst_tensor_filter_get_output_size (GstTensorFilter * self, guint index)
{
+ GstTensorFilterPrivate *priv;
GstTensorsInfo *info;
- g_assert (self->configured);
-
- info = &self->prop.output_meta;
+ priv = &self->priv;
+ info = &priv->prop.output_meta;
g_assert (index < info->num_tensors);
return gst_tensor_info_get_size (&info->info[index]);
const GValue * value, GParamSpec * pspec)
{
GstTensorFilter *self;
- GstTensorFilterProperties *prop;
+ GstTensorFilterPrivate *priv;
self = GST_TENSOR_FILTER (object);
- prop = &self->prop;
+ priv = &self->priv;
silent_debug ("Setting property for prop %d.\n", prop_id);
- switch (prop_id) {
- case PROP_SILENT:
- self->silent = g_value_get_boolean (value);
- silent_debug ("Debug mode = %d", self->silent);
- break;
- case PROP_FRAMEWORK:
- {
- const gchar *fw_name = g_value_get_string (value);
- const GstTensorFilterFramework *fw;
-
- if (self->fw != NULL) {
- /* close old framework */
- gst_tensor_filter_close_fw (self);
- }
-
- silent_debug ("Framework = %s\n", fw_name);
-
- fw = nnstreamer_filter_find (fw_name);
-
- /* See if mandatory methods are filled in */
- if (nnstreamer_filter_validate (fw)) {
- self->fw = fw;
- prop->fwname = g_strdup (fw_name);
- } else {
- GST_WARNING_OBJECT (self,
- "Cannot identify the given neural network framework, %s\n",
- fw_name);
- }
- break;
- }
- case PROP_MODEL:
- {
- const gchar *model_files = g_value_get_string (value);
- guint model_num;
-
- if (prop->model_file) {
- gst_tensor_filter_close_fw (self);
- g_free_const (prop->model_file);
- prop->model_file = NULL;
- }
-
- if (prop->model_file_sub) {
- gst_tensor_filter_close_fw (self);
- g_free_const (prop->model_file_sub);
- prop->model_file_sub = NULL;
- }
-
- /* Once configures, it cannot be changed in runtime */
- /** @todo by using `gst_element_get_state()`, reject configurations in RUNNING or other states */
- g_assert (model_files);
- model_num = gst_tensor_filter_parse_modelpaths_string (prop, model_files);
- if (model_num == 1) {
- silent_debug ("Model = %s\n", prop->model_file);
- if (!g_file_test (prop->model_file, G_FILE_TEST_IS_REGULAR))
- GST_ERROR_OBJECT (self, "Cannot find the model file: %s\n",
- prop->model_file);
- } else if (model_num == 2) {
- silent_debug ("Init Model = %s\n", prop->model_file_sub);
- silent_debug ("Pred Model = %s\n", prop->model_file);
- if (!g_file_test (prop->model_file_sub, G_FILE_TEST_IS_REGULAR))
- GST_ERROR_OBJECT (self, "Cannot find the init model file: %s\n",
- prop->model_file_sub);
- if (!g_file_test (prop->model_file, G_FILE_TEST_IS_REGULAR))
- GST_ERROR_OBJECT (self, "Cannot find the pred model file: %s\n",
- prop->model_file);
- } else if (model_num > 2) {
- /** @todo if the new NN framework requires more than 2 model files, this area will be implemented */
- GST_ERROR_OBJECT (self,
- "There is no NN framework that requires model files more than 2. Current Input model files are :%d\n",
- model_num);
- } else {
- GST_ERROR_OBJECT (self, "Set model file path first\n");
- }
- break;
- }
- case PROP_INPUT:
- g_assert (!prop->input_configured && value);
- /* Once configures, it cannot be changed in runtime */
- {
- guint num_dims;
-
- num_dims = gst_tensors_info_parse_dimensions_string (&prop->input_meta,
- g_value_get_string (value));
-
- if (prop->input_meta.num_tensors > 0 &&
- prop->input_meta.num_tensors != num_dims) {
- GST_WARNING_OBJECT (self,
- "Invalid input-dim, given param does not match with old value.");
- }
-
- prop->input_meta.num_tensors = num_dims;
- }
- break;
- case PROP_OUTPUT:
- g_assert (!prop->output_configured && value);
- /* Once configures, it cannot be changed in runtime */
- {
- guint num_dims;
-
- num_dims = gst_tensors_info_parse_dimensions_string (&prop->output_meta,
- g_value_get_string (value));
-
- if (prop->output_meta.num_tensors > 0 &&
- prop->output_meta.num_tensors != num_dims) {
- GST_WARNING_OBJECT (self,
- "Invalid output-dim, given param does not match with old value.");
- }
-
- prop->output_meta.num_tensors = num_dims;
- }
- break;
- case PROP_INPUTTYPE:
- g_assert (!prop->input_configured && value);
- /* Once configures, it cannot be changed in runtime */
- {
- guint num_types;
-
- num_types = gst_tensors_info_parse_types_string (&prop->input_meta,
- g_value_get_string (value));
-
- if (prop->input_meta.num_tensors > 0 &&
- prop->input_meta.num_tensors != num_types) {
- GST_WARNING_OBJECT (self,
- "Invalid input-type, given param does not match with old value.");
- }
-
- prop->input_meta.num_tensors = num_types;
- }
- break;
- case PROP_OUTPUTTYPE:
- g_assert (!prop->output_configured && value);
- /* Once configures, it cannot be changed in runtime */
- {
- guint num_types;
-
- num_types = gst_tensors_info_parse_types_string (&prop->output_meta,
- g_value_get_string (value));
-
- if (prop->output_meta.num_tensors > 0 &&
- prop->output_meta.num_tensors != num_types) {
- GST_WARNING_OBJECT (self,
- "Invalid output-type, given param does not match with old value.");
- }
-
- prop->output_meta.num_tensors = num_types;
- }
- break;
- case PROP_INPUTNAME:
- /* INPUTNAME is required by tensorflow to designate the order of tensors */
- g_assert (!prop->input_configured && value);
- /* Once configures, it cannot be changed in runtime */
- {
- guint num_names;
-
- num_names = gst_tensors_info_parse_names_string (&prop->input_meta,
- g_value_get_string (value));
-
- if (prop->input_meta.num_tensors > 0 &&
- prop->input_meta.num_tensors != num_names) {
- GST_WARNING_OBJECT (self,
- "Invalid input-name, given param does not match with old value.");
- }
-
- prop->input_meta.num_tensors = num_names;
- }
- break;
- case PROP_OUTPUTNAME:
- /* OUTPUTNAME is required by tensorflow to designate the order of tensors */
- g_assert (!prop->output_configured && value);
- /* Once configures, it cannot be changed in runtime */
- {
- guint num_names;
-
- num_names = gst_tensors_info_parse_names_string (&prop->output_meta,
- g_value_get_string (value));
-
- if (prop->output_meta.num_tensors > 0 &&
- prop->output_meta.num_tensors != num_names) {
- GST_WARNING_OBJECT (self,
- "Invalid output-name, given param does not match with old value.");
- }
-
- prop->output_meta.num_tensors = num_names;
- }
- break;
- case PROP_CUSTOM:
- /* In case updated custom properties in runtime! */
- g_free_const (prop->custom_properties);
- prop->custom_properties = g_value_dup_string (value);
- silent_debug ("Custom Option = %s\n", prop->custom_properties);
- break;
- case PROP_NNAPI:
- prop->nnapi = g_value_dup_string (value);
- if (!g_regex_match_simple (REGEX_NNAPI_OPTION, prop->nnapi, 0, 0)) {
- gchar *name = gst_object_get_name ((GstObject *) object);
- g_critical
- ("%s: nnapi: \'%s\' is not valid string: it should be in the form of BOOL:ACCELLERATOR or BOOL with a regex, "
- REGEX_NNAPI_OPTION "\n", name, prop->nnapi);
- g_free (name);
- break;
- }
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
+ if (!gst_tensor_filter_common_set_property (priv, prop_id, value, pspec))
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
/**
GValue * value, GParamSpec * pspec)
{
GstTensorFilter *self;
- GstTensorFilterProperties *prop;
+ GstTensorFilterPrivate *priv;
self = GST_TENSOR_FILTER (object);
- prop = &self->prop;
+ priv = &self->priv;
silent_debug ("Getting property for prop %d.\n", prop_id);
- switch (prop_id) {
- case PROP_SILENT:
- g_value_set_boolean (value, self->silent);
- break;
- default:
- if (!gst_tensor_filter_common_get_property (prop, prop_id, value, pspec))
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
+ if (!gst_tensor_filter_common_get_property (priv, prop_id, value, pspec))
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
/**
GstBuffer * inbuf, GstBuffer * outbuf)
{
GstTensorFilter *self;
+ GstTensorFilterPrivate *priv;
GstTensorFilterProperties *prop;
GstMemory *in_mem[NNS_TENSOR_SIZE_LIMIT];
GstMapInfo in_info[NNS_TENSOR_SIZE_LIMIT];
gint ret;
self = GST_TENSOR_FILTER_CAST (trans);
- prop = &self->prop;
+ priv = &self->priv;
+ prop = &priv->prop;
- if (G_UNLIKELY (!self->configured))
+ if (G_UNLIKELY (!priv->configured))
goto unknown_format;
- if (G_UNLIKELY (!self->fw))
+ if (G_UNLIKELY (!priv->fw))
goto unknown_framework;
- if (G_UNLIKELY (!self->fw->run_without_model) &&
+ if (G_UNLIKELY (!priv->fw->run_without_model) &&
G_UNLIKELY (!prop->model_file))
goto unknown_model;
- if (G_UNLIKELY (!self->fw->invoke_NN))
+ if (G_UNLIKELY (!priv->fw->invoke_NN))
goto unknown_invoke;
/* 0. Check all properties. */
- silent_debug ("Invoking %s with %s model\n", self->fw->name,
+ silent_debug ("Invoking %s with %s model\n", priv->fw->name,
GST_STR_NULL (prop->model_file));
/* 1. Set input tensors from inbuf. */
out_tensors[i].type = prop->output_meta.info[i].type;
/* allocate memory if allocate_in_invoke is FALSE */
- if (self->fw->allocate_in_invoke == FALSE) {
+ if (priv->fw->allocate_in_invoke == FALSE) {
out_mem[i] = gst_allocator_alloc (NULL, out_tensors[i].size, NULL);
g_assert (gst_memory_map (out_mem[i], &out_info[i], GST_MAP_WRITE));
}
/* 3. Call the filter-subplugin callback, "invoke" */
- gst_tensor_filter_call (self, ret, invoke_NN, in_tensors, out_tensors);
+ gst_tensor_filter_call (priv, ret, invoke_NN, in_tensors, out_tensors);
/** @todo define enum to indicate status code */
g_assert (ret >= 0);
/* 4. Update result and free map info. */
for (i = 0; i < prop->output_meta.num_tensors; i++) {
- if (self->fw->allocate_in_invoke) {
+ if (priv->fw->allocate_in_invoke) {
/* filter-subplugin allocated new memory, update this */
out_mem[i] =
gst_memory_new_wrapped (0, out_tensors[i].data, out_tensors[i].size,
0, out_tensors[i].size, out_tensors[i].data,
- self->fw->destroyNotify ? self->fw->destroyNotify : g_free);
+ priv->fw->destroyNotify ? priv->fw->destroyNotify : g_free);
} else {
gst_memory_unmap (out_mem[i], &out_info[i]);
}
static void
gst_tensor_filter_load_tensor_info (GstTensorFilter * self)
{
+ GstTensorFilterPrivate *priv;
GstTensorFilterProperties *prop;
GstTensorsInfo in_info, out_info;
int res;
- prop = &self->prop;
+ priv = &self->priv;
+ prop = &priv->prop;
gst_tensors_info_init (&in_info);
gst_tensors_info_init (&out_info);
/* supposed fixed in-tensor info if getInputDimension is defined. */
if (!prop->input_configured) {
- gst_tensor_filter_call (self, res, getInputDimension, &in_info);
+ gst_tensor_filter_call (priv, res, getInputDimension, &in_info);
if (res == 0) {
g_assert (in_info.num_tensors > 0);
/* supposed fixed out-tensor info if getOutputDimension is defined. */
if (!prop->output_configured) {
- gst_tensor_filter_call (self, res, getOutputDimension, &out_info);
+ gst_tensor_filter_call (priv, res, getOutputDimension, &out_info);
if (res == 0) {
g_assert (out_info.num_tensors > 0);
gst_tensor_filter_configure_tensor (GstTensorFilter * self,
const GstCaps * incaps)
{
+ GstTensorFilterPrivate *priv;
GstTensorFilterProperties *prop;
GstStructure *structure;
GstTensorsConfig in_config, out_config;
g_return_val_if_fail (incaps != NULL, FALSE);
- prop = &self->prop;
+ priv = &self->priv;
+ prop = &priv->prop;
gst_tensors_config_init (&in_config);
gst_tensors_config_init (&out_config);
int res;
gst_tensors_info_init (&out_info);
- gst_tensor_filter_call (self, res, setInputDimension, &in_config.info,
+ gst_tensor_filter_call (priv, res, setInputDimension, &in_config.info,
&out_info);
if (res == 0) {
out_config.rate_n = in_config.rate_n;
out_config.rate_d = in_config.rate_d;
- if (self->configured) {
+ if (priv->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));
+ g_assert (gst_tensors_config_is_equal (&priv->in_config, &in_config));
+ g_assert (gst_tensors_config_is_equal (&priv->out_config, &out_config));
} else {
- 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 (&priv->in_config.info, &in_config.info);
+ priv->in_config.rate_n = in_config.rate_n;
+ priv->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;
+ gst_tensors_info_copy (&priv->out_config.info, &out_config.info);
+ priv->out_config.rate_n = out_config.rate_n;
+ priv->out_config.rate_d = out_config.rate_d;
- self->configured = TRUE;
+ priv->configured = TRUE;
}
}
done:
gst_tensors_info_free (&in_config.info);
gst_tensors_info_free (&out_config.info);
- return self->configured;
+ return priv->configured;
}
/**
GstPadDirection direction, GstCaps * caps, GstCaps * filter)
{
GstTensorFilter *self;
+ GstTensorFilterPrivate *priv;
GstTensorsConfig config;
GstCaps *result;
GstStructure *structure;
self = GST_TENSOR_FILTER_CAST (trans);
+ priv = &self->priv;
/* Not ready */
- if (self->fw == NULL)
+ if (priv->fw == NULL)
return NULL;
gst_tensors_config_init (&config);
if (direction == GST_PAD_SINK) {
/* caps: sink pad. get src pad info */
- if (self->prop.output_configured) {
+ if (priv->prop.output_configured) {
/* fixed tensor info */
- config.info = self->prop.output_meta;
+ config.info = priv->prop.output_meta;
result = gst_tensor_filter_caps_from_config (self, &config);
} else {
/* check in-tensor info to call setInputDimension */
/* call setInputDimension with given input tensor */
gst_tensors_info_init (&out_info);
- gst_tensor_filter_call (self, res, setInputDimension, &config.info,
+ gst_tensor_filter_call (priv, res, setInputDimension, &config.info,
&out_info);
if (res == 0) {
}
} else {
/* caps: src pad. get sink pad info */
- if (self->prop.input_configured) {
+ if (priv->prop.input_configured) {
/* fixed tensor info */
- config.info = self->prop.input_meta;
+ config.info = priv->prop.input_meta;
result = gst_tensor_filter_caps_from_config (self, &config);
} else {
/* we don't know the exact tensor info from src pad caps */
GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
{
GstTensorFilter *self;
+ GstTensorFilterPrivate *priv;
GstCaps *result;
self = GST_TENSOR_FILTER_CAST (trans);
+ priv = &self->priv;
silent_debug ("fixate_caps, direction = %d\n", direction);
silent_debug_caps (caps, "caps");
GstCaps * incaps, GstCaps * outcaps)
{
GstTensorFilter *self;
+ GstTensorFilterPrivate *priv;
GstStructure *structure;
GstTensorsConfig config;
self = GST_TENSOR_FILTER_CAST (trans);
+ priv = &self->priv;
silent_debug_caps (incaps, "incaps");
silent_debug_caps (outcaps, "outcaps");
return FALSE;
}
- if (!gst_tensors_config_validate (&self->in_config)) {
+ if (!gst_tensors_config_validate (&priv->in_config)) {
GST_ERROR_OBJECT (self, "Failed to validate input tensor.");
return FALSE;
}
- if (!gst_tensors_config_validate (&self->out_config)) {
+ if (!gst_tensors_config_validate (&priv->out_config)) {
GST_ERROR_OBJECT (self, "Failed to validate output tensor.");
return FALSE;
}
structure = gst_caps_get_structure (outcaps, 0);
gst_tensors_config_from_structure (&config, structure);
- if (!gst_tensors_config_is_equal (&self->out_config, &config)) {
+ if (!gst_tensors_config_is_equal (&priv->out_config, &config)) {
GST_ERROR_OBJECT (self, "Invalid outcaps.");
return FALSE;
}
GstCaps * othercaps, gsize * othersize)
{
GstTensorFilter *self;
+ GstTensorFilterPrivate *priv;
self = GST_TENSOR_FILTER_CAST (trans);
+ priv = &self->priv;
- g_assert (self->configured);
+ g_assert (priv->configured);
/**
* Consider multi-tensors.
gst_tensor_filter_start (GstBaseTransform * trans)
{
GstTensorFilter *self;
+ GstTensorFilterPrivate *priv;
self = GST_TENSOR_FILTER_CAST (trans);
+ priv = &self->priv;
/* If it is not configured properly, don't allow to start! */
- if (self->fw == NULL)
+ if (priv->fw == NULL)
return FALSE;
- gst_tensor_filter_open_fw (self);
-
- if (self->prop.fw_opened == FALSE)
- return FALSE;
- return TRUE;
+ gst_tensor_filter_common_open_fw (priv);
+ return priv->prop.fw_opened;
}
/**
gst_tensor_filter_stop (GstBaseTransform * trans)
{
GstTensorFilter *self;
+ GstTensorFilterPrivate *priv;
self = GST_TENSOR_FILTER_CAST (trans);
+ priv = &self->priv;
- gst_tensor_filter_close_fw (self);
+ gst_tensor_filter_common_close_fw (priv);
return TRUE;
}
#ifndef __GST_TENSOR_FILTER_H__
#define __GST_TENSOR_FILTER_H__
-#include <stdint.h>
#include <gst/gst.h>
#include <gst/gstinfo.h>
#include <gst/base/gstbasetransform.h>
#include "tensor_common.h"
#include "nnstreamer_subplugin.h"
#include "nnstreamer_plugin_api_filter.h"
+#include "tensor_filter_common.h"
G_BEGIN_DECLS
{
GstBaseTransform element; /**< This is the parent object */
- void *privateData; /**< NNFW plugin's private data is stored here */
- GstTensorFilterProperties prop; /**< NNFW plugin's properties */
- const GstTensorFilterFramework *fw; /**< The implementation core of the NNFW. NULL if not configured */
-
- /* internal properties for tensor-filter */
- gboolean 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 */
+ GstTensorFilterPrivate priv; /**< Internal properties for tensor-filter */
};
/**
- * @brief Location of GstTensorFilter from privateData
- * @param p the "privateData" pointer of GstTensorFilter
- * @return the pointer to GstTensorFilter containing p as privateData
- */
-#define GstTensorFilter_of_privateData(p) ({ \
- const void **__mptr = (const void **)(p); \
- (GstTensorFilter *)( (char *)__mptr - offsetof(GstTensorFilter, privateData) );})
-
-/**
* @brief GstTensorFilterClass inherits GstBaseTransformClass.
*
* Referring another child (sibiling), GstVideoFilter (abstract class) and
#include "tensor_filter_common.h"
+#define REGEX_NNAPI_OPTION "(^(true|false)$|^(true|false)([:]?(cpu|gpu|npu)))"
+
+/**
+ * @brief Free memory
+ */
+#define g_free_const(x) g_free((void*)(long)(x))
+
+/**
+ * @brief GstTensorFilter properties.
+ */
+enum
+{
+ PROP_0,
+ PROP_SILENT,
+ PROP_FRAMEWORK,
+ PROP_MODEL,
+ PROP_INPUT,
+ PROP_INPUTTYPE,
+ PROP_INPUTNAME,
+ PROP_OUTPUT,
+ PROP_OUTPUTTYPE,
+ PROP_OUTPUTNAME,
+ PROP_CUSTOM,
+ PROP_SUBPLUGINS,
+ PROP_NNAPI
+};
+
/**
* @brief Validate filter sub-plugin's data.
*/
-gboolean
+static gboolean
nnstreamer_filter_validate (const GstTensorFilterFramework * tfsp)
{
if (!tfsp || !tfsp->name) {
return get_subplugin (NNS_SUBPLUGIN_FILTER, name);
}
-
/**
* @brief Parse the string of model
* @param[out] prop Struct containing the properties of the object
* @param[in] model_files the prediction model paths
* @return number of parsed model path
*/
-guint
+static guint
gst_tensor_filter_parse_modelpaths_string (GstTensorFilterProperties * prop,
const gchar * model_files)
{
}
/**
+ * @brief Initialize the properties for tensor-filter.
+ */
+void
+gst_tensor_filter_common_init_property (GstTensorFilterPrivate * priv)
+{
+ GstTensorFilterProperties *prop;
+
+ prop = &priv->prop;
+
+ /* init NNFW properties */
+ prop->fwname = NULL;
+ prop->fw_opened = FALSE;
+ prop->input_configured = FALSE;
+ prop->output_configured = FALSE;
+ prop->model_file = NULL;
+ prop->nnapi = NULL;
+ prop->custom_properties = NULL;
+ gst_tensors_info_init (&prop->input_meta);
+ gst_tensors_info_init (&prop->output_meta);
+
+ /* init internal properties */
+ priv->fw = NULL;
+ priv->privateData = NULL;
+ priv->silent = TRUE;
+ priv->configured = FALSE;
+ gst_tensors_config_init (&priv->in_config);
+ gst_tensors_config_init (&priv->out_config);
+}
+
+/**
+ * @brief Free the properties for tensor-filter.
+ */
+void
+gst_tensor_filter_common_free_property (GstTensorFilterPrivate * priv)
+{
+ GstTensorFilterProperties *prop;
+
+ prop = &priv->prop;
+
+ g_free_const (prop->fwname);
+ g_free_const (prop->model_file);
+ g_free_const (prop->custom_properties);
+
+ gst_tensors_info_free (&prop->input_meta);
+ gst_tensors_info_free (&prop->output_meta);
+
+ gst_tensors_info_free (&priv->in_config.info);
+ gst_tensors_info_free (&priv->out_config.info);
+}
+
+/**
+ * @brief Set the properties for tensor_filter
+ * @param[in] priv Struct containing the properties of the object
+ * @param[in] prop_id Id for the property
+ * @param[in] value Container to return the asked property
+ * @param[in] pspec Metadata to specify the parameter
+ * @return TRUE if prop_id is value, else FALSE
+ */
+gboolean
+gst_tensor_filter_common_set_property (GstTensorFilterPrivate * priv,
+ guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+ GstTensorFilterProperties *prop;
+
+ prop = &priv->prop;
+
+ switch (prop_id) {
+ case PROP_SILENT:
+ priv->silent = g_value_get_boolean (value);
+ break;
+ case PROP_FRAMEWORK:
+ {
+ const gchar *fw_name = g_value_get_string (value);
+ const GstTensorFilterFramework *fw;
+
+ if (priv->fw != NULL) {
+ /* close old framework */
+ gst_tensor_filter_common_close_fw (priv);
+ }
+
+ g_debug ("Framework = %s\n", fw_name);
+
+ fw = nnstreamer_filter_find (fw_name);
+
+ /* See if mandatory methods are filled in */
+ if (nnstreamer_filter_validate (fw)) {
+ priv->fw = fw;
+ prop->fwname = g_strdup (fw_name);
+ } else {
+ g_warning ("Cannot identify the given neural network framework, %s\n",
+ fw_name);
+ }
+ break;
+ }
+ case PROP_MODEL:
+ {
+ const gchar *model_files = g_value_get_string (value);
+ guint model_num;
+
+ if (prop->model_file) {
+ gst_tensor_filter_common_close_fw (priv);
+ g_free_const (prop->model_file);
+ prop->model_file = NULL;
+ }
+
+ if (prop->model_file_sub) {
+ gst_tensor_filter_common_close_fw (priv);
+ g_free_const (prop->model_file_sub);
+ prop->model_file_sub = NULL;
+ }
+
+ /* Once configures, it cannot be changed in runtime */
+ g_assert (model_files);
+ model_num = gst_tensor_filter_parse_modelpaths_string (prop, model_files);
+ if (model_num == 1) {
+ if (!g_file_test (prop->model_file, G_FILE_TEST_IS_REGULAR))
+ g_critical ("Cannot find the model file: %s\n", prop->model_file);
+ } else if (model_num == 2) {
+ if (!g_file_test (prop->model_file_sub, G_FILE_TEST_IS_REGULAR))
+ g_critical ("Cannot find the init model file: %s\n",
+ prop->model_file_sub);
+ if (!g_file_test (prop->model_file, G_FILE_TEST_IS_REGULAR))
+ g_critical ("Cannot find the pred model file: %s\n",
+ prop->model_file);
+ } else if (model_num > 2) {
+ /** @todo if the new NN framework requires more than 2 model files, this area will be implemented */
+ g_critical
+ ("There is no NN framework that requires model files more than 2. Current Input model files are :%d\n",
+ model_num);
+ } else {
+ g_critical ("Set model file path first\n");
+ }
+ break;
+ }
+ case PROP_INPUT:
+ g_assert (!prop->input_configured && value);
+ /* Once configures, it cannot be changed in runtime */
+ {
+ guint num_dims;
+
+ num_dims = gst_tensors_info_parse_dimensions_string (&prop->input_meta,
+ g_value_get_string (value));
+
+ if (prop->input_meta.num_tensors > 0 &&
+ prop->input_meta.num_tensors != num_dims) {
+ g_warning
+ ("Invalid input-dim, given param does not match with old value.");
+ }
+
+ prop->input_meta.num_tensors = num_dims;
+ }
+ break;
+ case PROP_OUTPUT:
+ g_assert (!prop->output_configured && value);
+ /* Once configures, it cannot be changed in runtime */
+ {
+ guint num_dims;
+
+ num_dims = gst_tensors_info_parse_dimensions_string (&prop->output_meta,
+ g_value_get_string (value));
+
+ if (prop->output_meta.num_tensors > 0 &&
+ prop->output_meta.num_tensors != num_dims) {
+ g_warning
+ ("Invalid output-dim, given param does not match with old value.");
+ }
+
+ prop->output_meta.num_tensors = num_dims;
+ }
+ break;
+ case PROP_INPUTTYPE:
+ g_assert (!prop->input_configured && value);
+ /* Once configures, it cannot be changed in runtime */
+ {
+ guint num_types;
+
+ num_types = gst_tensors_info_parse_types_string (&prop->input_meta,
+ g_value_get_string (value));
+
+ if (prop->input_meta.num_tensors > 0 &&
+ prop->input_meta.num_tensors != num_types) {
+ g_warning
+ ("Invalid input-type, given param does not match with old value.");
+ }
+
+ prop->input_meta.num_tensors = num_types;
+ }
+ break;
+ case PROP_OUTPUTTYPE:
+ g_assert (!prop->output_configured && value);
+ /* Once configures, it cannot be changed in runtime */
+ {
+ guint num_types;
+
+ num_types = gst_tensors_info_parse_types_string (&prop->output_meta,
+ g_value_get_string (value));
+
+ if (prop->output_meta.num_tensors > 0 &&
+ prop->output_meta.num_tensors != num_types) {
+ g_warning
+ ("Invalid output-type, given param does not match with old value.");
+ }
+
+ prop->output_meta.num_tensors = num_types;
+ }
+ break;
+ case PROP_INPUTNAME:
+ /* INPUTNAME is required by tensorflow to designate the order of tensors */
+ g_assert (!prop->input_configured && value);
+ /* Once configures, it cannot be changed in runtime */
+ {
+ guint num_names;
+
+ num_names = gst_tensors_info_parse_names_string (&prop->input_meta,
+ g_value_get_string (value));
+
+ if (prop->input_meta.num_tensors > 0 &&
+ prop->input_meta.num_tensors != num_names) {
+ g_warning
+ ("Invalid input-name, given param does not match with old value.");
+ }
+
+ prop->input_meta.num_tensors = num_names;
+ }
+ break;
+ case PROP_OUTPUTNAME:
+ /* OUTPUTNAME is required by tensorflow to designate the order of tensors */
+ g_assert (!prop->output_configured && value);
+ /* Once configures, it cannot be changed in runtime */
+ {
+ guint num_names;
+
+ num_names = gst_tensors_info_parse_names_string (&prop->output_meta,
+ g_value_get_string (value));
+
+ if (prop->output_meta.num_tensors > 0 &&
+ prop->output_meta.num_tensors != num_names) {
+ g_warning
+ ("Invalid output-name, given param does not match with old value.");
+ }
+
+ prop->output_meta.num_tensors = num_names;
+ }
+ break;
+ case PROP_CUSTOM:
+ /* In case updated custom properties in runtime! */
+ g_free_const (prop->custom_properties);
+ prop->custom_properties = g_value_dup_string (value);
+ g_debug ("Custom Option = %s\n", prop->custom_properties);
+ break;
+ case PROP_NNAPI:
+ prop->nnapi = g_value_dup_string (value);
+ if (!g_regex_match_simple (REGEX_NNAPI_OPTION, prop->nnapi, 0, 0)) {
+ g_critical
+ ("nnapi: \'%s\' is not valid string: it should be in the form of BOOL:ACCELLERATOR or BOOL with a regex, "
+ REGEX_NNAPI_OPTION "\n", prop->nnapi);
+ break;
+ }
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
* @brief Get the properties for tensor_filter
- * @param[in] prop Struct containing the properties of the object
+ * @param[in] priv Struct containing the properties of the object
* @param[in] prop_id Id for the property
* @param[in] value Container to return the asked property
* @param[in] pspec Metadata to specify the parameter
* @return TRUE if prop_id is value, else FALSE
*/
gboolean
-gst_tensor_filter_common_get_property (GstTensorFilterProperties * prop,
+gst_tensor_filter_common_get_property (GstTensorFilterPrivate * priv,
guint prop_id, GValue * value, GParamSpec * pspec)
{
- gboolean ret = TRUE;
+ GstTensorFilterProperties *prop;
+
+ prop = &priv->prop;
switch (prop_id) {
+ case PROP_SILENT:
+ g_value_set_boolean (value, priv->silent);
+ break;
case PROP_FRAMEWORK:
g_value_set_string (value, prop->fwname);
break;
g_value_set_string (value, prop->nnapi);
break;
default:
- ret = FALSE;
- break;
+ /* unknown property */
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * @brief Open NN framework.
+ */
+void
+gst_tensor_filter_common_open_fw (GstTensorFilterPrivate * priv)
+{
+ if (!priv->prop.fw_opened && priv->fw) {
+ if (priv->fw->open) {
+ if (priv->fw->open (&priv->prop, &priv->privateData) == 0)
+ priv->prop.fw_opened = TRUE;
+ } else {
+ priv->prop.fw_opened = TRUE;
+ }
}
+}
- return ret;
+/**
+ * @brief Close NN framework.
+ */
+void
+gst_tensor_filter_common_close_fw (GstTensorFilterPrivate * priv)
+{
+ if (priv->prop.fw_opened) {
+ if (priv->fw && priv->fw->close) {
+ priv->fw->close (&priv->prop, &priv->privateData);
+ }
+ priv->prop.fw_opened = FALSE;
+ g_free_const (priv->prop.fwname);
+ priv->prop.fwname = NULL;
+ priv->fw = NULL;
+ priv->privateData = NULL;
+ }
}
#ifndef __G_TENSOR_FILTER_COMMON_H__
#define __G_TENSOR_FILTER_COMMON_H__
-#include <glib-object.h>
-
#include <nnstreamer_subplugin.h>
#include <nnstreamer_plugin_api.h>
#include <nnstreamer_plugin_api_filter.h>
/**
- * @brief Free memory
+ * @brief Structure definition for common tensor-filter properties.
*/
-#define g_free_const(x) g_free((void*)(long)(x))
-
-/**
- * @brief GstTensorFilter properties.
- */
-enum
+typedef struct _GstTensorFilterPrivate
{
- PROP_0,
- PROP_SILENT,
- PROP_FRAMEWORK,
- PROP_MODEL,
- PROP_INPUT,
- PROP_INPUTTYPE,
- PROP_INPUTNAME,
- PROP_OUTPUT,
- PROP_OUTPUTTYPE,
- PROP_OUTPUTNAME,
- PROP_CUSTOM,
- PROP_SUBPLUGINS,
- PROP_NNAPI
-};
+ void *privateData; /**< NNFW plugin's private data is stored here */
+ GstTensorFilterProperties prop; /**< NNFW plugin's properties */
+ const GstTensorFilterFramework *fw; /**< The implementation core of the NNFW. NULL if not configured */
-/**
- * @brief Validate filter sub-plugin's data.
- */
-extern gboolean
-nnstreamer_filter_validate (const GstTensorFilterFramework * tfsp);
-
-/**
- * @brief Parse the string of model
- * @param[out] prop Struct containing the properties of the object
- * @param[in] model_files the prediction model paths
- * @return number of parsed model path
- * @todo Create a struct list to save multiple model files with key, value pair
- */
-extern guint
-gst_tensor_filter_parse_modelpaths_string (GstTensorFilterProperties * prop,
- const gchar * model_files);
+ /* internal properties for tensor-filter */
+ gboolean 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 */
+} GstTensorFilterPrivate;
/**
* @brief Printout the comparison results of two tensors.
gst_tensor_filter_compare_tensors (GstTensorsInfo * info1,
GstTensorsInfo * info2);
-
/**
* @brief Installs all the properties for tensor_filter
* @param[in] gobject_class Glib object class whose properties will be set
extern void
gst_tensor_filter_install_properties (GObjectClass * gobject_class);
+/**
+ * @brief Initialize the properties for tensor-filter.
+ */
+extern void
+gst_tensor_filter_common_init_property (GstTensorFilterPrivate * priv);
+
+/**
+ * @brief Free the properties for tensor-filter.
+ */
+extern void
+gst_tensor_filter_common_free_property (GstTensorFilterPrivate * priv);
+
+/**
+ * @brief Set the properties for tensor_filter
+ * @param[in] priv Struct containing the properties of the object
+ * @param[in] prop_id Id for the property
+ * @param[in] value Container to return the asked property
+ * @param[in] pspec Metadata to specify the parameter
+ * @return TRUE if prop_id is value, else FALSE
+ */
+extern gboolean
+gst_tensor_filter_common_set_property (GstTensorFilterPrivate * priv,
+ guint prop_id, const GValue * value, GParamSpec * pspec);
/**
* @brief Get the properties for tensor_filter
- * @param[in] prop Struct containing the properties of the object
+ * @param[in] priv Struct containing the properties of the object
* @param[in] prop_id Id for the property
* @param[in] value Container to return the asked property
* @param[in] pspec Metadata to specify the parameter
* @return TRUE if prop_id is value, else FALSE
*/
extern gboolean
-gst_tensor_filter_common_get_property (GstTensorFilterProperties *prop,
- guint prop_id, GValue *value, GParamSpec *pspec);
+gst_tensor_filter_common_get_property (GstTensorFilterPrivate * priv,
+ guint prop_id, GValue * value, GParamSpec * pspec);
+
+/**
+ * @brief Open NN framework.
+ */
+extern void
+gst_tensor_filter_common_open_fw (GstTensorFilterPrivate * priv);
+
+/**
+ * @brief Close NN framework.
+ */
+extern void
+gst_tensor_filter_common_close_fw (GstTensorFilterPrivate * priv);
#endif /* __G_TENSOR_FILTER_COMMON_H__ */