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