blob: 55f526800c593663a0832174a8612a9dd6f5b382 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:361/*
kjellander65c7f672016-02-12 08:05:012 * Copyright 2004 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:363 *
kjellander65c7f672016-02-12 08:05:014 * 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.
henrike@webrtc.org28e20752013-07-10 00:45:369 */
10
Steve Anton10542f22019-01-11 17:11:0011#include "pc/channel_manager.h"
henrike@webrtc.org28e20752013-07-10 00:45:3612
Steve Anton36b29d12017-10-30 16:57:4213#include <utility>
henrike@webrtc.org28e20752013-07-10 00:45:3614
Steve Anton64b626b2019-01-29 01:25:2615#include "absl/algorithm/container.h"
Karl Wiberg918f50c2018-07-05 09:40:3316#include "absl/memory/memory.h"
Niels Möller3c7d5992018-10-19 13:29:5417#include "absl/strings/match.h"
Steve Anton10542f22019-01-11 17:11:0018#include "media/base/media_constants.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3119#include "rtc_base/checks.h"
Yves Gerey3e707812018-11-28 15:47:4920#include "rtc_base/location.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3121#include "rtc_base/logging.h"
Yves Gerey3e707812018-11-28 15:47:4922#include "rtc_base/thread_checker.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3123#include "rtc_base/trace_event.h"
henrike@webrtc.org28e20752013-07-10 00:45:3624
25namespace cricket {
26
Steve Antonc9e15602017-11-06 23:40:0927ChannelManager::ChannelManager(
28 std::unique_ptr<MediaEngineInterface> media_engine,
29 std::unique_ptr<DataEngineInterface> data_engine,
30 rtc::Thread* worker_thread,
31 rtc::Thread* network_thread)
32 : media_engine_(std::move(media_engine)),
33 data_engine_(std::move(data_engine)),
34 main_thread_(rtc::Thread::Current()),
35 worker_thread_(worker_thread),
36 network_thread_(network_thread) {
37 RTC_DCHECK(data_engine_);
38 RTC_DCHECK(worker_thread_);
39 RTC_DCHECK(network_thread_);
henrike@webrtc.org28e20752013-07-10 00:45:3640}
41
42ChannelManager::~ChannelManager() {
wu@webrtc.org9dba5252013-08-05 20:36:5743 if (initialized_) {
henrike@webrtc.org28e20752013-07-10 00:45:3644 Terminate();
wu@webrtc.org9dba5252013-08-05 20:36:5745 }
perkjc11b1842016-03-08 01:34:1346 // The media engine needs to be deleted on the worker thread for thread safe
47 // destruction,
Steve Antonc9e15602017-11-06 23:40:0948 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] { media_engine_.reset(); });
henrike@webrtc.org28e20752013-07-10 00:45:3649}
50
51bool ChannelManager::SetVideoRtxEnabled(bool enable) {
52 // To be safe, this call is only allowed before initialization. Apps like
53 // Flute only have a singleton ChannelManager and we don't want this flag to
54 // be toggled between calls or when there's concurrent calls. We expect apps
55 // to enable this at startup and retain that setting for the lifetime of the
56 // app.
57 if (!initialized_) {
58 enable_rtx_ = enable;
59 return true;
60 } else {
Mirko Bonadei675513b2017-11-09 10:09:2561 RTC_LOG(LS_WARNING) << "Cannot toggle rtx after initialization!";
henrike@webrtc.org28e20752013-07-10 00:45:3662 return false;
63 }
64}
65
ossudedfd282016-06-14 14:12:3966void ChannelManager::GetSupportedAudioSendCodecs(
henrike@webrtc.org28e20752013-07-10 00:45:3667 std::vector<AudioCodec>* codecs) const {
zhihuang38ede132017-06-15 19:52:3268 if (!media_engine_) {
69 return;
70 }
Sebastian Jansson6eb8a162018-11-16 10:29:5571 *codecs = media_engine_->voice().send_codecs();
ossudedfd282016-06-14 14:12:3972}
henrike@webrtc.org28e20752013-07-10 00:45:3673
ossudedfd282016-06-14 14:12:3974void ChannelManager::GetSupportedAudioReceiveCodecs(
75 std::vector<AudioCodec>* codecs) const {
zhihuang38ede132017-06-15 19:52:3276 if (!media_engine_) {
77 return;
78 }
Sebastian Jansson6eb8a162018-11-16 10:29:5579 *codecs = media_engine_->voice().recv_codecs();
henrike@webrtc.org28e20752013-07-10 00:45:3680}
81
82void ChannelManager::GetSupportedAudioRtpHeaderExtensions(
83 RtpHeaderExtensions* ext) const {
zhihuang38ede132017-06-15 19:52:3284 if (!media_engine_) {
85 return;
86 }
Sebastian Jansson6eb8a162018-11-16 10:29:5587 *ext = media_engine_->voice().GetCapabilities().header_extensions;
henrike@webrtc.org28e20752013-07-10 00:45:3688}
89
magjed3cf8ece2016-11-10 11:36:5390void ChannelManager::GetSupportedVideoCodecs(
91 std::vector<VideoCodec>* codecs) const {
zhihuang38ede132017-06-15 19:52:3292 if (!media_engine_) {
93 return;
94 }
magjed3cf8ece2016-11-10 11:36:5395 codecs->clear();
96
Sebastian Jansson6eb8a162018-11-16 10:29:5597 std::vector<VideoCodec> video_codecs = media_engine_->video().codecs();
brandtrffc61182016-11-28 14:02:2298 for (const auto& video_codec : video_codecs) {
99 if (!enable_rtx_ &&
Niels Möller3c7d5992018-10-19 13:29:54100 absl::EqualsIgnoreCase(kRtxCodecName, video_codec.name)) {
magjed3cf8ece2016-11-10 11:36:53101 continue;
102 }
brandtrffc61182016-11-28 14:02:22103 codecs->push_back(video_codec);
henrike@webrtc.org28e20752013-07-10 00:45:36104 }
105}
106
107void ChannelManager::GetSupportedVideoRtpHeaderExtensions(
108 RtpHeaderExtensions* ext) const {
zhihuang38ede132017-06-15 19:52:32109 if (!media_engine_) {
110 return;
111 }
Sebastian Jansson6eb8a162018-11-16 10:29:55112 *ext = media_engine_->video().GetCapabilities().header_extensions;
henrike@webrtc.org28e20752013-07-10 00:45:36113}
114
115void ChannelManager::GetSupportedDataCodecs(
116 std::vector<DataCodec>* codecs) const {
Steve Antonc9e15602017-11-06 23:40:09117 *codecs = data_engine_->data_codecs();
henrike@webrtc.org28e20752013-07-10 00:45:36118}
119
120bool ChannelManager::Init() {
nisseede5da42017-01-12 13:15:36121 RTC_DCHECK(!initialized_);
henrike@webrtc.org28e20752013-07-10 00:45:36122 if (initialized_) {
123 return false;
124 }
Danil Chapovalov33b01f22016-05-11 17:55:27125 RTC_DCHECK(network_thread_);
126 RTC_DCHECK(worker_thread_);
127 if (!network_thread_->IsCurrent()) {
128 // Do not allow invoking calls to other threads on the network thread.
Steve Antonc9e15602017-11-06 23:40:09129 network_thread_->Invoke<void>(
Karl Wiberg32562252019-02-21 12:38:30130 RTC_FROM_HERE, [&] { network_thread_->DisallowBlockingCalls(); });
henrika@webrtc.org62f6e752015-02-11 08:38:35131 }
132
zhihuang38ede132017-06-15 19:52:32133 if (media_engine_) {
Steve Antonc9e15602017-11-06 23:40:09134 initialized_ = worker_thread_->Invoke<bool>(
135 RTC_FROM_HERE, [&] { return media_engine_->Init(); });
136 RTC_DCHECK(initialized_);
137 } else {
138 initialized_ = true;
zhihuang38ede132017-06-15 19:52:32139 }
Steve Antonc9e15602017-11-06 23:40:09140 return initialized_;
henrika@webrtc.org62f6e752015-02-11 08:38:35141}
142
henrike@webrtc.org28e20752013-07-10 00:45:36143void ChannelManager::Terminate() {
nisseede5da42017-01-12 13:15:36144 RTC_DCHECK(initialized_);
henrike@webrtc.org28e20752013-07-10 00:45:36145 if (!initialized_) {
146 return;
147 }
Steve Antonc9e15602017-11-06 23:40:09148 // Need to destroy the channels on the worker thread.
149 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
150 video_channels_.clear();
151 voice_channels_.clear();
152 data_channels_.clear();
153 });
henrike@webrtc.org28e20752013-07-10 00:45:36154 initialized_ = false;
155}
156
henrike@webrtc.org28e20752013-07-10 00:45:36157VoiceChannel* ChannelManager::CreateVoiceChannel(
nisseeaabdf62017-05-05 09:23:02158 webrtc::Call* call,
159 const cricket::MediaConfig& media_config,
Zhi Huang2dfc42d2017-12-04 21:38:48160 webrtc::RtpTransportInternal* rtp_transport,
Anton Sukhanov4f08faa2019-05-21 18:12:57161 const webrtc::MediaTransportConfig& media_transport_config,
Zhi Huang2dfc42d2017-12-04 21:38:48162 rtc::Thread* signaling_thread,
163 const std::string& content_name,
164 bool srtp_required,
Benjamin Wrighta54daf12018-10-11 22:33:17165 const webrtc::CryptoOptions& crypto_options,
Amit Hilbuchbcd39d42019-01-26 01:13:56166 rtc::UniqueRandomIdGenerator* ssrc_generator,
Zhi Huang2dfc42d2017-12-04 21:38:48167 const AudioOptions& options) {
168 if (!worker_thread_->IsCurrent()) {
169 return worker_thread_->Invoke<VoiceChannel*>(RTC_FROM_HERE, [&] {
Anton Sukhanov4f08faa2019-05-21 18:12:57170 return CreateVoiceChannel(call, media_config, rtp_transport,
171 media_transport_config, signaling_thread,
172 content_name, srtp_required, crypto_options,
173 ssrc_generator, options);
Zhi Huang2dfc42d2017-12-04 21:38:48174 });
175 }
176
177 RTC_DCHECK_RUN_ON(worker_thread_);
178 RTC_DCHECK(initialized_);
179 RTC_DCHECK(call);
180 if (!media_engine_) {
181 return nullptr;
182 }
183
Sebastian Jansson6eb8a162018-11-16 10:29:55184 VoiceMediaChannel* media_channel = media_engine_->voice().CreateMediaChannel(
185 call, media_config, options, crypto_options);
Zhi Huang2dfc42d2017-12-04 21:38:48186 if (!media_channel) {
187 return nullptr;
188 }
189
Karl Wiberg918f50c2018-07-05 09:40:33190 auto voice_channel = absl::make_unique<VoiceChannel>(
Amit Hilbuchbcd39d42019-01-26 01:13:56191 worker_thread_, network_thread_, signaling_thread,
Karl Wiberg918f50c2018-07-05 09:40:33192 absl::WrapUnique(media_channel), content_name, srtp_required,
Amit Hilbuchbcd39d42019-01-26 01:13:56193 crypto_options, ssrc_generator);
Zhi Huang2dfc42d2017-12-04 21:38:48194
Anton Sukhanov4f08faa2019-05-21 18:12:57195 voice_channel->Init_w(rtp_transport, media_transport_config);
Zhi Huang2dfc42d2017-12-04 21:38:48196
197 VoiceChannel* voice_channel_ptr = voice_channel.get();
198 voice_channels_.push_back(std::move(voice_channel));
199 return voice_channel_ptr;
200}
201
Fredrik Solenberg709ed672015-09-15 10:26:33202void ChannelManager::DestroyVoiceChannel(VoiceChannel* voice_channel) {
Peter Boström1a9d6152015-12-08 21:15:17203 TRACE_EVENT0("webrtc", "ChannelManager::DestroyVoiceChannel");
Steve Antonc9e15602017-11-06 23:40:09204 if (!voice_channel) {
205 return;
henrike@webrtc.org28e20752013-07-10 00:45:36206 }
Steve Antonc9e15602017-11-06 23:40:09207 if (!worker_thread_->IsCurrent()) {
208 worker_thread_->Invoke<void>(RTC_FROM_HERE,
209 [&] { DestroyVoiceChannel(voice_channel); });
210 return;
211 }
henrike@webrtc.org28e20752013-07-10 00:45:36212
nisseede5da42017-01-12 13:15:36213 RTC_DCHECK(initialized_);
Steve Anton774115c2017-08-30 17:48:46214
Steve Anton64b626b2019-01-29 01:25:26215 auto it = absl::c_find_if(voice_channels_,
216 [&](const std::unique_ptr<VoiceChannel>& p) {
217 return p.get() == voice_channel;
218 });
nisseede5da42017-01-12 13:15:36219 RTC_DCHECK(it != voice_channels_.end());
Steve Antonc9e15602017-11-06 23:40:09220 if (it == voice_channels_.end()) {
henrike@webrtc.org28e20752013-07-10 00:45:36221 return;
Steve Antonc9e15602017-11-06 23:40:09222 }
223
henrike@webrtc.org28e20752013-07-10 00:45:36224 voice_channels_.erase(it);
henrike@webrtc.org28e20752013-07-10 00:45:36225}
226
227VideoChannel* ChannelManager::CreateVideoChannel(
nisseeaabdf62017-05-05 09:23:02228 webrtc::Call* call,
229 const cricket::MediaConfig& media_config,
Zhi Huang2dfc42d2017-12-04 21:38:48230 webrtc::RtpTransportInternal* rtp_transport,
Anton Sukhanov4f08faa2019-05-21 18:12:57231 const webrtc::MediaTransportConfig& media_transport_config,
Zhi Huang2dfc42d2017-12-04 21:38:48232 rtc::Thread* signaling_thread,
233 const std::string& content_name,
234 bool srtp_required,
Benjamin Wrighta54daf12018-10-11 22:33:17235 const webrtc::CryptoOptions& crypto_options,
Amit Hilbuchbcd39d42019-01-26 01:13:56236 rtc::UniqueRandomIdGenerator* ssrc_generator,
Jonas Orelanda3aa9bd2019-04-17 05:38:40237 const VideoOptions& options,
238 webrtc::VideoBitrateAllocatorFactory* video_bitrate_allocator_factory) {
Zhi Huang2dfc42d2017-12-04 21:38:48239 if (!worker_thread_->IsCurrent()) {
240 return worker_thread_->Invoke<VideoChannel*>(RTC_FROM_HERE, [&] {
Anton Sukhanov4f08faa2019-05-21 18:12:57241 return CreateVideoChannel(
242 call, media_config, rtp_transport, media_transport_config,
243 signaling_thread, content_name, srtp_required, crypto_options,
244 ssrc_generator, options, video_bitrate_allocator_factory);
Zhi Huang2dfc42d2017-12-04 21:38:48245 });
246 }
247
248 RTC_DCHECK_RUN_ON(worker_thread_);
249 RTC_DCHECK(initialized_);
250 RTC_DCHECK(call);
251 if (!media_engine_) {
252 return nullptr;
253 }
254
Sebastian Jansson6eb8a162018-11-16 10:29:55255 VideoMediaChannel* media_channel = media_engine_->video().CreateMediaChannel(
Jonas Orelanda3aa9bd2019-04-17 05:38:40256 call, media_config, options, crypto_options,
257 video_bitrate_allocator_factory);
Zhi Huang2dfc42d2017-12-04 21:38:48258 if (!media_channel) {
259 return nullptr;
260 }
261
Karl Wiberg918f50c2018-07-05 09:40:33262 auto video_channel = absl::make_unique<VideoChannel>(
Zhi Huang2dfc42d2017-12-04 21:38:48263 worker_thread_, network_thread_, signaling_thread,
Karl Wiberg918f50c2018-07-05 09:40:33264 absl::WrapUnique(media_channel), content_name, srtp_required,
Amit Hilbuchbcd39d42019-01-26 01:13:56265 crypto_options, ssrc_generator);
Anton Sukhanov98a462c2018-10-17 20:15:42266
Anton Sukhanov4f08faa2019-05-21 18:12:57267 video_channel->Init_w(rtp_transport, media_transport_config);
Zhi Huang2dfc42d2017-12-04 21:38:48268
269 VideoChannel* video_channel_ptr = video_channel.get();
270 video_channels_.push_back(std::move(video_channel));
271 return video_channel_ptr;
272}
273
henrike@webrtc.org28e20752013-07-10 00:45:36274void ChannelManager::DestroyVideoChannel(VideoChannel* video_channel) {
Peter Boström1a9d6152015-12-08 21:15:17275 TRACE_EVENT0("webrtc", "ChannelManager::DestroyVideoChannel");
Steve Antonc9e15602017-11-06 23:40:09276 if (!video_channel) {
277 return;
henrike@webrtc.org28e20752013-07-10 00:45:36278 }
Steve Antonc9e15602017-11-06 23:40:09279 if (!worker_thread_->IsCurrent()) {
280 worker_thread_->Invoke<void>(RTC_FROM_HERE,
281 [&] { DestroyVideoChannel(video_channel); });
282 return;
283 }
henrike@webrtc.org28e20752013-07-10 00:45:36284
nisseede5da42017-01-12 13:15:36285 RTC_DCHECK(initialized_);
Steve Anton774115c2017-08-30 17:48:46286
Steve Anton64b626b2019-01-29 01:25:26287 auto it = absl::c_find_if(video_channels_,
288 [&](const std::unique_ptr<VideoChannel>& p) {
289 return p.get() == video_channel;
290 });
nisseede5da42017-01-12 13:15:36291 RTC_DCHECK(it != video_channels_.end());
Steve Antonc9e15602017-11-06 23:40:09292 if (it == video_channels_.end()) {
henrike@webrtc.org28e20752013-07-10 00:45:36293 return;
Steve Antonc9e15602017-11-06 23:40:09294 }
henrike@webrtc.org28e20752013-07-10 00:45:36295
296 video_channels_.erase(it);
henrike@webrtc.org28e20752013-07-10 00:45:36297}
298
deadbeef953c2ce2017-01-09 22:53:41299RtpDataChannel* ChannelManager::CreateRtpDataChannel(
nisseeaabdf62017-05-05 09:23:02300 const cricket::MediaConfig& media_config,
Zhi Huang2dfc42d2017-12-04 21:38:48301 webrtc::RtpTransportInternal* rtp_transport,
302 rtc::Thread* signaling_thread,
303 const std::string& content_name,
Zhi Huange830e682018-03-30 17:48:35304 bool srtp_required,
Amit Hilbuchbcd39d42019-01-26 01:13:56305 const webrtc::CryptoOptions& crypto_options,
306 rtc::UniqueRandomIdGenerator* ssrc_generator) {
Zhi Huang2dfc42d2017-12-04 21:38:48307 if (!worker_thread_->IsCurrent()) {
308 return worker_thread_->Invoke<RtpDataChannel*>(RTC_FROM_HERE, [&] {
309 return CreateRtpDataChannel(media_config, rtp_transport, signaling_thread,
Amit Hilbuchbcd39d42019-01-26 01:13:56310 content_name, srtp_required, crypto_options,
311 ssrc_generator);
Zhi Huang2dfc42d2017-12-04 21:38:48312 });
313 }
314
315 // This is ok to alloc from a thread other than the worker thread.
316 RTC_DCHECK(initialized_);
317 DataMediaChannel* media_channel = data_engine_->CreateChannel(media_config);
318 if (!media_channel) {
319 RTC_LOG(LS_WARNING) << "Failed to create RTP data channel.";
320 return nullptr;
321 }
322
Karl Wiberg918f50c2018-07-05 09:40:33323 auto data_channel = absl::make_unique<RtpDataChannel>(
Zhi Huang2dfc42d2017-12-04 21:38:48324 worker_thread_, network_thread_, signaling_thread,
Karl Wiberg918f50c2018-07-05 09:40:33325 absl::WrapUnique(media_channel), content_name, srtp_required,
Amit Hilbuchbcd39d42019-01-26 01:13:56326 crypto_options, ssrc_generator);
Anton Sukhanov4f08faa2019-05-21 18:12:57327
328 // Media Transports are not supported with Rtp Data Channel.
329 data_channel->Init_w(rtp_transport, webrtc::MediaTransportConfig());
Zhi Huang2dfc42d2017-12-04 21:38:48330
331 RtpDataChannel* data_channel_ptr = data_channel.get();
332 data_channels_.push_back(std::move(data_channel));
333 return data_channel_ptr;
334}
335
deadbeef953c2ce2017-01-09 22:53:41336void ChannelManager::DestroyRtpDataChannel(RtpDataChannel* data_channel) {
337 TRACE_EVENT0("webrtc", "ChannelManager::DestroyRtpDataChannel");
Steve Antonc9e15602017-11-06 23:40:09338 if (!data_channel) {
339 return;
henrike@webrtc.org28e20752013-07-10 00:45:36340 }
Steve Antonc9e15602017-11-06 23:40:09341 if (!worker_thread_->IsCurrent()) {
342 worker_thread_->Invoke<void>(
343 RTC_FROM_HERE, [&] { return DestroyRtpDataChannel(data_channel); });
344 return;
345 }
henrike@webrtc.org28e20752013-07-10 00:45:36346
nisseede5da42017-01-12 13:15:36347 RTC_DCHECK(initialized_);
Steve Anton774115c2017-08-30 17:48:46348
Steve Anton64b626b2019-01-29 01:25:26349 auto it = absl::c_find_if(data_channels_,
350 [&](const std::unique_ptr<RtpDataChannel>& p) {
351 return p.get() == data_channel;
352 });
nisseede5da42017-01-12 13:15:36353 RTC_DCHECK(it != data_channels_.end());
Steve Antonc9e15602017-11-06 23:40:09354 if (it == data_channels_.end()) {
henrike@webrtc.org28e20752013-07-10 00:45:36355 return;
Steve Antonc9e15602017-11-06 23:40:09356 }
Zhi Huang95e7dbb2018-03-29 00:08:03357
henrike@webrtc.org28e20752013-07-10 00:45:36358 data_channels_.erase(it);
henrike@webrtc.org28e20752013-07-10 00:45:36359}
360
ivocd66b44d2016-01-15 11:06:36361bool ChannelManager::StartAecDump(rtc::PlatformFile file,
362 int64_t max_size_bytes) {
Steve Antonc9e15602017-11-06 23:40:09363 return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Sebastian Jansson6eb8a162018-11-16 10:29:55364 return media_engine_->voice().StartAecDump(file, max_size_bytes);
Steve Antonc9e15602017-11-06 23:40:09365 });
wu@webrtc.orga9890802013-12-13 00:21:03366}
367
ivoc797ef122015-10-22 10:25:41368void ChannelManager::StopAecDump() {
Steve Antonc9e15602017-11-06 23:40:09369 worker_thread_->Invoke<void>(RTC_FROM_HERE,
Sebastian Jansson6eb8a162018-11-16 10:29:55370 [&] { media_engine_->voice().StopAecDump(); });
ivoc797ef122015-10-22 10:25:41371}
372
henrike@webrtc.org28e20752013-07-10 00:45:36373} // namespace cricket