README.md
1# AI<a name="EN-US_TOPIC_0000001072614474"></a>
2
3- [Introduction](#section187321516154516)
4- [Directory Structure](#section571610913453)
5- [Constraints](#section5748426453)
6- [Usage](#section6370123616447)
7- [Repositories Involved](#section10492183517430)
8- [Reference](#section6808423133718)
9
10## Introduction<a name="section187321516154516"></a>
11
12The AI subsystem is the part of OpenHarmony that provides native distributed AI capabilities. At the heart of the subsystem is a unified AI engine framework, which implements quick integration of AI algorithm plug-ins. The framework consists of the plug-in management, module management, and communication management modules, fulfilling lifecycle management and on-demand deployment of AI algorithms. Under this framework, AI algorithm APIs will be standardized to facilitate distributed calling of AI capabilities. In addition, unified inference APIs will be provided to adapt to different inference framework hierarchies.
13
14**Figure 1** AI engine framework<a name="fig17296164711526"></a>
15![](figures/ai-engine-framework.png "ai-engine-framework")
16
17## Directory Structure<a name="section571610913453"></a>
18
19```
20/foundation/ai/engine # Home directory of the AI subsystem
21├── interfaces
22│ └── kits # External APIs of the AI subsystem
23└── services
24│ ├── client # Client module of the AI subsystem
25│ │ ├── client_executor # Executor of the client module
26│ │ └── communication_adapter # Communication adaptation layer for the client module, with extension supported
27│ ├── common # Common tools and protocol modules of the AI subsystem
28│ │ ├── platform
29│ │ ├── protocol
30│ │ └── utils
31│ └── server # Server module of the AI subsystem
32│ │ ├── communication_adapter # Communication adaptation layer for the server module, with extension supported
33│ │ ├── plugin
34│ │ ├── asr
35│ │ └── keyword_spotting # ASR algorithm plug-in reference: keyword spotting
36│ │ └── cv
37│ │ └── image_classification # CV algorithm plug-in reference: image classification
38│ │ ├── plugin_manager
39│ │ └── server_executor # Executor of the server module
40```
41
42## Constraints<a name="section5748426453"></a>
43
44**Programming language**: C/C++
45
46**Operating system**: OpenHarmony
47
48**Others**: The System Ability Manager \(Samgr\) has been started and is running properly.
49
50## Usage<a name="section6370123616447"></a>
51
521. Compile the AI subsystem.
53
54 The source code for lightweight AI framework is available at **//foundation/ai/engine/services**.
55
56 The compilation procedure is as follows:
57
58 1. Set the compilation path.
59
60 ```
61 hb set -root dir (root dir is the root directory of the project code.)
62 ```
63
64 2. Specify the product for compilation. \(After the product list is displayed using the following command, move to the desired product with arrow keys and press **Enter**.\)
65
66 ```
67 hb set -p
68 ```
69
70 3. Start compilation.
71
72 ```
73 hb build -f (Use this command if you want to compile the entire repository.)
74 hb build ai_engine (Use this command if you want to compile only the ai_engine module.)
75 ```
76
77 **Note**: For details about the hb configuration, see the readme of the build\_lite subsystem.
78
792. Develop the plug-in, with keyword spotting as an example.
80
81 Directory: //foundation/ai/engine/services/server/plugin/asr/keyword\_spotting
82
83 **Note**: The plug-in must implement the **IPlugin** and **IPluginCallback** APIs provided by the server.
84
85 ```
86 #include "plugin/i_plugin.h
87 class KWSPlugin : public IPlugin { # Inherits the public base class of the IPlugin API for Keywords Spotting Plugin (KWSPlugin).
88 KWSPlugin();
89 ~KWSPlugin();
90
91 const long long GetVersion() const override;
92 const char* GetName() const override;
93 const char* GetInferMode() const override;
94
95 int32_t Prepare(long long transactionId, const DataInfo &amp;inputInfo, DataInfo &amp;outputInfo) override;
96 int32_t SetOption(int optionType, const DataInfo &amp;inputInfo) override;
97 int32_t GetOption(int optionType, const DataInfo &amp;inputInfo, DataInfo &amp;outputInfo) override;
98 int32_t SyncProcess(IRequest *request, IResponse *&amp;response) override;
99 int32_t AsyncProcess(IRequest *request, IPluginCallback*callback) override;
100 int32_t Release(bool isFullUnload, long long transactionId, const DataInfo &amp;inputInfo) override;
101 .
102 .
103 .
104 };
105 ```
106
107 **Note**: Depending on the algorithm in use, you only need to implement the **SyncProcess** or **AsyncProcess** API. Use an empty function as a placeholder for the other API. In this example, the KWS plug-in uses the synchronous algorithm. Therefore, you need to implement **SyncProcess** API and use an empty function as a placeholder for the **SyncProcess** API.
108
109 ```
110 #include "aie_log.h"
111 #include "aie_retcode_inner.h"
112 .
113 .
114 .
115
116 const long long KWSPlugin::GetVersion() const
117 {
118 return ALGOTYPE_VERSION_KWS;
119 }
120
121 const char *KWSPlugin::GetName() const
122 {
123 return ALGORITHM_NAME_KWS.c_str();
124 }
125
126 const char *KWSPlugin::GetInferMode() const
127 {
128 return DEFAULT_INFER_MODE.c_str();
129 }
130 .
131 .
132 .
133 int32_t KWSPlugin::AsyncProcess(IRequest *request, IPluginCallback *callback)
134 {
135 return RETCODE_SUCCESS;
136 }
137 ```
138
1393. Develop the SDK, with keyword spotting as an example.
140
141 Directory: //foundation/ai/engine/services/client/algorithm\_sdk/asr/keyword\_spotting
142
143 Keyword spotting SDK:
144
145 ```
146 class KWSSdk {
147 public:
148 KWSSdk();
149 virtual ~KWSSdk();
150
151 /**
152 * @brief Create a new session with KWS Plugin
153 *
154 * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
155 * returns a non-zero value otherwise.
156 */
157 int32_t Create();
158
159 /**
160 * @brief Synchronously execute keyword spotting once
161 *
162 * @param audioInput pcm data.
163 * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
164 * returns a non-zero value otherwise.
165 */
166 int32_t SyncExecute(const Array<int16_t> &audioInput);
167
168 /**
169 * @brief Asynchronously execute keyword spotting once
170 *
171 * @param audioInput pcm data.
172 * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
173 * returns a non-zero value otherwise.
174 */
175 int32_t AsyncExecute(const Array<int16_t> &audioInput);
176
177 /**
178 * @brief Set callback
179 *
180 * @param callback Callback function that will be called during the process.
181 * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
182 * returns a non-zero value otherwise.
183 */
184 int32_t SetCallback(const std::shared_ptr<KWSCallback> &callback);
185
186 /**
187 * @brief Destroy the created session with KWS Plugin
188 *
189 * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
190 * returns a non-zero value otherwise.
191 */
192 int32_t Destroy();
193 ```
194
195 **Note**: The sequence for the SDK to call client APIs of the AI engine is as follows: AieClientInit -\> AieClientPrepare -\> AieClientSyncProcess/AieClientAsyncProcess -\> AieClientRelease -\> AieClientDestroy. An exception will be thrown if the call sequence is violated. In addition, all these APIs must be called. Otherwise, a memory leakage may occur.
196
197 ```
198 int32_t KWSSdk::KWSSdkImpl::Create()
199 {
200 if (kwsHandle_ != INVALID_KWS_HANDLE) {
201 HILOGE("[KWSSdkImpl]The SDK has been created");
202 return KWS_RETCODE_FAILURE;
203 }
204 if (InitComponents() != RETCODE_SUCCESS) {
205 HILOGE("[KWSSdkImpl]Fail to init sdk components");
206 return KWS_RETCODE_FAILURE;
207 }
208 int32_t retCode = AieClientInit(configInfo_, clientInfo_, algorithmInfo_, nullptr);
209 if (retCode != RETCODE_SUCCESS) {
210 HILOGE("[KWSSdkImpl]AieClientInit failed. Error code[%d]", retCode);
211 return KWS_RETCODE_FAILURE;
212 }
213 if (clientInfo_.clientId == INVALID_CLIENT_ID) {
214 HILOGE("[KWSSdkImpl]Fail to allocate client id");
215 return KWS_RETCODE_FAILURE;
216 }
217 DataInfo inputInfo = {
218 .data = nullptr,
219 .length = 0,
220 };
221 DataInfo outputInfo = {
222 .data = nullptr,
223 .length = 0,
224 };
225 retCode = AieClientPrepare(clientInfo_, algorithmInfo_, inputInfo, outputInfo, nullptr);
226 if (retCode != RETCODE_SUCCESS) {
227 HILOGE("[KWSSdkImpl]AieclientPrepare failed. Error code[%d]", retCode);
228 return KWS_RETCODE_FAILURE;
229 }
230 if (outputInfo.data == nullptr || outputInfo.length <= 0) {
231 HILOGE("[KWSSdkImpl]The data or length of output info is invalid");
232 return KWS_RETCODE_FAILURE;
233 }
234 MallocPointerGuard<unsigned char> pointerGuard(outputInfo.data);
235 retCode = PluginHelper::UnSerializeHandle(outputInfo, kwsHandle_);
236 if (retCode != RETCODE_SUCCESS) {
237 HILOGE("[KWSSdkImpl]Get handle from inputInfo failed");
238 return KWS_RETCODE_FAILURE;
239 }
240 return KWS_RETCODE_SUCCESS;
241 }
242
243 int32_t KWSSdk::KWSSdkImpl::SyncExecute(const Array<uint16_t> &audioInput)
244 {
245 intptr_t newHandle = 0;
246 Array<int32_t> kwsResult = {
247 .data = nullptr,
248 .size = 0
249 };
250 DataInfo inputInfo = {
251 .data = nullptr,
252 .length = 0
253 };
254 DataInfo outputInfo = {
255 .data = nullptr,
256 .length = 0
257 };
258 int32_t retCode = PluginHelper::SerializeInputData(kwsHandle_, audioInput, inputInfo);
259 if (retCode != RETCODE_SUCCESS) {
260 HILOGE("[KWSSdkImpl]Fail to serialize input data");
261 callback_->OnError(KWS_RETCODE_SERIALIZATION_ERROR);
262 return RETCODE_FAILURE;
263 }
264 retCode = AieClientSyncProcess(clientInfo_, algorithmInfo_, inputInfo, outputInfo);
265 if (retCode != RETCODE_SUCCESS) {
266 HILOGE("[KWSSdkImpl]AieClientSyncProcess failed. Error code[%d]", retCode);
267 callback_->OnError(KWS_RETCODE_PLUGIN_EXECUTION_ERROR);
268 return RETCODE_FAILURE;
269 }
270 if (outputInfo.data == nullptr || outputInfo.length <= 0) {
271 HILOGE("[KWSSdkImpl] The data or length of outputInfo is invalid. Error code[%d]", retCode);
272 callback_->OnError(KWS_RETCODE_NULL_PARAM);
273 return RETCODE_FAILURE;
274 }
275 MallocPointerGuard<unsigned char> pointerGuard(outputInfo.data);
276 retCode = PluginHelper::UnSerializeOutputData(outputInfo, newHandle, kwsResult);
277 if (retCode != RETCODE_SUCCESS) {
278 HILOGE("[KWSSdkImpl]UnSerializeOutputData failed. Error code[%d]", retCode);
279 callback_->OnError(KWS_RETCODE_UNSERIALIZATION_ERROR);
280 return retCode;
281 }
282 if (kwsHandle_ != newHandle) {
283 HILOGE("[KWSSdkImpl]The handle[%lld] of output data is not equal to the current handle[%lld]",
284 (long long)newHandle, (long long)kwsHandle_);
285 callback_->OnError(KWS_RETCODE_PLUGIN_SESSION_ERROR);
286 return RETCODE_FAILURE;
287 }
288 callback_->OnResult(kwsResult);
289 return RETCODE_SUCCESS;
290 }
291
292 int32_t KWSSdk::KWSSdkImpl::Destroy()
293 {
294 if (kwsHandle_ == INVALID_KWS_HANDLE) {
295 return KWS_RETCODE_SUCCESS;
296 }
297 DataInfo inputInfo = {
298 .data = nullptr,
299 .length = 0
300 };
301 int32_t retCode = PluginHelper::SerializeHandle(kwsHandle_, inputInfo);
302 if (retCode != RETCODE_SUCCESS) {
303 HILOGE("[KWSSdkImpl]SerializeHandle failed. Error code[%d]", retCode);
304 return KWS_RETCODE_FAILURE;
305 }
306 retCode = AieClientRelease(clientInfo_, algorithmInfo_, inputInfo);
307 if (retCode != RETCODE_SUCCESS) {
308 HILOGE("[KWSSdkImpl]AieClientRelease failed. Error code[%d]", retCode);
309 return KWS_RETCODE_FAILURE;
310 }
311 retCode = AieClientDestroy(clientInfo_);
312 if (retCode != RETCODE_SUCCESS) {
313 HILOGE("[KWSSdkImpl]AieClientDestroy failed. Error code[%d]", retCode);
314 return KWS_RETCODE_FAILURE;
315 }
316 mfccProcessor_ = nullptr;
317 pcmIterator_ = nullptr;
318 callback_ = nullptr;
319 kwsHandle_ = INVALID_KWS_HANDLE;
320 return KWS_RETCODE_SUCCESS;
321 }
322 ```
323
3244. **Sample development** \(similar to keyword spotting\)
325
326 Directory: //applications/sample/camera/ai/asr/keyword\_spotting
327
328 Call the **Create** API.
329
330 ```
331 bool KwsManager::PreparedInference()
332 {
333 if (capturer_ == nullptr) {
334 printf("[KwsManager] only load plugin after AudioCapturer ready\n");
335 return false;
336 }
337 if (plugin_ != nullptr) {
338 printf("[KwsManager] stop created InferencePlugin at first\n");
339 StopInference();
340 }
341 plugin_ = std::make_shared<KWSSdk>();
342 if (plugin_ == nullptr) {
343 printf("[KwsManager] fail to create inferencePlugin\n");
344 return false;
345 }
346 if (plugin_->Create() != SUCCESS) {
347 printf("[KwsManager] KWSSdk fail to create.\n");
348 return false;
349 }
350 std::shared_ptr<KWSCallback> callback = std::make_shared<MyKwsCallback>();
351 if (callback == nullptr) {
352 printf("[KwsManager] new Callback failed.\n");
353 return false;
354 }
355 plugin_->SetCallback(callback);
356 return true;
357 }
358 ```
359
360 Call the **SyncExecute** API.
361
362 ```
363 void KwsManager::ConsumeSamples()
364 {
365 uintptr_t sampleAddr = 0;
366 size_t sampleSize = 0;
367 int32_t retCode = SUCCESS;
368 while (status_ == RUNNING) {
369 {
370 std::lock_guard<std::mutex> lock(mutex_);
371 if (cache_ == nullptr) {
372 printf("[KwsManager] cache_ is nullptr.\n");
373 break;
374 }
375 sampleSize = cache_->GetCapturedBuffer(sampleAddr);
376 }
377 if (sampleSize == 0 || sampleAddr == 0) {
378 continue;
379 }
380 Array<int16_t> input = {
381 .data = (int16_t *)(sampleAddr),
382 .size = sampleSize >> 1
383 };
384 {
385 std::lock_guard<std::mutex> lock(mutex_);
386 if (plugin_ == nullptr) {
387 printf("[KwsManager] cache_ is nullptr.\n");
388 break;
389 }
390 if ((retCode = plugin_->SyncExecute(input)) != SUCCESS) {
391 printf("[KwsManager] SyncExecute KWS failed with retCode = [%d]\n", retCode);
392 continue;
393 }
394 }
395 }
396 }
397 ```
398
399 Call the **Destroy** API.
400
401 ```
402 void KwsManager::StopInference()
403 {
404 printf("[KwsManager] StopInference\n");
405 if (plugin_ != nullptr) {
406 int ret = plugin_->Destroy();
407 if (ret != SUCCESS) {
408 printf("[KwsManager] plugin_ destroy failed.\n");
409 }
410 plugin_ = nullptr;
411 }
412 }
413 ```
414
415
416## Repositories Involved<a name="section10492183517430"></a>
417
418[AI subsystem](https://gitee.com/openharmony/docs/blob/master/en/readme/ai.md)
419
420**ai\_engine**
421
422Dependency repositories:
423
424[build\_lite](https://gitee.com/openharmony/build_lite/blob/master/README.md)
425
426[distributedschedule\_samgr\_lite](https://gitee.com/openharmony/distributedschedule_samgr_lite/blob/master/README.md)
427
428[startup\_init\_lite](https://gitee.com/openharmony/startup_init_lite/blob/master/README.md)
429
430## Reference<a name="section6808423133718"></a>
431
432- [AI Engine Framework Development Guide](https://gitee.com/openharmony/docs/blob/master/en/device-dev/subsystems/development-examples.md)
433
README_zh.md
1# AI业务子系统<a name="ZH-CN_TOPIC_0000001072614474"></a>
2
3- [简介](#section187321516154516)
4- [目录](#section571610913453)
5- [约束](#section5748426453)
6- [使用](#section6370123616447)
7- [涉及仓](#section10492183517430)
8- [AI引擎开发导航](#section6808423133718)
9
10## 简介<a name="section187321516154516"></a>
11
12AI业务子系统是OpenHarmony提供原生的分布式AI能力的子系统。本次开源范围是提供了统一的AI引擎框架,实现算法能力快速插件化集成。框架中主要包含插件管理、模块管理和通信管理等模块,对AI算法能力进行生命周期管理和按需部署。后续,会逐步定义统一的AI能力接口,便于AI能力的分布式调用。同时,提供适配不同推理框架层级的统一推理接口。
13
14**图 1** AI引擎框架<a name="fig17296164711526"></a>
15![](figures/AI引擎框架.png "AI引擎框架")
16
17## 目录<a name="section571610913453"></a>
18
19```
20/foundation/ai/engine # AI子系统主目录
21├── interfaces
22│ └── kits # AI子系统对外接口
23└── services
24│ ├── client # AI子系统Client模块
25│ │ ├── client_executor # Client模块执行主体
26│ │ └── communication_adapter # Client模块通信适配层,支持拓展
27│ ├── common # AI子系统公共工具、协议模块
28│ │ ├── platform
29│ │ ├── protocol
30│ │ └── utils
31│ └── server # AI子系统服务端模块
32│ │ ├── communication_adapter # Server模块通信适配层,支持拓展
33│ │ ├── plugin
34│ │ ├── asr
35│ │ └── keyword_spotting # ASR算法插件参考:唤醒词识别
36│ │ └── cv
37│ │ └── image_classification # CV算法插件参考:图片分类
38│ │ ├── plugin_manager
39│ │ └── server_executor # Server模块执行主体
40```
41
42## 约束<a name="section5748426453"></a>
43
44**语言限制**:C/C++语言
45
46**操作系统限制**:OpenHarmony操作系统
47
48**AI服务启动的约束与限制**:SAMGR(System Ability Manager)启动且运行正常
49
50## 使用<a name="section6370123616447"></a>
51
521. **AI业务子系统编译**
53
54 轻量级AI引擎框架模块,代码所在路径://foundation/ai/engine/services
55
56 编译指令如下:
57
58 **设置编译路径**
59
60 ```
61 hb set -root dir(项目代码根目录)
62 ```
63
64 **设置编译产品**(执行后用方向键和回车进行选择):
65
66 ```
67 hb set -p
68 ```
69
70 **执行编译**:
71
72 ```
73 hb build -f(编译全仓)
74 或者 hb build ai_engine(只编译ai_engine组件)
75 ```
76
77 **注意**:hb相关配置请参考编译构建子系统**build\_lite**
78
792. **插件开发**(以唤醒词识别为例)
80
81 位置://foundation/ai/engine/services/server/plugin/asr/keyword\_spotting
82
83 **注意**:插件需要实现server提供的IPlugin接口和IPluginCallback接口
84
85 ```
86 #include "plugin/i_plugin.h
87 class KWSPlugin : public IPlugin { # Keywords Spotting Plugin(KWSPlugin)继承IPlugin算法插件基类public:
88 KWSPlugin();
89 ~KWSPlugin();
90
91 const long long GetVersion() const override;
92 const char* GetName() const override;
93 const char* GetInferMode() const override;
94
95 int32_t Prepare(long long transactionId, const DataInfo &amp;inputInfo, DataInfo &amp;outputInfo) override;
96 int32_t SetOption(int optionType, const DataInfo &amp;inputInfo) override;
97 int32_t GetOption(int optionType, const DataInfo &amp;inputInfo, DataInfo &amp;outputInfo) override;
98 int32_t SyncProcess(IRequest *request, IResponse *&amp;response) override;
99 int32_t AsyncProcess(IRequest *request, IPluginCallback*callback) override;
100 int32_t Release(bool isFullUnload, long long transactionId, const DataInfo &amp;inputInfo) override;
101 .
102 .
103 .
104 };
105 ```
106
107 **注意**:SyncProcess和AsyncProcess接口只需要根据算法实际情况实现一个接口即可,另一个用空方法占位(这里KWS插件为同步算法,故异步接口为空实现)。
108
109 ```
110 #include "aie_log.h"
111 #include "aie_retcode_inner.h"
112 .
113 .
114 .
115
116 const long long KWSPlugin::GetVersion() const
117 {
118 return ALGOTYPE_VERSION_KWS;
119 }
120
121 const char *KWSPlugin::GetName() const
122 {
123 return ALGORITHM_NAME_KWS.c_str();
124 }
125
126 const char *KWSPlugin::GetInferMode() const
127 {
128 return DEFAULT_INFER_MODE.c_str();
129 }
130 .
131 .
132 .
133 int32_t KWSPlugin::AsyncProcess(IRequest *request, IPluginCallback *callback)
134 {
135 return RETCODE_SUCCESS;
136 }
137 ```
138
1393. **插件SDK开发**(以唤醒词识别kws\_sdk为例)
140
141 位置://foundation/ai/engine/services/client/algorithm\_sdk/asr/keyword\_spotting
142
143 唤醒词识别SDK:
144
145 ```
146 class KWSSdk {
147 public:
148 KWSSdk();
149 virtual ~KWSSdk();
150
151 /**
152 * @brief Create a new session with KWS Plugin
153 *
154 * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
155 * returns a non-zero value otherwise.
156 */
157 int32_t Create();
158
159 /**
160 * @brief Synchronously execute keyword spotting once
161 *
162 * @param audioInput pcm data.
163 * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
164 * returns a non-zero value otherwise.
165 */
166 int32_t SyncExecute(const Array<int16_t> &audioInput);
167
168 /**
169 * @brief Asynchronously execute keyword spotting once
170 *
171 * @param audioInput pcm data.
172 * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
173 * returns a non-zero value otherwise.
174 */
175 int32_t AsyncExecute(const Array<int16_t> &audioInput);
176
177 /**
178 * @brief Set callback
179 *
180 * @param callback Callback function that will be called during the process.
181 * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
182 * returns a non-zero value otherwise.
183 */
184 int32_t SetCallback(const std::shared_ptr<KWSCallback> &callback);
185
186 /**
187 * @brief Destroy the created session with KWS Plugin
188 *
189 * @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
190 * returns a non-zero value otherwise.
191 */
192 int32_t Destroy();
193 ```
194
195 **注意**:SDK调用AI引擎客户端接口顺序应遵循AieClientInit-\>AieClientPrepare-\>AieClientSyncProcess/AieClientAsyncProcess-\>AieClientRelease-\>AieClientDestroy,否则调用接口会返回错误码;同时应保证各个接口都有调用到,要不然会引起内存泄漏。
196
197 ```
198 int32_t KWSSdk::KWSSdkImpl::Create()
199 {
200 if (kwsHandle_ != INVALID_KWS_HANDLE) {
201 HILOGE("[KWSSdkImpl]The SDK has been created");
202 return KWS_RETCODE_FAILURE;
203 }
204 if (InitComponents() != RETCODE_SUCCESS) {
205 HILOGE("[KWSSdkImpl]Fail to init sdk components");
206 return KWS_RETCODE_FAILURE;
207 }
208 int32_t retCode = AieClientInit(configInfo_, clientInfo_, algorithmInfo_, nullptr);
209 if (retCode != RETCODE_SUCCESS) {
210 HILOGE("[KWSSdkImpl]AieClientInit failed. Error code[%d]", retCode);
211 return KWS_RETCODE_FAILURE;
212 }
213 if (clientInfo_.clientId == INVALID_CLIENT_ID) {
214 HILOGE("[KWSSdkImpl]Fail to allocate client id");
215 return KWS_RETCODE_FAILURE;
216 }
217 DataInfo inputInfo = {
218 .data = nullptr,
219 .length = 0,
220 };
221 DataInfo outputInfo = {
222 .data = nullptr,
223 .length = 0,
224 };
225 retCode = AieClientPrepare(clientInfo_, algorithmInfo_, inputInfo, outputInfo, nullptr);
226 if (retCode != RETCODE_SUCCESS) {
227 HILOGE("[KWSSdkImpl]AieclientPrepare failed. Error code[%d]", retCode);
228 return KWS_RETCODE_FAILURE;
229 }
230 if (outputInfo.data == nullptr || outputInfo.length <= 0) {
231 HILOGE("[KWSSdkImpl]The data or length of output info is invalid");
232 return KWS_RETCODE_FAILURE;
233 }
234 MallocPointerGuard<unsigned char> pointerGuard(outputInfo.data);
235 retCode = PluginHelper::UnSerializeHandle(outputInfo, kwsHandle_);
236 if (retCode != RETCODE_SUCCESS) {
237 HILOGE("[KWSSdkImpl]Get handle from inputInfo failed");
238 return KWS_RETCODE_FAILURE;
239 }
240 return KWS_RETCODE_SUCCESS;
241 }
242
243 int32_t KWSSdk::KWSSdkImpl::SyncExecute(const Array<uint16_t> &audioInput)
244 {
245 intptr_t newHandle = 0;
246 Array<int32_t> kwsResult = {
247 .data = nullptr,
248 .size = 0
249 };
250 DataInfo inputInfo = {
251 .data = nullptr,
252 .length = 0
253 };
254 DataInfo outputInfo = {
255 .data = nullptr,
256 .length = 0
257 };
258 int32_t retCode = PluginHelper::SerializeInputData(kwsHandle_, audioInput, inputInfo);
259 if (retCode != RETCODE_SUCCESS) {
260 HILOGE("[KWSSdkImpl]Fail to serialize input data");
261 callback_->OnError(KWS_RETCODE_SERIALIZATION_ERROR);
262 return RETCODE_FAILURE;
263 }
264 retCode = AieClientSyncProcess(clientInfo_, algorithmInfo_, inputInfo, outputInfo);
265 if (retCode != RETCODE_SUCCESS) {
266 HILOGE("[KWSSdkImpl]AieClientSyncProcess failed. Error code[%d]", retCode);
267 callback_->OnError(KWS_RETCODE_PLUGIN_EXECUTION_ERROR);
268 return RETCODE_FAILURE;
269 }
270 if (outputInfo.data == nullptr || outputInfo.length <= 0) {
271 HILOGE("[KWSSdkImpl] The data or length of outputInfo is invalid. Error code[%d]", retCode);
272 callback_->OnError(KWS_RETCODE_NULL_PARAM);
273 return RETCODE_FAILURE;
274 }
275 MallocPointerGuard<unsigned char> pointerGuard(outputInfo.data);
276 retCode = PluginHelper::UnSerializeOutputData(outputInfo, newHandle, kwsResult);
277 if (retCode != RETCODE_SUCCESS) {
278 HILOGE("[KWSSdkImpl]UnSerializeOutputData failed. Error code[%d]", retCode);
279 callback_->OnError(KWS_RETCODE_UNSERIALIZATION_ERROR);
280 return retCode;
281 }
282 if (kwsHandle_ != newHandle) {
283 HILOGE("[KWSSdkImpl]The handle[%lld] of output data is not equal to the current handle[%lld]",
284 (long long)newHandle, (long long)kwsHandle_);
285 callback_->OnError(KWS_RETCODE_PLUGIN_SESSION_ERROR);
286 return RETCODE_FAILURE;
287 }
288 callback_->OnResult(kwsResult);
289 return RETCODE_SUCCESS;
290 }
291
292 int32_t KWSSdk::KWSSdkImpl::Destroy()
293 {
294 if (kwsHandle_ == INVALID_KWS_HANDLE) {
295 return KWS_RETCODE_SUCCESS;
296 }
297 DataInfo inputInfo = {
298 .data = nullptr,
299 .length = 0
300 };
301 int32_t retCode = PluginHelper::SerializeHandle(kwsHandle_, inputInfo);
302 if (retCode != RETCODE_SUCCESS) {
303 HILOGE("[KWSSdkImpl]SerializeHandle failed. Error code[%d]", retCode);
304 return KWS_RETCODE_FAILURE;
305 }
306 retCode = AieClientRelease(clientInfo_, algorithmInfo_, inputInfo);
307 if (retCode != RETCODE_SUCCESS) {
308 HILOGE("[KWSSdkImpl]AieClientRelease failed. Error code[%d]", retCode);
309 return KWS_RETCODE_FAILURE;
310 }
311 retCode = AieClientDestroy(clientInfo_);
312 if (retCode != RETCODE_SUCCESS) {
313 HILOGE("[KWSSdkImpl]AieClientDestroy failed. Error code[%d]", retCode);
314 return KWS_RETCODE_FAILURE;
315 }
316 mfccProcessor_ = nullptr;
317 pcmIterator_ = nullptr;
318 callback_ = nullptr;
319 kwsHandle_ = INVALID_KWS_HANDLE;
320 return KWS_RETCODE_SUCCESS;
321 }
322 ```
323
3244. **sample开发**(参考唤醒词识别demo)
325
326 位置://applications/sample/camera/ai/asr/keyword\_spotting
327
328 **调用Create**
329
330 ```
331 bool KwsManager::PreparedInference()
332 {
333 if (capturer_ == nullptr) {
334 printf("[KwsManager] only load plugin after AudioCapturer ready\n");
335 return false;
336 }
337 if (plugin_ != nullptr) {
338 printf("[KwsManager] stop created InferencePlugin at first\n");
339 StopInference();
340 }
341 plugin_ = std::make_shared<KWSSdk>();
342 if (plugin_ == nullptr) {
343 printf("[KwsManager] fail to create inferencePlugin\n");
344 return false;
345 }
346 if (plugin_->Create() != SUCCESS) {
347 printf("[KwsManager] KWSSdk fail to create.\n");
348 return false;
349 }
350 std::shared_ptr<KWSCallback> callback = std::make_shared<MyKwsCallback>();
351 if (callback == nullptr) {
352 printf("[KwsManager] new Callback failed.\n");
353 return false;
354 }
355 plugin_->SetCallback(callback);
356 return true;
357 }
358 ```
359
360 **调用SyncExecute**
361
362 ```
363 void KwsManager::ConsumeSamples()
364 {
365 uintptr_t sampleAddr = 0;
366 size_t sampleSize = 0;
367 int32_t retCode = SUCCESS;
368 while (status_ == RUNNING) {
369 {
370 std::lock_guard<std::mutex> lock(mutex_);
371 if (cache_ == nullptr) {
372 printf("[KwsManager] cache_ is nullptr.\n");
373 break;
374 }
375 sampleSize = cache_->GetCapturedBuffer(sampleAddr);
376 }
377 if (sampleSize == 0 || sampleAddr == 0) {
378 continue;
379 }
380 Array<int16_t> input = {
381 .data = (int16_t *)(sampleAddr),
382 .size = sampleSize >> 1
383 };
384 {
385 std::lock_guard<std::mutex> lock(mutex_);
386 if (plugin_ == nullptr) {
387 printf("[KwsManager] cache_ is nullptr.\n");
388 break;
389 }
390 if ((retCode = plugin_->SyncExecute(input)) != SUCCESS) {
391 printf("[KwsManager] SyncExecute KWS failed with retCode = [%d]\n", retCode);
392 continue;
393 }
394 }
395 }
396 }
397 ```
398
399 **调用Destroy**
400
401 ```
402 void KwsManager::StopInference()
403 {
404 printf("[KwsManager] StopInference\n");
405 if (plugin_ != nullptr) {
406 int ret = plugin_->Destroy();
407 if (ret != SUCCESS) {
408 printf("[KwsManager] plugin_ destroy failed.\n");
409 }
410 plugin_ = nullptr;
411 }
412 }
413 ```
414
415
416## 涉及仓<a name="section10492183517430"></a>
417
418[AI子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/AI%E4%B8%9A%E5%8A%A1%E5%AD%90%E7%B3%BB%E7%BB%9F.md)
419
420**ai\_engine**
421
422依赖仓:
423
424[build\_lite](https://gitee.com/openharmony/build_lite/blob/master/README_zh.md)
425
426[distributedschedule\_samgr\_lite](https://gitee.com/openharmony/distributedschedule_samgr_lite/blob/master/README_zh.md)
427
428[startup\_init\_lite](https://gitee.com/openharmony/startup_init_lite/blob/master/README_zh.md)
429
430## AI引擎开发导航<a name="section6808423133718"></a>
431
432- [《AI插件开发指南》](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/%E5%BC%80%E5%8F%91%E7%A4%BA%E4%BE%8B.md)
433
434
435