1 /*
2 * Copyright 2004 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "pc/peer_connection_factory.h"
12
13 #include <memory>
14 #include <utility>
15
16 #include "absl/strings/match.h"
17 #include "api/async_resolver_factory.h"
18 #include "api/call/call_factory_interface.h"
19 #include "api/fec_controller.h"
20 #include "api/ice_transport_interface.h"
21 #include "api/media_stream_proxy.h"
22 #include "api/media_stream_track_proxy.h"
23 #include "api/network_state_predictor.h"
24 #include "api/packet_socket_factory.h"
25 #include "api/peer_connection_factory_proxy.h"
26 #include "api/peer_connection_proxy.h"
27 #include "api/rtc_event_log/rtc_event_log.h"
28 #include "api/sequence_checker.h"
29 #include "api/transport/bitrate_settings.h"
30 #include "api/units/data_rate.h"
31 #include "call/audio_state.h"
32 #include "media/base/media_engine.h"
33 #include "p2p/base/basic_async_resolver_factory.h"
34 #include "p2p/base/basic_packet_socket_factory.h"
35 #include "p2p/base/default_ice_transport_factory.h"
36 #include "p2p/client/basic_port_allocator.h"
37 #include "pc/audio_track.h"
38 #include "pc/local_audio_source.h"
39 #include "pc/media_stream.h"
40 #include "pc/peer_connection.h"
41 #include "pc/rtp_parameters_conversion.h"
42 #include "pc/session_description.h"
43 #include "pc/video_track.h"
44 #include "rtc_base/checks.h"
45 #include "rtc_base/experiments/field_trial_parser.h"
46 #include "rtc_base/experiments/field_trial_units.h"
47 #include "rtc_base/location.h"
48 #include "rtc_base/logging.h"
49 #include "rtc_base/numerics/safe_conversions.h"
50 #include "rtc_base/ref_counted_object.h"
51 #include "rtc_base/system/file_wrapper.h"
52
53 namespace webrtc {
54
55 rtc::scoped_refptr<PeerConnectionFactoryInterface>
CreateModularPeerConnectionFactory(PeerConnectionFactoryDependencies dependencies)56 CreateModularPeerConnectionFactory(
57 PeerConnectionFactoryDependencies dependencies) {
58 // The PeerConnectionFactory must be created on the signaling thread.
59 if (dependencies.signaling_thread &&
60 !dependencies.signaling_thread->IsCurrent()) {
61 return dependencies.signaling_thread
62 ->Invoke<rtc::scoped_refptr<PeerConnectionFactoryInterface>>(
63 RTC_FROM_HERE, [&dependencies] {
64 return CreateModularPeerConnectionFactory(
65 std::move(dependencies));
66 });
67 }
68
69 auto pc_factory = PeerConnectionFactory::Create(std::move(dependencies));
70 if (!pc_factory) {
71 return nullptr;
72 }
73 // Verify that the invocation and the initialization ended up agreeing on the
74 // thread.
75 RTC_DCHECK_RUN_ON(pc_factory->signaling_thread());
76 return PeerConnectionFactoryProxy::Create(
77 pc_factory->signaling_thread(), pc_factory->worker_thread(), pc_factory);
78 }
79
80 // Static
Create(PeerConnectionFactoryDependencies dependencies)81 rtc::scoped_refptr<PeerConnectionFactory> PeerConnectionFactory::Create(
82 PeerConnectionFactoryDependencies dependencies) {
83 auto context = ConnectionContext::Create(&dependencies);
84 if (!context) {
85 return nullptr;
86 }
87 return new rtc::RefCountedObject<PeerConnectionFactory>(context,
88 &dependencies);
89 }
90
PeerConnectionFactory(rtc::scoped_refptr<ConnectionContext> context,PeerConnectionFactoryDependencies * dependencies)91 PeerConnectionFactory::PeerConnectionFactory(
92 rtc::scoped_refptr<ConnectionContext> context,
93 PeerConnectionFactoryDependencies* dependencies)
94 : context_(context),
95 task_queue_factory_(std::move(dependencies->task_queue_factory)),
96 event_log_factory_(std::move(dependencies->event_log_factory)),
97 fec_controller_factory_(std::move(dependencies->fec_controller_factory)),
98 network_state_predictor_factory_(
99 std::move(dependencies->network_state_predictor_factory)),
100 injected_network_controller_factory_(
101 std::move(dependencies->network_controller_factory)),
102 neteq_factory_(std::move(dependencies->neteq_factory)) {}
103
PeerConnectionFactory(PeerConnectionFactoryDependencies dependencies)104 PeerConnectionFactory::PeerConnectionFactory(
105 PeerConnectionFactoryDependencies dependencies)
106 : PeerConnectionFactory(ConnectionContext::Create(&dependencies),
107 &dependencies) {}
108
~PeerConnectionFactory()109 PeerConnectionFactory::~PeerConnectionFactory() {
110 RTC_DCHECK_RUN_ON(signaling_thread());
111 }
112
SetOptions(const Options & options)113 void PeerConnectionFactory::SetOptions(const Options& options) {
114 RTC_DCHECK_RUN_ON(signaling_thread());
115 options_ = options;
116 }
117
GetRtpSenderCapabilities(cricket::MediaType kind) const118 RtpCapabilities PeerConnectionFactory::GetRtpSenderCapabilities(
119 cricket::MediaType kind) const {
120 RTC_DCHECK_RUN_ON(signaling_thread());
121 switch (kind) {
122 case cricket::MEDIA_TYPE_AUDIO: {
123 cricket::AudioCodecs cricket_codecs;
124 channel_manager()->GetSupportedAudioSendCodecs(&cricket_codecs);
125 return ToRtpCapabilities(
126 cricket_codecs,
127 channel_manager()->GetDefaultEnabledAudioRtpHeaderExtensions());
128 }
129 case cricket::MEDIA_TYPE_VIDEO: {
130 cricket::VideoCodecs cricket_codecs;
131 channel_manager()->GetSupportedVideoSendCodecs(&cricket_codecs);
132 return ToRtpCapabilities(
133 cricket_codecs,
134 channel_manager()->GetDefaultEnabledVideoRtpHeaderExtensions());
135 }
136 case cricket::MEDIA_TYPE_DATA:
137 return RtpCapabilities();
138 case cricket::MEDIA_TYPE_UNSUPPORTED:
139 return RtpCapabilities();
140 }
141 RTC_CHECK_NOTREACHED();
142 }
143
GetRtpReceiverCapabilities(cricket::MediaType kind) const144 RtpCapabilities PeerConnectionFactory::GetRtpReceiverCapabilities(
145 cricket::MediaType kind) const {
146 RTC_DCHECK_RUN_ON(signaling_thread());
147 switch (kind) {
148 case cricket::MEDIA_TYPE_AUDIO: {
149 cricket::AudioCodecs cricket_codecs;
150 channel_manager()->GetSupportedAudioReceiveCodecs(&cricket_codecs);
151 return ToRtpCapabilities(
152 cricket_codecs,
153 channel_manager()->GetDefaultEnabledAudioRtpHeaderExtensions());
154 }
155 case cricket::MEDIA_TYPE_VIDEO: {
156 cricket::VideoCodecs cricket_codecs;
157 channel_manager()->GetSupportedVideoReceiveCodecs(&cricket_codecs);
158 return ToRtpCapabilities(
159 cricket_codecs,
160 channel_manager()->GetDefaultEnabledVideoRtpHeaderExtensions());
161 }
162 case cricket::MEDIA_TYPE_DATA:
163 return RtpCapabilities();
164 case cricket::MEDIA_TYPE_UNSUPPORTED:
165 return RtpCapabilities();
166 }
167 RTC_CHECK_NOTREACHED();
168 }
169
170 rtc::scoped_refptr<AudioSourceInterface>
CreateAudioSource(const cricket::AudioOptions & options)171 PeerConnectionFactory::CreateAudioSource(const cricket::AudioOptions& options) {
172 RTC_DCHECK(signaling_thread()->IsCurrent());
173 rtc::scoped_refptr<LocalAudioSource> source(
174 LocalAudioSource::Create(&options));
175 return source;
176 }
177
StartAecDump(FILE * file,int64_t max_size_bytes)178 bool PeerConnectionFactory::StartAecDump(FILE* file, int64_t max_size_bytes) {
179 RTC_DCHECK_RUN_ON(worker_thread());
180 return channel_manager()->StartAecDump(FileWrapper(file), max_size_bytes);
181 }
182
StopAecDump()183 void PeerConnectionFactory::StopAecDump() {
184 RTC_DCHECK_RUN_ON(worker_thread());
185 channel_manager()->StopAecDump();
186 }
187
188 rtc::scoped_refptr<PeerConnectionInterface>
CreatePeerConnection(const PeerConnectionInterface::RTCConfiguration & configuration,std::unique_ptr<cricket::PortAllocator> allocator,std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,PeerConnectionObserver * observer)189 PeerConnectionFactory::CreatePeerConnection(
190 const PeerConnectionInterface::RTCConfiguration& configuration,
191 std::unique_ptr<cricket::PortAllocator> allocator,
192 std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
193 PeerConnectionObserver* observer) {
194 // Convert the legacy API into the new dependency structure.
195 PeerConnectionDependencies dependencies(observer);
196 dependencies.allocator = std::move(allocator);
197 dependencies.cert_generator = std::move(cert_generator);
198 // Pass that into the new API.
199 return CreatePeerConnection(configuration, std::move(dependencies));
200 }
201
202 rtc::scoped_refptr<PeerConnectionInterface>
CreatePeerConnection(const PeerConnectionInterface::RTCConfiguration & configuration,PeerConnectionDependencies dependencies)203 PeerConnectionFactory::CreatePeerConnection(
204 const PeerConnectionInterface::RTCConfiguration& configuration,
205 PeerConnectionDependencies dependencies) {
206 auto result =
207 CreatePeerConnectionOrError(configuration, std::move(dependencies));
208 if (result.ok()) {
209 return result.MoveValue();
210 } else {
211 return nullptr;
212 }
213 }
214
215 RTCErrorOr<rtc::scoped_refptr<PeerConnectionInterface>>
CreatePeerConnectionOrError(const PeerConnectionInterface::RTCConfiguration & configuration,PeerConnectionDependencies dependencies)216 PeerConnectionFactory::CreatePeerConnectionOrError(
217 const PeerConnectionInterface::RTCConfiguration& configuration,
218 PeerConnectionDependencies dependencies) {
219 RTC_DCHECK_RUN_ON(signaling_thread());
220 RTC_DCHECK(!(dependencies.allocator && dependencies.packet_socket_factory))
221 << "You can't set both allocator and packet_socket_factory; "
222 "the former is going away (see bugs.webrtc.org/7447";
223
224 // Set internal defaults if optional dependencies are not set.
225 if (!dependencies.cert_generator) {
226 dependencies.cert_generator =
227 std::make_unique<rtc::RTCCertificateGenerator>(signaling_thread(),
228 network_thread());
229 }
230 if (!dependencies.allocator) {
231 rtc::PacketSocketFactory* packet_socket_factory;
232 if (dependencies.packet_socket_factory)
233 packet_socket_factory = dependencies.packet_socket_factory.get();
234 else
235 packet_socket_factory = context_->default_socket_factory();
236
237 dependencies.allocator = std::make_unique<cricket::BasicPortAllocator>(
238 context_->default_network_manager(), packet_socket_factory,
239 configuration.turn_customizer);
240 }
241
242 if (!dependencies.async_resolver_factory) {
243 dependencies.async_resolver_factory =
244 std::make_unique<webrtc::BasicAsyncResolverFactory>();
245 }
246
247 if (!dependencies.ice_transport_factory) {
248 dependencies.ice_transport_factory =
249 std::make_unique<DefaultIceTransportFactory>();
250 }
251
252 dependencies.allocator->SetNetworkIgnoreMask(options().network_ignore_mask);
253
254 std::unique_ptr<RtcEventLog> event_log =
255 worker_thread()->Invoke<std::unique_ptr<RtcEventLog>>(
256 RTC_FROM_HERE, [this] { return CreateRtcEventLog_w(); });
257
258 std::unique_ptr<Call> call = worker_thread()->Invoke<std::unique_ptr<Call>>(
259 RTC_FROM_HERE,
260 [this, &event_log] { return CreateCall_w(event_log.get()); });
261
262 auto result = PeerConnection::Create(context_, options_, std::move(event_log),
263 std::move(call), configuration,
264 std::move(dependencies));
265 if (!result.ok()) {
266 return result.MoveError();
267 }
268 // We configure the proxy with a pointer to the network thread for methods
269 // that need to be invoked there rather than on the signaling thread.
270 // Internally, the proxy object has a member variable named |worker_thread_|
271 // which will point to the network thread (and not the factory's
272 // worker_thread()). All such methods have thread checks though, so the code
273 // should still be clear (outside of macro expansion).
274 rtc::scoped_refptr<PeerConnectionInterface> result_proxy =
275 PeerConnectionProxy::Create(signaling_thread(), network_thread(),
276 result.MoveValue());
277 return result_proxy;
278 }
279
280 rtc::scoped_refptr<MediaStreamInterface>
CreateLocalMediaStream(const std::string & stream_id)281 PeerConnectionFactory::CreateLocalMediaStream(const std::string& stream_id) {
282 RTC_DCHECK(signaling_thread()->IsCurrent());
283 return MediaStreamProxy::Create(signaling_thread(),
284 MediaStream::Create(stream_id));
285 }
286
CreateVideoTrack(const std::string & id,VideoTrackSourceInterface * source)287 rtc::scoped_refptr<VideoTrackInterface> PeerConnectionFactory::CreateVideoTrack(
288 const std::string& id,
289 VideoTrackSourceInterface* source) {
290 RTC_DCHECK(signaling_thread()->IsCurrent());
291 rtc::scoped_refptr<VideoTrackInterface> track(
292 VideoTrack::Create(id, source, worker_thread()));
293 return VideoTrackProxy::Create(signaling_thread(), worker_thread(), track);
294 }
295
CreateAudioTrack(const std::string & id,AudioSourceInterface * source)296 rtc::scoped_refptr<AudioTrackInterface> PeerConnectionFactory::CreateAudioTrack(
297 const std::string& id,
298 AudioSourceInterface* source) {
299 RTC_DCHECK(signaling_thread()->IsCurrent());
300 rtc::scoped_refptr<AudioTrackInterface> track(AudioTrack::Create(id, source));
301 return AudioTrackProxy::Create(signaling_thread(), track);
302 }
303
channel_manager()304 cricket::ChannelManager* PeerConnectionFactory::channel_manager() {
305 return context_->channel_manager();
306 }
307
CreateRtcEventLog_w()308 std::unique_ptr<RtcEventLog> PeerConnectionFactory::CreateRtcEventLog_w() {
309 RTC_DCHECK_RUN_ON(worker_thread());
310
311 auto encoding_type = RtcEventLog::EncodingType::Legacy;
312 if (IsTrialEnabled("WebRTC-RtcEventLogNewFormat"))
313 encoding_type = RtcEventLog::EncodingType::NewFormat;
314 return event_log_factory_
315 ? event_log_factory_->CreateRtcEventLog(encoding_type)
316 : std::make_unique<RtcEventLogNull>();
317 }
318
CreateCall_w(RtcEventLog * event_log)319 std::unique_ptr<Call> PeerConnectionFactory::CreateCall_w(
320 RtcEventLog* event_log) {
321 RTC_DCHECK_RUN_ON(worker_thread());
322
323 webrtc::Call::Config call_config(event_log, network_thread());
324 if (!channel_manager()->media_engine() || !context_->call_factory()) {
325 return nullptr;
326 }
327 call_config.audio_state =
328 channel_manager()->media_engine()->voice().GetAudioState();
329
330 FieldTrialParameter<DataRate> min_bandwidth("min",
331 DataRate::KilobitsPerSec(30));
332 FieldTrialParameter<DataRate> start_bandwidth("start",
333 DataRate::KilobitsPerSec(300));
334 FieldTrialParameter<DataRate> max_bandwidth("max",
335 DataRate::KilobitsPerSec(2000));
336 ParseFieldTrial({&min_bandwidth, &start_bandwidth, &max_bandwidth},
337 trials().Lookup("WebRTC-PcFactoryDefaultBitrates"));
338
339 call_config.bitrate_config.min_bitrate_bps =
340 rtc::saturated_cast<int>(min_bandwidth->bps());
341 call_config.bitrate_config.start_bitrate_bps =
342 rtc::saturated_cast<int>(start_bandwidth->bps());
343 call_config.bitrate_config.max_bitrate_bps =
344 rtc::saturated_cast<int>(max_bandwidth->bps());
345
346 call_config.fec_controller_factory = fec_controller_factory_.get();
347 call_config.task_queue_factory = task_queue_factory_.get();
348 call_config.network_state_predictor_factory =
349 network_state_predictor_factory_.get();
350 call_config.neteq_factory = neteq_factory_.get();
351
352 if (IsTrialEnabled("WebRTC-Bwe-InjectedCongestionController")) {
353 RTC_LOG(LS_INFO) << "Using injected network controller factory";
354 call_config.network_controller_factory =
355 injected_network_controller_factory_.get();
356 } else {
357 RTC_LOG(LS_INFO) << "Using default network controller factory";
358 }
359
360 call_config.trials = &trials();
361
362 return std::unique_ptr<Call>(
363 context_->call_factory()->CreateCall(call_config));
364 }
365
IsTrialEnabled(absl::string_view key) const366 bool PeerConnectionFactory::IsTrialEnabled(absl::string_view key) const {
367 return absl::StartsWith(trials().Lookup(key), "Enabled");
368 }
369
370 } // namespace webrtc
371