2 * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "common/logger.h"
20 #include "ml_singleshot.h"
23 using common::PlatformResult;
24 using common::ErrorCode;
29 SingleShot::SingleShot(int id, ml_single_h handle, bool dynamic_mode)
32 dynamic_mode_{dynamic_mode},
33 tensor_data_out_handle_{nullptr},
34 tensor_info_out_handle_{nullptr} {
35 ScopeLogger("id: %d", id_);
38 // 'this' owns a handle_, and invalidates 'o'
39 SingleShot::SingleShot(SingleShot&& o)
42 dynamic_mode_(o.dynamic_mode_),
43 tensor_data_out_handle_(o.tensor_data_out_handle_),
44 tensor_info_out_handle_(o.tensor_info_out_handle_) {
45 ScopeLogger("id: %d", id_);
47 o.tensor_data_out_handle_ = nullptr;
48 o.tensor_info_out_handle_ = nullptr;
51 SingleShot::~SingleShot() {
52 ScopeLogger("id: %d", id_);
53 // not dynamic mode uses ml_single_invoke_fast, which reuses handles, so they need to be freed
55 if (nullptr != tensor_data_out_handle_) {
56 int ret = ml_tensors_data_destroy(tensor_data_out_handle_);
57 if (ML_ERROR_NONE != ret) {
58 LoggerW("ml_tensors_data_destroy failed: %d (%s)", ret, get_error_message(ret));
62 if (nullptr != tensor_info_out_handle_) {
63 int ret = ml_tensors_info_destroy(tensor_info_out_handle_);
64 if (ML_ERROR_NONE != ret) {
65 LoggerW("ml_tensors_info_destroy failed: %d (%s)", ret, get_error_message(ret));
70 int ret = ml_single_close(handle_);
71 if (ML_ERROR_NONE != ret) {
72 LoggerW("ml_single_close failed: %d (%s)", ret, get_error_message(ret));
76 PlatformResult SingleShot::GetTensorsInfo(bool get_input_mode, ml_tensors_info_h* result) {
78 ml_tensors_info_h info = nullptr;
81 ret = ml_single_get_input_info(handle_, &info);
83 ret = ml_single_get_output_info(handle_, &info);
85 if (ML_ERROR_NONE != ret) {
86 LoggerE("%s failed: %d (%s)",
87 get_input_mode ? "ml_single_get_input_info" : "ml_single_get_output_info", ret,
88 get_error_message(ret));
89 return util::ToPlatformResult(ret, "Failed to get tensors info");
93 return PlatformResult{};
96 PlatformResult SingleShot::SetInputInfo(ml_tensors_info_h in_info) {
98 int ret = ml_single_set_input_info(handle_, in_info);
99 if (ML_ERROR_NONE != ret) {
100 LoggerE("ml_single_set_input_info failed: %d (%s)", ret, get_error_message(ret));
101 return util::ToPlatformResult(ret, "Failed to set input info");
103 // invalidate output info and data in case of input change
104 if (nullptr != tensor_info_out_handle_) {
105 int ret = ml_tensors_info_destroy(tensor_info_out_handle_);
106 if (ML_ERROR_NONE != ret) {
107 LoggerE("ml_tensors_info_destroy failed: %d (%s)", ret, get_error_message(ret));
108 return PlatformResult(ErrorCode::ABORT_ERR, "Internal SingleShot error");
110 tensor_info_out_handle_ = nullptr;
112 if (nullptr != tensor_data_out_handle_) {
113 int ret = ml_tensors_data_destroy(tensor_data_out_handle_);
114 if (ML_ERROR_NONE != ret) {
115 LoggerE("ml_tensors_data_destroy failed: %d (%s)", ret, get_error_message(ret));
116 return PlatformResult(ErrorCode::ABORT_ERR, "Internal SingleShot error");
118 tensor_data_out_handle_ = nullptr;
120 return PlatformResult{};
123 PlatformResult SingleShot::Invoke(ml_tensors_data_h in_data, ml_tensors_info_h in_info,
124 ml_tensors_data_h* out_data, ml_tensors_info_h* out_info,
125 bool* should_copy_data) {
127 PlatformResult result;
129 result = InvokeDynamicInternal(in_data, in_info);
131 result = InvokeInternal(in_data, in_info);
137 *out_data = tensor_data_out_handle_;
138 *out_info = tensor_info_out_handle_;
139 *should_copy_data = !dynamic_mode_;
141 return PlatformResult{};
144 PlatformResult SingleShot::InvokeInternal(ml_tensors_data_h in_data, ml_tensors_info_h in_info) {
146 if (nullptr == tensor_info_out_handle_) {
147 PlatformResult result = GetTensorsInfo(false, &tensor_info_out_handle_);
149 LoggerE("GetTensorsInfo failed");
154 if (nullptr == tensor_data_out_handle_) {
155 int ret = ml_tensors_data_create(tensor_info_out_handle_, &tensor_data_out_handle_);
156 if (ML_ERROR_NONE != ret) {
157 LoggerE("ml_tensors_data_create failed: %d (%s)", ret, get_error_message(ret));
158 return PlatformResult(ErrorCode::ABORT_ERR, "Internal SingleShot error");
162 int ret = ml_single_invoke_fast(handle_, in_data, tensor_data_out_handle_);
163 if (ML_ERROR_NONE != ret) {
164 LoggerE("ml_single_invoke failed: %d (%s)", ret, get_error_message(ret));
165 return util::ToPlatformResult(ret, "Failed to invoke");
167 return PlatformResult{};
170 PlatformResult SingleShot::InvokeDynamicInternal(ml_tensors_data_h in_data,
171 ml_tensors_info_h in_info) {
173 int ret = ml_single_invoke_dynamic(handle_, in_data, in_info, &tensor_data_out_handle_,
174 &tensor_info_out_handle_);
175 if (ML_ERROR_NONE != ret) {
176 LoggerE("ml_single_invoke_dynamic failed: %d (%s)", ret, get_error_message(ret));
177 return util::ToPlatformResult(ret, "Failed to invoke");
180 return PlatformResult{};
183 PlatformResult SingleShot::CleanUpAfterInvoke() {
187 if (nullptr != tensor_data_out_handle_) {
188 int ret = ml_tensors_data_destroy(tensor_data_out_handle_);
189 if (ML_ERROR_NONE != ret) {
191 LoggerE("ml_tensors_data_destroy failed: %d (%s)", ret, get_error_message(ret));
193 tensor_data_out_handle_ = nullptr;
197 if (nullptr != tensor_info_out_handle_) {
198 int ret = ml_tensors_info_destroy(tensor_info_out_handle_);
199 if (ML_ERROR_NONE != ret) {
201 LoggerE("ml_tensors_info_destroy failed: %d (%s)", ret, get_error_message(ret));
203 tensor_info_out_handle_ = nullptr;
207 return PlatformResult(ErrorCode::ABORT_ERR, "Internal SingleShot error");
211 return PlatformResult{};
214 PlatformResult SingleShot::GetValue(const std::string& name, std::string& value) {
217 gchar* out_value = nullptr;
218 int ret = ml_single_get_property(handle_, name.c_str(), &out_value);
219 if (ML_ERROR_NONE != ret) {
220 LoggerE("ml_single_get_property failed: %d (%s)", ret, get_error_message(ret));
221 return util::ToPlatformResult(ret, "Failed to get value");
224 if (nullptr == out_value) {
225 LoggerW("ml_single_get_property returned nullptr, returning empty string instead");
226 // set value to an empty string as ml_single_get_property returned ML_ERROR_NONE
227 value = std::string{};
229 value = std::string{out_value};
233 return PlatformResult{};
236 PlatformResult SingleShot::SetValue(const std::string& name, const std::string& value) {
238 int ret = ml_single_set_property(handle_, name.c_str(), value.c_str());
239 if (ML_ERROR_NONE != ret) {
240 LoggerE("ml_single_set_property failed: %d (%s)", ret, get_error_message(ret));
241 return util::ToPlatformResult(ret, "Failed to set value");
244 return PlatformResult{};
247 PlatformResult SingleShot::SetTimeout(unsigned long timeout) {
249 int ret = ml_single_set_timeout(handle_, timeout);
250 if (ML_ERROR_NONE != ret) {
251 LoggerE("ml_single_set_timeout failed: %d (%s)", ret, get_error_message(ret));
252 return util::ToPlatformResult(ret, "Failed to set timeout");
255 return PlatformResult{};
258 PlatformResult SingleShot::Close() {
260 int ret = ml_single_close(handle_);
261 if (ML_ERROR_NONE != ret) {
262 LoggerE("ml_single_close failed: %d (%s)", ret, get_error_message(ret));
263 return util::ToPlatformResult(ret, "Failed to close");
266 return PlatformResult{};
269 } // namespace extension