前言

webrtc越来越弱化流的概念,而是将轨交给用户。视频轨和音频轨。
实现
从下面的箭头位置打断点
先手动双击启动peerconnection_server.exe,peerconnection_client.exe,然后client单击连接信令服务器。此时再单击vs2019的调试器启动peerconnection_client并单击连接,此时该页面就会显示前面连接进来的client。双击该用户。
此时就会进来该断点处。
该部分代码逻辑
MainWnd::OnDefaultAction
else if (ui_ == LIST_PEERS) {LRESULT sel = ::SendMessage(listbox_, LB_GETCURSEL, 0, 0);if (sel != LB_ERR) {LRESULT peer_id = ::SendMessage(listbox_, LB_GETITEMDATA, sel, 0);if (peer_id != -1 && callback_) {callback_->ConnectToPeer(peer_id);}}先获取clientA的id,然后连接
Conductor::ConnectToPeer
void Conductor::ConnectToPeer(int peer_id) {RTC_DCHECK(peer_id_ == -1);RTC_DCHECK(peer_id != -1);if (peer_connection_.get()) {main_wnd_->MessageBox("Error", "We only support connecting to one peer at a time", true);return;}// 初始化PeerConnectionif (InitializePeerConnection()) {peer_id_ = peer_id;peer_connection_->CreateOffer(this, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());} else {main_wnd_->MessageBox("Error", "Failed to initialize PeerConnection", true);}}
Conductor::InitializePeerConnection
bool Conductor::InitializePeerConnection() {RTC_DCHECK(!peer_connection_factory_);RTC_DCHECK(!peer_connection_);peer_connection_factory_ = webrtc::CreatePeerConnectionFactory(nullptr /* network_thread */, nullptr /* worker_thread */,nullptr /* signaling_thread */, nullptr /* default_adm */,webrtc::CreateBuiltinAudioEncoderFactory(),webrtc::CreateBuiltinAudioDecoderFactory(),webrtc::CreateBuiltinVideoEncoderFactory(),webrtc::CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */,nullptr /* audio_processing */);if (!peer_connection_factory_) {main_wnd_->MessageBox("Error", "Failed to initialize PeerConnectionFactory",true);DeletePeerConnection();return false;}if (!CreatePeerConnection(/*dtls=*/true)) {main_wnd_->MessageBox("Error", "CreatePeerConnection failed", true);DeletePeerConnection();}AddTracks();return peer_connection_ != nullptr;}
里面主要是 webrtc::CreatePeerConnectionFactory,和Conductor::CreatePeerConnection。
webrtc::CreatePeerConnectionFactory
Conductor::CreatePeerConnection
bool Conductor::CreatePeerConnection(bool dtls) {RTC_DCHECK(peer_connection_factory_);RTC_DCHECK(!peer_connection_);// 先设定一些参数,包括sdp方式,使能dtls和添加iceserver信息webrtc::PeerConnectionInterface::RTCConfiguration config;//新版本是默认unifiedPlan,也可以选择PlanBconfig.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;config.enable_dtls_srtp = dtls;// 设置ice serverwebrtc::PeerConnectionInterface::IceServer server;server.uri = GetPeerConnectionString();config.servers.push_back(server);// 调用PeerConnectionFactoryInterface::CreatePeerConnectionpeer_connection_ = peer_connection_factory_->CreatePeerConnection(config, nullptr, nullptr, this);return peer_connection_ != nullptr;}
PeerConnectionFactoryInterface::CreatePeerConnection
PROXYMETHOD4(rtc::scoped_refptr
CreatePeerConnection,
const PeerConnectionInterface::RTCConfiguration&,
std::unique_ptr
std::unique_ptr
PeerConnectionObserver*) 
这里传入的参数 peer_connection
config, nullptr, nullptr, this);
最后的是this,则该类Conductor一定是继承了 webrtc::PeerConnectionObserver ,并实现它的一些方法。
当PeerConnection对象创建好后,还需要为其添加本地音视频轨,这是非常关键的一步。对于刚入门的读者来说,这一步是很容易被遗忘的。如果没有添加本地音视频轨,WebRTC内部就无法为其产生带有媒体信息的SDP,媒体协商时就会失败,双方也就无法进行通信了。所以Conductor::CreatePeerConnection调用完后,Conductor::InitializePeerConnection函数里面就会调用Conductor::AddTracks添加音视频轨。
Conductor::AddTracks
void Conductor::AddTracks() {if (!peer_connection_->GetSenders().empty()) {return; // Already added tracks.}// 创建音频轨,并添加到peerconnectionrtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(peer_connection_factory_->CreateAudioTrack(kAudioLabel, peer_connection_factory_->CreateAudioSource(cricket::AudioOptions())));auto result_or_error = peer_connection_->AddTrack(audio_track, {kStreamId});if (!result_or_error.ok()) {RTC_LOG(LS_ERROR) << "Failed to add audio track to PeerConnection: "<< result_or_error.error().message();}// 创建视频设备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();}} else {RTC_LOG(LS_ERROR) << "OpenVideoCaptureDevice failed";}// 切换到显示视频渲染界面main_wnd_->SwitchToStreamingUI();}
视频源video_device是由自定义类CapturerTrackSource的静态方法Create()生成的。在Create()方法内部会遍历设备列表,从中找到第一个可用的设备,然后通过该设备采集视频
边看视频,边看电子书《WebRTC音视频实时互动技术:原理、实战与源码分析-李超编著》
