da397f6a57cfcadadeeb3efb40c155c5607ed68b
[platform/core/api/webapi-plugins.git] / src / ml / ml_singleshot.cc
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 #include <glib.h>
17 #include <tizen.h>
18
19 #include "common/logger.h"
20 #include "ml_singleshot.h"
21 #include "ml_utils.h"
22
23 using common::PlatformResult;
24 using common::ErrorCode;
25
26 namespace extension {
27 namespace ml {
28
29 SingleShot::SingleShot(int id, ml_single_h handle, bool dynamic_mode)
30     : id_{id},
31       handle_{handle},
32       dynamic_mode_{dynamic_mode},
33       tensor_data_out_handle_{nullptr},
34       tensor_info_out_handle_{nullptr} {
35   ScopeLogger("id: %d", id_);
36 }
37
38 // 'this' owns a handle_, and invalidates 'o'
39 SingleShot::SingleShot(SingleShot&& o)
40     : id_(o.id_),
41       handle_(o.handle_),
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_);
46   o.handle_ = nullptr;
47   o.tensor_data_out_handle_ = nullptr;
48   o.tensor_info_out_handle_ = nullptr;
49 }
50
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
54   if (!dynamic_mode_) {
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));
59       }
60     }
61
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));
66       }
67     }
68   }
69
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));
73   }
74 }
75
76 PlatformResult SingleShot::GetTensorsInfo(bool get_input_mode, ml_tensors_info_h* result) {
77   ScopeLogger();
78   ml_tensors_info_h info = nullptr;
79   int ret = 0;
80   if (get_input_mode) {
81     ret = ml_single_get_input_info(handle_, &info);
82   } else {
83     ret = ml_single_get_output_info(handle_, &info);
84   }
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");
90   }
91
92   *result = info;
93   return PlatformResult{};
94 }
95
96 PlatformResult SingleShot::SetInputInfo(ml_tensors_info_h in_info) {
97   ScopeLogger();
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");
102   }
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");
109     }
110     tensor_info_out_handle_ = nullptr;
111   }
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");
117     }
118     tensor_data_out_handle_ = nullptr;
119   }
120   return PlatformResult{};
121 }
122
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) {
126   ScopeLogger();
127   PlatformResult result;
128   if (dynamic_mode_) {
129     result = InvokeDynamicInternal(in_data, in_info);
130   } else {
131     result = InvokeInternal(in_data, in_info);
132   }
133   if (!result) {
134     return result;
135   }
136
137   *out_data = tensor_data_out_handle_;
138   *out_info = tensor_info_out_handle_;
139   *should_copy_data = !dynamic_mode_;
140
141   return PlatformResult{};
142 }
143
144 PlatformResult SingleShot::InvokeInternal(ml_tensors_data_h in_data, ml_tensors_info_h in_info) {
145   ScopeLogger();
146   if (nullptr == tensor_info_out_handle_) {
147     PlatformResult result = GetTensorsInfo(false, &tensor_info_out_handle_);
148     if (!result) {
149       LoggerE("GetTensorsInfo failed");
150       return result;
151     }
152   }
153
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");
159     }
160   }
161
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");
166   }
167   return PlatformResult{};
168 }
169
170 PlatformResult SingleShot::InvokeDynamicInternal(ml_tensors_data_h in_data,
171                                                  ml_tensors_info_h in_info) {
172   ScopeLogger();
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");
178   }
179
180   return PlatformResult{};
181 }
182
183 PlatformResult SingleShot::CleanUpAfterInvoke() {
184   ScopeLogger();
185   if (dynamic_mode_) {
186     bool is_ok = true;
187     if (nullptr != tensor_data_out_handle_) {
188       int ret = ml_tensors_data_destroy(tensor_data_out_handle_);
189       if (ML_ERROR_NONE != ret) {
190         is_ok = false;
191         LoggerE("ml_tensors_data_destroy failed: %d (%s)", ret, get_error_message(ret));
192       } else {
193         tensor_data_out_handle_ = nullptr;
194       }
195     }
196
197     if (nullptr != tensor_info_out_handle_) {
198       int ret = ml_tensors_info_destroy(tensor_info_out_handle_);
199       if (ML_ERROR_NONE != ret) {
200         is_ok = false;
201         LoggerE("ml_tensors_info_destroy failed: %d (%s)", ret, get_error_message(ret));
202       } else {
203         tensor_info_out_handle_ = nullptr;
204       }
205     }
206     if (!is_ok) {
207       return PlatformResult(ErrorCode::ABORT_ERR, "Internal SingleShot error");
208     }
209   }
210
211   return PlatformResult{};
212 }
213
214 PlatformResult SingleShot::GetValue(const std::string& name, std::string& value) {
215   ScopeLogger();
216
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");
222   }
223
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{};
228   } else {
229     value = std::string{out_value};
230     g_free(out_value);
231   }
232
233   return PlatformResult{};
234 }
235
236 PlatformResult SingleShot::SetValue(const std::string& name, const std::string& value) {
237   ScopeLogger();
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");
242   }
243
244   return PlatformResult{};
245 }
246
247 PlatformResult SingleShot::SetTimeout(unsigned long timeout) {
248   ScopeLogger();
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");
253   }
254
255   return PlatformResult{};
256 }
257
258 PlatformResult SingleShot::Close() {
259   ScopeLogger();
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");
264   }
265
266   return PlatformResult{};
267 }
268
269 }  // namespace extension
270 }  // namespace ml