(Android-RTC-9)PeerConnectionFactory

开篇前瞎扯。很久没发技术文章了,此文一直放着草稿箱没有完成,感觉自己在家庭和工作中找到了拖延的借口,开始慢慢变得懒惰了,那是万万不行的。恰逢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.

### 回答1: List<Ticket> getAllTickets() { return ticketDAO.getAllTickets(); } @Override public void addTicket(Ticket ticket) { ticketDAO.addTicket(ticket); } } ``` 6. 创建View层。在View层中,你需要编Temper-RTC是一种集成了温度传感器和实时时钟(RTC)功能的电子元器写一些页面,用于显示用户信息和票务信息。这些页面需要调用Service层的方法,并将返回的件。它通常用于需要同时测量温度和计时的应用场景,例如温度控制系统、数据显示在页面上。代码如下: - user.jsp ```jsp <%@ page language="java" contentType="text/html;环境监测系统、电子钟表等。 Temper-RTC的温度传感器通常采用数字式温 charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/j度传感器,可以提供高精度、高稳定性的温度测量结果。其RTC功能则可以提sp/jstl/core" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>供高精度的时间计数和日期记录,可以用于实现时间戳、定时器、日历等功能。 个人中心</title> </head> <body> <h1>个人中心</h1> <h2在使用Temper-RTC时,需要注意正确配置温度传感器和RTC参数,以确保其测量精度>用户信息</h2> <table> <thead> <tr> <th>ID</th> <th和计时精度符合要求。同时,还需要注意电源和引脚连接等方面的问题,以避>用户名</th> <th>邮箱</th> </tr> </thead> <tbody> <tr免电路干扰和信号损失等问题。 ### 回答2: temper-rtc是一种温度记录器和控制器。它主要用于监测和控制温度,广泛应用于实验室、医疗、食品加工和其他需要精确温度控制的领域。 temper-rtc具有高精度的温度测量能力,可以实时监测温度变化,并显示在屏幕上。同时,它还可以将温度数据存储在内部存储器中,以便之后进行数据分析和记录。此外,temper-rtc还可以通过无线或有线方式与计算机或其他外部设备连接,以便实现远程监控和控制。 temper-rtc还具有温度控制功能。用户可以设置温度上下限,并根据实际需求进行调整。一旦温度超过或低于设定的限制,temper-rtc将自动触发报警系统,以提醒用户温度异常。此外,temper-rtc还可以根据预设的控制参数自动调整温度控制设备的工作,以维持温度稳定。 temper-rtc具有小巧、便携和易于操作的特点。它通常由一个控制器和一个温度传感器组成,用户可以轻松携带和安装。控制器上配备了直观的操作界面和显示屏,用户可以方便地设置参数和查看温度信息。 总而言之,temper-rtc是一种功能强大的温度记录器和控制器,可以准确测量和监控温度,并实现远程控制和报警功能。它在各种需要精确温度控制的环境中广泛应用,为用户提供了方便、灵活和可靠的温度管理解决方案。 ### 回答3: temper-rtc是一款基于实时时钟(RTC)的温度传感器。RTC是一种能够实时测量和记录时间的电子设备,常用于计算机、电子设备和检测设备中。temper-rtc结合了RTC技术和温度传感器技术,提供了实时测量环境温度的功能。 temper-rtc的工作原理是通过温度传感器实时感知环境的温度,并将温度数据传输给RTCRTC通过内部的时钟来记录测量的时间,并保存温度数据。用户可以通过连接temper-rtc与电脑或其他设备,读取温度数据并进行分析和处理。 temper-rtc有多种用途。首先,它可以用于监控环境温度,例如在实验室、仓库或其他需要保持特定温度的场所。其次,temper-rtc可以用于数据记录和分析。用户可以使用temper-rtc来记录温度变化情况,比如在气象研究中分析气温的变化趋势。最后,temper-rtc也可以用于温度控制系统中。通过实时监测温度,并根据预设条件调整环境温度,实现温度的自动调控。 总之,temper-rtc是一款基于实时时钟的温度传感器,结合了RTC技术和温度传感器技术,能够实时感知环境温度并记录温度数据。它有广泛的应用领域,包括环境监测、数据记录和分析以及温度控制系统中。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr_Zzr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值