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