快速开始
初始化
首先配置 SDK 日志输出等级和存储位置:
// 在程序初始化时调用此方法初始化 SDK log 配置,不调用 == 无输出
QNRoomInterface::SetLogParams(qiniu_v2::LOG_INFO, "rtc-log", "rtc.log");
注:SDK log 输出每次以覆盖的方式写入文件,中途没有文件大小及磁盘剩余空间的检测。
- 创建房间
QNRoomInterface
实例(全局唯一):
// 释放时调用 QNRoomInterface::DestroyRoomInterface 方法接口
QNRoomInterface* _rtc_room_interface = QNRoomInterface::ObtainRoomInterface();
- 分别获取音频和视频模块接口指针:
QNAudioInterface* _rtc_audio_interface = _rtc_room_interface->ObtainAudioInterface();
QNVideoInterface* _rtc_video_interface = _rtc_room_interface->ObtainVideoInterface();
- 创建一子类,分别继承于
QNRoomInterface::QNRoomListener
、QNAudioInterface::QNAudioListener
和QNVideoInterface::QNVideoListener
用于接收相应的事件或回调通知,然后为各模块设置其监听接口:
// this 为实现了所有回调接口类的对象指针
_rtc_room_interface->SetRoomListener(this);
_rtc_audio_interface->SetAudioListener(this);
_rtc_video_interface->SetVideoListener(this);
枚举视频采集设备
- 获取本地视频采集设备数量,以及其所支持的采集参数:
// 获取本地视频采集设备数量
int camera_count = _rtc_video_interface->GetCameraCount();
// 枚举所有设备列表,及其所支持的采集参数
unordered_map<string, CameraDeviceInfo> _camera_dev_map; // key:device id; value:CameraDeviceInfo
for (int i(0); i < camera_count; ++i) {
CameraDeviceInfo ci = _rtc_video_interface->GetCameraInfo(i);
_camera_dev_map[ci.device_id] = ci;
}
驱动 SDK 内部引擎
需要开发者在上层开启定时器,并定时调用(比如:20ms 触发一次)
_rtc_room_interface->Loop();
方法,以保证 SDK 的事件及时通知给用户,否则 SDK 内部回调不会触发;
注:Loop 方法实际是用于处理 SDK 内部通知给开发者的消息; 此处建议开发者在自己的主线程(UI 线程)中开启定时器,以定时调用 Loop 方法,保证 SDK 回调均在上层主线程中触发,可方便开发者的 UI 操作。
加入房间
auto ret = _rtc_room_interface->JoinRoom(_room_token);
if (QNRTC_OK != ret) {
// 加入房间失败,请检查您的 room token 是否有效和当前房间网络状态,开发者无需再等待加入房间异步通知
...
return;
}
...
// 如果 JoinRoom 返回 QNRTC_OK,那么等待 `QNRoomListener::OnJoinResult` 回调通知最终是否成功加入房间,error_code 为 QNRTC_OK 即表示加入房间成功
void CRtcDemoV2::OnJoinResult(
int error_code_,
const string& error_str_,
const qiniu_v2::UserInfoList& user_vec_,
const qiniu_v2::TrackInfoList& tracks_vec_,
bool reconnect_flag_)
{
if (0 == error_code_) {
// 登录成功
// 开发者可以在处调用发布和订阅相关接口以直接开启音视频通话
} else {
// 登录失败,请根据 error_str_ 提示,检查您的网络状态和 room token 有效性
}
}
注:此处
_room_token
建议开发者的应用程序从自己的 Server 端获取,关于 Server 如何生成 token 可查阅服务端开发文档。
发布音/视频
- 发布音视频流需先创建对应的 TrackInfo,然后在已登录房间的前提下进行发布:
qiniu_v2::TrackInfoList track_list;
auto video_track_ptr = qiniu_v2::TrackInfo::CreateVideoTrackInfo(
camera_device_id,
CAMERA_TAG, // 开发者自定义 tag,SDK 会透传此 tag,开发者可用其区分不同的 Track
GetDlgItem(IDC_STATIC_VIDEO_PREVIEW)->m_hWnd, // 视频渲染窗口句柄
640, // 须是摄像头所支持的采集尺寸
480, // 须是摄像头所支持的采集尺寸
15, // 帧率,单位:帧/秒
300000, // 码率,单位:bits/秒
qiniu_v2::tst_Camera, // 标识 Track 类型,tst_Camera 标识此 Track 为摄像头采集源
false // 如果用户不需要与 v1.2 之前的 SDK 版本互通,那么此参数配置为 false 即可
);
// 创建音频 Track
// 音频 Track 同时只能发布一路,如果开发者没有主动配置音频设备的话,SDK 将使用系统默认的音频设备
auto audio_track = qiniu_v2::TrackInfo::CreateAudioTrackInfo(
MICROPHONE_TAG, // 开发者自定义 tag,SDK 会透传此 tag
64000, // 码率,单位:bits/秒
false // 如果用户不需要与 v1.2 之前的 SDK 版本互通,那么此参数配置为 false 即可
);
// 将需要发布的 TrackInfo 添加进 TrackList 中
track_list.emplace_back(video_track_ptr);
track_list.emplace_back(audio_track);
// 发布
auto ret = _rtc_room_interface->PublishTracks(track_list);
if (ret == Err_Tracks_Publish_All_Failed) {
// 发布失败
} else
// 实际发布结果由 QNRoomListener::OnPublishTracksResult 回调进行通知
}
订阅远端音/视频
- 在远端用户发布媒体流的回调通知中订阅该用户
void CRtcXXX::OnRemoteAddTracks(const TrackInfoList& track_list_)
{
qiniu_v2::TrackInfoList sub_tracks_list;
// 本地记录并分配视频渲染窗口
for (auto&& itor : track_list_) {
auto tmp_track_ptr = qiniu_v2::TrackInfo::Copy(itor);
shared_ptr<TrackInfoUI> tiu(new TrackInfoUI(this, tmp_track_ptr));
if (tiu->render_wnd_ptr) {
tmp_track_ptr->SetRenderHwnd((void*)tiu->render_wnd_ptr->m_hWnd);
}
_remote_tracks_map.insert_or_assign(tmp_track_ptr->GetTrackId(), tiu);
sub_tracks_list.emplace_back(tmp_track_ptr);
}
// 发布订阅命令,订阅结果在 QNRoomListener::OnSubscribeTracksResult 回调中通知;如果订阅成功,SDK 将直接渲染在窗口上
_rtc_room_interface->SubscribeTracks(sub_tracks_list);
}
注:用于渲染视频的窗口句柄,在 MFC 中直接使用窗口类的 m_hWnd 成员变量获取,Qt 中通过窗口类的 winId() 方法进行获取。