Home | History | Annotate | Download | only in media
      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 {
     64   CaptureStateParams(cricket::VideoCapturer* c, cricket::CaptureState s)
     65       : capturer(c),
     66         state(s) {}
     67   cricket::VideoCapturer* capturer;
     68   cricket::CaptureState state;
     69 };
     70 
     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)
     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 
     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 
     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 
    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 
    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 
    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 
    175 int ChannelManager::GetCapabilities() {
    176   return media_engine_->GetCapabilities() & device_manager_->GetCapabilities();
    177 }
    178 
    179 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 
    190 void ChannelManager::GetSupportedAudioRtpHeaderExtensions(
    191     RtpHeaderExtensions* ext) const {
    192   *ext = media_engine_->audio_rtp_header_extensions();
    193 }
    194 
    195 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 
    209 void ChannelManager::GetSupportedVideoRtpHeaderExtensions(
    210     RtpHeaderExtensions* ext) const {
    211   *ext = media_engine_->video_rtp_header_extensions();
    212 }
    213 
    214 void ChannelManager::GetSupportedDataCodecs(
    215     std::vector<DataCodec>* codecs) const {
    216   *codecs = data_media_engine_->data_codecs();
    217 }
    218 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    468 Soundclip* ChannelManager::CreateSoundclip() {
    469   return worker_thread_->Invoke<Soundclip*>(
    470       Bind(&ChannelManager::CreateSoundclip_w, this));
    471 }
    472 
    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 
    487 void ChannelManager::DestroySoundclip(Soundclip* soundclip) {
    488   if (soundclip) {
    489     worker_thread_->Invoke<void>(
    490         Bind(&ChannelManager::DestroySoundclip_w, this, soundclip));
    491   }
    492 }
    493 
    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 
    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 
    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 
    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 
    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.
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    715 VideoCapturer* ChannelManager::CreateScreenCapturer(
    716     const ScreencastId& screenid) {
    717   return device_manager_->CreateScreenCapturer(screenid);
    718 }
    719 
    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 
    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 
    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 
    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 
    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.
    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 
    786 bool ChannelManager::RegisterVideoProcessor_w(VideoCapturer* capturer,
    787                                               VideoProcessor* processor) {
    788   return capture_manager_->AddVideoProcessor(capturer, processor);
    789 }
    790 
    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 
    798 bool ChannelManager::UnregisterVideoProcessor_w(VideoCapturer* capturer,
    799                                                 VideoProcessor* processor) {
    800   return capture_manager_->RemoveVideoProcessor(capturer, processor);
    801 }
    802 
    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 
    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.
    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 
    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 
    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 
    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 
    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 
    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 
    873 bool ChannelManager::IsScreencastRunning() const {
    874   return initialized_ && worker_thread_->Invoke<bool>(
    875       Bind(&ChannelManager::IsScreencastRunning_w, this));
    876 }
    877 
    878 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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    954 VideoFormat ChannelManager::GetStartCaptureFormat() {
    955   return worker_thread_->Invoke<VideoFormat>(
    956       Bind(&MediaEngineInterface::GetStartCaptureFormat, media_engine_.get()));
    957 }
    958 
    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