创建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 工厂的创建
- 创建PeerConnectionFactory 工厂,调用的函数 webrtc::CreatePeerConnectionFactory,此方法将返回一个pc_connection,参数还是比较多,有10个之多。我们先看下在webrtc 中client 中的Conductor 的调用。
- 可以发现传入的参数,只有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.
//
};