小程序音视频通话 SDK (Linux) Beta
# 小程序音视频通话 SDK (for Linux) (内测)
此 SDK 运行于搭载 Linux 系统的硬件设备上,为设备提供向手机微信内的小程序拨打 VoIP 通话的能力。使用此 SDK 之前,参考《小程序音视频通话(for 硬件)》完成前置的接入和小程序开发流程。
# 1. 系统要求
- C++:提供 libstdc++.so.6,且支持 C++14
- 音频输入:必须支持 PCM,可选支持 OPUS、G711、G729
- 音频输出:PCM
- 视频输入(如有摄像头):H.264 编码的视频流
- 如果设备采用 EMMC,需确保 RPMB 分区未被使用
# 2. 下载 SDK
内测阶段请先使用内测群中提供的 SDK。解压之后,你将看到如下目录:
- include: SDK 的头文件
- lib: SDK 的动态库文件
- example:独立可运行的 Demo 案例
以下介绍的接口,都可以在 include
目录中找到,example
中也有对应的用法案例,请结合头文件和示例代码阅读此文档。
# 3. 接口说明
初次接入,建议按顺序阅读文档。本章首先介绍 VoIP SDK 使用中的核心概念。接下来的两章分别介绍如何适配硬件抽象层以及如何使用 VoIP SDK 发起通话。
# 3.1 wx_operation 说明
头文件:wmpf/operation.h
。
此SDK中的接口存在大量异步操作。如果看到一个函数的返回值类型为wx_operation_t
,则说明此函数是一个异步函数,需要你在合适的时机调用如下任一函数以等待来异步执行的结果:
wx_operation_wait()
:同步阻塞式等待。支持设置超时时间。wx_operation_await()
:异步等待,不会阻塞当前线程。支持设置回调函数。
如果你不关心异步操作的结果,可以调用如下函数释放wx_operation_t
对象。
wx_operation_destroy()
:主动销毁wx_operation_t
对象。异步操作会继续执行。
如果你想取消一个异步操作,可以调用如下函数:
wx_operation_cancel()
:取消异步操作。
请特别注意wx_operation_t
对象的生命周期,以免造成内存泄漏:
- 调用
wx_operation_wait
或wx_operation_await
函数直至异步调用结束,那么wx_operation_t
对象会被自动回收。 - 如果调用
wx_operation_wait
超时,你可以重新调用wx_operation_wait
函数以继续等待,或者调用wx_operation_cancel()
主动结束此次异步调用。cancel后wx_operation_t
对象亦会被自动回收。 - 你也可以手动调用
wx_operation_destroy()
销毁operation对象,这种情况下异步操作还会继续进行,但是你将不会收到异步调用的结果。
# 3.1.1 wx_operation_wait
同步阻塞式等待。支持设置超时时间。
wx_error_t wx_operation_wait(wx_operation_t operation, uint32_t timeout_ms);
# 参数
# 返回值
# 3.1.2 wx_operation_await
异步等待,不会阻塞当前线程。异步操作的结果将通过回调函数通知给你。wx_operation_t
对象将会被自动回收。
void wx_operation_await(
wx_operation_t operation,
wx_operation_callback_t callback,
void* user_data);
# 参数
# 3.1.3 wx_operation_cancel
取消异步操作。取消之后wx_operation_t
对象将会被自动回收。调用该函数之后,不应该再对operation对象执行任何操作。
wx_error_t wx_operation_cancel(wx_operation_t operation);
# 参数
# 返回值
# 3.1.4 wx_operation_destroy
主动释放wx_operation_t
对象,但不会取消异步操作本身。调用该函数之后,不应该再对operation对象执行任何操作。
如果你没有对wx_operation_t
对象调用wait或cancel函数,并且你也不关心异步操作的结果,那么你可以调用此函数手动释放wx_operation_t
对象。
如果你调用了wait函数并且收到了WXERROR_TIMEOUT
错误码,那么你也可以调用此函数来释放wx_operation_t
对象。
其他情况下wx_operation_t
对象会被自动释放,你不应该再调用此函数主动释放它。
void wx_operation_destroy(wx_operation_t operation);
# 参数
# 4. 硬件抽象层
VoIP SDK 正常工作依赖你的硬件设备平台提供的软硬件接口,包括麦克风、扬声器、摄像头、屏幕渲染、加密库等模块。我们设计了硬件抽象层,提供一致的接口定义,具体的接口实现需要SDK的接入方提供。
# 4.1 Module
抽象
头文件:wmpf/module.h
。
我们把每个模块抽象成一个wx_module
类型,目前有如下几种module:
当你按需实现了这几种Module,那么在调用wx_init()
初始化VoIP SDK的时候,将使用如下函数指针把你的Module提供给VoIP SDK使用:
typedef wx_error_t (*wx_get_module_t)(const char* id,
struct wx_module** module);
VoIP SDK 调用你实现的这个函数时,会传给你一个ID,需要你返回此ID所对应的wx_module
的实例。
# 参数
当前支持的module ID已经预先定义在各个头文件中:
# 返回值
# 示例代码
// 假设已经实现了如下module:
extern struct wx_audio_module audio_module;
extern struct wx_camera_module camera_module;
extern struct wx_crypto_module crypto_module;
// 现实现HAL获取Module的函数如下:
wx_error_t hal_get_module(const char* id, struct wx_module** module_out) {
if (!strcmp(id, WX_AUDIO_MODULE_ID)) {
*module_out = (struct wx_module*)&audio_module;
return WXERROR_OK;
} else if (!strcmp(id, WX_CAMERA_MODULE_ID)) {
*module_out = (struct wx_module*)&camera_module;
return WXERROR_OK;
} else if (!strcmp(id, WX_CRYPTO_MODULE_ID)) {
*module_out = (struct wx_module*)&crypto_module;
return WXERROR_OK;
}
// 假设当前设备没有屏幕,因此不需提供wx_display_module,那么就返回WXERROR_UNIMPLEMENTED
return WXERROR_UNIMPLEMENTED;
}
# 4.2 音频模块 wx_audio_module
头文件:wmpf/hardware/audio.h
。
音频模块,需要配置一个wx_audio_module类型的实例。该类型主要包含如下几个函数指针:
运行时,VoIP将顺序调用这4个函数,完成对音频输入/输出设备的配置。
# 4.2.1 get_number_of_devices
获取指定类型(如WX_AUDIO_DEVICE_IN表示麦克风)的设备的数量。
wx_error_t (*get_number_of_devices)(struct wx_audio_module* module,
wx_audio_device_type_t device_type,
size_t* num_devices_out);
# 参数
# 返回值
# 4.2.2 get_device_name
查询指定类型(如WX_AUDIO_DEVICE_IN表示麦克风)设备列表中第index个设备的ID
wx_error_t (*get_device_name)(struct wx_audio_module* module,
size_t index,
wx_audio_device_type_t device_type,
char** device_name_out);
# 参数
# 返回值
# 4.2.3 get_device_info
查询指定类型(如WX_AUDIO_DEVICE_IN表示麦克风)、指定设备ID的详细信息。
wx_error_t (*get_device_info)(struct wx_audio_module* module,
const char* id,
wx_audio_device_type_t device_type,
const struct wx_metadata** metadata_out);
# 参数
# 返回值
# 4.2.4 open
获取指定设备。
wx_error_t (*open)(struct wx_audio_module* module,
const char* id,
wx_audio_device_type_t device_type,
struct wx_audio_device** device_out);
# 参数
# 返回值
# wx_audio_device 类型
可以看到,struct wx_audio_device
本身的功能不多,主要是对于设备的描述。真正需要重点关注的是它的两个拓展类型:
- wx_audio_device_in
- wx_audio_device_out
# wx_audio_device_in 类型
对于麦克风设备的抽象。这个类型的关键是需要你提供open_input_stream函数实现,运行时VoIP SDK将调用此函数,创建音频输入流对象wx_audio_stream_in。VoIP SDK使用wx_audio_stream_in对象的实例进一步控制音频采集。
open_input_stream的参数:
# wx_audio_stream_in 类型
# wx_audio_stream_in_listener 类型
# wx_audio_device_out 类型
对于扬声器设备的抽象。这个类型的关键是提供open_output_stream函数实现,运行时VoIP SDK将调用此函数,创建音频输出流对象wx_audio_stream_out。VoIP SDK使用wx_audio_stream_out对象的实例进一步控制音频播放。
open_output_stream的参数:
# wx_audio_stream_out 类型
# wx_audio_stream_out_listener 类型
# 4.3 签名算法模块 wx_crypto_module
头文件:wmpf/crypto.h
。
VoIP SDK依赖系统内置的签名算法,我们提供了openssl、mbedtls、wolfssl的Demo实现,存放在example目录中。如果你使用上述crypto实现,通常可以直接使用example的代码实现,否则请参考example实现进行适配。
Demo实现:
- example/crypto_mbedtls.c
- example/crypto_openssl.c
- example/crypto_wolfssl.c
# 4.4 [可选]摄像头模块 wx_camera_module
头文件:wmpf/hardware/camera.h
。
摄像头模块,需要配置一个 wx_camera_module 类型的实例。该类型主要是需要你提供如下几个函数指针:
运行时,VoIP SDK将顺序调用这3个函数,完成对摄像头设备的配置。
# 4.4.1 get_number_of_devices
获取摄像头设备的数量。
wx_error_t (*get_number_of_devices)(struct wx_camera_module* module,
size_t* num_devices_out);
# 参数
# 返回值
# 4.4.2 get_device_info
查询指定设备的详细信息。
wx_error_t (*get_device_info)(struct wx_camera_module* module,
size_t index,
struct wx_camera_device_info* device_info);
# 参数
# 返回值
# 4.4.3 open
获取指定设备。
wx_error_t (*open)(struct wx_camera_module* module,
const char* id,
struct wx_camera_device** device_out);
# 参数
# 返回值
# 5. 使用 VoIP SDK 通话
# 5.1 初始化SDK
头文件:wmpf/wmpf.h
。
你的进程每次启动后,调用任意VoIP SDK的接口之前,需要首先调用如下方法对VoIP SDK进行初始化。
wx_operation_t wx_init(const wx_init_config_t* config,
wx_get_module_t get_module);
# 参数
# 返回值
# wx_init_config_t
提供初始化VoIP SDK所需的一系列参数。
# 5.2 注册设备
头文件:wmpf/wmpf.h
。
SDK初始化成功之后,应当首先检查设备是否已经注册过。如果没有注册过,则需对设备进行注册,然后才能发起通话。
# 5.2.1 检查当前设备是否已注册
wx_error_t wx_device_is_registered(bool* is_registered_out);
# 参数
# 返回值
# 5.2.2 设备注册
wx_operation_t wx_device_register(const char* sn_ticket);
# 参数
# 返回值
# 5.3 配置 Session
头文件:wmpf/voip.h
。
发起通话之前,需要首先创建一个Session。Session中将配置通话发起方(也就是接入此SDK的设备)的信息,设置通话状态回调等。
# 5.3.1 初始化Session对象
调用wx_voip_session_new()
以配置wx_voip_session_t
对象。此对象用于进一步发起通话。Session对象可以重复使用,反复发起通话。
wx_error_t
wx_voip_session_new(wx_voip_session_type_t,
wx_voip_session_scene_t,
const struct wx_voip_session_listener* listener,
void* user_data,
const wx_voip_member_t* caller,
const wx_voip_session_config_t* config,
wx_voip_session_t* session);
# 参数
# 返回值
# caller 参数说明
设备端(通话发起方)的wx_voip_member_t设置如下:
# 5.3.2 销毁Session对象
当不需要发起通话之后,需要销毁之前创建的Session对象,防止内存泄漏。
void wx_voip_session_destroy(wx_voip_session_t session);
# 参数
# 5.4 通话
头文件:wmpf/voip.h
。
成功创建了wx_voip_session_type_t
对象,就可以进一步发起通话了。调用wx_voip_session_call()
发起通话,调用wx_voip_session_hangup()
主动结束通话。通话也可能被对方挂断,或者被异常挂断,相关事件通过创建session时设置的回调去监听。
# 5.4.1 发起通话
调用异步函数wx_voip_session_call()
发起通话:
wx_operation_t
wx_voip_session_call(wx_voip_session_t session,
const wx_voip_member_t* callee);
# 参数
# 返回值
# callee 参数说明
小程序端(通话接听方)的 wx_voip_member_t
设置如下:
# 5.4.2 主动结束通话
wx_operation_t
wx_voip_session_hangup(wx_voip_session_t session,
wx_voip_hangup_reason_t reason);
# 参数
# 返回值
# 5.5 关闭SDK
头文件:wmpf/wmpf.h
。
当你不再使用VoIP SDK所提供的功能,想要释放资源,可以调用如下函数。
调用此函数之前,请务必确保之前的所有wx_operation、wx_voip_session等对象已经释放,否则可能造成未知的后果。
成功调用此函数之后,如何你还想再次使用VoIP SDK,那么需要重新走一遍5.1开始的各个流程。
wx_error_t wx_stop();