概述
本文主要介绍如何基于 anyRTC SDK 实现一个简单的视频通话功能。本文仅罗列最常用的几个接口,如果您希望了解更多的接口函数,请参见 API 文档。
示例代码
音频通话
1. 初始化 SDK
使用 anyRTC SDK 的第一步,是先通过 createARRtcEngine
创建一个 IRtcEngine
对象的指针 IRtcEngine*
,并配置开发者信息和注册监听 SDK 事件的回调。
- 继承
IRtcEngineEventHandler
事件回调接口类,重写关键事件的回调接口,包括本地用户进房/退房事件、远端用户加入/退出事件、错误事件和警告事件等。 - 调用
initialize
接口配置开发者信息并注册监听 SDK 事件。
CArObject *CArObject::GetArObject(LPCTSTR lpAppId)
{
if (m_lpArObject == NULL)
m_lpArObject = new CArObject();
if (m_lpArEngine == NULL)
// 创建实例。
m_lpArEngine = (IRtcEngine *)createARRtcEngine();
if (lpAppId == NULL)
return m_lpArObject;
RtcEngineContext ctx;
// 添加注册回调和事件。
ctx.eventHandler = &m_EngineEventHandler;
#ifdef UNICODE
char szAppId[128];
::WideCharToMultiByte(CP_ACP, 0, lpAppId, -1, szAppId, 128, NULL, NULL);
// 输入你的 App ID。
ctx.appId = szAppId;
#else
ctx.appId = lpAppId;
#endif
// 初始化 IRtcEngine。
m_lpArEngine->initialize(ctx);
return m_lpArObject;
}
// 继承 IRtcEngineEventHandler 类中的回调与事件。
class CAGEngineEventHandler :
public IRtcEngineEventHandler
{
public:
CAGEngineEventHandler(void);
~CAGEngineEventHandler(void);
void SetMsgReceiver(HWND hWnd = NULL);
HWND GetMsgReceiver() {return m_hMainWnd;};
// 注册 onJoinChannelSuccess 回调。
// 本地用户成功加入频道时,会触发该回调。
virtual void onJoinChannelSuccess(const char* channel, uid_t uid, int elapsed);
// 注册 onLeaveChannel 回调。
// 本地用户成功离开频道时,会触发该回调。
virtual void onLeaveChannel(const RtcStats& stat);
// 注册 onUserOffline 回调。
// 远端用户离开频道或掉线时,会触发该回调。
virtual void onUserOffline(uid_t uid, USER_OFFLINE_REASON_TYPE reason);
private:
HWND m_hMainWnd;
};
2. 设置本地视图
anyRTC SDK 并不会默认打开视频模块,enableVideo
可以开启视频模块,开启模块后才能调用本地采集以及接收远端视频。
调用 enableVideo
开启视频模块。
调用 setupLocalVideo
接口,打开本地视频采集。
?>
1.在调用joinChannel
前,setupLocalVideo
并不会立即显示视频,需要调用startPreview
方法才能获得预览。
2.如果调用setupLocalVideo
方法后,立即调用joinChannel
后可立即显示本地视频。
// 启用视频模块。
m_lpArObject->GetEngine()->enableVideo();
// 设置本地视图。
VideoCanvas vc;
vc.uid = 0;
vc.view = m_wndLocal.GetSafeHwnd();
vc.renderMode = RENDER_MODE_FIT;
m_lpArObject->GetEngine()->setupLocalVideo(vc);
3. 加入频道
调用 joinChannel 可以加入频道。 参数:
channelName
:频道名称,只有输入相同的频道才能进行通信。token
:权限密钥,项目启动了权限密钥功能,加入房间必须使用Token。对安全要求高的用户,请开启该功能。uid
:用户本地ID,一般为业务用户的uid,请保持频道内该uid唯一。设置NULL,SDK会自动分配一个uid给该用户。
// 加入频道。
BOOL CArObject::JoinChannel(LPCTSTR lpChannelName, UINT nUID,LPCTSTR lpToken)
{
int nRet = 0;
#ifdef UNICODE
CHAR szChannelName[128];
::WideCharToMultiByte(CP_UTF8, 0, lpChannelName, -1, szChannelName, 128, NULL, NULL);
char szToken[128];
::WideCharToMultiByte(CP_UTF8, 0, lpToken, -1, szToken, 128, NULL, NULL);
if(0 == _tcslen(lpToken))
nRet = m_lpArEngine->joinChannel(NULL, szChannelName, NULL, nUID);
else
nRet = m_lpArEngine->joinChannel(szToken, szChannelName, NULL, nUID);
#else
if(0 == _tcslen(lpToken))
nRet = m_lpArEngine->joinChannel(NULL, lpChannelName, NULL, nUID);
else
nRet = m_lpArEngine->joinChannel(lpToken, lpChannelName, NULL, nUID);
#endif
if (nRet == 0)
m_strChannelName = lpChannelName;
return nRet == 0 ? TRUE : FALSE;
}
4. 观看远端视频流
anyRTC SDK 并不会默认拉取远端的视频流,当房间里有用户上行视频数据时,频道里的其他用户可以通过 IRtcEngineEventHandler 中的 OnFirstRemoteVideoDecoded
回调获知该用户的 uid
。之后,即可调用 setupRemoteVideo 方法来显示该用户的视频画面。
// SDK 接收到第一帧远端视频并成功解码时,会触发该回调。
// 在该回调中调用 setupRemoteVideo 方法设置远端视图。
LRESULT CArTutorialDlg::OnFirstRemoteVideoDecoded(WPARAM wParam, LPARAM lParam)
{
LPAGE_FIRST_REMOTE_VIDEO_DECODED lpData = (LPAGE_FIRST_REMOTE_VIDEO_DECODED)wParam;
VideoCanvas vc;
vc.renderMode = RENDER_MODE_FIT;
vc.uid = lpData->uid;
vc.view = m_wndRemote.GetSafeHwnd();
// 设置远端视图。
m_lpArObject->GetEngine()->setupRemoteVideo(vc);
delete lpData;
return 0;
}
5. 退出频道
调用 leaveChannel 方法退出频道。不论当前是否还在通话中,调用该方法会把音频通话相关的所有资源释放掉。
BOOL CArObject::LeaveChannel()
{
m_lpArEngine->stopPreview();
// 离开频道。
int nRet = m_lpArEngine->leaveChannel();
return nRet == 0 ? TRUE : FALSE;
}
void CArObject::CloseArObject()
{
if(m_lpArEngine != NULL)
// 释放 IRtcEngine 对象。
m_lpArEngine->release();
if(m_lpArObject != NULL)
delete m_lpArObject;
m_lpArEngine = NULL;
m_lpArObject = NULL;
}