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/channel_manager.h"
12
13 #include <utility>
14
15 #include "absl/algorithm/container.h"
16 #include "absl/memory/memory.h"
17 #include "absl/strings/match.h"
18 #include "media/base/media_constants.h"
19 #include "rtc_base/checks.h"
20 #include "rtc_base/location.h"
21 #include "rtc_base/logging.h"
22 #include "rtc_base/thread_checker.h"
23 #include "rtc_base/trace_event.h"
24
25 namespace cricket {
26
ChannelManager(std::unique_ptr<MediaEngineInterface> media_engine,std::unique_ptr<DataEngineInterface> data_engine,rtc::Thread * worker_thread,rtc::Thread * network_thread)27 ChannelManager::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_);
40 }
41
~ChannelManager()42 ChannelManager::~ChannelManager() {
43 if (initialized_) {
44 Terminate();
45 }
46 // The media engine needs to be deleted on the worker thread for thread safe
47 // destruction,
48 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] { media_engine_.reset(); });
49 }
50
SetVideoRtxEnabled(bool enable)51 bool 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 {
61 RTC_LOG(LS_WARNING) << "Cannot toggle rtx after initialization!";
62 return false;
63 }
64 }
65
GetSupportedAudioSendCodecs(std::vector<AudioCodec> * codecs) const66 void ChannelManager::GetSupportedAudioSendCodecs(
67 std::vector<AudioCodec>* codecs) const {
68 if (!media_engine_) {
69 return;
70 }
71 *codecs = media_engine_->voice().send_codecs();
72 }
73
GetSupportedAudioReceiveCodecs(std::vector<AudioCodec> * codecs) const74 void ChannelManager::GetSupportedAudioReceiveCodecs(
75 std::vector<AudioCodec>* codecs) const {
76 if (!media_engine_) {
77 return;
78 }
79 *codecs = media_engine_->voice().recv_codecs();
80 }
81
GetSupportedVideoSendCodecs(std::vector<VideoCodec> * codecs) const82 void ChannelManager::GetSupportedVideoSendCodecs(
83 std::vector<VideoCodec>* codecs) const {
84 if (!media_engine_) {
85 return;
86 }
87 codecs->clear();
88
89 std::vector<VideoCodec> video_codecs = media_engine_->video().send_codecs();
90 for (const auto& video_codec : video_codecs) {
91 if (!enable_rtx_ &&
92 absl::EqualsIgnoreCase(kRtxCodecName, video_codec.name)) {
93 continue;
94 }
95 codecs->push_back(video_codec);
96 }
97 }
98
GetSupportedVideoReceiveCodecs(std::vector<VideoCodec> * codecs) const99 void ChannelManager::GetSupportedVideoReceiveCodecs(
100 std::vector<VideoCodec>* codecs) const {
101 if (!media_engine_) {
102 return;
103 }
104 codecs->clear();
105
106 std::vector<VideoCodec> video_codecs = media_engine_->video().recv_codecs();
107 for (const auto& video_codec : video_codecs) {
108 if (!enable_rtx_ &&
109 absl::EqualsIgnoreCase(kRtxCodecName, video_codec.name)) {
110 continue;
111 }
112 codecs->push_back(video_codec);
113 }
114 }
115
GetSupportedDataCodecs(std::vector<DataCodec> * codecs) const116 void ChannelManager::GetSupportedDataCodecs(
117 std::vector<DataCodec>* codecs) const {
118 *codecs = data_engine_->data_codecs();
119 }
120
Init()121 bool ChannelManager::Init() {
122 RTC_DCHECK(!initialized_);
123 if (initialized_) {
124 return false;
125 }
126 RTC_DCHECK(network_thread_);
127 RTC_DCHECK(worker_thread_);
128 if (!network_thread_->IsCurrent()) {
129 // Do not allow invoking calls to other threads on the network thread.
130 network_thread_->Invoke<void>(
131 RTC_FROM_HERE, [&] { network_thread_->DisallowBlockingCalls(); });
132 }
133
134 if (media_engine_) {
135 initialized_ = worker_thread_->Invoke<bool>(
136 RTC_FROM_HERE, [&] { return media_engine_->Init(); });
137 RTC_DCHECK(initialized_);
138 } else {
139 initialized_ = true;
140 }
141 return initialized_;
142 }
143
GetDefaultEnabledAudioRtpHeaderExtensions() const144 RtpHeaderExtensions ChannelManager::GetDefaultEnabledAudioRtpHeaderExtensions()
145 const {
146 if (!media_engine_)
147 return {};
148 return GetDefaultEnabledRtpHeaderExtensions(media_engine_->voice());
149 }
150
151 std::vector<webrtc::RtpHeaderExtensionCapability>
GetSupportedAudioRtpHeaderExtensions() const152 ChannelManager::GetSupportedAudioRtpHeaderExtensions() const {
153 if (!media_engine_)
154 return {};
155 return media_engine_->voice().GetRtpHeaderExtensions();
156 }
157
GetDefaultEnabledVideoRtpHeaderExtensions() const158 RtpHeaderExtensions ChannelManager::GetDefaultEnabledVideoRtpHeaderExtensions()
159 const {
160 if (!media_engine_)
161 return {};
162 return GetDefaultEnabledRtpHeaderExtensions(media_engine_->video());
163 }
164
165 std::vector<webrtc::RtpHeaderExtensionCapability>
GetSupportedVideoRtpHeaderExtensions() const166 ChannelManager::GetSupportedVideoRtpHeaderExtensions() const {
167 if (!media_engine_)
168 return {};
169 return media_engine_->video().GetRtpHeaderExtensions();
170 }
171
Terminate()172 void ChannelManager::Terminate() {
173 RTC_DCHECK(initialized_);
174 if (!initialized_) {
175 return;
176 }
177 // Need to destroy the channels on the worker thread.
178 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
179 video_channels_.clear();
180 voice_channels_.clear();
181 data_channels_.clear();
182 });
183 initialized_ = false;
184 }
185
CreateVoiceChannel(webrtc::Call * call,const cricket::MediaConfig & media_config,webrtc::RtpTransportInternal * rtp_transport,rtc::Thread * signaling_thread,const std::string & content_name,bool srtp_required,const webrtc::CryptoOptions & crypto_options,rtc::UniqueRandomIdGenerator * ssrc_generator,const AudioOptions & options)186 VoiceChannel* ChannelManager::CreateVoiceChannel(
187 webrtc::Call* call,
188 const cricket::MediaConfig& media_config,
189 webrtc::RtpTransportInternal* rtp_transport,
190 rtc::Thread* signaling_thread,
191 const std::string& content_name,
192 bool srtp_required,
193 const webrtc::CryptoOptions& crypto_options,
194 rtc::UniqueRandomIdGenerator* ssrc_generator,
195 const AudioOptions& options) {
196 if (!worker_thread_->IsCurrent()) {
197 return worker_thread_->Invoke<VoiceChannel*>(RTC_FROM_HERE, [&] {
198 return CreateVoiceChannel(call, media_config, rtp_transport,
199 signaling_thread, content_name, srtp_required,
200 crypto_options, ssrc_generator, options);
201 });
202 }
203
204 RTC_DCHECK_RUN_ON(worker_thread_);
205 RTC_DCHECK(initialized_);
206 RTC_DCHECK(call);
207 if (!media_engine_) {
208 return nullptr;
209 }
210
211 VoiceMediaChannel* media_channel = media_engine_->voice().CreateMediaChannel(
212 call, media_config, options, crypto_options);
213 if (!media_channel) {
214 return nullptr;
215 }
216
217 auto voice_channel = std::make_unique<VoiceChannel>(
218 worker_thread_, network_thread_, signaling_thread,
219 absl::WrapUnique(media_channel), content_name, srtp_required,
220 crypto_options, ssrc_generator);
221
222 voice_channel->Init_w(rtp_transport);
223
224 VoiceChannel* voice_channel_ptr = voice_channel.get();
225 voice_channels_.push_back(std::move(voice_channel));
226 return voice_channel_ptr;
227 }
228
DestroyVoiceChannel(VoiceChannel * voice_channel)229 void ChannelManager::DestroyVoiceChannel(VoiceChannel* voice_channel) {
230 TRACE_EVENT0("webrtc", "ChannelManager::DestroyVoiceChannel");
231 if (!voice_channel) {
232 return;
233 }
234 if (!worker_thread_->IsCurrent()) {
235 worker_thread_->Invoke<void>(RTC_FROM_HERE,
236 [&] { DestroyVoiceChannel(voice_channel); });
237 return;
238 }
239
240 RTC_DCHECK(initialized_);
241
242 auto it = absl::c_find_if(voice_channels_,
243 [&](const std::unique_ptr<VoiceChannel>& p) {
244 return p.get() == voice_channel;
245 });
246 RTC_DCHECK(it != voice_channels_.end());
247 if (it == voice_channels_.end()) {
248 return;
249 }
250
251 voice_channels_.erase(it);
252 }
253
CreateVideoChannel(webrtc::Call * call,const cricket::MediaConfig & media_config,webrtc::RtpTransportInternal * rtp_transport,rtc::Thread * signaling_thread,const std::string & content_name,bool srtp_required,const webrtc::CryptoOptions & crypto_options,rtc::UniqueRandomIdGenerator * ssrc_generator,const VideoOptions & options,webrtc::VideoBitrateAllocatorFactory * video_bitrate_allocator_factory)254 VideoChannel* ChannelManager::CreateVideoChannel(
255 webrtc::Call* call,
256 const cricket::MediaConfig& media_config,
257 webrtc::RtpTransportInternal* rtp_transport,
258 rtc::Thread* signaling_thread,
259 const std::string& content_name,
260 bool srtp_required,
261 const webrtc::CryptoOptions& crypto_options,
262 rtc::UniqueRandomIdGenerator* ssrc_generator,
263 const VideoOptions& options,
264 webrtc::VideoBitrateAllocatorFactory* video_bitrate_allocator_factory) {
265 if (!worker_thread_->IsCurrent()) {
266 return worker_thread_->Invoke<VideoChannel*>(RTC_FROM_HERE, [&] {
267 return CreateVideoChannel(call, media_config, rtp_transport,
268 signaling_thread, content_name, srtp_required,
269 crypto_options, ssrc_generator, options,
270 video_bitrate_allocator_factory);
271 });
272 }
273
274 RTC_DCHECK_RUN_ON(worker_thread_);
275 RTC_DCHECK(initialized_);
276 RTC_DCHECK(call);
277 if (!media_engine_) {
278 return nullptr;
279 }
280
281 VideoMediaChannel* media_channel = media_engine_->video().CreateMediaChannel(
282 call, media_config, options, crypto_options,
283 video_bitrate_allocator_factory);
284 if (!media_channel) {
285 return nullptr;
286 }
287
288 auto video_channel = std::make_unique<VideoChannel>(
289 worker_thread_, network_thread_, signaling_thread,
290 absl::WrapUnique(media_channel), content_name, srtp_required,
291 crypto_options, ssrc_generator);
292
293 video_channel->Init_w(rtp_transport);
294
295 VideoChannel* video_channel_ptr = video_channel.get();
296 video_channels_.push_back(std::move(video_channel));
297 return video_channel_ptr;
298 }
299
DestroyVideoChannel(VideoChannel * video_channel)300 void ChannelManager::DestroyVideoChannel(VideoChannel* video_channel) {
301 TRACE_EVENT0("webrtc", "ChannelManager::DestroyVideoChannel");
302 if (!video_channel) {
303 return;
304 }
305 if (!worker_thread_->IsCurrent()) {
306 worker_thread_->Invoke<void>(RTC_FROM_HERE,
307 [&] { DestroyVideoChannel(video_channel); });
308 return;
309 }
310
311 RTC_DCHECK(initialized_);
312
313 auto it = absl::c_find_if(video_channels_,
314 [&](const std::unique_ptr<VideoChannel>& p) {
315 return p.get() == video_channel;
316 });
317 RTC_DCHECK(it != video_channels_.end());
318 if (it == video_channels_.end()) {
319 return;
320 }
321
322 video_channels_.erase(it);
323 }
324
CreateRtpDataChannel(const cricket::MediaConfig & media_config,webrtc::RtpTransportInternal * rtp_transport,rtc::Thread * signaling_thread,const std::string & content_name,bool srtp_required,const webrtc::CryptoOptions & crypto_options,rtc::UniqueRandomIdGenerator * ssrc_generator)325 RtpDataChannel* ChannelManager::CreateRtpDataChannel(
326 const cricket::MediaConfig& media_config,
327 webrtc::RtpTransportInternal* rtp_transport,
328 rtc::Thread* signaling_thread,
329 const std::string& content_name,
330 bool srtp_required,
331 const webrtc::CryptoOptions& crypto_options,
332 rtc::UniqueRandomIdGenerator* ssrc_generator) {
333 if (!worker_thread_->IsCurrent()) {
334 return worker_thread_->Invoke<RtpDataChannel*>(RTC_FROM_HERE, [&] {
335 return CreateRtpDataChannel(media_config, rtp_transport, signaling_thread,
336 content_name, srtp_required, crypto_options,
337 ssrc_generator);
338 });
339 }
340
341 // This is ok to alloc from a thread other than the worker thread.
342 RTC_DCHECK(initialized_);
343 DataMediaChannel* media_channel = data_engine_->CreateChannel(media_config);
344 if (!media_channel) {
345 RTC_LOG(LS_WARNING) << "Failed to create RTP data channel.";
346 return nullptr;
347 }
348
349 auto data_channel = std::make_unique<RtpDataChannel>(
350 worker_thread_, network_thread_, signaling_thread,
351 absl::WrapUnique(media_channel), content_name, srtp_required,
352 crypto_options, ssrc_generator);
353
354 // Media Transports are not supported with Rtp Data Channel.
355 data_channel->Init_w(rtp_transport);
356
357 RtpDataChannel* data_channel_ptr = data_channel.get();
358 data_channels_.push_back(std::move(data_channel));
359 return data_channel_ptr;
360 }
361
DestroyRtpDataChannel(RtpDataChannel * data_channel)362 void ChannelManager::DestroyRtpDataChannel(RtpDataChannel* data_channel) {
363 TRACE_EVENT0("webrtc", "ChannelManager::DestroyRtpDataChannel");
364 if (!data_channel) {
365 return;
366 }
367 if (!worker_thread_->IsCurrent()) {
368 worker_thread_->Invoke<void>(
369 RTC_FROM_HERE, [&] { return DestroyRtpDataChannel(data_channel); });
370 return;
371 }
372
373 RTC_DCHECK(initialized_);
374
375 auto it = absl::c_find_if(data_channels_,
376 [&](const std::unique_ptr<RtpDataChannel>& p) {
377 return p.get() == data_channel;
378 });
379 RTC_DCHECK(it != data_channels_.end());
380 if (it == data_channels_.end()) {
381 return;
382 }
383
384 data_channels_.erase(it);
385 }
386
StartAecDump(webrtc::FileWrapper file,int64_t max_size_bytes)387 bool ChannelManager::StartAecDump(webrtc::FileWrapper file,
388 int64_t max_size_bytes) {
389 return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
390 return media_engine_->voice().StartAecDump(std::move(file), max_size_bytes);
391 });
392 }
393
StopAecDump()394 void ChannelManager::StopAecDump() {
395 worker_thread_->Invoke<void>(RTC_FROM_HERE,
396 [&] { media_engine_->voice().StopAecDump(); });
397 }
398
399 } // namespace cricket
400