blob: 987cec7092f081ac2d09427277a5e03c9c27c975 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2004 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "talk/session/media/channelmanager.h"
29
30#ifdef HAVE_CONFIG_H
31#include <config.h>
32#endif
33
34#include <algorithm>
35
henrike@webrtc.org28e20752013-07-10 00:45:36 +000036#include "talk/media/base/capturemanager.h"
37#include "talk/media/base/hybriddataengine.h"
38#include "talk/media/base/rtpdataengine.h"
39#include "talk/media/base/videocapturer.h"
henrike@webrtc.org723d6832013-07-12 16:04:50 +000040#include "talk/media/devices/devicemanager.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000041#ifdef HAVE_SCTP
42#include "talk/media/sctp/sctpdataengine.h"
43#endif
wu@webrtc.org9dba5252013-08-05 20:36:57 +000044#include "talk/session/media/srtpfilter.h"
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +000045#include "webrtc/base/bind.h"
46#include "webrtc/base/common.h"
47#include "webrtc/base/logging.h"
48#include "webrtc/base/sigslotrepeater.h"
49#include "webrtc/base/stringencode.h"
50#include "webrtc/base/stringutils.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000051
52namespace cricket {
53
54enum {
55 MSG_VIDEOCAPTURESTATE = 1,
56};
57
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000058using rtc::Bind;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000059
60static const int kNotSetOutputVolume = -1;
61
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000062struct CaptureStateParams : public rtc::MessageData {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000063 CaptureStateParams(cricket::VideoCapturer* c, cricket::CaptureState s)
64 : capturer(c),
65 state(s) {}
66 cricket::VideoCapturer* capturer;
67 cricket::CaptureState state;
68};
69
70static DataEngineInterface* ConstructDataEngine() {
71#ifdef HAVE_SCTP
72 return new HybridDataEngine(new RtpDataEngine(), new SctpDataEngine());
73#else
74 return new RtpDataEngine();
75#endif
76}
77
henrike@webrtc.org28e20752013-07-10 00:45:36 +000078ChannelManager::ChannelManager(MediaEngineInterface* me,
79 DataEngineInterface* dme,
80 DeviceManagerInterface* dm,
81 CaptureManager* cm,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000082 rtc::Thread* worker_thread) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000083 Construct(me, dme, dm, cm, worker_thread);
84}
85
86ChannelManager::ChannelManager(MediaEngineInterface* me,
87 DeviceManagerInterface* dm,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000088 rtc::Thread* worker_thread) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000089 Construct(me,
90 ConstructDataEngine(),
91 dm,
92 new CaptureManager(),
93 worker_thread);
94}
95
96void ChannelManager::Construct(MediaEngineInterface* me,
97 DataEngineInterface* dme,
98 DeviceManagerInterface* dm,
99 CaptureManager* cm,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000100 rtc::Thread* worker_thread) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000101 media_engine_.reset(me);
102 data_media_engine_.reset(dme);
103 device_manager_.reset(dm);
104 capture_manager_.reset(cm);
105 initialized_ = false;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000106 main_thread_ = rtc::Thread::Current();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000107 worker_thread_ = worker_thread;
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000108 // Get the default audio options from the media engine.
109 audio_options_ = media_engine_->GetAudioOptions();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000110 audio_in_device_ = DeviceManagerInterface::kDefaultDeviceName;
111 audio_out_device_ = DeviceManagerInterface::kDefaultDeviceName;
henrike@webrtc.org0481f152014-08-19 14:56:59 +0000112 audio_delay_offset_ = kDefaultAudioDelayOffset;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000113 audio_output_volume_ = kNotSetOutputVolume;
114 local_renderer_ = NULL;
115 capturing_ = false;
116 monitoring_ = false;
117 enable_rtx_ = false;
118
119 // Init the device manager immediately, and set up our default video device.
120 SignalDevicesChange.repeat(device_manager_->SignalDevicesChange);
121 device_manager_->Init();
122
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000123 capture_manager_->SignalCapturerStateChange.connect(
124 this, &ChannelManager::OnVideoCaptureStateChange);
125}
126
127ChannelManager::~ChannelManager() {
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000128 if (initialized_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000129 Terminate();
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000130 // If srtp is initialized (done by the Channel) then we must call
131 // srtp_shutdown to free all crypto kernel lists. But we need to make sure
132 // shutdown always called at the end, after channels are destroyed.
133 // ChannelManager d'tor is always called last, it's safe place to call
134 // shutdown.
135 ShutdownSrtp();
136 }
hbos@webrtc.org4aef5fe2015-02-25 10:09:05 +0000137 // Some deletes need to be on the worker thread for thread safe destruction,
138 // this includes the media engine and capture manager.
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000139 worker_thread_->Invoke<void>(Bind(
hbos@webrtc.org4aef5fe2015-02-25 10:09:05 +0000140 &ChannelManager::DestructorDeletes_w, this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000141}
142
143bool ChannelManager::SetVideoRtxEnabled(bool enable) {
144 // To be safe, this call is only allowed before initialization. Apps like
145 // Flute only have a singleton ChannelManager and we don't want this flag to
146 // be toggled between calls or when there's concurrent calls. We expect apps
147 // to enable this at startup and retain that setting for the lifetime of the
148 // app.
149 if (!initialized_) {
150 enable_rtx_ = enable;
151 return true;
152 } else {
153 LOG(LS_WARNING) << "Cannot toggle rtx after initialization!";
154 return false;
155 }
156}
157
158int ChannelManager::GetCapabilities() {
159 return media_engine_->GetCapabilities() & device_manager_->GetCapabilities();
160}
161
162void ChannelManager::GetSupportedAudioCodecs(
163 std::vector<AudioCodec>* codecs) const {
164 codecs->clear();
165
166 for (std::vector<AudioCodec>::const_iterator it =
167 media_engine_->audio_codecs().begin();
168 it != media_engine_->audio_codecs().end(); ++it) {
169 codecs->push_back(*it);
170 }
171}
172
173void ChannelManager::GetSupportedAudioRtpHeaderExtensions(
174 RtpHeaderExtensions* ext) const {
175 *ext = media_engine_->audio_rtp_header_extensions();
176}
177
178void ChannelManager::GetSupportedVideoCodecs(
179 std::vector<VideoCodec>* codecs) const {
180 codecs->clear();
181
182 std::vector<VideoCodec>::const_iterator it;
183 for (it = media_engine_->video_codecs().begin();
184 it != media_engine_->video_codecs().end(); ++it) {
185 if (!enable_rtx_ && _stricmp(kRtxCodecName, it->name.c_str()) == 0) {
186 continue;
187 }
188 codecs->push_back(*it);
189 }
190}
191
192void ChannelManager::GetSupportedVideoRtpHeaderExtensions(
193 RtpHeaderExtensions* ext) const {
194 *ext = media_engine_->video_rtp_header_extensions();
195}
196
197void ChannelManager::GetSupportedDataCodecs(
198 std::vector<DataCodec>* codecs) const {
199 *codecs = data_media_engine_->data_codecs();
200}
201
202bool ChannelManager::Init() {
203 ASSERT(!initialized_);
204 if (initialized_) {
205 return false;
206 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000207 ASSERT(worker_thread_ != NULL);
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000208 if (!worker_thread_) {
209 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000210 }
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000211 if (worker_thread_ != rtc::Thread::Current()) {
212 // Do not allow invoking calls to other threads on the worker thread.
213 worker_thread_->Invoke<bool>(rtc::Bind(
214 &rtc::Thread::SetAllowBlockingCalls, worker_thread_, false));
215 }
216
217 initialized_ = worker_thread_->Invoke<bool>(Bind(
218 &ChannelManager::InitMediaEngine_w, this));
219 ASSERT(initialized_);
220 if (!initialized_) {
221 return false;
222 }
223
224 // Now that we're initialized, apply any stored preferences. A preferred
225 // device might have been unplugged. In this case, we fallback to the
226 // default device but keep the user preferences. The preferences are
227 // changed only when the Javascript FE changes them.
228 const std::string preferred_audio_in_device = audio_in_device_;
229 const std::string preferred_audio_out_device = audio_out_device_;
230 const std::string preferred_camera_device = camera_device_;
231 Device device;
232 if (!device_manager_->GetAudioInputDevice(audio_in_device_, &device)) {
233 LOG(LS_WARNING) << "The preferred microphone '" << audio_in_device_
234 << "' is unavailable. Fall back to the default.";
235 audio_in_device_ = DeviceManagerInterface::kDefaultDeviceName;
236 }
237 if (!device_manager_->GetAudioOutputDevice(audio_out_device_, &device)) {
238 LOG(LS_WARNING) << "The preferred speaker '" << audio_out_device_
239 << "' is unavailable. Fall back to the default.";
240 audio_out_device_ = DeviceManagerInterface::kDefaultDeviceName;
241 }
242 if (!device_manager_->GetVideoCaptureDevice(camera_device_, &device)) {
243 if (!camera_device_.empty()) {
244 LOG(LS_WARNING) << "The preferred camera '" << camera_device_
245 << "' is unavailable. Fall back to the default.";
246 }
247 camera_device_ = DeviceManagerInterface::kDefaultDeviceName;
248 }
249
250 if (!SetAudioOptions(audio_in_device_, audio_out_device_,
251 audio_options_, audio_delay_offset_)) {
252 LOG(LS_WARNING) << "Failed to SetAudioOptions with"
253 << " microphone: " << audio_in_device_
254 << " speaker: " << audio_out_device_
255 << " options: " << audio_options_.ToString()
256 << " delay: " << audio_delay_offset_;
257 }
258
259 // If audio_output_volume_ has been set via SetOutputVolume(), set the
260 // audio output volume of the engine.
261 if (kNotSetOutputVolume != audio_output_volume_ &&
262 !SetOutputVolume(audio_output_volume_)) {
263 LOG(LS_WARNING) << "Failed to SetOutputVolume to "
264 << audio_output_volume_;
265 }
266 if (!SetCaptureDevice(camera_device_) && !camera_device_.empty()) {
267 LOG(LS_WARNING) << "Failed to SetCaptureDevice with camera: "
268 << camera_device_;
269 }
270
271 // Restore the user preferences.
272 audio_in_device_ = preferred_audio_in_device;
273 audio_out_device_ = preferred_audio_out_device;
274 camera_device_ = preferred_camera_device;
275
276 // Now apply the default video codec that has been set earlier.
277 if (default_video_encoder_config_.max_codec.id != 0) {
278 SetDefaultVideoEncoderConfig(default_video_encoder_config_);
279 }
280
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000281 return initialized_;
282}
283
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000284bool ChannelManager::InitMediaEngine_w() {
285 ASSERT(worker_thread_ == rtc::Thread::Current());
286 return (media_engine_->Init(worker_thread_));
287}
288
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000289void ChannelManager::Terminate() {
290 ASSERT(initialized_);
291 if (!initialized_) {
292 return;
293 }
294 worker_thread_->Invoke<void>(Bind(&ChannelManager::Terminate_w, this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000295 initialized_ = false;
296}
297
hbos@webrtc.org4aef5fe2015-02-25 10:09:05 +0000298void ChannelManager::DestructorDeletes_w() {
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000299 ASSERT(worker_thread_ == rtc::Thread::Current());
300 media_engine_.reset(NULL);
hbos@webrtc.org4aef5fe2015-02-25 10:09:05 +0000301 capture_manager_.reset(NULL);
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000302}
303
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000304void ChannelManager::Terminate_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000305 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000306 // Need to destroy the voice/video channels
307 while (!video_channels_.empty()) {
308 DestroyVideoChannel_w(video_channels_.back());
309 }
310 while (!voice_channels_.empty()) {
Fredrik Solenberg4b60c732015-05-07 14:07:48 +0200311 DestroyVoiceChannel_w(voice_channels_.back(), nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000312 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000313 if (!SetCaptureDevice_w(NULL)) {
314 LOG(LS_WARNING) << "failed to delete video capturer";
315 }
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000316 media_engine_->Terminate();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000317}
318
319VoiceChannel* ChannelManager::CreateVoiceChannel(
320 BaseSession* session, const std::string& content_name, bool rtcp) {
321 return worker_thread_->Invoke<VoiceChannel*>(
322 Bind(&ChannelManager::CreateVoiceChannel_w, this,
323 session, content_name, rtcp));
324}
325
326VoiceChannel* ChannelManager::CreateVoiceChannel_w(
327 BaseSession* session, const std::string& content_name, bool rtcp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000328 ASSERT(initialized_);
Fredrik Solenberg4b60c732015-05-07 14:07:48 +0200329 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000330 VoiceMediaChannel* media_channel = media_engine_->CreateChannel();
331 if (media_channel == NULL)
332 return NULL;
333
334 VoiceChannel* voice_channel = new VoiceChannel(
335 worker_thread_, media_engine_.get(), media_channel,
336 session, content_name, rtcp);
337 if (!voice_channel->Init()) {
338 delete voice_channel;
339 return NULL;
340 }
341 voice_channels_.push_back(voice_channel);
342 return voice_channel;
343}
344
Fredrik Solenberg4b60c732015-05-07 14:07:48 +0200345void ChannelManager::DestroyVoiceChannel(VoiceChannel* voice_channel,
346 VideoChannel* video_channel) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000347 if (voice_channel) {
348 worker_thread_->Invoke<void>(
Fredrik Solenberg4b60c732015-05-07 14:07:48 +0200349 Bind(&ChannelManager::DestroyVoiceChannel_w, this, voice_channel,
350 video_channel));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000351 }
352}
353
Fredrik Solenberg4b60c732015-05-07 14:07:48 +0200354void ChannelManager::DestroyVoiceChannel_w(VoiceChannel* voice_channel,
355 VideoChannel* video_channel) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000356 // Destroy voice channel.
357 ASSERT(initialized_);
Fredrik Solenberg4b60c732015-05-07 14:07:48 +0200358 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000359 VoiceChannels::iterator it = std::find(voice_channels_.begin(),
360 voice_channels_.end(), voice_channel);
361 ASSERT(it != voice_channels_.end());
362 if (it == voice_channels_.end())
363 return;
364
Fredrik Solenberg4b60c732015-05-07 14:07:48 +0200365 if (video_channel) {
366 video_channel->media_channel()->DetachVoiceChannel();
367 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000368 voice_channels_.erase(it);
369 delete voice_channel;
370}
371
372VideoChannel* ChannelManager::CreateVideoChannel(
buildbot@webrtc.org1ecbe452014-10-14 20:29:28 +0000373 BaseSession* session,
374 const std::string& content_name,
375 bool rtcp,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000376 VoiceChannel* voice_channel) {
377 return worker_thread_->Invoke<VideoChannel*>(
buildbot@webrtc.org1ecbe452014-10-14 20:29:28 +0000378 Bind(&ChannelManager::CreateVideoChannel_w,
379 this,
380 session,
381 content_name,
382 rtcp,
383 VideoOptions(),
384 voice_channel));
385}
386
387VideoChannel* ChannelManager::CreateVideoChannel(
388 BaseSession* session,
389 const std::string& content_name,
390 bool rtcp,
391 const VideoOptions& options,
392 VoiceChannel* voice_channel) {
393 return worker_thread_->Invoke<VideoChannel*>(
394 Bind(&ChannelManager::CreateVideoChannel_w,
395 this,
396 session,
397 content_name,
398 rtcp,
399 options,
400 voice_channel));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000401}
402
403VideoChannel* ChannelManager::CreateVideoChannel_w(
buildbot@webrtc.org1ecbe452014-10-14 20:29:28 +0000404 BaseSession* session,
405 const std::string& content_name,
406 bool rtcp,
407 const VideoOptions& options,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000408 VoiceChannel* voice_channel) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000409 ASSERT(initialized_);
Fredrik Solenberg4b60c732015-05-07 14:07:48 +0200410 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000411 VideoMediaChannel* media_channel =
412 // voice_channel can be NULL in case of NullVoiceEngine.
buildbot@webrtc.org1ecbe452014-10-14 20:29:28 +0000413 media_engine_->CreateVideoChannel(
414 options, voice_channel ? voice_channel->media_channel() : NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000415 if (media_channel == NULL)
416 return NULL;
417
418 VideoChannel* video_channel = new VideoChannel(
419 worker_thread_, media_engine_.get(), media_channel,
Fredrik Solenberg7fb711f2015-04-22 15:30:51 +0200420 session, content_name, rtcp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000421 if (!video_channel->Init()) {
422 delete video_channel;
423 return NULL;
424 }
425 video_channels_.push_back(video_channel);
426 return video_channel;
427}
428
429void ChannelManager::DestroyVideoChannel(VideoChannel* video_channel) {
430 if (video_channel) {
431 worker_thread_->Invoke<void>(
432 Bind(&ChannelManager::DestroyVideoChannel_w, this, video_channel));
433 }
434}
435
436void ChannelManager::DestroyVideoChannel_w(VideoChannel* video_channel) {
437 // Destroy video channel.
438 ASSERT(initialized_);
Fredrik Solenberg4b60c732015-05-07 14:07:48 +0200439 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000440 VideoChannels::iterator it = std::find(video_channels_.begin(),
441 video_channels_.end(), video_channel);
442 ASSERT(it != video_channels_.end());
443 if (it == video_channels_.end())
444 return;
445
446 video_channels_.erase(it);
447 delete video_channel;
448}
449
450DataChannel* ChannelManager::CreateDataChannel(
451 BaseSession* session, const std::string& content_name,
452 bool rtcp, DataChannelType channel_type) {
453 return worker_thread_->Invoke<DataChannel*>(
454 Bind(&ChannelManager::CreateDataChannel_w, this, session, content_name,
455 rtcp, channel_type));
456}
457
458DataChannel* ChannelManager::CreateDataChannel_w(
459 BaseSession* session, const std::string& content_name,
460 bool rtcp, DataChannelType data_channel_type) {
461 // This is ok to alloc from a thread other than the worker thread.
462 ASSERT(initialized_);
463 DataMediaChannel* media_channel = data_media_engine_->CreateChannel(
464 data_channel_type);
465 if (!media_channel) {
466 LOG(LS_WARNING) << "Failed to create data channel of type "
467 << data_channel_type;
468 return NULL;
469 }
470
471 DataChannel* data_channel = new DataChannel(
472 worker_thread_, media_channel,
473 session, content_name, rtcp);
474 if (!data_channel->Init()) {
475 LOG(LS_WARNING) << "Failed to init data channel.";
476 delete data_channel;
477 return NULL;
478 }
479 data_channels_.push_back(data_channel);
480 return data_channel;
481}
482
483void ChannelManager::DestroyDataChannel(DataChannel* data_channel) {
484 if (data_channel) {
485 worker_thread_->Invoke<void>(
486 Bind(&ChannelManager::DestroyDataChannel_w, this, data_channel));
487 }
488}
489
490void ChannelManager::DestroyDataChannel_w(DataChannel* data_channel) {
491 // Destroy data channel.
492 ASSERT(initialized_);
493 DataChannels::iterator it = std::find(data_channels_.begin(),
494 data_channels_.end(), data_channel);
495 ASSERT(it != data_channels_.end());
496 if (it == data_channels_.end())
497 return;
498
499 data_channels_.erase(it);
500 delete data_channel;
501}
502
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000503bool ChannelManager::GetAudioOptions(std::string* in_name,
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000504 std::string* out_name,
505 AudioOptions* options) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000506 if (in_name)
507 *in_name = audio_in_device_;
508 if (out_name)
509 *out_name = audio_out_device_;
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000510 if (options)
511 *options = audio_options_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000512 return true;
513}
514
515bool ChannelManager::SetAudioOptions(const std::string& in_name,
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000516 const std::string& out_name,
517 const AudioOptions& options) {
518 return SetAudioOptions(in_name, out_name, options, audio_delay_offset_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000519}
520
521bool ChannelManager::SetAudioOptions(const std::string& in_name,
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000522 const std::string& out_name,
523 const AudioOptions& options,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000524 int delay_offset) {
525 // Get device ids from DeviceManager.
526 Device in_dev, out_dev;
527 if (!device_manager_->GetAudioInputDevice(in_name, &in_dev)) {
528 LOG(LS_WARNING) << "Failed to GetAudioInputDevice: " << in_name;
529 return false;
530 }
531 if (!device_manager_->GetAudioOutputDevice(out_name, &out_dev)) {
532 LOG(LS_WARNING) << "Failed to GetAudioOutputDevice: " << out_name;
533 return false;
534 }
535
536 // If we're initialized, pass the settings to the media engine.
537 bool ret = true;
538 if (initialized_) {
539 ret = worker_thread_->Invoke<bool>(
540 Bind(&ChannelManager::SetAudioOptions_w, this,
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000541 options, delay_offset, &in_dev, &out_dev));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000542 }
543
544 // If all worked well, save the values for use in GetAudioOptions.
545 if (ret) {
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000546 audio_options_ = options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000547 audio_in_device_ = in_name;
548 audio_out_device_ = out_name;
549 audio_delay_offset_ = delay_offset;
550 }
551 return ret;
552}
553
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000554bool ChannelManager::SetAudioOptions_w(
555 const AudioOptions& options, int delay_offset,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000556 const Device* in_dev, const Device* out_dev) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000557 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000558 ASSERT(initialized_);
559
560 // Set audio options
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000561 bool ret = media_engine_->SetAudioOptions(options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000562
563 if (ret) {
564 ret = media_engine_->SetAudioDelayOffset(delay_offset);
565 }
566
567 // Set the audio devices
568 if (ret) {
569 ret = media_engine_->SetSoundDevices(in_dev, out_dev);
570 }
571
572 return ret;
573}
574
buildbot@webrtc.org88d9fa62014-06-16 14:11:32 +0000575// Sets Engine-specific audio options according to enabled experiments.
576bool ChannelManager::SetEngineAudioOptions(const AudioOptions& options) {
577 // If we're initialized, pass the settings to the media engine.
578 bool ret = false;
579 if (initialized_) {
580 ret = worker_thread_->Invoke<bool>(
581 Bind(&ChannelManager::SetEngineAudioOptions_w, this, options));
582 }
583
584 // If all worked well, save the audio options.
585 if (ret) {
586 audio_options_ = options;
587 }
588 return ret;
589}
590
591bool ChannelManager::SetEngineAudioOptions_w(const AudioOptions& options) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000592 ASSERT(worker_thread_ == rtc::Thread::Current());
buildbot@webrtc.org88d9fa62014-06-16 14:11:32 +0000593 ASSERT(initialized_);
594
595 return media_engine_->SetAudioOptions(options);
596}
597
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000598bool ChannelManager::GetOutputVolume(int* level) {
599 if (!initialized_) {
600 return false;
601 }
602 return worker_thread_->Invoke<bool>(
603 Bind(&MediaEngineInterface::GetOutputVolume, media_engine_.get(), level));
604}
605
606bool ChannelManager::SetOutputVolume(int level) {
607 bool ret = level >= 0 && level <= 255;
608 if (initialized_) {
609 ret &= worker_thread_->Invoke<bool>(
610 Bind(&MediaEngineInterface::SetOutputVolume,
611 media_engine_.get(), level));
612 }
613
614 if (ret) {
615 audio_output_volume_ = level;
616 }
617
618 return ret;
619}
620
621bool ChannelManager::IsSameCapturer(const std::string& capturer_name,
622 VideoCapturer* capturer) {
623 if (capturer == NULL) {
624 return false;
625 }
626 Device device;
627 if (!device_manager_->GetVideoCaptureDevice(capturer_name, &device)) {
628 return false;
629 }
630 return capturer->GetId() == device.id;
631}
632
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000633bool ChannelManager::GetVideoCaptureDevice(Device* device) {
634 std::string device_name;
635 if (!GetCaptureDevice(&device_name)) {
636 return false;
637 }
638 return device_manager_->GetVideoCaptureDevice(device_name, device);
639}
640
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000641bool ChannelManager::GetCaptureDevice(std::string* cam_name) {
642 if (camera_device_.empty()) {
643 // Initialize camera_device_ with default.
644 Device device;
645 if (!device_manager_->GetVideoCaptureDevice(
646 DeviceManagerInterface::kDefaultDeviceName, &device)) {
647 LOG(LS_WARNING) << "Device manager can't find default camera: " <<
648 DeviceManagerInterface::kDefaultDeviceName;
649 return false;
650 }
651 camera_device_ = device.name;
652 }
653 *cam_name = camera_device_;
654 return true;
655}
656
657bool ChannelManager::SetCaptureDevice(const std::string& cam_name) {
658 Device device;
659 bool ret = true;
660 if (!device_manager_->GetVideoCaptureDevice(cam_name, &device)) {
661 if (!cam_name.empty()) {
662 LOG(LS_WARNING) << "Device manager can't find camera: " << cam_name;
663 }
664 ret = false;
665 }
666
667 // If we're running, tell the media engine about it.
668 if (initialized_ && ret) {
669 ret = worker_thread_->Invoke<bool>(
670 Bind(&ChannelManager::SetCaptureDevice_w, this, &device));
671 }
672
673 // If everything worked, retain the name of the selected camera.
674 if (ret) {
675 camera_device_ = device.name;
676 } else if (camera_device_.empty()) {
677 // When video option setting fails, we still want camera_device_ to be in a
678 // good state, so we initialize it with default if it's empty.
679 Device default_device;
680 if (!device_manager_->GetVideoCaptureDevice(
681 DeviceManagerInterface::kDefaultDeviceName, &default_device)) {
682 LOG(LS_WARNING) << "Device manager can't find default camera: " <<
683 DeviceManagerInterface::kDefaultDeviceName;
684 }
685 camera_device_ = default_device.name;
686 }
687
688 return ret;
689}
690
691VideoCapturer* ChannelManager::CreateVideoCapturer() {
692 Device device;
693 if (!device_manager_->GetVideoCaptureDevice(camera_device_, &device)) {
694 if (!camera_device_.empty()) {
695 LOG(LS_WARNING) << "Device manager can't find camera: " << camera_device_;
696 }
697 return NULL;
698 }
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +0000699 VideoCapturer* capturer = device_manager_->CreateVideoCapturer(device);
700 if (capturer && default_video_encoder_config_.max_codec.id != 0) {
701 // For now, use the aspect ratio of the default_video_encoder_config_,
702 // which may be different than the native aspect ratio of the start
703 // format the camera may use.
704 capturer->UpdateAspectRatio(
705 default_video_encoder_config_.max_codec.width,
706 default_video_encoder_config_.max_codec.height);
707 }
708 return capturer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000709}
710
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +0000711VideoCapturer* ChannelManager::CreateScreenCapturer(
712 const ScreencastId& screenid) {
713 return device_manager_->CreateScreenCapturer(screenid);
714}
715
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000716bool ChannelManager::SetCaptureDevice_w(const Device* cam_device) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000717 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000718 ASSERT(initialized_);
719
720 if (!cam_device) {
721 video_device_name_.clear();
722 return true;
723 }
724 video_device_name_ = cam_device->name;
725 return true;
726}
727
728bool ChannelManager::SetDefaultVideoEncoderConfig(const VideoEncoderConfig& c) {
buildbot@webrtc.org992febb2014-09-05 16:39:08 +0000729 bool ret = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000730 if (initialized_) {
buildbot@webrtc.org992febb2014-09-05 16:39:08 +0000731 ret = worker_thread_->Invoke<bool>(
732 Bind(&MediaEngineInterface::SetDefaultVideoEncoderConfig,
733 media_engine_.get(), c));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000734 }
buildbot@webrtc.org992febb2014-09-05 16:39:08 +0000735 if (ret) {
736 default_video_encoder_config_ = c;
737 }
738 return ret;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000739}
740
741bool ChannelManager::SetLocalMonitor(bool enable) {
742 bool ret = initialized_ && worker_thread_->Invoke<bool>(
743 Bind(&MediaEngineInterface::SetLocalMonitor,
744 media_engine_.get(), enable));
745 if (ret) {
746 monitoring_ = enable;
747 }
748 return ret;
749}
750
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000751void ChannelManager::SetVoiceLogging(int level, const char* filter) {
752 if (initialized_) {
753 worker_thread_->Invoke<void>(
754 Bind(&MediaEngineInterface::SetVoiceLogging,
755 media_engine_.get(), level, filter));
756 } else {
757 media_engine_->SetVoiceLogging(level, filter);
758 }
759}
760
761void ChannelManager::SetVideoLogging(int level, const char* filter) {
762 if (initialized_) {
763 worker_thread_->Invoke<void>(
764 Bind(&MediaEngineInterface::SetVideoLogging,
765 media_engine_.get(), level, filter));
766 } else {
767 media_engine_->SetVideoLogging(level, filter);
768 }
769}
770
hbos@webrtc.org1e642632015-02-25 09:49:41 +0000771std::vector<cricket::VideoFormat> ChannelManager::GetSupportedFormats(
772 VideoCapturer* capturer) const {
773 ASSERT(capturer != NULL);
774 std::vector<VideoFormat> formats;
775 worker_thread_->Invoke<void>(rtc::Bind(&ChannelManager::GetSupportedFormats_w,
776 this, capturer, &formats));
777 return formats;
778}
779
780void ChannelManager::GetSupportedFormats_w(
781 VideoCapturer* capturer,
782 std::vector<cricket::VideoFormat>* out_formats) const {
783 const std::vector<VideoFormat>* formats = capturer->GetSupportedFormats();
784 if (formats != NULL)
785 *out_formats = *formats;
786}
787
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000788// TODO(janahan): For now pass this request through the mediaengine to the
789// voice and video engines to do the real work. Once the capturer refactoring
790// is done, we will access the capturer using the ssrc (similar to how the
791// renderer is accessed today) and register with it directly.
792bool ChannelManager::RegisterVideoProcessor(VideoCapturer* capturer,
793 VideoProcessor* processor) {
794 return initialized_ && worker_thread_->Invoke<bool>(
795 Bind(&ChannelManager::RegisterVideoProcessor_w, this,
796 capturer, processor));
797}
798
799bool ChannelManager::RegisterVideoProcessor_w(VideoCapturer* capturer,
800 VideoProcessor* processor) {
801 return capture_manager_->AddVideoProcessor(capturer, processor);
802}
803
804bool ChannelManager::UnregisterVideoProcessor(VideoCapturer* capturer,
805 VideoProcessor* processor) {
806 return initialized_ && worker_thread_->Invoke<bool>(
807 Bind(&ChannelManager::UnregisterVideoProcessor_w, this,
808 capturer, processor));
809}
810
811bool ChannelManager::UnregisterVideoProcessor_w(VideoCapturer* capturer,
812 VideoProcessor* processor) {
813 return capture_manager_->RemoveVideoProcessor(capturer, processor);
814}
815
816bool ChannelManager::RegisterVoiceProcessor(
817 uint32 ssrc,
818 VoiceProcessor* processor,
819 MediaProcessorDirection direction) {
820 return initialized_ && worker_thread_->Invoke<bool>(
821 Bind(&MediaEngineInterface::RegisterVoiceProcessor, media_engine_.get(),
822 ssrc, processor, direction));
823}
824
825bool ChannelManager::UnregisterVoiceProcessor(
826 uint32 ssrc,
827 VoiceProcessor* processor,
828 MediaProcessorDirection direction) {
829 return initialized_ && worker_thread_->Invoke<bool>(
830 Bind(&MediaEngineInterface::UnregisterVoiceProcessor,
831 media_engine_.get(), ssrc, processor, direction));
832}
833
834// The following are done in the new "CaptureManager" style that
835// all local video capturers, processors, and managers should move
836// to.
837// TODO(pthatcher): Add more of the CaptureManager interface.
838bool ChannelManager::StartVideoCapture(
839 VideoCapturer* capturer, const VideoFormat& video_format) {
840 return initialized_ && worker_thread_->Invoke<bool>(
841 Bind(&CaptureManager::StartVideoCapture,
842 capture_manager_.get(), capturer, video_format));
843}
844
845bool ChannelManager::MuteToBlackThenPause(
846 VideoCapturer* video_capturer, bool muted) {
847 if (!initialized_) {
848 return false;
849 }
850 worker_thread_->Invoke<void>(
851 Bind(&VideoCapturer::MuteToBlackThenPause, video_capturer, muted));
852 return true;
853}
854
855bool ChannelManager::StopVideoCapture(
856 VideoCapturer* capturer, const VideoFormat& video_format) {
857 return initialized_ && worker_thread_->Invoke<bool>(
858 Bind(&CaptureManager::StopVideoCapture,
859 capture_manager_.get(), capturer, video_format));
860}
861
862bool ChannelManager::RestartVideoCapture(
863 VideoCapturer* video_capturer,
864 const VideoFormat& previous_format,
865 const VideoFormat& desired_format,
866 CaptureManager::RestartOptions options) {
867 return initialized_ && worker_thread_->Invoke<bool>(
868 Bind(&CaptureManager::RestartVideoCapture, capture_manager_.get(),
869 video_capturer, previous_format, desired_format, options));
870}
871
872bool ChannelManager::AddVideoRenderer(
873 VideoCapturer* capturer, VideoRenderer* renderer) {
874 return initialized_ && worker_thread_->Invoke<bool>(
875 Bind(&CaptureManager::AddVideoRenderer,
876 capture_manager_.get(), capturer, renderer));
877}
878
879bool ChannelManager::RemoveVideoRenderer(
880 VideoCapturer* capturer, VideoRenderer* renderer) {
881 return initialized_ && worker_thread_->Invoke<bool>(
882 Bind(&CaptureManager::RemoveVideoRenderer,
883 capture_manager_.get(), capturer, renderer));
884}
885
886bool ChannelManager::IsScreencastRunning() const {
887 return initialized_ && worker_thread_->Invoke<bool>(
888 Bind(&ChannelManager::IsScreencastRunning_w, this));
889}
890
891bool ChannelManager::IsScreencastRunning_w() const {
892 VideoChannels::const_iterator it = video_channels_.begin();
893 for ( ; it != video_channels_.end(); ++it) {
894 if ((*it) && (*it)->IsScreencasting()) {
895 return true;
896 }
897 }
898 return false;
899}
900
901void ChannelManager::OnVideoCaptureStateChange(VideoCapturer* capturer,
902 CaptureState result) {
903 // TODO(whyuan): Check capturer and signal failure only for camera video, not
904 // screencast.
905 capturing_ = result == CS_RUNNING;
906 main_thread_->Post(this, MSG_VIDEOCAPTURESTATE,
907 new CaptureStateParams(capturer, result));
908}
909
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000910void ChannelManager::OnMessage(rtc::Message* message) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000911 switch (message->message_id) {
912 case MSG_VIDEOCAPTURESTATE: {
913 CaptureStateParams* data =
914 static_cast<CaptureStateParams*>(message->pdata);
915 SignalVideoCaptureStateChange(data->capturer, data->state);
916 delete data;
917 break;
918 }
919 }
920}
921
922
923static void GetDeviceNames(const std::vector<Device>& devs,
924 std::vector<std::string>* names) {
925 names->clear();
926 for (size_t i = 0; i < devs.size(); ++i) {
927 names->push_back(devs[i].name);
928 }
929}
930
931bool ChannelManager::GetAudioInputDevices(std::vector<std::string>* names) {
932 names->clear();
933 std::vector<Device> devs;
934 bool ret = device_manager_->GetAudioInputDevices(&devs);
935 if (ret)
936 GetDeviceNames(devs, names);
937
938 return ret;
939}
940
941bool ChannelManager::GetAudioOutputDevices(std::vector<std::string>* names) {
942 names->clear();
943 std::vector<Device> devs;
944 bool ret = device_manager_->GetAudioOutputDevices(&devs);
945 if (ret)
946 GetDeviceNames(devs, names);
947
948 return ret;
949}
950
951bool ChannelManager::GetVideoCaptureDevices(std::vector<std::string>* names) {
952 names->clear();
953 std::vector<Device> devs;
954 bool ret = device_manager_->GetVideoCaptureDevices(&devs);
955 if (ret)
956 GetDeviceNames(devs, names);
957
958 return ret;
959}
960
961void ChannelManager::SetVideoCaptureDeviceMaxFormat(
962 const std::string& usb_id,
963 const VideoFormat& max_format) {
964 device_manager_->SetVideoCaptureDeviceMaxFormat(usb_id, max_format);
965}
966
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000967bool ChannelManager::StartAecDump(rtc::PlatformFile file) {
wu@webrtc.orga9890802013-12-13 00:21:03 +0000968 return worker_thread_->Invoke<bool>(
969 Bind(&MediaEngineInterface::StartAecDump, media_engine_.get(), file));
970}
971
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000972} // namespace cricket