webrtc源码学习 - 点对点(P2P)链接过程(peer connection)

创建PC

pc 是 peer connection 的简写,以下文章中pc 都特指 peer connection
PeerConnection 是webrtc 中链接过程非常重要的接口,提供了包括,链接、ICE、track、编解码流程控制

流程图

peer connection 的在整个框架中的位置
在这里插入图片描述

创建代码

  • 1、创建PeerConnectionFactory 工厂
  • 2、创建peer_connection
  • 3、创建audio track 和 video track
bool Conductor::InitializePeerConnection() {
  RTC_DCHECK(!peer_connection_factory_);
  RTC_DCHECK(!peer_connection_);
  //1. 创建PeerConnectionFactory 工厂
  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;
  }
  //2. 创建peer_connection
  if (!CreatePeerConnection(/*dtls=*/true)) {
    main_wnd_->MessageBox("Error", "CreatePeerConnection failed", true);
    DeletePeerConnection();
  }
  //3. 创建audio track 和 video track
  AddTracks();

  return peer_connection_ != nullptr;
}

1、创建PC工厂的过程

类图(PC工厂和 PC )
在这里插入图片描述

PC 工厂的创建

  1. 创建PeerConnectionFactory 工厂,调用的函数 webrtc::CreatePeerConnectionFactory,此方法将返回一个pc_connection,参数还是比较多,有10个之多。我们先看下在webrtc 中client 中的Conductor 的调用。
  2. 可以发现传入的参数,只有4个音视频codec 的工厂。其他的参数都为nullptr,后面我们会看下这些参数的作用

  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 */);

CreatePeerConnectionFactory 的定义,只是简单的函数封装,构建了PeerConnectionFactoryDependencies ,具体的含义等到后边会介绍

  • 1、media engine ,参数包括:adm, 4个音视频 codec 工厂,audio_mixer, audio_processing ,7个参数都是由参数传入的。
  • 2、创建call 工厂 ,不依赖参数
  • 3、创建EventLog 工厂
  • 4、构建dependence
  • 5、传入dependence调用CreateModularPeerConnectionFactory
rtc::scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory(
    rtc::Thread* network_thread,
    rtc::Thread* worker_thread,
    rtc::Thread* signaling_thread,
    rtc::scoped_refptr<AudioDeviceModule> default_adm,
    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
    std::unique_ptr<VideoEncoderFactory> video_encoder_factory,
    std::unique_ptr<VideoDecoderFactory> video_decoder_factory,
    rtc::scoped_refptr<AudioMixer> audio_mixer,
    rtc::scoped_refptr<AudioProcessing> audio_processing) {

	//1. 创建meida_engin,依赖7个参数
  if (!audio_processing)
    audio_processing = AudioProcessingBuilder().Create();

  std::unique_ptr<cricket::MediaEngineInterface> media_engine =
      cricket::WebRtcMediaEngineFactory::Create(
          default_adm, audio_encoder_factory, audio_decoder_factory,
          std::move(video_encoder_factory), std::move(video_decoder_factory),
          audio_mixer, audio_processing);
  //2. 创建call 工厂
  std::unique_ptr<CallFactoryInterface> call_factory = CreateCallFactory();
  //3. 创建EventLog 工厂
  std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory =
      CreateRtcEventLogFactory();

  //4. 构建dependence
  PeerConnectionFactoryDependencies dependencies;
  //4.1 传参设置
  dependencies.network_thread = network_thread;
  dependencies.worker_thread = worker_thread;
  dependencies.signaling_thread = signaling_thread;

  //4.1 有上面1-3步进行创建
  dependencies.media_engine = std::move(media_engine);
  dependencies.call_factory = std::move(call_factory);
  dependencies.event_log_factory = std::move(event_log_factory);

  //5. 传入dependencies 创建PC Factory
  return CreateModularPeerConnectionFactory(std::move(dependencies));
}

CreateModularPeerConnectionFactory 的实现

  • 1、创建pc_factory,参数dependencies
  • 2、调用PeerConnectionFactory::Initialize,需要同步调用,但是需要要求在signaling_thread(信令线程)执行,等待执行结果使用到跨线程同步执行。跨线程可参考 webrtc源码学习 - 3种异步处理 中2.3 小结
  • 3、返回工厂代理,保证pc_factor了所有的调用接口,是在signaling_thread线程中运行的。Proxy 的实现可参考webrtc源码学习 - PROXY 类对象跨线程同步问题
rtc::scoped_refptr<PeerConnectionFactoryInterface>
CreateModularPeerConnectionFactory(
    PeerConnectionFactoryDependencies dependencies) {
	//1. 创建pc_factory,参数dependencies
  rtc::scoped_refptr<PeerConnectionFactory> pc_factory(
      new rtc::RefCountedObject<PeerConnectionFactory>(
          std::move(dependencies)));
  
  //2. 调用PeerConnectionFactory::Initialize,需要同步调用,
  //   但是需要要求在signaling_thread(信令线程)执行,等待执行结果使用到跨线程执行结果
  MethodCall0<PeerConnectionFactory, bool> call(
      pc_factory.get(), &PeerConnectionFactory::Initialize);
  bool result = call.Marshal(RTC_FROM_HERE, pc_factory->signaling_thread());

  if (!result) {
    return nullptr;
  }
  //3. 返回工厂代理,保证pc_factor了所有的调用接口,是在signaling_thread线程中运行的。
  return PeerConnectionFactoryProxy::Create(pc_factory->signaling_thread(),
                                            pc_factory);
}

PeerConnectionFactory 构造函数

  • 如果3个线程没有创建(设置),就自己创建(设置)3个线程
PeerConnectionFactory::PeerConnectionFactory(
    PeerConnectionFactoryDependencies dependencies)
    : wraps_current_thread_(false),
      network_thread_(dependencies.network_thread),
      worker_thread_(dependencies.worker_thread),
      signaling_thread_(dependencies.signaling_thread),
      task_queue_factory_(std::move(dependencies.task_queue_factory)),
      media_engine_(std::move(dependencies.media_engine)),
      call_factory_(std::move(dependencies.call_factory)),
      event_log_factory_(std::move(dependencies.event_log_factory)),
      fec_controller_factory_(std::move(dependencies.fec_controller_factory)),
      network_state_predictor_factory_(
          std::move(dependencies.network_state_predictor_factory)),
      injected_network_controller_factory_(
          std::move(dependencies.network_controller_factory)),
      media_transport_factory_(
          std::move(dependencies.media_transport_factory)) {

  //1. 创建网络线程,所有网络请求都是在此线程处理
  if (!network_thread_) {
    owned_network_thread_ = rtc::Thread::CreateWithSocketServer();
    owned_network_thread_->SetName("pc_network_thread", nullptr);
    owned_network_thread_->Start();
    network_thread_ = owned_network_thread_.get();
  }

  //2. 工作线程
  if (!worker_thread_) {
    owned_worker_thread_ = rtc::Thread::Create();
    owned_worker_thread_->SetName("pc_worker_thread", nullptr);
    owned_worker_thread_->Start();
    worker_thread_ = owned_worker_thread_.get();
  }

  //3. 信令相关的处理,在signaling_thread_线程执行,运行的线程就是signal_thread
  if (!signaling_thread_) {
    signaling_thread_ = rtc::Thread::Current();
    if (!signaling_thread_) {
      // If this thread isn't already wrapped by an rtc::Thread, create a
      // wrapper and own it in this class.
      signaling_thread_ = rtc::ThreadManager::Instance()->WrapCurrentThread();
      wraps_current_thread_ = true;
    }
  }
}

在之前一步中,我知道,在signal_thread 同步执行了 PeerConnectionFactory::Initialize,我们来看下具体的实现

  • 创建network manager
  • 创建socket 工厂,运行在网络线程
  • 创建和初始化ChannelManager ,依赖参数media_engine_ ,RtpDataEngine,worker_thread_,network_thread_
bool PeerConnectionFactory::Initialize() {
  RTC_DCHECK(signaling_thread_->IsCurrent());
  rtc::InitRandom(rtc::Time32());
  //1. 创建network manager
  default_network_manager_.reset(new rtc::BasicNetworkManager());
  if (!default_network_manager_) {
    return false;
  }
  //2. 创建socket 工厂,运行在网络线程
  default_socket_factory_.reset(
      new rtc::BasicPacketSocketFactory(network_thread_));
  if (!default_socket_factory_) {
    return false;
  }
  
  //3. 创建和初始化ChannelManager ,依赖参数media_engine_ ,RtpDataEngine,worker_thread_,network_thread_
  channel_manager_ = absl::make_unique<cricket::ChannelManager>(
      std::move(media_engine_), absl::make_unique<cricket::RtpDataEngine>(),
      worker_thread_, network_thread_);

  channel_manager_->SetVideoRtxEnabled(true);
  if (!channel_manager_->Init()) {
    return false;
  }

  return true;
}

工厂中包含很多的属性,在工厂中属性可以理解为,为创建每个pc 所依赖的资源。

class PeerConnectionFactory : public PeerConnectionFactoryInterface {
parivate:
rtc::Thread* network_thread_;
  rtc::Thread* worker_thread_;
  rtc::Thread* signaling_thread_;
  std::unique_ptr<rtc::Thread> owned_network_thread_;
  std::unique_ptr<rtc::Thread> owned_worker_thread_;
  const std::unique_ptr<TaskQueueFactory> task_queue_factory_; //任务队列
  Options options_;
  std::unique_ptr<cricket::ChannelManager> channel_manager_;   //通道管理
  std::unique_ptr<rtc::BasicNetworkManager> default_network_manager_;//网络管理
  std::unique_ptr<rtc::BasicPacketSocketFactory> default_socket_factory_;//
  std::unique_ptr<cricket::MediaEngineInterface> media_engine_;
  std::unique_ptr<webrtc::CallFactoryInterface> call_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<MediaTransportFactory> media_transport_factory_;
};

PeerConnectionFactory 的函数的功能

  • 最重要的就是创建cp
  • 获取rtp
  • 创建媒体流
  • 创建音视频track
  • 获取一些属性
class PeerConnectionFactory : public PeerConnectionFactoryInterface {
 public:
  void SetOptions(const Options& options) override;
  // 1. 创建pc
  rtc::scoped_refptr<PeerConnectionInterface> CreatePeerConnection(
      const PeerConnectionInterface::RTCConfiguration& configuration,
      std::unique_ptr<cricket::PortAllocator> allocator,
      std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
      PeerConnectionObserver* observer) override;

  rtc::scoped_refptr<PeerConnectionInterface> CreatePeerConnection(
      const PeerConnectionInterface::RTCConfiguration& configuration,
      PeerConnectionDependencies dependencies) override;

  bool Initialize();
  // 2. 获取RTP 能力
  RtpCapabilities GetRtpSenderCapabilities(
      cricket::MediaType kind) const override;

  RtpCapabilities GetRtpReceiverCapabilities(
      cricket::MediaType kind) const override;
  // 3. 创建媒体流 
  rtc::scoped_refptr<MediaStreamInterface> CreateLocalMediaStream(
      const std::string& stream_id) override;

  rtc::scoped_refptr<AudioSourceInterface> CreateAudioSource(
      const cricket::AudioOptions& options) override;

  // 4. 创建audio /video track
  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;
  // 5. Aec 文件
  bool StartAecDump(rtc::PlatformFile file, int64_t max_size_bytes) override;
  void StopAecDump() override;

  // 6. sctp 传输
  virtual std::unique_ptr<cricket::SctpTransportInternalFactory>
  CreateSctpTransportInternalFactory();

  // 7. 获取一些属性
  virtual cricket::ChannelManager* channel_manager();

  rtc::Thread* signaling_thread() {
    // This method can be called on a different thread when the factory is
    // created in CreatePeerConnectionFactory().
    return signaling_thread_;
  }
  rtc::Thread* worker_thread() { return worker_thread_; }
  rtc::Thread* network_thread() { return network_thread_; }

  const Options& options() const { return options_; }

  MediaTransportFactory* media_transport_factory() {
    return media_transport_factory_.get();
  }

};

PC 的创建过程

client 是pc_factory_proxy 创建的pc,大概分成2部分,接下来会分成2部分介绍,单独介绍下RTCConfiguration 和 PC 的初始化流程

  • 参数的构建,rtc config 的配置
  • 传入rtcconfig 创建 pc
bool Conductor::CreatePeerConnection(bool dtls) {
  RTC_DCHECK(peer_connection_factory_);
  RTC_DCHECK(!peer_connection_);

  //1. rtc config的配置
  webrtc::PeerConnectionInterface::RTCConfiguration config;
  config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;
  config.enable_dtls_srtp = dtls;
  webrtc::PeerConnectionInterface::IceServer server;
  server.uri = GetPeerConnectionString();
  config.servers.push_back(server);
  //2. 传入rtcconfig 创建pc
  peer_connection_ = peer_connection_factory_->CreatePeerConnection(
      config, nullptr, nullptr, this);
  return peer_connection_ != nullptr;
}

RTCConfiguration 介绍

todo : 作者去了解 ICE 等概念去了!!!回来在补充

BundlePolicy

在同一个端口已多路复用技术,传输多种媒体信号。
可以设置使用绑定的首选策略,不管策略是怎样的,应用会尝试协商绑定在同一个端口传输。

 // https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24#section-4.1.1
  enum BundlePolicy {
    kBundlePolicyBalanced,		//
    kBundlePolicyMaxBundle,		//
    kBundlePolicyMaxCompat
  };

m字段
​ m=(媒体)(端口)(传送层)(格式列表)

​ m=audio 2345 RTP/SAVPF 111 103 104

struct RTC_EXPORT RTCConfiguration {
    // This struct is subject to reorganization, both for naming
    // consistency, and to group settings to match where they are used
    // in the implementation. To do that, we need getter and setter
    // methods for all settings which are of interest to applications,
    // Chrome in particular.

    static const int kUndefined = -1;
    // Default maximum number of packets in the audio jitter buffer.
    static const int kAudioJitterBufferMaxPackets = 200;
    // ICE connection receiving timeout for aggressive configuration.
    static const int kAggressiveIceConnectionReceivingTimeout = 1000;

    
    // The below few fields mirror the standard RTCConfiguration dictionary:
    // https://w3c.github.io/webrtc-pc/#rtcconfiguration-dictionary
    

    // TODO(pthatcher): Rename this ice_servers, but update Chromium
    // at the same time.
    IceServers servers;
    // TODO(pthatcher): Rename this ice_transport_type, but update
    // Chromium at the same time.
    IceTransportsType type = kAll;
    BundlePolicy bundle_policy = kBundlePolicyBalanced;
    RtcpMuxPolicy rtcp_mux_policy = kRtcpMuxPolicyRequire;
    std::vector<rtc::scoped_refptr<rtc::RTCCertificate>> certificates;
    int ice_candidate_pool_size = 0;

    //
    // The below fields correspond to constraints from the deprecated
    // constraints interface for constructing a PeerConnection.
    //
    // absl::optional fields can be "missing", in which case the implementation
    // default will be used.
    //

    // If set to true, don't gather IPv6 ICE candidates.
    // TODO(deadbeef): Remove this? IPv6 support has long stopped being
    // experimental
    bool disable_ipv6 = false;

    // If set to true, don't gather IPv6 ICE candidates on Wi-Fi.
    // Only intended to be used on specific devices. Certain phones disable IPv6
    // when the screen is turned off and it would be better to just disable the
    // IPv6 ICE candidates on Wi-Fi in those cases.
    bool disable_ipv6_on_wifi = false;

    // By default, the PeerConnection will use a limited number of IPv6 network
    // interfaces, in order to avoid too many ICE candidate pairs being created
    // and delaying ICE completion.
    //
    // Can be set to INT_MAX to effectively disable the limit.
    int max_ipv6_networks = cricket::kDefaultMaxIPv6Networks;

    // Exclude link-local network interfaces
    // from considertaion for gathering ICE candidates.
    bool disable_link_local_networks = false;

    // If set to true, use RTP data channels instead of SCTP.
    // TODO(deadbeef): Remove this. We no longer commit to supporting RTP data
    // channels, though some applications are still working on moving off of
    // them.
    bool enable_rtp_data_channel = false;

    // Minimum bitrate at which screencast video tracks will be encoded at.
    // This means adding padding bits up to this bitrate, which can help
    // when switching from a static scene to one with motion.
    absl::optional<int> screencast_min_bitrate;

    // Use new combined audio/video bandwidth estimation?
    absl::optional<bool> combined_audio_video_bwe;

    // TODO(bugs.webrtc.org/9891) - Move to crypto_options
    // Can be used to disable DTLS-SRTP. This should never be done, but can be
    // useful for testing purposes, for example in setting up a loopback call
    // with a single PeerConnection.
    absl::optional<bool> enable_dtls_srtp;

    /
    // The below fields are not part of the standard.
    /

    // Can be used to disable TCP candidate generation.
    TcpCandidatePolicy tcp_candidate_policy = kTcpCandidatePolicyEnabled;

    // Can be used to avoid gathering candidates for a "higher cost" network,
    // if a lower cost one exists. For example, if both Wi-Fi and cellular
    // interfaces are available, this could be used to avoid using the cellular
    // interface.
    CandidateNetworkPolicy candidate_network_policy =
        kCandidateNetworkPolicyAll;

    // The maximum number of packets that can be stored in the NetEq audio
    // jitter buffer. Can be reduced to lower tolerated audio latency.
    int audio_jitter_buffer_max_packets = kAudioJitterBufferMaxPackets;

    // Whether to use the NetEq "fast mode" which will accelerate audio quicker
    // if it falls behind.
    bool audio_jitter_buffer_fast_accelerate = false;

    // The minimum delay in milliseconds for the audio jitter buffer.
    int audio_jitter_buffer_min_delay_ms = 0;

    // Whether the audio jitter buffer adapts the delay to retransmitted
    // packets.
    bool audio_jitter_buffer_enable_rtx_handling = false;

    // Timeout in milliseconds before an ICE candidate pair is considered to be
    // "not receiving", after which a lower priority candidate pair may be
    // selected.
    int ice_connection_receiving_timeout = kUndefined;

    // Interval in milliseconds at which an ICE "backup" candidate pair will be
    // pinged. This is a candidate pair which is not actively in use, but may
    // be switched to if the active candidate pair becomes unusable.
    //
    // This is relevant mainly to Wi-Fi/cell handoff; the application may not
    // want this backup cellular candidate pair pinged frequently, since it
    // consumes data/battery.
    int ice_backup_candidate_pair_ping_interval = kUndefined;

    // Can be used to enable continual gathering, which means new candidates
    // will be gathered as network interfaces change. Note that if continual
    // gathering is used, the candidate removal API should also be used, to
    // avoid an ever-growing list of candidates.
    ContinualGatheringPolicy continual_gathering_policy = GATHER_ONCE;

    // If set to true, candidate pairs will be pinged in order of most likely
    // to work (which means using a TURN server, generally), rather than in
    // standard priority order.
    bool prioritize_most_likely_ice_candidate_pairs = false;

    // Implementation defined settings. A public member only for the benefit of
    // the implementation. Applications must not access it directly, and should
    // instead use provided accessor methods, e.g., set_cpu_adaptation.
    struct cricket::MediaConfig media_config;

    // If set to true, only one preferred TURN allocation will be used per
    // network interface. UDP is preferred over TCP and IPv6 over IPv4. This
    // can be used to cut down on the number of candidate pairings.
    bool prune_turn_ports = false;

    // If set to true, this means the ICE transport should presume TURN-to-TURN
    // candidate pairs will succeed, even before a binding response is received.
    // This can be used to optimize the initial connection time, since the DTLS
    // handshake can begin immediately.
    bool presume_writable_when_fully_relayed = false;

    // If true, "renomination" will be added to the ice options in the transport
    // description.
    // See: https://tools.ietf.org/html/draft-thatcher-ice-renomination-00
    bool enable_ice_renomination = false;

    // If true, the ICE role is re-determined when the PeerConnection sets a
    // local transport description that indicates an ICE restart.
    //
    // This is standard RFC5245 ICE behavior, but causes unnecessary role
    // thrashing, so an application may wish to avoid it. This role
    // re-determining was removed in ICEbis (ICE v2).
    bool redetermine_role_on_ice_restart = true;

    // The following fields define intervals in milliseconds at which ICE
    // connectivity checks are sent.
    //
    // We consider ICE is "strongly connected" for an agent when there is at
    // least one candidate pair that currently succeeds in connectivity check
    // from its direction i.e. sending a STUN ping and receives a STUN ping
    // response, AND all candidate pairs have sent a minimum number of pings for
    // connectivity (this number is implementation-specific). Otherwise, ICE is
    // considered in "weak connectivity".
    //
    // Note that the above notion of strong and weak connectivity is not defined
    // in RFC 5245, and they apply to our current ICE implementation only.
    //
    // 1) ice_check_interval_strong_connectivity defines the interval applied to
    // ALL candidate pairs when ICE is strongly connected, and it overrides the
    // default value of this interval in the ICE implementation;
    // 2) ice_check_interval_weak_connectivity defines the counterpart for ALL
    // pairs when ICE is weakly connected, and it overrides the default value of
    // this interval in the ICE implementation;
    // 3) ice_check_min_interval defines the minimal interval (equivalently the
    // maximum rate) that overrides the above two intervals when either of them
    // is less.
    absl::optional<int> ice_check_interval_strong_connectivity;
    absl::optional<int> ice_check_interval_weak_connectivity;
    absl::optional<int> ice_check_min_interval;

    // The min time period for which a candidate pair must wait for response to
    // connectivity checks before it becomes unwritable. This parameter
    // overrides the default value in the ICE implementation if set.
    absl::optional<int> ice_unwritable_timeout;

    // The min number of connectivity checks that a candidate pair must sent
    // without receiving response before it becomes unwritable. This parameter
    // overrides the default value in the ICE implementation if set.
    absl::optional<int> ice_unwritable_min_checks;

    // The min time period for which a candidate pair must wait for response to
    // connectivity checks it becomes inactive. This parameter overrides the
    // default value in the ICE implementation if set.
    absl::optional<int> ice_inactive_timeout;

    // The interval in milliseconds at which STUN candidates will resend STUN
    // binding requests to keep NAT bindings open.
    absl::optional<int> stun_candidate_keepalive_interval;

    // ICE Periodic Regathering
    // If set, WebRTC will periodically create and propose candidates without
    // starting a new ICE generation. The regathering happens continuously with
    // interval specified in milliseconds by the uniform distribution [a, b].
    absl::optional<rtc::IntervalRange> ice_regather_interval_range;

    // Optional TurnCustomizer.
    // With this class one can modify outgoing TURN messages.
    // The object passed in must remain valid until PeerConnection::Close() is
    // called.
    webrtc::TurnCustomizer* turn_customizer = nullptr;

    // Preferred network interface.
    // A candidate pair on a preferred network has a higher precedence in ICE
    // than one on an un-preferred network, regardless of priority or network
    // cost.
    absl::optional<rtc::AdapterType> network_preference;

    // Configure the SDP semantics used by this PeerConnection. Note that the
    // WebRTC 1.0 specification requires kUnifiedPlan semantics. The
    // RtpTransceiver API is only available with kUnifiedPlan semantics.
    //
    // kPlanB will cause PeerConnection to create offers and answers with at
    // most one audio and one video m= section with multiple RtpSenders and
    // RtpReceivers specified as multiple a=ssrc lines within the section. This
    // will also cause PeerConnection to ignore all but the first m= section of
    // the same media type.
    //
    // kUnifiedPlan will cause PeerConnection to create offers and answers with
    // multiple m= sections where each m= section maps to one RtpSender and one
    // RtpReceiver (an RtpTransceiver), either both audio or both video. This
    // will also cause PeerConnection to ignore all but the first a=ssrc lines
    // that form a Plan B stream.
    //
    // For users who wish to send multiple audio/video streams and need to stay
    // interoperable with legacy WebRTC implementations or use legacy APIs,
    // specify kPlanB.
    //
    // For all other users, specify kUnifiedPlan.
    SdpSemantics sdp_semantics = SdpSemantics::kPlanB;

    // TODO(bugs.webrtc.org/9891) - Move to crypto_options or remove.
    // Actively reset the SRTP parameters whenever the DTLS transports
    // underneath are reset for every offer/answer negotiation.
    // This is only intended to be a workaround for crbug.com/835958
    // WARNING: This would cause RTP/RTCP packets decryption failure if not used
    // correctly. This flag will be deprecated soon. Do not rely on it.
    bool active_reset_srtp_params = false;

    // If MediaTransportFactory is provided in PeerConnectionFactory, this flag
    // informs PeerConnection that it should use the MediaTransportInterface for
    // media (audio/video). It's invalid to set it to |true| if the
    // MediaTransportFactory wasn't provided.
    bool use_media_transport = false;

    // If MediaTransportFactory is provided in PeerConnectionFactory, this flag
    // informs PeerConnection that it should use the MediaTransportInterface for
    // data channels.  It's invalid to set it to |true| if the
    // MediaTransportFactory wasn't provided.  Data channels over media
    // transport are not compatible with RTP or SCTP data channels.  Setting
    // both |use_media_transport_for_data_channels| and
    // |enable_rtp_data_channel| is invalid.
    bool use_media_transport_for_data_channels = false;

    // Defines advanced optional cryptographic settings related to SRTP and
    // frame encryption for native WebRTC. Setting this will overwrite any
    // settings set in PeerConnectionFactory (which is deprecated).
    absl::optional<CryptoOptions> crypto_options;

    // Configure if we should include the SDP attribute extmap-allow-mixed in
    // our offer. Although we currently do support this, it's not included in
    // our offer by default due to a previous bug that caused the SDP parser to
    // abort parsing if this attribute was present. This is fixed in Chrome 71.
    // TODO(webrtc:9985): Change default to true once sufficient time has
    // passed.
    bool offer_extmap_allow_mixed = false;

    //
    // Don't forget to update operator== if adding something.
    //
  };
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值