开篇前瞎扯。很久没发技术文章了,此文一直放着草稿箱没有完成,感觉自己在家庭和工作中找到了拖延的借口,开始慢慢变得懒惰了,那是万万不行的。恰逢2023开年ChatGPT的爆火,更让我这些普通程序员危机感瞬间飙升,无限感受到自己的知识储备已经跟不上时代的节奏了。所以还是继续学习吧,活到老学到老。
还记得系列开篇的这张流程分析图嚒,不知不觉已经基本分析全了PeerConnectionFactory之上的内容。有兴趣需要补课的同学follow这个专栏。
现在把目光回归到PeerConnectionFactory这个关键节点,拆解中心环节继续向深进发。
从java层接口出发,很容易就找到源码.\sdk\android\src\jni\pc\peer_connection_factory.cc文件中的函数JNI_PeerConnectionFactory_CreatePeerConnectionFactory,最终调用CreatePeerConnectionFactoryForJava,一起看看代码内容。
// .\sdk\android\src\jni\pc\peer_connection_factory.cc文件中的
// 函数JNI_PeerConnectionFactory_CreatePeerConnectionFactory -> CreatePeerConnectionFactoryForJava
//为了节省篇幅,函数内部很多RTC_CHECK省去了。
ScopedJavaLocalRef<jobject> CreatePeerConnectionFactoryForJava(
JNIEnv* jni,
const JavaParamRef<jobject>& jcontext,
const JavaParamRef<jobject>& joptions,
// 节省篇幅,入参列表简化如下。
// |audio_device_module|, |jencoder_factory|, |jdecoder_factory|,
// |audio_processor|, |fec_controller_factory|,
// |network_state_predictor_factory|, |neteq_factory|.) {
// 1、创建三类工作线程,
std::unique_ptr<rtc::Thread> network_thread =
rtc::Thread::CreateWithSocketServer();
network_thread->SetName("network_thread", nullptr);
std::unique_ptr<rtc::Thread> worker_thread = rtc::Thread::Create();
worker_thread->SetName("worker_thread", nullptr);
std::unique_ptr<rtc::Thread> signaling_thread = rtc::Thread::Create();
signaling_thread->SetName("signaling_thread", NULL);
const absl::optional<PeerConnectionFactoryInterface::Options> options =
JavaToNativePeerConnectionFactoryOptions(jni, joptions);
// 2、创建PeerConnectionFactoryDependencies
PeerConnectionFactoryDependencies dependencies;
dependencies.network_thread = network_thread.get();
dependencies.worker_thread = worker_thread.get();
dependencies.signaling_thread = signaling_thread.get();
dependencies.task_queue_factory = CreateDefaultTaskQueueFactory();
dependencies.call_factory = CreateCallFactory();
dependencies.event_log_factory = std::make_unique<RtcEventLogFactory>(
dependencies.task_queue_factory.get());
dependencies.fec_controller_factory = std::move(fec_controller_factory);
dependencies.network_controller_factory =
std::move(network_controller_factory);
dependencies.network_state_predictor_factory =
std::move(network_state_predictor_factory);
dependencies.neteq_factory = std::move(neteq_factory);
if (!(options && options->disable_network_monitor)) {
dependencies.network_monitor_factory =
std::make_unique<AndroidNetworkMonitorFactory>();
}
// 3、创建PeerConnectionFactoryDependencies所需的MediaEngineDependencies
cricket::MediaEngineDependencies media_dependencies;
media_dependencies.task_queue_factory = dependencies.task_queue_factory.get();
media_dependencies.adm = std::move(audio_device_module);
media_dependencies.audio_encoder_factory = std::move(audio_encoder_factory);
media_dependencies.audio_decoder_factory = std::move(audio_decoder_factory);
media_dependencies.audio_processing = std::move(audio_processor);
media_dependencies.video_encoder_factory =
absl::WrapUnique(CreateVideoEncoderFactory(jni, jencoder_factory));
media_dependencies.video_decoder_factory =
absl::WrapUnique(CreateVideoDecoderFactory(jni, jdecoder_factory));
dependencies.media_engine =
cricket::CreateMediaEngine(std::move(media_dependencies));
// 4、通过PeerConnectionFactoryDependencies创建CreateModularPeerConnectionFactory
rtc::scoped_refptr<PeerConnectionFactoryInterface> factory =
CreateModularPeerConnectionFactory(std::move(dependencies));
if (options)
factory->SetOptions(*options);
return NativeToScopedJavaPeerConnectionFactory(
jni, factory, std::move(network_thread), std::move(worker_thread),
std::move(signaling_thread));
}
函数内容有点多,不过总结起来其实就几个部分,
1、创建三类内部组件,network_thread/worker_thread/signaling_thread,虽然他们都是rtc::Thread,虽然命名是线程,但其实不是我们所了解的线程,反而有点类似Android Handler,包含着消息队列和内部执行循环。
2、创建PeerConnectionFactoryDependencies,其中需要关注几个关键量 call_factory(p2p链接) / fec_controller_factory(丢包纠错) / network_state_predictor_factory(网络带宽预测)/ media_dependencies(媒体相关) 以上几个都是webrtc的重点难点,都是需要开坑逐一分析学习。
3、创建PeerConnectionFactoryDependencies所依赖的MediaEngineDependencies,MediaEngineDependencies的入参就是之前分析过的几个video/audio-encoder/decoder factory
4、最后就是根据PeerConnectionFactoryDependencies,创建集大成的PeerConnectionFactory。
一图概述就是这样:
继续往下看看CreateModularPeerConnectionFactory的内容
rtc::scoped_refptr<PeerConnectionFactoryInterface>
CreateModularPeerConnectionFactory(
PeerConnectionFactoryDependencies dependencies) {
// The PeerConnectionFactory must be created on the signaling thread.
if (dependencies.signaling_thread &&
!dependencies.signaling_thread->IsCurrent()) {
return dependencies.signaling_thread
->Invoke<rtc::scoped_refptr<PeerConnectionFactoryInterface>>(
RTC_FROM_HERE, [&dependencies] {
return CreateModularPeerConnectionFactory(
std::move(dependencies));
});
}
auto pc_factory = PeerConnectionFactory::Create(std::move(dependencies));
if (!pc_factory) {
return nullptr;
}
// Verify that the invocation and the initialization ended up agreeing on the
// thread.
RTC_DCHECK_RUN_ON(pc_factory->signaling_thread());
return PeerConnectionFactoryProxy::Create(
pc_factory->signaling_thread(), pc_factory->worker_thread(), pc_factory);
}
// Static
rtc::scoped_refptr<PeerConnectionFactory> PeerConnectionFactory::Create(
PeerConnectionFactoryDependencies dependencies) {
auto context = ConnectionContext::Create(&dependencies);
if (!context) {
return nullptr;
}
return rtc::make_ref_counted<PeerConnectionFactory>(context, &dependencies);
}
其中PeerConnectionFactory::Create就是真正创建PeerConnectionFactory的地方,其中还包含了一个ConnectionContext的创建,还有一个比较难明白的地方就是CreateModularPeerConnectionFactory函数的返回,PeerConnectionFactoryProxy,为啥不直接使用PeerConnectionFactory?
而且,用普通的阅读器是跟踪不到具体的实现文件。我是用VSCode带C++插件的才能跟踪到,跟踪进去会发现这是一个完全由宏定义去生成的代理类。大家有空可以自己去观摩,我这里就不贴代码了,位置在.\api\peer_connection_factory_proxy.h。
接下来直接看看PeerConnectionFactory的头定义,先大致了解其结构组成部分。
class PeerConnectionFactory : public PeerConnectionFactoryInterface {
public:
void SetOptions(const Options& options) override;
RTCErrorOr<rtc::scoped_refptr<PeerConnectionInterface>>
CreatePeerConnectionOrError(
const PeerConnectionInterface::RTCConfiguration& configuration,
PeerConnectionDependencies dependencies) override;
RtpCapabilities GetRtpSenderCapabilities(
cricket::MediaType kind) const override;
RtpCapabilities GetRtpReceiverCapabilities(
cricket::MediaType kind) const override;
rtc::scoped_refptr<MediaStreamInterface> CreateLocalMediaStream(
const std::string& stream_id) override;
rtc::scoped_refptr<AudioSourceInterface> CreateAudioSource(
const cricket::AudioOptions& options) override;
rtc::scoped_refptr<VideoTrackInterface> CreateVideoTrack(
const std::string& id,
VideoTrackSourceInterface* video_source) override;
rtc::scoped_refptr<AudioTrackInterface> CreateAudioTrack(
const std::string& id,
AudioSourceInterface* audio_source) override;
bool StartAecDump(FILE* file, int64_t max_size_bytes) override;
void StopAecDump() override;
SctpTransportFactoryInterface* sctp_transport_factory() {
return context_->sctp_transport_factory();
}
virtual cricket::ChannelManager* channel_manager();
rtc::Thread* signaling_thread() const {
// This method can be called on a different thread when the factory is
// created in CreatePeerConnectionFactory().
return context_->signaling_thread();
}
rtc::Thread* worker_thread() const { return context_->worker_thread(); }
const Options& options() const {
RTC_DCHECK_RUN_ON(signaling_thread());
return options_;
}
const WebRtcKeyValueConfig& trials() const { return context_->trials(); }
protected:
virtual ~PeerConnectionFactory();
private:
rtc::Thread* network_thread() const { return context_->network_thread(); }
bool IsTrialEnabled(absl::string_view key) const;
const cricket::ChannelManager* channel_manager() const {
return context_->channel_manager();
}
std::unique_ptr<RtcEventLog> CreateRtcEventLog_w();
std::unique_ptr<Call> CreateCall_w(RtcEventLog* event_log);
rtc::scoped_refptr<ConnectionContext> context_;
PeerConnectionFactoryInterface::Options options_
RTC_GUARDED_BY(signaling_thread());
std::unique_ptr<TaskQueueFactory> task_queue_factory_;
std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory_;
std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory_;
std::unique_ptr<NetworkStatePredictorFactoryInterface>
network_state_predictor_factory_;
std::unique_ptr<NetworkControllerFactoryInterface>
injected_network_controller_factory_;
std::unique_ptr<NetEqFactory> neteq_factory_;
};
功能性方法先不急着深入,先大致拆分结构性组成部分。
1、CreatePeerConnectionOrError公开方法和CreateCall_w私有方法,应该和创建PeerConnection有着密切联系。这个留着下一篇文件 创建PeerConnection分析。
2、结合CreateModularPeerConnectionFactory方法和PeerConnectionFactory的头定义文件,大致可以看出ConnectionContext也是一个很重要的组成部分。
3、ChannelManager也是一个独立的组成部分。
其他也没啥了,接着在快速看看ConeectionContext的结构组成。
// This class contains resources needed by PeerConnection and associated
// objects. A reference to this object is passed to each PeerConnection. The
// methods on this object are assumed not to change the state in any way that
// interferes with the operation of other PeerConnections.
//
// This class must be created and destroyed on the signaling thread.
class ConnectionContext final
: public rtc::RefCountedNonVirtual<ConnectionContext> {
public:
// Creates a ConnectionContext. May return null if initialization fails.
// The Dependencies class allows simple management of all new dependencies
// being added to the ConnectionContext.
static rtc::scoped_refptr<ConnectionContext> Create(
PeerConnectionFactoryDependencies* dependencies);
// This class is not copyable or movable.
ConnectionContext(const ConnectionContext&) = delete;
ConnectionContext& operator=(const ConnectionContext&) = delete;
// Functions called from PeerConnection and friends
SctpTransportFactoryInterface* sctp_transport_factory() const {
return sctp_factory_.get();
}
cricket::ChannelManager* channel_manager() const;
rtc::Thread* signaling_thread() { return signaling_thread_; }
const rtc::Thread* signaling_thread() const { return signaling_thread_; }
rtc::Thread* worker_thread() { return worker_thread_; }
const rtc::Thread* worker_thread() const { return worker_thread_; }
rtc::Thread* network_thread() { return network_thread_; }
const rtc::Thread* network_thread() const { return network_thread_; }
const WebRtcKeyValueConfig& trials() const { return *trials_.get(); }
// Accessors only used from the PeerConnectionFactory class
rtc::BasicNetworkManager* default_network_manager() {
RTC_DCHECK_RUN_ON(signaling_thread_);
return default_network_manager_.get();
}
rtc::BasicPacketSocketFactory* default_socket_factory() {
RTC_DCHECK_RUN_ON(signaling_thread_);
return default_socket_factory_.get();
}
CallFactoryInterface* call_factory() {
RTC_DCHECK_RUN_ON(worker_thread_);
return call_factory_.get();
}
private:
rtc::Thread* const network_thread_;
rtc::Thread* const worker_thread_;
rtc::Thread* const signaling_thread_;
// channel_manager is accessed both on signaling thread and worker thread.
std::unique_ptr<cricket::ChannelManager> channel_manager_;
std::unique_ptr<rtc::NetworkMonitorFactory> const network_monitor_factory_
RTC_GUARDED_BY(signaling_thread_);
std::unique_ptr<rtc::BasicNetworkManager> default_network_manager_
RTC_GUARDED_BY(signaling_thread_);
std::unique_ptr<webrtc::CallFactoryInterface> const call_factory_
RTC_GUARDED_BY(worker_thread_);
std::unique_ptr<rtc::BasicPacketSocketFactory> default_socket_factory_
RTC_GUARDED_BY(signaling_thread_);
std::unique_ptr<SctpTransportFactoryInterface> const sctp_factory_;
// Accessed both on signaling thread and worker thread.
std::unique_ptr<WebRtcKeyValueConfig> const trials_;
};
有备注看备注,翻译过来的意思:ConnectionContext此类包含PeerConnection和关联对象所需的资源。该对象的引用将传递给每个PeerConnection。且ConnectionContext此对象上的方法不会干扰其他操作的方式 去更改其PeerConnection对象的任何状态。
看方法可以知道PeerConnectionFactory很多方法是直接引用ConnectionContext的,甚至channel_manager / sctp_transport_factory / call_factory 也是直接引用ConnectionContext对象。
重要组成部分:ChannelManager、SctpTransportFactory、BasicNetworkManager、BasicPacketSocketFactory、CallFactory。一图总结概述(和上图的总结不冲突哈,其他更应该把这两图结合一起看。)
本篇主要介绍了PeerConnectionFactory的整体结构组成,简单揭开了其真正的面纱和其背后隐藏起来的关键部分(ConnectionContext)。之后会通过CreatePeerConnection-PeerConnection功能去继续分析WebRTC的整体脉络,力求全面、清晰、深入浅出。
That is all.