• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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