[C-Api] new function to copy data handle
authorJaeyun Jung <jy1210.jung@samsung.net>
Tue, 17 Jan 2023 08:13:10 +0000 (17:13 +0900)
committerSangjung Woo <again4you@gmail.com>
Wed, 18 Jan 2023 05:07:10 +0000 (14:07 +0900)
Add new util function to copy tensor data.

Signed-off-by: Jaeyun Jung <jy1210.jung@samsung.net>
c/src/ml-api-common.c
c/src/ml-api-internal.h
tests/capi/unittest_capi_inference.cc

index 81f1c12..3766e77 100644 (file)
@@ -763,6 +763,47 @@ _ml_tensors_data_clone_no_alloc (const ml_tensors_data_s * data_src,
 }
 
 /**
+ * @brief Copies the tensor data frame.
+ */
+int
+ml_tensors_data_clone (const ml_tensors_data_h in, ml_tensors_data_h * out)
+{
+  int status;
+  unsigned int i;
+  ml_tensors_data_s *_in, *_out;
+
+  check_feature_state (ML_FEATURE);
+
+  if (in == NULL)
+    _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+        "The parameter, in, is NULL. It should be a valid ml_tensors_data_h handle, which is usually created by ml_tensors_data_create ().");
+
+  if (out == NULL)
+    _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+        "The parameter, out, is NULL. It should be a valid pointer to ml_tensors_data_h handle.");
+
+  _in = (ml_tensors_data_s *) in;
+  G_LOCK_UNLESS_NOLOCK (*_in);
+
+  status = ml_tensors_data_create (_in->info, out);
+  if (status != ML_ERROR_NONE) {
+    _ml_loge ("Failed to create new handle to copy tensor data.");
+    goto error;
+  }
+
+  _out = (ml_tensors_data_s *) (*out);
+
+  for (i = 0; i < _out->num_tensors; ++i) {
+    memcpy (_out->tensors[i].tensor, _in->tensors[i].tensor,
+        _in->tensors[i].size);
+  }
+
+error:
+  G_UNLOCK_UNLESS_NOLOCK (*_in);
+  return status;
+}
+
+/**
  * @brief Allocates a tensor data frame with the given tensors info. (more info in nnstreamer.h)
  */
 int
index 5cbdaab..75b912f 100644 (file)
@@ -281,6 +281,20 @@ void _ml_tensors_info_free (ml_tensors_info_s *info);
 int _ml_tensors_data_clone_no_alloc (const ml_tensors_data_s * data_src, ml_tensors_data_h * data);
 
 /**
+ * @brief Copies the tensor data frame.
+ * @since_tizen 7.5
+ * @param[in] in The handle of tensors data to be cloned.
+ * @param[out] out The handle of tensors data. The caller is responsible for freeing the allocated data with ml_tensors_data_destroy().
+ * @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.
+ * @retval #ML_ERROR_OUT_OF_MEMORY Failed to allocate required memory.
+ * @todo Consider adding new API from tizen 7.5.
+ */
+int ml_tensors_data_clone (const ml_tensors_data_h in, ml_tensors_data_h *out);
+
+/**
  * @brief Replaces string.
  * This function deallocates the input source string.
  * This is copied from nnstreamer/tensor_common.c by the nnstreamer maintainer.
index 74ad59f..9e2391f 100644 (file)
@@ -3591,6 +3591,78 @@ TEST (nnstreamer_capi_util, data_set_tdata_05_n)
 }
 
 /**
+ * @brief Test utility functions - clone data.
+ */
+TEST (nnstreamer_capi_util, data_clone_01_p)
+{
+  int status;
+  ml_tensors_info_h info;
+  ml_tensors_data_h data;
+  ml_tensors_data_h data_out;
+  ml_tensor_dimension dim = { 5, 1, 1, 1 };
+  const int raw_data[5] = { 10, 20, 30, 40, 50 };
+  int *result = nullptr;
+  size_t data_size, result_size;
+
+  ml_tensors_info_create (&info);
+  ml_tensors_info_set_count (info, 1);
+  ml_tensors_info_set_tensor_type (info, 0, ML_TENSOR_TYPE_INT32);
+  ml_tensors_info_set_tensor_dimension (info, 0, dim);
+  ml_tensors_info_get_tensor_size (info, 0, &data_size);
+
+  ml_tensors_data_create (info, &data);
+  ml_tensors_data_set_tensor_data (data, 0, (const void *) raw_data, data_size);
+
+  /* test code : clone data and compare raw value. */
+  status = ml_tensors_data_clone (data, &data_out);
+  EXPECT_EQ (status, ML_ERROR_NONE);
+
+  status = ml_tensors_data_get_tensor_data (data_out, 0, (void **) &result, &result_size);
+  EXPECT_EQ (status, ML_ERROR_NONE);
+  for (unsigned int i = 0; i < 5; i++)
+    EXPECT_EQ (result[i], raw_data[i]);
+
+  ml_tensors_info_destroy (info);
+  ml_tensors_data_destroy (data);
+  ml_tensors_data_destroy (data_out);
+}
+
+/**
+ * @brief Test utility functions - clone data.
+ */
+TEST (nnstreamer_capi_util, data_clone_02_n)
+{
+  int status;
+  ml_tensors_info_h info;
+  ml_tensors_data_h data;
+  ml_tensor_dimension dim = { 5, 1, 1, 1 };
+
+  ml_tensors_info_create (&info);
+  ml_tensors_info_set_count (info, 1);
+  ml_tensors_info_set_tensor_type (info, 0, ML_TENSOR_TYPE_INT32);
+  ml_tensors_info_set_tensor_dimension (info, 0, dim);
+  ml_tensors_data_create (info, &data);
+
+  status = ml_tensors_data_clone (data, nullptr);
+  EXPECT_EQ (status, ML_ERROR_INVALID_PARAMETER);
+
+  ml_tensors_info_destroy (info);
+  ml_tensors_data_destroy (data);
+}
+
+/**
+ * @brief Test utility functions - clone data.
+ */
+TEST (nnstreamer_capi_util, data_clone_03_n)
+{
+  int status;
+  ml_tensors_data_h data_out;
+
+  status = ml_tensors_data_clone (nullptr, &data_out);
+  EXPECT_EQ (status, ML_ERROR_INVALID_PARAMETER);
+}
+
+/**
  * @brief Test to replace string.
  */
 TEST (nnstreamer_capi_util, replaceStr01)