[C-Api] update util functions
authorJaeyun <jy1210.jung@samsung.com>
Fri, 15 Nov 2019 06:28:32 +0000 (15:28 +0900)
committerMyungJoo Ham <myungjoo.ham@samsung.com>
Wed, 11 Dec 2019 02:09:27 +0000 (11:09 +0900)
1. add new function to compare tensors metadata (type, dimension)
2. refactor function to create tensors data handle

Signed-off-by: Jaeyun Jung <jy1210.jung@samsung.com>
api/capi/include/nnstreamer-capi-private.h
api/capi/src/nnstreamer-capi-util.c
tests/tizen_capi/unittest_tizen_capi.cpp

index 452640d..117333f 100644 (file)
@@ -246,9 +246,13 @@ typedef struct _ml_pipeline_valve {
 
 /**
  * @brief Macro to check the tensors info is valid.
- * @since_tizen 5.5
  */
-#define ml_tensors_info_is_valid(i,v) (ml_tensors_info_validate ((i), &(v)) == ML_ERROR_NONE && (v))
+#define ml_tensors_info_is_valid(i) ({bool v; (ml_tensors_info_validate ((i), &v) == ML_ERROR_NONE && v);})
+
+/**
+ * @brief Macro to compare the tensors info.
+ */
+#define ml_tensors_info_is_equal(i1,i2) ({bool e; (ml_tensors_info_compare ((i1), (i2), &e) == ML_ERROR_NONE && e);})
 
 /**
  * @brief Gets the byte size of the given tensor info.
@@ -266,6 +270,20 @@ size_t ml_tensor_info_get_size (const ml_tensor_info_s *info);
 int ml_tensors_info_initialize (ml_tensors_info_s *info);
 
 /**
+ * @brief Compares the given tensors information.
+ * @details If the function returns an error, @a equal is not changed.
+ * @since_tizen 6.0
+ * @param[in] info1 The handle of tensors information to be compared.
+ * @param[in] info2 The handle of tensors information to be compared.
+ * @param[out] equal @c true if given tensors information is equal, @c false if if it's not equal.
+ * @return @c 0 on success. Otherwise a negative error value.
+ * @retval #ML_ERROR_NONE Successful
+ * @retval #ML_ERROR_NOT_SUPPORTED Not supported.
+ * @retval #ML_ERROR_INVALID_PARAMETER Given parameter is invalid.
+ */
+int ml_tensors_info_compare (const ml_tensors_info_h info1, const ml_tensors_info_h info2, bool *equal);
+
+/**
  * @brief Frees the tensors info pointer.
  * @since_tizen 5.5
  * @param[in] info The tensors info pointer to be freed.
@@ -289,6 +307,7 @@ GstCaps * ml_tensors_info_get_caps (const ml_tensors_info_s *info);
 
 /**
  * @brief Creates a tensor data frame wihout buffer with the given tensors information.
+ * @details If @a info is null, this allocates data handle with empty tensor data.
  * @param[in] info The handle of tensors information for the allocation.
  * @param[out] data The handle of tensors data.
  * @return @c 0 on success. Otherwise a negative error value.
index 9b801ab..699c30a 100644 (file)
@@ -120,6 +120,28 @@ ml_tensor_info_validate (const ml_tensor_info_s * info)
 }
 
 /**
+ * @brief Compares the given tensor info.
+ */
+static gboolean
+ml_tensor_info_compare (const ml_tensor_info_s * i1, const ml_tensor_info_s * i2)
+{
+  guint i;
+
+  if (i1 == NULL || i2 == NULL)
+    return FALSE;
+
+  if (i1->type != i2->type)
+    return FALSE;
+
+  for (i = 0; i < ML_TENSOR_RANK_LIMIT; i++) {
+    if (i1->dimension[i] != i2->dimension[i])
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
  * @brief Validates the given tensors info is valid.
  */
 int
@@ -153,6 +175,41 @@ done:
 }
 
 /**
+ * @brief Compares the given tensors information.
+ */
+int
+ml_tensors_info_compare (const ml_tensors_info_h info1,
+    const ml_tensors_info_h info2, bool * equal)
+{
+  ml_tensors_info_s *i1, *i2;
+  guint i;
+
+  check_feature_state ();
+
+  if (info1 == NULL || info2 == NULL || equal == NULL)
+    return ML_ERROR_INVALID_PARAMETER;
+
+  i1 = (ml_tensors_info_s *) info1;
+  i2 = (ml_tensors_info_s *) info2;
+
+  /* init false */
+  *equal = false;
+
+  if (i1->num_tensors != i2->num_tensors)
+    goto done;
+
+  for (i = 0; i < i1->num_tensors; i++) {
+    if (!ml_tensor_info_compare (&i1->info[i], &i2->info[i]))
+      goto done;
+  }
+
+  *equal = true;
+
+done:
+  return ML_ERROR_NONE;
+}
+
+/**
  * @brief Sets the number of tensors with given handle of tensors information.
  */
 int
@@ -482,15 +539,15 @@ ml_tensors_data_create_no_alloc (const ml_tensors_info_h info,
     ml_tensors_data_h * data)
 {
   ml_tensors_data_s *_data;
-  ml_tensors_info_s *tensors_info;
+  ml_tensors_info_s *_info;
   gint i;
 
   check_feature_state ();
 
-  if (!info || !data)
+  if (data == NULL)
     return ML_ERROR_INVALID_PARAMETER;
 
-  tensors_info = (ml_tensors_info_s *) info;
+  /* init null */
   *data = NULL;
 
   _data = g_new0 (ml_tensors_data_s, 1);
@@ -499,10 +556,13 @@ ml_tensors_data_create_no_alloc (const ml_tensors_info_h info,
     return ML_ERROR_OUT_OF_MEMORY;
   }
 
-  _data->num_tensors = tensors_info->num_tensors;
-  for (i = 0; i < _data->num_tensors; i++) {
-    _data->tensors[i].size = ml_tensor_info_get_size (&tensors_info->info[i]);
-    _data->tensors[i].tensor = NULL;
+  _info = (ml_tensors_info_s *) info;
+  if (_info != NULL) {
+    _data->num_tensors = _info->num_tensors;
+    for (i = 0; i < _data->num_tensors; i++) {
+      _data->tensors[i].size = ml_tensor_info_get_size (&_info->info[i]);
+      _data->tensors[i].tensor = NULL;
+    }
   }
 
   *data = _data;
@@ -520,6 +580,11 @@ ml_tensors_data_create (const ml_tensors_info_h info,
   ml_tensors_data_s *_data = NULL;
   gint i;
 
+  check_feature_state ();
+
+  if (info == NULL || data == NULL)
+    return ML_ERROR_INVALID_PARAMETER;
+
   status = ml_tensors_data_create_no_alloc (info, (ml_tensors_data_h *) &_data);
 
   if (status != ML_ERROR_NONE) {
index 6126b11..2086239 100644 (file)
@@ -1366,6 +1366,56 @@ TEST (nnstreamer_capi_util, tensors_info)
   EXPECT_EQ (status, ML_ERROR_NONE);
 }
 
+/**
+ * @brief Test utility functions
+ */
+TEST (nnstreamer_capi_util, compare_info)
+{
+  ml_tensors_info_h info1, info2;
+  ml_tensor_dimension dim;
+  int status;
+
+  status = ml_tensors_info_create (&info1);
+  EXPECT_EQ (status, ML_ERROR_NONE);
+
+  status = ml_tensors_info_create (&info2);
+  EXPECT_EQ (status, ML_ERROR_NONE);
+
+  dim[0] = 3;
+  dim[1] = 4;
+  dim[2] = 4;
+  dim[3] = 1;
+
+  ml_tensors_info_set_count (info1, 1);
+  ml_tensors_info_set_tensor_type (info1, 0, ML_TENSOR_TYPE_UINT8);
+  ml_tensors_info_set_tensor_dimension (info1, 0, dim);
+
+  ml_tensors_info_set_count (info2, 1);
+  ml_tensors_info_set_tensor_type (info2, 0, ML_TENSOR_TYPE_UINT8);
+  ml_tensors_info_set_tensor_dimension (info2, 0, dim);
+
+  /* compare info */
+  EXPECT_TRUE (ml_tensors_info_is_equal (info1, info2));
+
+  /* change type */
+  ml_tensors_info_set_tensor_type (info2, 0, ML_TENSOR_TYPE_UINT16);
+  EXPECT_FALSE (ml_tensors_info_is_equal (info1, info2));
+
+  /* validate info */
+  EXPECT_TRUE (ml_tensors_info_is_valid (info2));
+
+  /* validate invalid dimension */
+  dim[3] = 0;
+  ml_tensors_info_set_tensor_dimension (info2, 0, dim);
+  EXPECT_FALSE (ml_tensors_info_is_valid (info2));
+
+  status = ml_tensors_info_destroy (info1);
+  EXPECT_EQ (status, ML_ERROR_NONE);
+
+  status = ml_tensors_info_destroy (info2);
+  EXPECT_EQ (status, ML_ERROR_NONE);
+}
+
 #ifdef ENABLE_TENSORFLOW_LITE
 /**
  * @brief Test NNStreamer single shot (tensorflow-lite)