提交 785da043 编写于 作者: O openharmony_ci 提交者: Gitee

!746 添加ai业务子系统.md和ai.md文件

Merge pull request !746 from maoqian/master
# AI<a name="EN-US_TOPIC_0000001087226912"></a>
- [Introduction](#section187321516154516)
- [Directory Structure](#section571610913453)
- [Constraints](#section5748426453)
- [Usage](#section6370123616447)
- [Repositories Involved](#section10492183517430)
- [Reference](#section6808423133718)
## Introduction<a name="section187321516154516"></a>
The 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.
**Figure 1** AI engine framework<a name="fig17296164711526"></a>
![](figures/ai-engine-framework.png "ai-engine-framework")
## Directory Structure<a name="section571610913453"></a>
```
/foundation/ai/engine # Home directory of the AI subsystem
├── interfaces
│ └── kits # External APIs of the AI subsystem
└── services
│ ├── client # Client module of the AI subsystem
│ │ ├── client_executor # Executor of the client module
│ │ └── communication_adapter # Communication adaptation layer for the client module, with extension supported
│ ├── common # Common tools and protocol modules of the AI subsystem
│ │ ├── platform
│ │ ├── protocol
│ │ └── utils
│ └── server # Server module of the AI subsystem
│ │ ├── communication_adapter # Communication adaptation layer for the server module, with extension supported
│ │ ├── plugin
│ │ ├── asr
│ │ └── keyword_spotting # ASR algorithm plug-in reference: keyword spotting
│ │ └── cv
│ │ └── image_classification # CV algorithm plug-in reference: image classification
│ │ ├── plugin_manager
│ │ └── server_executor # Executor of the server module
```
## Constraints<a name="section5748426453"></a>
* **Programming language**: C/C++
* **Operating system**: OpenHarmony
* **Others**: The System Ability Manager \(Samgr\) has been started and is running properly.
## Usage<a name="section6370123616447"></a>
1. Compile the AI subsystem.
The source code for lightweight AI framework is available at **//foundation/ai/engine/services**.
The compilation procedure is as follows:
1. Set the compilation path.
```
hb set -root dir (root dir is the root directory of the project code.)
```
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**.\)
```
hb set -p
```
3. Start compilation.
```
hb build -f (Use this command if you want to compile the entire repository.)
hb build ai_engine (Use this command if you want to compile only the ai_engine module.)
```
>**Note**: For details about the hb configuration, see the readme of the build\_lite subsystem.
2. Develop the plug-in, with keyword spotting as an example.
Directory: //foundation/ai/engine/services/server/plugin/asr/keyword\_spotting
>**Note**: The plug-in must implement the **IPlugin** and **IPluginCallback** APIs provided by the server.
```
#include "plugin/i_plugin.h
class KWSPlugin : public IPlugin { # Inherits the public base class of the IPlugin API for Keywords Spotting Plugin (KWSPlugin).
KWSPlugin();
~KWSPlugin();
const long long GetVersion() const override;
const char* GetName() const override;
const char* GetInferMode() const override;
int32_t Prepare(long long transactionId, const DataInfo &amp;amp;inputInfo, DataInfo &amp;amp;outputInfo) override;
int32_t SetOption(int optionType, const DataInfo &amp;amp;inputInfo) override;
int32_t GetOption(int optionType, const DataInfo &amp;amp;inputInfo, DataInfo &amp;amp;outputInfo) override;
int32_t SyncProcess(IRequest *request, IResponse *&amp;amp;response) override;
int32_t AsyncProcess(IRequest *request, IPluginCallback*callback) override;
int32_t Release(bool isFullUnload, long long transactionId, const DataInfo &amp;amp;inputInfo) override;
.
.
.
};
```
>**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.
```
#include "aie_log.h"
#include "aie_retcode_inner.h"
.
.
.
const long long KWSPlugin::GetVersion() const
{
return ALGOTYPE_VERSION_KWS;
}
const char *KWSPlugin::GetName() const
{
return ALGORITHM_NAME_KWS.c_str();
}
const char *KWSPlugin::GetInferMode() const
{
return DEFAULT_INFER_MODE.c_str();
}
.
.
.
int32_t KWSPlugin::AsyncProcess(IRequest *request, IPluginCallback *callback)
{
return RETCODE_SUCCESS;
}
```
3. Develop the SDK, with keyword spotting as an example.
Directory: //foundation/ai/engine/services/client/algorithm\_sdk/asr/keyword\_spotting
Keyword spotting SDK:
```
class KWSSdk {
public:
KWSSdk();
virtual ~KWSSdk();
/**
* @brief Create a new session with KWS Plugin
*
* @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
* returns a non-zero value otherwise.
*/
int32_t Create();
/**
* @brief Synchronously execute keyword spotting once
*
* @param audioInput pcm data.
* @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
* returns a non-zero value otherwise.
*/
int32_t SyncExecute(const Array<int16_t> &audioInput);
/**
* @brief Asynchronously execute keyword spotting once
*
* @param audioInput pcm data.
* @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
* returns a non-zero value otherwise.
*/
int32_t AsyncExecute(const Array<int16_t> &audioInput);
/**
* @brief Set callback
*
* @param callback Callback function that will be called during the process.
* @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
* returns a non-zero value otherwise.
*/
int32_t SetCallback(const std::shared_ptr<KWSCallback> &callback);
/**
* @brief Destroy the created session with KWS Plugin
*
* @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
* returns a non-zero value otherwise.
*/
int32_t Destroy();
```
>**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.
```
int32_t KWSSdk::KWSSdkImpl::Create()
{
if (kwsHandle_ != INVALID_KWS_HANDLE) {
HILOGE("[KWSSdkImpl]The SDK has been created");
return KWS_RETCODE_FAILURE;
}
if (InitComponents() != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]Fail to init sdk components");
return KWS_RETCODE_FAILURE;
}
int32_t retCode = AieClientInit(configInfo_, clientInfo_, algorithmInfo_, nullptr);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]AieClientInit failed. Error code[%d]", retCode);
return KWS_RETCODE_FAILURE;
}
if (clientInfo_.clientId == INVALID_CLIENT_ID) {
HILOGE("[KWSSdkImpl]Fail to allocate client id");
return KWS_RETCODE_FAILURE;
}
DataInfo inputInfo = {
.data = nullptr,
.length = 0,
};
DataInfo outputInfo = {
.data = nullptr,
.length = 0,
};
retCode = AieClientPrepare(clientInfo_, algorithmInfo_, inputInfo, outputInfo, nullptr);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]AieclientPrepare failed. Error code[%d]", retCode);
return KWS_RETCODE_FAILURE;
}
if (outputInfo.data == nullptr || outputInfo.length <= 0) {
HILOGE("[KWSSdkImpl]The data or length of output info is invalid");
return KWS_RETCODE_FAILURE;
}
MallocPointerGuard<unsigned char> pointerGuard(outputInfo.data);
retCode = PluginHelper::UnSerializeHandle(outputInfo, kwsHandle_);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]Get handle from inputInfo failed");
return KWS_RETCODE_FAILURE;
}
return KWS_RETCODE_SUCCESS;
}
int32_t KWSSdk::KWSSdkImpl::SyncExecute(const Array<uint16_t> &audioInput)
{
intptr_t newHandle = 0;
Array<int32_t> kwsResult = {
.data = nullptr,
.size = 0
};
DataInfo inputInfo = {
.data = nullptr,
.length = 0
};
DataInfo outputInfo = {
.data = nullptr,
.length = 0
};
int32_t retCode = PluginHelper::SerializeInputData(kwsHandle_, audioInput, inputInfo);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]Fail to serialize input data");
callback_->OnError(KWS_RETCODE_SERIALIZATION_ERROR);
return RETCODE_FAILURE;
}
retCode = AieClientSyncProcess(clientInfo_, algorithmInfo_, inputInfo, outputInfo);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]AieClientSyncProcess failed. Error code[%d]", retCode);
callback_->OnError(KWS_RETCODE_PLUGIN_EXECUTION_ERROR);
return RETCODE_FAILURE;
}
if (outputInfo.data == nullptr || outputInfo.length <= 0) {
HILOGE("[KWSSdkImpl] The data or length of outputInfo is invalid. Error code[%d]", retCode);
callback_->OnError(KWS_RETCODE_NULL_PARAM);
return RETCODE_FAILURE;
}
MallocPointerGuard<unsigned char> pointerGuard(outputInfo.data);
retCode = PluginHelper::UnSerializeOutputData(outputInfo, newHandle, kwsResult);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]UnSerializeOutputData failed. Error code[%d]", retCode);
callback_->OnError(KWS_RETCODE_UNSERIALIZATION_ERROR);
return retCode;
}
if (kwsHandle_ != newHandle) {
HILOGE("[KWSSdkImpl]The handle[%lld] of output data is not equal to the current handle[%lld]",
(long long)newHandle, (long long)kwsHandle_);
callback_->OnError(KWS_RETCODE_PLUGIN_SESSION_ERROR);
return RETCODE_FAILURE;
}
callback_->OnResult(kwsResult);
return RETCODE_SUCCESS;
}
int32_t KWSSdk::KWSSdkImpl::Destroy()
{
if (kwsHandle_ == INVALID_KWS_HANDLE) {
return KWS_RETCODE_SUCCESS;
}
DataInfo inputInfo = {
.data = nullptr,
.length = 0
};
int32_t retCode = PluginHelper::SerializeHandle(kwsHandle_, inputInfo);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]SerializeHandle failed. Error code[%d]", retCode);
return KWS_RETCODE_FAILURE;
}
retCode = AieClientRelease(clientInfo_, algorithmInfo_, inputInfo);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]AieClientRelease failed. Error code[%d]", retCode);
return KWS_RETCODE_FAILURE;
}
retCode = AieClientDestroy(clientInfo_);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]AieClientDestroy failed. Error code[%d]", retCode);
return KWS_RETCODE_FAILURE;
}
mfccProcessor_ = nullptr;
pcmIterator_ = nullptr;
callback_ = nullptr;
kwsHandle_ = INVALID_KWS_HANDLE;
return KWS_RETCODE_SUCCESS;
}
```
4. **Sample development** [\(similar to keyword spotting\)](https://gitee.com/openharmony/applications_sample_camera/tree/master/ai)
Directory: //applications/sample/camera/ai/asr/keyword\_spotting
Call the **Create** API.
```
bool KwsManager::PreparedInference()
{
if (capturer_ == nullptr) {
printf("[KwsManager] only load plugin after AudioCapturer ready\n");
return false;
}
if (plugin_ != nullptr) {
printf("[KwsManager] stop created InferencePlugin at first\n");
StopInference();
}
plugin_ = std::make_shared<KWSSdk>();
if (plugin_ == nullptr) {
printf("[KwsManager] fail to create inferencePlugin\n");
return false;
}
if (plugin_->Create() != SUCCESS) {
printf("[KwsManager] KWSSdk fail to create.\n");
return false;
}
std::shared_ptr<KWSCallback> callback = std::make_shared<MyKwsCallback>();
if (callback == nullptr) {
printf("[KwsManager] new Callback failed.\n");
return false;
}
plugin_->SetCallback(callback);
return true;
}
```
Call the **SyncExecute** API.
```
void KwsManager::ConsumeSamples()
{
uintptr_t sampleAddr = 0;
size_t sampleSize = 0;
int32_t retCode = SUCCESS;
while (status_ == RUNNING) {
{
std::lock_guard<std::mutex> lock(mutex_);
if (cache_ == nullptr) {
printf("[KwsManager] cache_ is nullptr.\n");
break;
}
sampleSize = cache_->GetCapturedBuffer(sampleAddr);
}
if (sampleSize == 0 || sampleAddr == 0) {
continue;
}
Array<int16_t> input = {
.data = (int16_t *)(sampleAddr),
.size = sampleSize >> 1
};
{
std::lock_guard<std::mutex> lock(mutex_);
if (plugin_ == nullptr) {
printf("[KwsManager] cache_ is nullptr.\n");
break;
}
if ((retCode = plugin_->SyncExecute(input)) != SUCCESS) {
printf("[KwsManager] SyncExecute KWS failed with retCode = [%d]\n", retCode);
continue;
}
}
}
}
```
Call the **Destroy** API.
```
void KwsManager::StopInference()
{
printf("[KwsManager] StopInference\n");
if (plugin_ != nullptr) {
int ret = plugin_->Destroy();
if (ret != SUCCESS) {
printf("[KwsManager] plugin_ destroy failed.\n");
}
plugin_ = nullptr;
}
}
```
## Repositories Involved<a name="section10492183517430"></a>
AI subsystem:
ai\_engine
Dependency repositories:
build\_lite
distributedschedule\_services\_samgr\_lite
startup\_init\_lite
## Reference<a name="section6808423133718"></a>
[AI Engine Framework Development Guide](https://gitee.com/openharmony/docs/blob/master/en/device-dev/subsystems/development-examples.md)
# AI业务子系统<a name="ZH-CN_TOPIC_0000001083278044"></a>
- [简介](#section187321516154516)
- [目录](#section571610913453)
- [约束](#section5748426453)
- [使用](#section7981135212144)
- [涉及仓](#section10492183517430)
- [AI引擎开发导航](#section6808423133718)
## 简介<a name="section187321516154516"></a>
AI业务子系统是OpenHarmony提供原生的分布式AI能力的子系统。本次开源范围是提供了统一的AI引擎框架,实现算法能力快速插件化集成。框架中主要包含插件管理、模块管理和通信管理等模块,对AI算法能力进行生命周期管理和按需部署。后续,会逐步定义统一的AI能力接口,便于AI能力的分布式调用。同时,提供适配不同推理框架层级的统一推理接口。
**图 1** AI引擎框架<a name="fig17296164711526"></a>
![](figures/AI引擎框架.png "AI引擎框架")
## 目录<a name="section571610913453"></a>
```
/foundation/ai/engine # AI子系统主目录
├── interfaces
│ └── kits # AI子系统对外接口
└── services
│ ├── client # AI子系统Client模块
│ │ ├── client_executor # Client模块执行主体
│ │ └── communication_adapter # Client模块通信适配层,支持拓展
│ ├── common # AI子系统公共工具、协议模块
│ │ ├── platform
│ │ ├── protocol
│ │ └── utils
│ └── server # AI子系统服务端模块
│ │ ├── communication_adapter # Server模块通信适配层,支持拓展
│ │ ├── plugin
│ │ ├── asr
│ │ └── keyword_spotting # ASR算法插件参考:唤醒词识别
│ │ └── cv
│ │ └── image_classification # CV算法插件参考:图片分类
│ │ ├── plugin_manager
│ │ └── server_executor # Server模块执行主体
```
## 约束<a name="section5748426453"></a>
* **语言限制**:C/C++语言
* **操作系统限制**:OpenHarmony操作系统
* **AI服务启动的约束与限制**:SAMGR(System Ability Manager)启动且运行正常
## 使用<a name="section7981135212144"></a>
1. **AI业务子系统编译**
轻量级AI引擎框架模块,代码所在路径://foundation/ai/engine/services
编译指令如下:
1. **设置编译路径**
```
hb set -root dir(项目代码根目录)
```
2. **设置编译产品**(执行后用方向键和回车进行选择):
```
hb set -p
```
3. **执行编译**:
```
hb build -f(编译全仓)
或者 hb build ai_engine(只编译ai_engine组件)
```
>**注意**:hb相关配置请参考编译构建子系统**build\_lite**
2. **插件开发**(以唤醒词识别为例)
位置://foundation/ai/engine/services/server/plugin/asr/keyword\_spotting
>**注意**:插件需要实现server提供的IPlugin接口和IPluginCallback接口
```
#include "plugin/i_plugin.h
class KWSPlugin : public IPlugin { # Keywords Spotting Plugin(KWSPlugin)继承IPlugin算法插件基类public:
KWSPlugin();
~KWSPlugin();
const long long GetVersion() const override;
const char* GetName() const override;
const char* GetInferMode() const override;
int32_t Prepare(long long transactionId, const DataInfo &amp;amp;inputInfo, DataInfo &amp;amp;outputInfo) override;
int32_t SetOption(int optionType, const DataInfo &amp;amp;inputInfo) override;
int32_t GetOption(int optionType, const DataInfo &amp;amp;inputInfo, DataInfo &amp;amp;outputInfo) override;
int32_t SyncProcess(IRequest *request, IResponse *&amp;amp;response) override;
int32_t AsyncProcess(IRequest *request, IPluginCallback*callback) override;
int32_t Release(bool isFullUnload, long long transactionId, const DataInfo &amp;amp;inputInfo) override;
.
.
.
};
```
>**注意**:SyncProcess和AsyncProcess接口只需要根据算法实际情况实现一个接口即可,另一个用空方法占位(这里KWS插件为同步算法,故异步接口为空实现)。
```
#include "aie_log.h"
#include "aie_retcode_inner.h"
.
.
.
const long long KWSPlugin::GetVersion() const
{
return ALGOTYPE_VERSION_KWS;
}
const char *KWSPlugin::GetName() const
{
return ALGORITHM_NAME_KWS.c_str();
}
const char *KWSPlugin::GetInferMode() const
{
return DEFAULT_INFER_MODE.c_str();
}
.
.
.
int32_t KWSPlugin::AsyncProcess(IRequest *request, IPluginCallback *callback)
{
return RETCODE_SUCCESS;
}
```
3. **插件SDK开发**(以唤醒词识别kws\_sdk为例)
位置://foundation/ai/engine/services/client/algorithm\_sdk/asr/keyword\_spotting
唤醒词识别SDK:
```
class KWSSdk {
public:
KWSSdk();
virtual ~KWSSdk();
/**
* @brief Create a new session with KWS Plugin
*
* @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
* returns a non-zero value otherwise.
*/
int32_t Create();
/**
* @brief Synchronously execute keyword spotting once
*
* @param audioInput pcm data.
* @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
* returns a non-zero value otherwise.
*/
int32_t SyncExecute(const Array<int16_t> &audioInput);
/**
* @brief Asynchronously execute keyword spotting once
*
* @param audioInput pcm data.
* @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
* returns a non-zero value otherwise.
*/
int32_t AsyncExecute(const Array<int16_t> &audioInput);
/**
* @brief Set callback
*
* @param callback Callback function that will be called during the process.
* @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
* returns a non-zero value otherwise.
*/
int32_t SetCallback(const std::shared_ptr<KWSCallback> &callback);
/**
* @brief Destroy the created session with KWS Plugin
*
* @return Returns KWS_RETCODE_SUCCESS(0) if the operation is successful,
* returns a non-zero value otherwise.
*/
int32_t Destroy();
```
>**注意**:SDK调用AI引擎客户端接口顺序应遵循AieClientInit-\>AieClientPrepare-\>AieClientSyncProcess/AieClientAsyncProcess-\>AieClientRelease-\>AieClientDestroy,否则调用接口会返回错误码;同时应保证各个接口都有调用到,要不然会引起内存泄漏。
```
int32_t KWSSdk::KWSSdkImpl::Create()
{
if (kwsHandle_ != INVALID_KWS_HANDLE) {
HILOGE("[KWSSdkImpl]The SDK has been created");
return KWS_RETCODE_FAILURE;
}
if (InitComponents() != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]Fail to init sdk components");
return KWS_RETCODE_FAILURE;
}
int32_t retCode = AieClientInit(configInfo_, clientInfo_, algorithmInfo_, nullptr);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]AieClientInit failed. Error code[%d]", retCode);
return KWS_RETCODE_FAILURE;
}
if (clientInfo_.clientId == INVALID_CLIENT_ID) {
HILOGE("[KWSSdkImpl]Fail to allocate client id");
return KWS_RETCODE_FAILURE;
}
DataInfo inputInfo = {
.data = nullptr,
.length = 0,
};
DataInfo outputInfo = {
.data = nullptr,
.length = 0,
};
retCode = AieClientPrepare(clientInfo_, algorithmInfo_, inputInfo, outputInfo, nullptr);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]AieclientPrepare failed. Error code[%d]", retCode);
return KWS_RETCODE_FAILURE;
}
if (outputInfo.data == nullptr || outputInfo.length <= 0) {
HILOGE("[KWSSdkImpl]The data or length of output info is invalid");
return KWS_RETCODE_FAILURE;
}
MallocPointerGuard<unsigned char> pointerGuard(outputInfo.data);
retCode = PluginHelper::UnSerializeHandle(outputInfo, kwsHandle_);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]Get handle from inputInfo failed");
return KWS_RETCODE_FAILURE;
}
return KWS_RETCODE_SUCCESS;
}
int32_t KWSSdk::KWSSdkImpl::SyncExecute(const Array<uint16_t> &audioInput)
{
intptr_t newHandle = 0;
Array<int32_t> kwsResult = {
.data = nullptr,
.size = 0
};
DataInfo inputInfo = {
.data = nullptr,
.length = 0
};
DataInfo outputInfo = {
.data = nullptr,
.length = 0
};
int32_t retCode = PluginHelper::SerializeInputData(kwsHandle_, audioInput, inputInfo);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]Fail to serialize input data");
callback_->OnError(KWS_RETCODE_SERIALIZATION_ERROR);
return RETCODE_FAILURE;
}
retCode = AieClientSyncProcess(clientInfo_, algorithmInfo_, inputInfo, outputInfo);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]AieClientSyncProcess failed. Error code[%d]", retCode);
callback_->OnError(KWS_RETCODE_PLUGIN_EXECUTION_ERROR);
return RETCODE_FAILURE;
}
if (outputInfo.data == nullptr || outputInfo.length <= 0) {
HILOGE("[KWSSdkImpl] The data or length of outputInfo is invalid. Error code[%d]", retCode);
callback_->OnError(KWS_RETCODE_NULL_PARAM);
return RETCODE_FAILURE;
}
MallocPointerGuard<unsigned char> pointerGuard(outputInfo.data);
retCode = PluginHelper::UnSerializeOutputData(outputInfo, newHandle, kwsResult);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]UnSerializeOutputData failed. Error code[%d]", retCode);
callback_->OnError(KWS_RETCODE_UNSERIALIZATION_ERROR);
return retCode;
}
if (kwsHandle_ != newHandle) {
HILOGE("[KWSSdkImpl]The handle[%lld] of output data is not equal to the current handle[%lld]",
(long long)newHandle, (long long)kwsHandle_);
callback_->OnError(KWS_RETCODE_PLUGIN_SESSION_ERROR);
return RETCODE_FAILURE;
}
callback_->OnResult(kwsResult);
return RETCODE_SUCCESS;
}
int32_t KWSSdk::KWSSdkImpl::Destroy()
{
if (kwsHandle_ == INVALID_KWS_HANDLE) {
return KWS_RETCODE_SUCCESS;
}
DataInfo inputInfo = {
.data = nullptr,
.length = 0
};
int32_t retCode = PluginHelper::SerializeHandle(kwsHandle_, inputInfo);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]SerializeHandle failed. Error code[%d]", retCode);
return KWS_RETCODE_FAILURE;
}
retCode = AieClientRelease(clientInfo_, algorithmInfo_, inputInfo);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]AieClientRelease failed. Error code[%d]", retCode);
return KWS_RETCODE_FAILURE;
}
retCode = AieClientDestroy(clientInfo_);
if (retCode != RETCODE_SUCCESS) {
HILOGE("[KWSSdkImpl]AieClientDestroy failed. Error code[%d]", retCode);
return KWS_RETCODE_FAILURE;
}
mfccProcessor_ = nullptr;
pcmIterator_ = nullptr;
callback_ = nullptr;
kwsHandle_ = INVALID_KWS_HANDLE;
return KWS_RETCODE_SUCCESS;
}
```
4. **sample开发** [(参考唤醒词识别demo)](https://gitee.com/openharmony/applications_sample_camera/tree/master/ai)
位置://applications/sample/camera/ai/asr/keyword\_spotting
**调用Create**
```
bool KwsManager::PreparedInference()
{
if (capturer_ == nullptr) {
printf("[KwsManager] only load plugin after AudioCapturer ready\n");
return false;
}
if (plugin_ != nullptr) {
printf("[KwsManager] stop created InferencePlugin at first\n");
StopInference();
}
plugin_ = std::make_shared<KWSSdk>();
if (plugin_ == nullptr) {
printf("[KwsManager] fail to create inferencePlugin\n");
return false;
}
if (plugin_->Create() != SUCCESS) {
printf("[KwsManager] KWSSdk fail to create.\n");
return false;
}
std::shared_ptr<KWSCallback> callback = std::make_shared<MyKwsCallback>();
if (callback == nullptr) {
printf("[KwsManager] new Callback failed.\n");
return false;
}
plugin_->SetCallback(callback);
return true;
}
```
**调用SyncExecute**
```
void KwsManager::ConsumeSamples()
{
uintptr_t sampleAddr = 0;
size_t sampleSize = 0;
int32_t retCode = SUCCESS;
while (status_ == RUNNING) {
{
std::lock_guard<std::mutex> lock(mutex_);
if (cache_ == nullptr) {
printf("[KwsManager] cache_ is nullptr.\n");
break;
}
sampleSize = cache_->GetCapturedBuffer(sampleAddr);
}
if (sampleSize == 0 || sampleAddr == 0) {
continue;
}
Array<int16_t> input = {
.data = (int16_t *)(sampleAddr),
.size = sampleSize >> 1
};
{
std::lock_guard<std::mutex> lock(mutex_);
if (plugin_ == nullptr) {
printf("[KwsManager] cache_ is nullptr.\n");
break;
}
if ((retCode = plugin_->SyncExecute(input)) != SUCCESS) {
printf("[KwsManager] SyncExecute KWS failed with retCode = [%d]\n", retCode);
continue;
}
}
}
}
```
**调用Destroy**
```
void KwsManager::StopInference()
{
printf("[KwsManager] StopInference\n");
if (plugin_ != nullptr) {
int ret = plugin_->Destroy();
if (ret != SUCCESS) {
printf("[KwsManager] plugin_ destroy failed.\n");
}
plugin_ = nullptr;
}
}
```
## 涉及仓<a name="section10492183517430"></a>
AI子系统
ai_engine
依赖仓:
build\_lite
distributedschedule\_services\_samgr\_lite
startup\_init\_lite
## AI引擎开发导航<a name="section6808423133718"></a>
[《AI插件开发指南》](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/subsys-aiframework-guide.md)
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册