From cf79302e205f9b7822fbf86f44ddcba69b1f4e13 Mon Sep 17 00:00:00 2001 From: Jaeyun Jung Date: Tue, 17 Jan 2023 17:13:10 +0900 Subject: [PATCH] [C-Api] new function to copy data handle Add new util function to copy tensor data. Signed-off-by: Jaeyun Jung --- c/src/ml-api-common.c | 41 ++++++++++++++++++++ c/src/ml-api-internal.h | 14 +++++++ tests/capi/unittest_capi_inference.cc | 72 +++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) diff --git a/c/src/ml-api-common.c b/c/src/ml-api-common.c index 81f1c12..3766e77 100644 --- a/c/src/ml-api-common.c +++ b/c/src/ml-api-common.c @@ -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 diff --git a/c/src/ml-api-internal.h b/c/src/ml-api-internal.h index 5cbdaab..75b912f 100644 --- a/c/src/ml-api-internal.h +++ b/c/src/ml-api-internal.h @@ -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. diff --git a/tests/capi/unittest_capi_inference.cc b/tests/capi/unittest_capi_inference.cc index 74ad59f..9e2391f 100644 --- a/tests/capi/unittest_capi_inference.cc +++ b/tests/capi/unittest_capi_inference.cc @@ -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) -- 2.7.4