Skip to content
This repository has been archived by the owner on Nov 13, 2024. It is now read-only.

Commit

Permalink
Readme Update
Browse files Browse the repository at this point in the history
  • Loading branch information
sunz10 committed May 6, 2021
1 parent 3675b32 commit 21aceb9
Show file tree
Hide file tree
Showing 2 changed files with 272 additions and 2 deletions.
267 changes: 267 additions & 0 deletions Demo/Plugin_API.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
# 集成头文件

**Android**

1. 获取 Agora_Native_SDK_for_Android 安装包并解压。
2. 将 sdk/low_level_api/include 文件拷贝至你的扩展项目文件夹中。

**iOS**

1. 获取 Agora_Native_SDK_for_iOS 安装包并解压。
2. 打开 Xcode,进入 TARGETS > Project Name > General > Frameworks, Libraries, and Embedded Content 菜单,点击 + > Add Other... > Add Files,将安装包中的 AgoraRtcKit2.framework 文件添加至你的项目中。确保 Embed 属性设置为 Do Not Embed。

# 实现 IVideoFilter 接口

视频插件通过 IVideoFilter 接口实现。该接口位于 NGIAgoraMediaNode.h 文件中。你需要先实现这个接口类,并至少实现该类的如下方法:

```c++
class IVideoFilter {
public:
virtual bool adaptVideoFrame(const media::base::VideoFrame& capturedFrame,
media::base::VideoFrame& adaptedFrame);
virtual void setEnabled(bool enable);
virtual bool isEnabled();
virtual size_t setProperty(const char* key, const void* buf, size_t buf_size);
virtual size_t getProperty(const char* key, void* buf, size_t buf_size);
};
```
### setEnabled
启用或关闭视频插件。
```c++
virtual void setEnabled(bool enable) {}
```

| 参数 | 描述 |
| :----- | :---------------------------------------- |
| enable | true: 启用视频插件。false: 关闭视频插件。 |

### isEnabled

检查视频插件是否已启用。

```c++
virtual bool isEnabled() { return true; }
```
| 参数 | 描述 |
| :----- | :-------------------------------------------- |
| enable | true: 视频插件已启用。false: 视频插件已关闭。 |
### **setProperty**
该方法设置提供的扩展服务。API 原型和描述如下:
```cpp
size_t setProperty(const char* key, const void* buf, size_t buf_size)
```



| 参数 | 描述 |
| :------- | :----------------------------------------------------------- |
| key | 扩展服务的 key。 |
| buf | 扩展服务的 key 值对应的地址,数据形式为 json 字符串。我们推荐使用第三方的 nlohmann/json library 开源库,帮助实现 C++ 的 struct 和 json 字符串之前的序列和反序列化。 |
| buf_size | 代表扩展服务地址的 json 字符串的大小。 |



### adaptVideoFrame

处理视频帧。该方法是 IVideoFilter 类的核心方法,处理 capturedFrame,返回 adaptedFrame。该方法目前仅支持输入输出 YUV I420 格式的视频数据。

```cpp
bool adaptVideoFrame(const media::base::VideoFrame& capturedFrame, media::base::VideoFrame& adaptedFrame)
```
| 参数 | 描述 |
| :------------ | :------------------------- |
| capturedFrame | 输入参数。待处理的视频帧。 |
| adaptedFrame | 输出参数。处理后的视频帧。 |
### 示例代码
```cpp
// 在收到需要处理的视频数据后,调用 adaptVideoFrame 方法,对收到的视频数据进行处理。
bool ExtensionVideoFilter::adaptVideoFrame(const agora::media::base::VideoFrame &caoturedFrame, agora::media::base::VideoFrame &adaptedFrame) {
if (!isInitOpenGL) {
isInitOpenGL = byteDanceProcessor_->initOpenGL();
}
byteDanceProcessor_->processFrame(capturedFrame);
adaptedFrame = capturedFrame;
return true;
}
// 调用 setProperty 设置视频插件参数。
size_t ExtensionVideoFilter::setProperty(const char *key, const void *buf, size_t buf_size) {
return 0;
}
// 调用 getProperty 查询视频插件参数。
size_t ExtensionVideoFilter::getProperty(const char *key, void *buf, size_t buf_size) {
return 0;
}
// 调用 setEnabled 开启视频插件。
void ExtensionVideoFilter::setEnabled(bool enabled) {
}
// 调用 isEnabled 查询视频插件开启状态。
bool ExtensionVideoFilter::isEnabled() {
return true;
}
```

# 封装扩展服务

封装扩展服务通过 IExtensionProvider 接口类实现。该接口位于 NGIAgoraExtensionProvider.h 文件中。你需要先实现这个接口类,并至少实现该类的如下接口:

```cpp
class IExtensionProvider {
public:
virtual PROVIDER_TYPE getProviderType();
virtual void setExtensionControl(IExtensionControl* control);
virtual agora_refptr<IVideoFilter> createVideoFilter(const char* id);
};
```
### getProviderType
指定你想要封装的扩展服务类型。
```cpp
virtual PROVIDER_TYPE getProviderType()
```

收到该回调后,你需要通过返回值指定你想要封装的扩展服务类型。其中 PROVIDER_TYPE 是指插件在音视频 Pipeline 中的位置,定义如下:

```cpp
enum PROVIDER_TYPE {
// 本地音频插件
LOCAL_AUDIO_FILTER,
// 尚未实现
REMOTE_AUDIO_FILTER
// 本地视频插件
LOCAL_VIDEO_FILTER,
// 远端视频插件
REMOTE_VIDEO_FILTER,
// 尚未实现
LOCAL_VIDEO_SINK,
// 尚未实现
REMOTE_VIDEO_SINK,
// 预留参数
UNKNOWN,
};
```

如果你在 getProviderType 方法中返回的插件类型为 LOCAL_VIDEO_FILTER 或 REMOTE_VIDEO_FILTER,则 IExtensionProvider 对象会在生命周期内调用 createVideoFilter 方法。你需要在该方法的返回值中传入 IVideoFilter 实例。

### setExtensionControl

设置扩展控制。

```cpp
virtual void setExtensionControl(IExtensionControl* control)
```
成功调用该方法后,你需要保存 SDK 在该方法中返回的 IExtensionControl 对象。该对象用于触发事件或日志,实现插件与 app 之间的交互。例如,如果你调用了 IExtensionControl 中的 fireEvent 方法:
```cpp
void ByteDanceProcessor::dataCallback(const char* data){
if (control_ != nullptr) {
control_->fireEvent(id_, "beauty", data);
}
}
```

app 层在初始化 RtcEngine 时注册的 IMediaExtensionObserver 实例会收到该信息,并在 app 层触发如下回调:

```cpp
@Override
public void onEvent(String vendor, String key, String value) {
// 其中的 vendor 为注册插件时的 VENDOR_NAME,key/value是插件消息的键值对
......
}
```
### createVideoFilter
创建视频插件。
```cpp
virtual agora_refptr<IVideoFilter> createVideoFilter()
```

成功创建 Video Filter 实例后,扩展服务会在合适的时机通过 IVideoFilter 类对输入的视频数据进行处理。

### 示例代码

```cpp

agora-refptr<agora::rtc::IVideoFilter> ExtensionProvider::createVideoFilter(const char* id) {
byteDanceProcessor_->setExtensionVendor(id);
auto videoFilter = new agora::RefcountedObject<agora::extension::ExtensionVideoFilter>(byteDanceProcessor_);
return videoFilter;
}

ExtensionProvider::PROVIDER_TYPE ExtensionProvider::getProviderType() {
return ExtensionProvider::PROVIDER_TYPE::LOCAL_VIDEO_FILTER;
}

void eXTENSIONprovider::setExtensionControl(rtc::IExtensionControl* control){
byteDanceProcessor_->setExtensionControl(control);
}
```
# 示例项目
详细的代码逻辑可以参考如下链接:
<https://github.com/AgoraIO-Community/RTE-2021-Innovation-Challenge/tree/master/Demo>
# 打包扩展
**Android**
1. 扩展是 .aar 格式的文件。
2. Java 提供一个公开的静态方法:nativeGetExtensionProvider。你需要参考如下行调用 jni 方法:
```cpp
extern "C" JNIEXPORT jlong JNICALL
Java_io_agora_extension_ExtensionManager_nativeGetExtensionProvider(
JNIEnv* env,
jclass clazz, jobject context)
```

该方法会返回一个 IExtensionProvider 接口,并向 app 触发一个事件句柄。

**iOS**

1. 扩展是 .framework 格式的库文件。

2. 扩展文件通过 mediaFilterExtension 方法提供一个 BDVideoExtensionObject 类,其中实现了 AgoraMediaFilterExtensionDelegate 协议。

```cpp
- (BDVideoExtensionObject *)mediaFilterExtension {
BDVideoExtensionObject *obj = [BDVideoExtensionObject new];
obj.vendorName = kVendorName;

if (_bdProvider) {
obj.mediaFilterProvider = _bdProvider.get();
} else {
obj.mediaFilterProvider = nullptr;
}

return obj;
}
```
7 changes: 5 additions & 2 deletions Demo/Readme.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# 字节 Plugin 简介
该 Demo App 用于展示在 Agora SDK 中加载 IVideoFilter/IAudioFilter 类型的插件,主要功能包括
# 声网插件封装示例
该 Demo App 用于展示如何在 Agora SDK 中加载 IVideoFilter/IAudioFilter 类型的插件,主要功能包括

1. IVideoFilter -- 将 “字节火山引擎” 封装为 Agora SDK 的 IVideoFilter 类型的插件,并提供人脸检测、美颜、添加道具等功能,Demo App 主界面下方的按钮可以 Enable/Disable该功能

Expand All @@ -10,6 +10,9 @@
[点击下载 Android 平台](https://download.agora.io/demo/test/Agora_Extension_Android.zip)
[点击下载 iOS 平台](https://download.agora.io/demo/test/Agora_Extension_iOS.zip)

关于插件封装的相关接口使用方法,请参考下列文档。
[点击查看接口文档](Plugin_API.md)

# 字节 Plugin 的使用方法
### 1. 将所需相关依赖文件放到指定目录
|依赖文件|存放路径|
Expand Down

0 comments on commit 21aceb9

Please sign in to comment.