1 /*
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
36 #include "talk/base/bind.h"
37 #include "talk/base/common.h"
38 #include "talk/base/logging.h"
39 #include "talk/base/sigslotrepeater.h"
40 #include "talk/base/stringencode.h"
41 #include "talk/base/stringutils.h"
42 #include "talk/media/base/capturemanager.h"
43 #include "talk/media/base/hybriddataengine.h"
44 #include "talk/media/base/rtpdataengine.h"
45 #include "talk/media/base/videocapturer.h"
46 #include "talk/media/devices/devicemanager.h"
47 #ifdef HAVE_SCTP
48 #include "talk/media/sctp/sctpdataengine.h"
49 #endif
50 #include "talk/session/media/soundclip.h"
51 #include "talk/session/media/srtpfilter.h"
52
53 namespace cricket {
54
55 enum {
56 MSG_VIDEOCAPTURESTATE = 1,
57 };
58
59 using talk_base::Bind;
60
61 static const int kNotSetOutputVolume = -1;
62
63 struct CaptureStateParams : public talk_base::MessageData {
CaptureStateParamscricket::CaptureStateParams64 CaptureStateParams(cricket::VideoCapturer* c, cricket::CaptureState s)
65 : capturer(c),
66 state(s) {}
67 cricket::VideoCapturer* capturer;
68 cricket::CaptureState state;
69 };
70
ConstructDataEngine()71 static DataEngineInterface* ConstructDataEngine() {
72 #ifdef HAVE_SCTP
73 return new HybridDataEngine(new RtpDataEngine(), new SctpDataEngine());
74 #else
75 return new RtpDataEngine();
76 #endif
77 }
78
79 #if !defined(DISABLE_MEDIA_ENGINE_FACTORY)
ChannelManager(talk_base::Thread * worker_thread)80 ChannelManager::ChannelManager(talk_base::Thread* worker_thread) {
81 Construct(MediaEngineFactory::Create(),
82 ConstructDataEngine(),
83 cricket::DeviceManagerFactory::Create(),
84 new CaptureManager(),
85 worker_thread);
86 }
87 #endif
88
ChannelManager(MediaEngineInterface * me,DataEngineInterface * dme,DeviceManagerInterface * dm,CaptureManager * cm,talk_base::Thread * worker_thread)89 ChannelManager::ChannelManager(MediaEngineInterface* me,
90 DataEngineInterface* dme,
91 DeviceManagerInterface* dm,
92 CaptureManager* cm,
93 talk_base::Thread* worker_thread) {
94 Construct(me, dme, dm, cm, worker_thread);
95 }
96
ChannelManager(MediaEngineInterface * me,DeviceManagerInterface * dm,talk_base::Thread * worker_thread)97 ChannelManager::ChannelManager(MediaEngineInterface* me,
98 DeviceManagerInterface* dm,
99 talk_base::Thread* worker_thread) {
100 Construct(me,
101 ConstructDataEngine(),
102 dm,
103 new CaptureManager(),
104 worker_thread);
105 }
106
Construct(MediaEngineInterface * me,DataEngineInterface * dme,DeviceManagerInterface * dm,CaptureManager * cm,talk_base::Thread * worker_thread)107 void ChannelManager::Construct(MediaEngineInterface* me,
108 DataEngineInterface* dme,
109 DeviceManagerInterface* dm,
110 CaptureManager* cm,
111 talk_base::Thread* worker_thread) {
112 media_engine_.reset(me);
113 data_media_engine_.reset(dme);
114 device_manager_.reset(dm);
115 capture_manager_.reset(cm);
116 initialized_ = false;
117 main_thread_ = talk_base::Thread::Current();
118 worker_thread_ = worker_thread;
119 // Get the default audio options from the media engine.
120 audio_options_ = media_engine_->GetAudioOptions();
121 audio_in_device_ = DeviceManagerInterface::kDefaultDeviceName;
122 audio_out_device_ = DeviceManagerInterface::kDefaultDeviceName;
123 audio_delay_offset_ = MediaEngineInterface::kDefaultAudioDelayOffset;
124 audio_output_volume_ = kNotSetOutputVolume;
125 local_renderer_ = NULL;
126 capturing_ = false;
127 monitoring_ = false;
128 enable_rtx_ = false;
129
130 // Init the device manager immediately, and set up our default video device.
131 SignalDevicesChange.repeat(device_manager_->SignalDevicesChange);
132 device_manager_->Init();
133
134 // Camera is started asynchronously, request callbacks when startup
135 // completes to be able to forward them to the rendering manager.
136 media_engine_->SignalVideoCaptureStateChange().connect(
137 this, &ChannelManager::OnVideoCaptureStateChange);
138 capture_manager_->SignalCapturerStateChange.connect(
139 this, &ChannelManager::OnVideoCaptureStateChange);
140 }
141
~ChannelManager()142 ChannelManager::~ChannelManager() {
143 if (initialized_) {
144 Terminate();
145 // If srtp is initialized (done by the Channel) then we must call
146 // srtp_shutdown to free all crypto kernel lists. But we need to make sure
147 // shutdown always called at the end, after channels are destroyed.
148 // ChannelManager d'tor is always called last, it's safe place to call
149 // shutdown.
150 ShutdownSrtp();
151 }
152 }
153
SetVideoRtxEnabled(bool enable)154 bool ChannelManager::SetVideoRtxEnabled(bool enable) {
155 // To be safe, this call is only allowed before initialization. Apps like
156 // Flute only have a singleton ChannelManager and we don't want this flag to
157 // be toggled between calls or when there's concurrent calls. We expect apps
158 // to enable this at startup and retain that setting for the lifetime of the
159 // app.
160 if (!initialized_) {
161 enable_rtx_ = enable;
162 return true;
163 } else {
164 LOG(LS_WARNING) << "Cannot toggle rtx after initialization!";
165 return false;
166 }
167 }
168
GetCapabilities()169 int ChannelManager::GetCapabilities() {
170 return media_engine_->GetCapabilities() & device_manager_->GetCapabilities();
171 }
172
GetSupportedAudioCodecs(std::vector<AudioCodec> * codecs) const173 void ChannelManager::GetSupportedAudioCodecs(
174 std::vector<AudioCodec>* codecs) const {
175 codecs->clear();
176
177 for (std::vector<AudioCodec>::const_iterator it =
178 media_engine_->audio_codecs().begin();
179 it != media_engine_->audio_codecs().end(); ++it) {
180 codecs->push_back(*it);
181 }
182 }
183
GetSupportedAudioRtpHeaderExtensions(RtpHeaderExtensions * ext) const184 void ChannelManager::GetSupportedAudioRtpHeaderExtensions(
185 RtpHeaderExtensions* ext) const {
186 *ext = media_engine_->audio_rtp_header_extensions();
187 }
188
GetSupportedVideoCodecs(std::vector<VideoCodec> * codecs) const189 void ChannelManager::GetSupportedVideoCodecs(
190 std::vector<VideoCodec>* codecs) const {
191 codecs->clear();
192
193 std::vector<VideoCodec>::const_iterator it;
194 for (it = media_engine_->video_codecs().begin();
195 it != media_engine_->video_codecs().end(); ++it) {
196 if (!enable_rtx_ && _stricmp(kRtxCodecName, it->name.c_str()) == 0) {
197 continue;
198 }
199 codecs->push_back(*it);
200 }
201 }
202
GetSupportedVideoRtpHeaderExtensions(RtpHeaderExtensions * ext) const203 void ChannelManager::GetSupportedVideoRtpHeaderExtensions(
204 RtpHeaderExtensions* ext) const {
205 *ext = media_engine_->video_rtp_header_extensions();
206 }
207
GetSupportedDataCodecs(std::vector<DataCodec> * codecs) const208 void ChannelManager::GetSupportedDataCodecs(
209 std::vector<DataCodec>* codecs) const {
210 *codecs = data_media_engine_->data_codecs();
211 }
212
Init()213 bool ChannelManager::Init() {
214 ASSERT(!initialized_);
215 if (initialized_) {
216 return false;
217 }
218
219 ASSERT(worker_thread_ != NULL);
220 if (worker_thread_ && worker_thread_->started()) {
221 if (media_engine_->Init(worker_thread_)) {
222 initialized_ = true;
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 // And the local renderer.
281 if (local_renderer_) {
282 SetLocalRenderer(local_renderer_);
283 }
284 }
285 }
286 return initialized_;
287 }
288
Terminate()289 void ChannelManager::Terminate() {
290 ASSERT(initialized_);
291 if (!initialized_) {
292 return;
293 }
294 worker_thread_->Invoke<void>(Bind(&ChannelManager::Terminate_w, this));
295 media_engine_->Terminate();
296 initialized_ = false;
297 }
298
Terminate_w()299 void ChannelManager::Terminate_w() {
300 ASSERT(worker_thread_ == talk_base::Thread::Current());
301 // Need to destroy the voice/video channels
302 while (!video_channels_.empty()) {
303 DestroyVideoChannel_w(video_channels_.back());
304 }
305 while (!voice_channels_.empty()) {
306 DestroyVoiceChannel_w(voice_channels_.back());
307 }
308 while (!soundclips_.empty()) {
309 DestroySoundclip_w(soundclips_.back());
310 }
311 if (!SetCaptureDevice_w(NULL)) {
312 LOG(LS_WARNING) << "failed to delete video capturer";
313 }
314 }
315
CreateVoiceChannel(BaseSession * session,const std::string & content_name,bool rtcp)316 VoiceChannel* ChannelManager::CreateVoiceChannel(
317 BaseSession* session, const std::string& content_name, bool rtcp) {
318 return worker_thread_->Invoke<VoiceChannel*>(
319 Bind(&ChannelManager::CreateVoiceChannel_w, this,
320 session, content_name, rtcp));
321 }
322
CreateVoiceChannel_w(BaseSession * session,const std::string & content_name,bool rtcp)323 VoiceChannel* ChannelManager::CreateVoiceChannel_w(
324 BaseSession* session, const std::string& content_name, bool rtcp) {
325 // This is ok to alloc from a thread other than the worker thread
326 ASSERT(initialized_);
327 VoiceMediaChannel* media_channel = media_engine_->CreateChannel();
328 if (media_channel == NULL)
329 return NULL;
330
331 VoiceChannel* voice_channel = new VoiceChannel(
332 worker_thread_, media_engine_.get(), media_channel,
333 session, content_name, rtcp);
334 if (!voice_channel->Init()) {
335 delete voice_channel;
336 return NULL;
337 }
338 voice_channels_.push_back(voice_channel);
339 return voice_channel;
340 }
341
DestroyVoiceChannel(VoiceChannel * voice_channel)342 void ChannelManager::DestroyVoiceChannel(VoiceChannel* voice_channel) {
343 if (voice_channel) {
344 worker_thread_->Invoke<void>(
345 Bind(&ChannelManager::DestroyVoiceChannel_w, this, voice_channel));
346 }
347 }
348
DestroyVoiceChannel_w(VoiceChannel * voice_channel)349 void ChannelManager::DestroyVoiceChannel_w(VoiceChannel* voice_channel) {
350 // Destroy voice channel.
351 ASSERT(initialized_);
352 VoiceChannels::iterator it = std::find(voice_channels_.begin(),
353 voice_channels_.end(), voice_channel);
354 ASSERT(it != voice_channels_.end());
355 if (it == voice_channels_.end())
356 return;
357
358 voice_channels_.erase(it);
359 delete voice_channel;
360 }
361
CreateVideoChannel(BaseSession * session,const std::string & content_name,bool rtcp,VoiceChannel * voice_channel)362 VideoChannel* ChannelManager::CreateVideoChannel(
363 BaseSession* session, const std::string& content_name, bool rtcp,
364 VoiceChannel* voice_channel) {
365 return worker_thread_->Invoke<VideoChannel*>(
366 Bind(&ChannelManager::CreateVideoChannel_w, this, session,
367 content_name, rtcp, voice_channel));
368 }
369
CreateVideoChannel_w(BaseSession * session,const std::string & content_name,bool rtcp,VoiceChannel * voice_channel)370 VideoChannel* ChannelManager::CreateVideoChannel_w(
371 BaseSession* session, const std::string& content_name, bool rtcp,
372 VoiceChannel* voice_channel) {
373 // This is ok to alloc from a thread other than the worker thread
374 ASSERT(initialized_);
375 VideoMediaChannel* media_channel =
376 // voice_channel can be NULL in case of NullVoiceEngine.
377 media_engine_->CreateVideoChannel(voice_channel ?
378 voice_channel->media_channel() : NULL);
379 if (media_channel == NULL)
380 return NULL;
381
382 VideoChannel* video_channel = new VideoChannel(
383 worker_thread_, media_engine_.get(), media_channel,
384 session, content_name, rtcp, voice_channel);
385 if (!video_channel->Init()) {
386 delete video_channel;
387 return NULL;
388 }
389 video_channels_.push_back(video_channel);
390 return video_channel;
391 }
392
DestroyVideoChannel(VideoChannel * video_channel)393 void ChannelManager::DestroyVideoChannel(VideoChannel* video_channel) {
394 if (video_channel) {
395 worker_thread_->Invoke<void>(
396 Bind(&ChannelManager::DestroyVideoChannel_w, this, video_channel));
397 }
398 }
399
DestroyVideoChannel_w(VideoChannel * video_channel)400 void ChannelManager::DestroyVideoChannel_w(VideoChannel* video_channel) {
401 // Destroy video channel.
402 ASSERT(initialized_);
403 VideoChannels::iterator it = std::find(video_channels_.begin(),
404 video_channels_.end(), video_channel);
405 ASSERT(it != video_channels_.end());
406 if (it == video_channels_.end())
407 return;
408
409 video_channels_.erase(it);
410 delete video_channel;
411 }
412
CreateDataChannel(BaseSession * session,const std::string & content_name,bool rtcp,DataChannelType channel_type)413 DataChannel* ChannelManager::CreateDataChannel(
414 BaseSession* session, const std::string& content_name,
415 bool rtcp, DataChannelType channel_type) {
416 return worker_thread_->Invoke<DataChannel*>(
417 Bind(&ChannelManager::CreateDataChannel_w, this, session, content_name,
418 rtcp, channel_type));
419 }
420
CreateDataChannel_w(BaseSession * session,const std::string & content_name,bool rtcp,DataChannelType data_channel_type)421 DataChannel* ChannelManager::CreateDataChannel_w(
422 BaseSession* session, const std::string& content_name,
423 bool rtcp, DataChannelType data_channel_type) {
424 // This is ok to alloc from a thread other than the worker thread.
425 ASSERT(initialized_);
426 DataMediaChannel* media_channel = data_media_engine_->CreateChannel(
427 data_channel_type);
428 if (!media_channel) {
429 LOG(LS_WARNING) << "Failed to create data channel of type "
430 << data_channel_type;
431 return NULL;
432 }
433
434 DataChannel* data_channel = new DataChannel(
435 worker_thread_, media_channel,
436 session, content_name, rtcp);
437 if (!data_channel->Init()) {
438 LOG(LS_WARNING) << "Failed to init data channel.";
439 delete data_channel;
440 return NULL;
441 }
442 data_channels_.push_back(data_channel);
443 return data_channel;
444 }
445
DestroyDataChannel(DataChannel * data_channel)446 void ChannelManager::DestroyDataChannel(DataChannel* data_channel) {
447 if (data_channel) {
448 worker_thread_->Invoke<void>(
449 Bind(&ChannelManager::DestroyDataChannel_w, this, data_channel));
450 }
451 }
452
DestroyDataChannel_w(DataChannel * data_channel)453 void ChannelManager::DestroyDataChannel_w(DataChannel* data_channel) {
454 // Destroy data channel.
455 ASSERT(initialized_);
456 DataChannels::iterator it = std::find(data_channels_.begin(),
457 data_channels_.end(), data_channel);
458 ASSERT(it != data_channels_.end());
459 if (it == data_channels_.end())
460 return;
461
462 data_channels_.erase(it);
463 delete data_channel;
464 }
465
CreateSoundclip()466 Soundclip* ChannelManager::CreateSoundclip() {
467 return worker_thread_->Invoke<Soundclip*>(
468 Bind(&ChannelManager::CreateSoundclip_w, this));
469 }
470
CreateSoundclip_w()471 Soundclip* ChannelManager::CreateSoundclip_w() {
472 ASSERT(initialized_);
473 ASSERT(worker_thread_ == talk_base::Thread::Current());
474
475 SoundclipMedia* soundclip_media = media_engine_->CreateSoundclip();
476 if (!soundclip_media) {
477 return NULL;
478 }
479
480 Soundclip* soundclip = new Soundclip(worker_thread_, soundclip_media);
481 soundclips_.push_back(soundclip);
482 return soundclip;
483 }
484
DestroySoundclip(Soundclip * soundclip)485 void ChannelManager::DestroySoundclip(Soundclip* soundclip) {
486 if (soundclip) {
487 worker_thread_->Invoke<void>(
488 Bind(&ChannelManager::DestroySoundclip_w, this, soundclip));
489 }
490 }
491
DestroySoundclip_w(Soundclip * soundclip)492 void ChannelManager::DestroySoundclip_w(Soundclip* soundclip) {
493 // Destroy soundclip.
494 ASSERT(initialized_);
495 Soundclips::iterator it = std::find(soundclips_.begin(),
496 soundclips_.end(), soundclip);
497 ASSERT(it != soundclips_.end());
498 if (it == soundclips_.end())
499 return;
500
501 soundclips_.erase(it);
502 delete soundclip;
503 }
504
GetAudioOptions(std::string * in_name,std::string * out_name,AudioOptions * options)505 bool ChannelManager::GetAudioOptions(std::string* in_name,
506 std::string* out_name,
507 AudioOptions* options) {
508 if (in_name)
509 *in_name = audio_in_device_;
510 if (out_name)
511 *out_name = audio_out_device_;
512 if (options)
513 *options = audio_options_;
514 return true;
515 }
516
SetAudioOptions(const std::string & in_name,const std::string & out_name,const AudioOptions & options)517 bool ChannelManager::SetAudioOptions(const std::string& in_name,
518 const std::string& out_name,
519 const AudioOptions& options) {
520 return SetAudioOptions(in_name, out_name, options, audio_delay_offset_);
521 }
522
SetAudioOptions(const std::string & in_name,const std::string & out_name,const AudioOptions & options,int delay_offset)523 bool ChannelManager::SetAudioOptions(const std::string& in_name,
524 const std::string& out_name,
525 const AudioOptions& options,
526 int delay_offset) {
527 // Get device ids from DeviceManager.
528 Device in_dev, out_dev;
529 if (!device_manager_->GetAudioInputDevice(in_name, &in_dev)) {
530 LOG(LS_WARNING) << "Failed to GetAudioInputDevice: " << in_name;
531 return false;
532 }
533 if (!device_manager_->GetAudioOutputDevice(out_name, &out_dev)) {
534 LOG(LS_WARNING) << "Failed to GetAudioOutputDevice: " << out_name;
535 return false;
536 }
537
538 // If we're initialized, pass the settings to the media engine.
539 bool ret = true;
540 if (initialized_) {
541 ret = worker_thread_->Invoke<bool>(
542 Bind(&ChannelManager::SetAudioOptions_w, this,
543 options, delay_offset, &in_dev, &out_dev));
544 }
545
546 // If all worked well, save the values for use in GetAudioOptions.
547 if (ret) {
548 audio_options_ = options;
549 audio_in_device_ = in_name;
550 audio_out_device_ = out_name;
551 audio_delay_offset_ = delay_offset;
552 }
553 return ret;
554 }
555
SetAudioOptions_w(const AudioOptions & options,int delay_offset,const Device * in_dev,const Device * out_dev)556 bool ChannelManager::SetAudioOptions_w(
557 const AudioOptions& options, int delay_offset,
558 const Device* in_dev, const Device* out_dev) {
559 ASSERT(worker_thread_ == talk_base::Thread::Current());
560 ASSERT(initialized_);
561
562 // Set audio options
563 bool ret = media_engine_->SetAudioOptions(options);
564
565 if (ret) {
566 ret = media_engine_->SetAudioDelayOffset(delay_offset);
567 }
568
569 // Set the audio devices
570 if (ret) {
571 ret = media_engine_->SetSoundDevices(in_dev, out_dev);
572 }
573
574 return ret;
575 }
576
GetOutputVolume(int * level)577 bool ChannelManager::GetOutputVolume(int* level) {
578 if (!initialized_) {
579 return false;
580 }
581 return worker_thread_->Invoke<bool>(
582 Bind(&MediaEngineInterface::GetOutputVolume, media_engine_.get(), level));
583 }
584
SetOutputVolume(int level)585 bool ChannelManager::SetOutputVolume(int level) {
586 bool ret = level >= 0 && level <= 255;
587 if (initialized_) {
588 ret &= worker_thread_->Invoke<bool>(
589 Bind(&MediaEngineInterface::SetOutputVolume,
590 media_engine_.get(), level));
591 }
592
593 if (ret) {
594 audio_output_volume_ = level;
595 }
596
597 return ret;
598 }
599
IsSameCapturer(const std::string & capturer_name,VideoCapturer * capturer)600 bool ChannelManager::IsSameCapturer(const std::string& capturer_name,
601 VideoCapturer* capturer) {
602 if (capturer == NULL) {
603 return false;
604 }
605 Device device;
606 if (!device_manager_->GetVideoCaptureDevice(capturer_name, &device)) {
607 return false;
608 }
609 return capturer->GetId() == device.id;
610 }
611
GetVideoCaptureDevice(Device * device)612 bool ChannelManager::GetVideoCaptureDevice(Device* device) {
613 std::string device_name;
614 if (!GetCaptureDevice(&device_name)) {
615 return false;
616 }
617 return device_manager_->GetVideoCaptureDevice(device_name, device);
618 }
619
GetCaptureDevice(std::string * cam_name)620 bool ChannelManager::GetCaptureDevice(std::string* cam_name) {
621 if (camera_device_.empty()) {
622 // Initialize camera_device_ with default.
623 Device device;
624 if (!device_manager_->GetVideoCaptureDevice(
625 DeviceManagerInterface::kDefaultDeviceName, &device)) {
626 LOG(LS_WARNING) << "Device manager can't find default camera: " <<
627 DeviceManagerInterface::kDefaultDeviceName;
628 return false;
629 }
630 camera_device_ = device.name;
631 }
632 *cam_name = camera_device_;
633 return true;
634 }
635
SetCaptureDevice(const std::string & cam_name)636 bool ChannelManager::SetCaptureDevice(const std::string& cam_name) {
637 Device device;
638 bool ret = true;
639 if (!device_manager_->GetVideoCaptureDevice(cam_name, &device)) {
640 if (!cam_name.empty()) {
641 LOG(LS_WARNING) << "Device manager can't find camera: " << cam_name;
642 }
643 ret = false;
644 }
645
646 // If we're running, tell the media engine about it.
647 if (initialized_ && ret) {
648 ret = worker_thread_->Invoke<bool>(
649 Bind(&ChannelManager::SetCaptureDevice_w, this, &device));
650 }
651
652 // If everything worked, retain the name of the selected camera.
653 if (ret) {
654 camera_device_ = device.name;
655 } else if (camera_device_.empty()) {
656 // When video option setting fails, we still want camera_device_ to be in a
657 // good state, so we initialize it with default if it's empty.
658 Device default_device;
659 if (!device_manager_->GetVideoCaptureDevice(
660 DeviceManagerInterface::kDefaultDeviceName, &default_device)) {
661 LOG(LS_WARNING) << "Device manager can't find default camera: " <<
662 DeviceManagerInterface::kDefaultDeviceName;
663 }
664 camera_device_ = default_device.name;
665 }
666
667 return ret;
668 }
669
CreateVideoCapturer()670 VideoCapturer* ChannelManager::CreateVideoCapturer() {
671 Device device;
672 if (!device_manager_->GetVideoCaptureDevice(camera_device_, &device)) {
673 if (!camera_device_.empty()) {
674 LOG(LS_WARNING) << "Device manager can't find camera: " << camera_device_;
675 }
676 return NULL;
677 }
678 VideoCapturer* capturer = device_manager_->CreateVideoCapturer(device);
679 if (capturer && default_video_encoder_config_.max_codec.id != 0) {
680 // For now, use the aspect ratio of the default_video_encoder_config_,
681 // which may be different than the native aspect ratio of the start
682 // format the camera may use.
683 capturer->UpdateAspectRatio(
684 default_video_encoder_config_.max_codec.width,
685 default_video_encoder_config_.max_codec.height);
686 }
687 return capturer;
688 }
689
SetCaptureDevice_w(const Device * cam_device)690 bool ChannelManager::SetCaptureDevice_w(const Device* cam_device) {
691 ASSERT(worker_thread_ == talk_base::Thread::Current());
692 ASSERT(initialized_);
693
694 if (!cam_device) {
695 video_device_name_.clear();
696 return true;
697 }
698 video_device_name_ = cam_device->name;
699 return true;
700 }
701
SetDefaultVideoEncoderConfig(const VideoEncoderConfig & c)702 bool ChannelManager::SetDefaultVideoEncoderConfig(const VideoEncoderConfig& c) {
703 bool ret = true;
704 if (initialized_) {
705 ret = worker_thread_->Invoke<bool>(
706 Bind(&MediaEngineInterface::SetDefaultVideoEncoderConfig,
707 media_engine_.get(), c));
708 }
709 if (ret) {
710 default_video_encoder_config_ = c;
711 }
712 return ret;
713 }
714
SetLocalMonitor(bool enable)715 bool ChannelManager::SetLocalMonitor(bool enable) {
716 bool ret = initialized_ && worker_thread_->Invoke<bool>(
717 Bind(&MediaEngineInterface::SetLocalMonitor,
718 media_engine_.get(), enable));
719 if (ret) {
720 monitoring_ = enable;
721 }
722 return ret;
723 }
724
SetLocalRenderer(VideoRenderer * renderer)725 bool ChannelManager::SetLocalRenderer(VideoRenderer* renderer) {
726 bool ret = true;
727 if (initialized_) {
728 ret = worker_thread_->Invoke<bool>(
729 Bind(&MediaEngineInterface::SetLocalRenderer,
730 media_engine_.get(), renderer));
731 }
732 if (ret) {
733 local_renderer_ = renderer;
734 }
735 return ret;
736 }
737
SetVoiceLogging(int level,const char * filter)738 void ChannelManager::SetVoiceLogging(int level, const char* filter) {
739 if (initialized_) {
740 worker_thread_->Invoke<void>(
741 Bind(&MediaEngineInterface::SetVoiceLogging,
742 media_engine_.get(), level, filter));
743 } else {
744 media_engine_->SetVoiceLogging(level, filter);
745 }
746 }
747
SetVideoLogging(int level,const char * filter)748 void ChannelManager::SetVideoLogging(int level, const char* filter) {
749 if (initialized_) {
750 worker_thread_->Invoke<void>(
751 Bind(&MediaEngineInterface::SetVideoLogging,
752 media_engine_.get(), level, filter));
753 } else {
754 media_engine_->SetVideoLogging(level, filter);
755 }
756 }
757
758 // TODO(janahan): For now pass this request through the mediaengine to the
759 // voice and video engines to do the real work. Once the capturer refactoring
760 // is done, we will access the capturer using the ssrc (similar to how the
761 // renderer is accessed today) and register with it directly.
RegisterVideoProcessor(VideoCapturer * capturer,VideoProcessor * processor)762 bool ChannelManager::RegisterVideoProcessor(VideoCapturer* capturer,
763 VideoProcessor* processor) {
764 return initialized_ && worker_thread_->Invoke<bool>(
765 Bind(&ChannelManager::RegisterVideoProcessor_w, this,
766 capturer, processor));
767 }
768
RegisterVideoProcessor_w(VideoCapturer * capturer,VideoProcessor * processor)769 bool ChannelManager::RegisterVideoProcessor_w(VideoCapturer* capturer,
770 VideoProcessor* processor) {
771 return capture_manager_->AddVideoProcessor(capturer, processor);
772 }
773
UnregisterVideoProcessor(VideoCapturer * capturer,VideoProcessor * processor)774 bool ChannelManager::UnregisterVideoProcessor(VideoCapturer* capturer,
775 VideoProcessor* processor) {
776 return initialized_ && worker_thread_->Invoke<bool>(
777 Bind(&ChannelManager::UnregisterVideoProcessor_w, this,
778 capturer, processor));
779 }
780
UnregisterVideoProcessor_w(VideoCapturer * capturer,VideoProcessor * processor)781 bool ChannelManager::UnregisterVideoProcessor_w(VideoCapturer* capturer,
782 VideoProcessor* processor) {
783 return capture_manager_->RemoveVideoProcessor(capturer, processor);
784 }
785
RegisterVoiceProcessor(uint32 ssrc,VoiceProcessor * processor,MediaProcessorDirection direction)786 bool ChannelManager::RegisterVoiceProcessor(
787 uint32 ssrc,
788 VoiceProcessor* processor,
789 MediaProcessorDirection direction) {
790 return initialized_ && worker_thread_->Invoke<bool>(
791 Bind(&MediaEngineInterface::RegisterVoiceProcessor, media_engine_.get(),
792 ssrc, processor, direction));
793 }
794
UnregisterVoiceProcessor(uint32 ssrc,VoiceProcessor * processor,MediaProcessorDirection direction)795 bool ChannelManager::UnregisterVoiceProcessor(
796 uint32 ssrc,
797 VoiceProcessor* processor,
798 MediaProcessorDirection direction) {
799 return initialized_ && worker_thread_->Invoke<bool>(
800 Bind(&MediaEngineInterface::UnregisterVoiceProcessor,
801 media_engine_.get(), ssrc, processor, direction));
802 }
803
804 // The following are done in the new "CaptureManager" style that
805 // all local video capturers, processors, and managers should move
806 // to.
807 // TODO(pthatcher): Add more of the CaptureManager interface.
StartVideoCapture(VideoCapturer * capturer,const VideoFormat & video_format)808 bool ChannelManager::StartVideoCapture(
809 VideoCapturer* capturer, const VideoFormat& video_format) {
810 return initialized_ && worker_thread_->Invoke<bool>(
811 Bind(&CaptureManager::StartVideoCapture,
812 capture_manager_.get(), capturer, video_format));
813 }
814
MuteToBlackThenPause(VideoCapturer * video_capturer,bool muted)815 bool ChannelManager::MuteToBlackThenPause(
816 VideoCapturer* video_capturer, bool muted) {
817 if (!initialized_) {
818 return false;
819 }
820 worker_thread_->Invoke<void>(
821 Bind(&VideoCapturer::MuteToBlackThenPause, video_capturer, muted));
822 return true;
823 }
824
StopVideoCapture(VideoCapturer * capturer,const VideoFormat & video_format)825 bool ChannelManager::StopVideoCapture(
826 VideoCapturer* capturer, const VideoFormat& video_format) {
827 return initialized_ && worker_thread_->Invoke<bool>(
828 Bind(&CaptureManager::StopVideoCapture,
829 capture_manager_.get(), capturer, video_format));
830 }
831
RestartVideoCapture(VideoCapturer * video_capturer,const VideoFormat & previous_format,const VideoFormat & desired_format,CaptureManager::RestartOptions options)832 bool ChannelManager::RestartVideoCapture(
833 VideoCapturer* video_capturer,
834 const VideoFormat& previous_format,
835 const VideoFormat& desired_format,
836 CaptureManager::RestartOptions options) {
837 return initialized_ && worker_thread_->Invoke<bool>(
838 Bind(&CaptureManager::RestartVideoCapture, capture_manager_.get(),
839 video_capturer, previous_format, desired_format, options));
840 }
841
AddVideoRenderer(VideoCapturer * capturer,VideoRenderer * renderer)842 bool ChannelManager::AddVideoRenderer(
843 VideoCapturer* capturer, VideoRenderer* renderer) {
844 return initialized_ && worker_thread_->Invoke<bool>(
845 Bind(&CaptureManager::AddVideoRenderer,
846 capture_manager_.get(), capturer, renderer));
847 }
848
RemoveVideoRenderer(VideoCapturer * capturer,VideoRenderer * renderer)849 bool ChannelManager::RemoveVideoRenderer(
850 VideoCapturer* capturer, VideoRenderer* renderer) {
851 return initialized_ && worker_thread_->Invoke<bool>(
852 Bind(&CaptureManager::RemoveVideoRenderer,
853 capture_manager_.get(), capturer, renderer));
854 }
855
IsScreencastRunning() const856 bool ChannelManager::IsScreencastRunning() const {
857 return initialized_ && worker_thread_->Invoke<bool>(
858 Bind(&ChannelManager::IsScreencastRunning_w, this));
859 }
860
IsScreencastRunning_w() const861 bool ChannelManager::IsScreencastRunning_w() const {
862 VideoChannels::const_iterator it = video_channels_.begin();
863 for ( ; it != video_channels_.end(); ++it) {
864 if ((*it) && (*it)->IsScreencasting()) {
865 return true;
866 }
867 }
868 return false;
869 }
870
OnVideoCaptureStateChange(VideoCapturer * capturer,CaptureState result)871 void ChannelManager::OnVideoCaptureStateChange(VideoCapturer* capturer,
872 CaptureState result) {
873 // TODO(whyuan): Check capturer and signal failure only for camera video, not
874 // screencast.
875 capturing_ = result == CS_RUNNING;
876 main_thread_->Post(this, MSG_VIDEOCAPTURESTATE,
877 new CaptureStateParams(capturer, result));
878 }
879
OnMessage(talk_base::Message * message)880 void ChannelManager::OnMessage(talk_base::Message* message) {
881 switch (message->message_id) {
882 case MSG_VIDEOCAPTURESTATE: {
883 CaptureStateParams* data =
884 static_cast<CaptureStateParams*>(message->pdata);
885 SignalVideoCaptureStateChange(data->capturer, data->state);
886 delete data;
887 break;
888 }
889 }
890 }
891
892
GetDeviceNames(const std::vector<Device> & devs,std::vector<std::string> * names)893 static void GetDeviceNames(const std::vector<Device>& devs,
894 std::vector<std::string>* names) {
895 names->clear();
896 for (size_t i = 0; i < devs.size(); ++i) {
897 names->push_back(devs[i].name);
898 }
899 }
900
GetAudioInputDevices(std::vector<std::string> * names)901 bool ChannelManager::GetAudioInputDevices(std::vector<std::string>* names) {
902 names->clear();
903 std::vector<Device> devs;
904 bool ret = device_manager_->GetAudioInputDevices(&devs);
905 if (ret)
906 GetDeviceNames(devs, names);
907
908 return ret;
909 }
910
GetAudioOutputDevices(std::vector<std::string> * names)911 bool ChannelManager::GetAudioOutputDevices(std::vector<std::string>* names) {
912 names->clear();
913 std::vector<Device> devs;
914 bool ret = device_manager_->GetAudioOutputDevices(&devs);
915 if (ret)
916 GetDeviceNames(devs, names);
917
918 return ret;
919 }
920
GetVideoCaptureDevices(std::vector<std::string> * names)921 bool ChannelManager::GetVideoCaptureDevices(std::vector<std::string>* names) {
922 names->clear();
923 std::vector<Device> devs;
924 bool ret = device_manager_->GetVideoCaptureDevices(&devs);
925 if (ret)
926 GetDeviceNames(devs, names);
927
928 return ret;
929 }
930
SetVideoCaptureDeviceMaxFormat(const std::string & usb_id,const VideoFormat & max_format)931 void ChannelManager::SetVideoCaptureDeviceMaxFormat(
932 const std::string& usb_id,
933 const VideoFormat& max_format) {
934 device_manager_->SetVideoCaptureDeviceMaxFormat(usb_id, max_format);
935 }
936
GetStartCaptureFormat()937 VideoFormat ChannelManager::GetStartCaptureFormat() {
938 return worker_thread_->Invoke<VideoFormat>(
939 Bind(&MediaEngineInterface::GetStartCaptureFormat, media_engine_.get()));
940 }
941
SetAudioOptions(const AudioOptions & options)942 bool ChannelManager::SetAudioOptions(const AudioOptions& options) {
943 if (!media_engine_->SetAudioOptions(options)) {
944 return false;
945 }
946 audio_options_ = options;
947 return true;
948 }
949
950 } // namespace cricket
951