本文基于 WebRTC 中的示例应用 peerconnection_client 分析 WebRTC Audio 接收和发送的关键过程。首先是发送的过程,然后是接收的过程。
1、创建 webrtc::AudioState
应用程序择机初始化 PeerConnectionFactory:
#0 Init () at webrtc/src/pc/channel_manager.cc:121
#1 Initialize () at webrtc/src/pc/peer_connection_factory.cc:139
#6 webrtc::CreateModularPeerConnectionFactory(webrtc::PeerConnectionFactoryDependencies) () at webrtc/src/pc/peer_connection_factory.cc:55
#7 webrtc::CreatePeerConnectionFactory(rtc::Thread*, rtc::Thread*, rtc::Thread*, rtc::scoped_refptr<webrtc::AudioDeviceModule>, rtc::scoped_refptr<webrtc::AudioEncoderFactory>, rtc::scoped_refptr<webrtc::AudioDecoderFactory>, std::__1::unique_ptr<webrtc::VideoEncoderFactory, std::__1::default_delete<webrtc::VideoEncoderFactory> >, std::__1::unique_ptr<webrtc::VideoDecoderFactory, std::__1::default_delete<webrtc::VideoDecoderFactory> >, rtc::scoped_refptr<webrtc::AudioMixer>, rtc::scoped_refptr<webrtc::AudioProcessing>) () at webrtc/src/api/create_peerconnection_factory.cc:65
#8 InitializePeerConnection () at webrtc/src/examples/peerconnection/client/conductor.cc:132
#9 ConnectToPeer () at webrtc/src/examples/peerconnection/client/conductor.cc:422
#10 OnRowActivated () at webrtc/src/examples/peerconnection/client/linux/main_wnd.cc:433
#11 (anonymous namespace)::OnRowActivatedCallback(_GtkTreeView*, _GtkTreePath*, _GtkTreeViewColumn*, void*) () at webrtc/src/examples/peerconnection/client/linux/main_wnd.cc:70
由 Conductor::InitializePeerConnection() 的代码可知,PeerConnectionFactory 竟然是随同 peer connection一起创建的。
在 webrtc/src/pc/channel_manager.cc 文件里定义的 ChannelManager::Init() 函数中会在另一个线程中起一个 task,调用 media_engine_->Init(),完成媒体引擎的初始化:
bool ChannelManager::Init() {
RTC_DCHECK(!initialized_);
if (initialized_) {
return false;
}
RTC_DCHECK(network_thread_);
RTC_DCHECK(worker_thread_);
if (!network_thread_->IsCurrent()) {
// Do not allow invoking calls to other threads on the network thread.
network_thread_->Invoke<void>(
RTC_FROM_HERE, [&] { network_thread_->DisallowBlockingCalls(); });
}
if (media_engine_) {
initialized_ = worker_thread_->Invoke<bool>(
RTC_FROM_HERE, [&] { return media_engine_->Init(); });
RTC_DCHECK(initialized_);
} else {
initialized_ = true;
}
return initialized_;
}
媒体引擎初始化过程中,将会创建 AudioState:
#0 webrtc::AudioState::Create(webrtc::AudioState::Config const&) () at webrtc/src/audio/audio_state.cc:188
#1 Init () at webrtc/src/media/engine/webrtc_voice_engine.cc:260
#2 cricket::CompositeMediaEngine::Init() () at webrtc/src/media/base/media_engine.cc:155
#3 cricket::ChannelManager::Init()::$_3::operator()() const () at webrtc/src/pc/channel_manager.cc:135
AudioState 伴随着 PeerConnectionFactory
、ChannelManager
和 MediaEngine
的创建及初始化一起创建。
2、创建 WebRTC Call
应用程序根据需要创建 peer connection:
#0 CreatePeerConnection () at webrtc/src/pc/peer_connection_factory.cc:240
#1 webrtc::PeerConnectionFactory::CreatePeerConnection(webrtc::PeerConnectionInterface::RTCConfiguration const&, std::__1::unique_ptr<cricket::PortAllocator, std::__1::default_delete<cricket::PortAllocator> >, std::__1::unique_ptr<rtc::RTCCertificateGeneratorInterface, std::__1::default_delete<rtc::RTCCertificateGeneratorInterface> >, webrtc::PeerConnectionObserver*) () at webrtc/src/pc/peer_connection_factory.cc:233
#7 CreatePeerConnection () at webrtc/src/examples/peerconnection/client/conductor.cc:184
#8 InitializePeerConnection () at webrtc/src/examples/peerconnection/client/conductor.cc:148
#9 ConnectToPeer () at webrtc/src/examples/peerconnection/client/conductor.cc:422
#10 OnRowActivated () at webrtc/src/examples/peerconnection/client/linux/main_wnd.cc:433
#11 (anonymous namespace)::OnRowActivatedCallback(_GtkTreeView*, _GtkTreePath*, _GtkTreeViewColumn*, void*) () at webrtc/src/examples/peerconnection/client/linux/main_wnd.cc:70
PeerConnectionFactory::CreatePeerConnection()
在创建 connection 时,会在另一个线程中起一个task 来创建 Call:
rtc::scoped_refptr<PeerConnectionInterface>
PeerConnectionFactory::CreatePeerConnection(
const PeerConnectionInterface::RTCConfiguration& configuration,
PeerConnectionDependencies dependencies) {
RTC_DCHECK(signaling_thread_->IsCurrent());
// Set internal defaults if optional dependencies are not set.
if (!dependencies.cert_generator) {
dependencies.cert_generator =
absl::make_unique<rtc::RTCCertificateGenerator>(signaling_thread_,
network_thread_);
}
if (!dependencies.allocator) {
network_thread_->Invoke<void>(RTC_FROM_HERE, [this, &configuration,
&dependencies]() {
dependencies.allocator = absl::make_unique<cricket::BasicPortAllocator>(
default_network_manager_.get(), default_socket_factory_.get(),
configuration.turn_customizer);
});
}
// TODO(zstein): Once chromium injects its own AsyncResolverFactory, set
// |dependencies.async_resolver_factory| to a new
// |rtc::BasicAsyncResolverFactory| if no factory is provided.
network_thread_->Invoke<void>(
RTC_FROM_HERE,
rtc::Bind(&cricket::PortAllocator::SetNetworkIgnoreMask,
dependencies.allocator.get(), options_.network_ignore_mask));
std::unique_ptr<RtcEventLog> event_log =
worker_thread_->Invoke<std::unique_ptr<RtcEventLog>>(
RTC_FROM_HERE,
rtc::Bind(&PeerConnectionFactory::CreateRtcEventLog_w, this));
std::unique_ptr<Call> call = worker_thread_->Invoke<std::unique_ptr<Call>>(
RTC_FROM_HERE,
rtc::Bind(&PeerConnectionFactory::CreateCall_w, this, event_log.get()));
rtc::scoped_refptr<PeerConnection> pc(
new rtc: