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