基本流程
webrtc native的接口,主要就是围绕着PeerConnection
对象,一个PeerConnection
对象它代表了一次音视频会话。
那么通过PeerConnection
对象建立音视频通话,包括如下步骤:
- 创建
PeerConnectionFactory
,通过工厂方法webrtc::CreatePeerConnectionFactory
。 - 创建
PeerConnection
,通过它的PeerConnectionFactory的CreatePeerConnection
方法。 - 调用
PeerConnectionFactory
的CreateAudioTrack
和CreateVideoTrack
方法创建Track。 - 调用
PeerConncetion
的AddTrack
方法添加Track,track最终会反映到sdp中的m行中。协商成功的Track在随后会通过onAddTrack
回调告知应用层,根据Track的类型来确定是回放视频还是音频。 -
如果是本地为发起端则需调用
PeerConnection
的CreateOffer
方法,产生本地sdp信息(抽象为了webrtc::SessionDescriptionInterface
**对象),触发 **CreateSessionDescriptionObserver
**中 **OnSu***ess
方法,在OnSu***ess
方法中调用PeerConnection
的SetLocalDescription
方法,获取sdp字符串后通过信令协议给到远端。 - 如果远端是发起,在收到信令服务传来的远端sdp消息,调用
PeerConnection
的SetRemoteDescription
方法(需将sdp字符转换为webrtc::SessionDescriptionInterface
对象)。然后调用PeerConnection
的CreateAnswer
方法(产生的local sdp应该还是会通过CreateSessionDescriptionObserver
的OnSu***ess
回调给出,最终还是通过PeerConnection
的SetLocalDescription
方法设置,需要调试一下,追踪流程)。
整个过程本质就是获取本地sdp信息和远端sdp信息,再进行协商,流程可以概括为如下图。
状态回调类
上述流程都是异步,所以会有状态回调来告知应用状态。主要的两个Observer
就是CreateSessionDescriptionObserver
和PeerConnectionObserver
,前者是告知sdp创建,协商的状态。后者是PC对象的状态。如下图。
Conductor
类在examples/peerconnection/client/conductor.h
,是webrtc native的pc对象封装示例代码。
实现一个pc client,可以参照它的实现,首先是要继承CreateSessionDescriptionObserver
和PeerConnectionObserver
,再是有PeerConnectionInterface
(PC对象)和PeerConnectionFactoryInterface
(用于创建PC对象)的成员变量。
sdp的中媒体行
sdp中核心的信息就是描述媒体信息的内容,简称m行或媒体行。通过pc对象的AddTrack或AddTransceiver方法添加track,会直接反映到sdp中。
如下代码,添加了两个VideoTrack,最终反映到sdp中为两个sendrecv的m行。
rtc::scoped_refptr<CapturerTrackSource> video_device =
CapturerTrackSource::Create();
if (video_device) {
rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track_(
peer_connection_factory_->CreateVideoTrack(kVideoLabel, video_device));
main_wnd_->StartLocalRenderer(video_track_);
result_or_error = peer_connection_->AddTrack(video_track_, {kStreamId});
if (!result_or_error.ok()) {
RTC_LOG(LS_ERROR) << "Failed to add video track to PeerConnection: "
<< result_or_error.error().message();
}
//添加第二个video track
rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track_1(
peer_connection_factory_->CreateVideoTrack("video_track_1", video_device));
result_or_error = peer_connection_->AddTrack(video_track_1, {kStreamId});
if (!result_or_error.ok()) {
RTC_LOG(LS_ERROR) << "Failed to add video track to PeerConnection: "
<< result_or_error.error().message();
}
} else {
RTC_LOG(LS_ERROR) << "OpenVideoCaptureDevice failed";
}
如下代码添加了一个VieoTrack,方向为recvonly。
//video recvonly
webrtc::RtpTransceiverInit init;
init.direction = webrtc::RtpTransceiverDirection::kRecvOnly;
peer_connection_->AddTransceiver(cricket::MediaType::MEDIA_TYPE_VIDEO, init);
pc对象
一个PC对象表示一次P2P会话,它包括sdp handle,call。可以产生多个PC对象,PC对象之间相互不关联。std::unique_ptr<SdpOfferAnswerHandler> sdp_handler_;
用以处理sdp协商。std::unique_ptr<Call> call_;
管理PC sdp中对应的stream,如下类图为它提供的核心方法:
一个PC对象中video/audio send/receive stream都被webrtc::interal::call
对象管理,也是通过它的接口进行创建。
sdp中一个m行对应一个RtpTransceiver
对象,最终被映射成MediaChannel
和 video/audio的各种send/receive stream(比如webrtc::internal::VideoSendStream
),而这些stream就是直接管理编解码器。