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