• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libjingle
3  * Copyright 2004 Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "talk/session/media/channelmanager.h"
29 
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33 
34 #include <algorithm>
35 
36 #include "talk/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 {
CaptureStateParamscricket::CaptureStateParams64   CaptureStateParams(cricket::VideoCapturer* c, cricket::CaptureState s)
65       : capturer(c),
66         state(s) {}
67   cricket::VideoCapturer* capturer;
68   cricket::CaptureState state;
69 };
70 
ConstructDataEngine()71 static DataEngineInterface* ConstructDataEngine() {
72 #ifdef HAVE_SCTP
73   return new HybridDataEngine(new RtpDataEngine(), new SctpDataEngine());
74 #else
75   return new RtpDataEngine();
76 #endif
77 }
78 
79 #if !defined(DISABLE_MEDIA_ENGINE_FACTORY)
ChannelManager(talk_base::Thread * worker_thread)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 
ChannelManager(MediaEngineInterface * me,DataEngineInterface * dme,DeviceManagerInterface * dm,CaptureManager * cm,talk_base::Thread * worker_thread)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 
ChannelManager(MediaEngineInterface * me,DeviceManagerInterface * dm,talk_base::Thread * worker_thread)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 
Construct(MediaEngineInterface * me,DataEngineInterface * dme,DeviceManagerInterface * dm,CaptureManager * cm,talk_base::Thread * worker_thread)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 
~ChannelManager()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 
SetVideoRtxEnabled(bool enable)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 
GetCapabilities()169 int ChannelManager::GetCapabilities() {
170   return media_engine_->GetCapabilities() & device_manager_->GetCapabilities();
171 }
172 
GetSupportedAudioCodecs(std::vector<AudioCodec> * codecs) const173 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 
GetSupportedAudioRtpHeaderExtensions(RtpHeaderExtensions * ext) const184 void ChannelManager::GetSupportedAudioRtpHeaderExtensions(
185     RtpHeaderExtensions* ext) const {
186   *ext = media_engine_->audio_rtp_header_extensions();
187 }
188 
GetSupportedVideoCodecs(std::vector<VideoCodec> * codecs) const189 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 
GetSupportedVideoRtpHeaderExtensions(RtpHeaderExtensions * ext) const203 void ChannelManager::GetSupportedVideoRtpHeaderExtensions(
204     RtpHeaderExtensions* ext) const {
205   *ext = media_engine_->video_rtp_header_extensions();
206 }
207 
GetSupportedDataCodecs(std::vector<DataCodec> * codecs) const208 void ChannelManager::GetSupportedDataCodecs(
209     std::vector<DataCodec>* codecs) const {
210   *codecs = data_media_engine_->data_codecs();
211 }
212 
Init()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 
Terminate()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 
Terminate_w()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 
CreateVoiceChannel(BaseSession * session,const std::string & content_name,bool rtcp)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 
CreateVoiceChannel_w(BaseSession * session,const std::string & content_name,bool rtcp)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 
DestroyVoiceChannel(VoiceChannel * voice_channel)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 
DestroyVoiceChannel_w(VoiceChannel * voice_channel)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 
CreateVideoChannel(BaseSession * session,const std::string & content_name,bool rtcp,VoiceChannel * voice_channel)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 
CreateVideoChannel_w(BaseSession * session,const std::string & content_name,bool rtcp,VoiceChannel * voice_channel)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 
DestroyVideoChannel(VideoChannel * video_channel)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 
DestroyVideoChannel_w(VideoChannel * video_channel)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 
CreateDataChannel(BaseSession * session,const std::string & content_name,bool rtcp,DataChannelType channel_type)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 
CreateDataChannel_w(BaseSession * session,const std::string & content_name,bool rtcp,DataChannelType data_channel_type)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 
DestroyDataChannel(DataChannel * data_channel)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 
DestroyDataChannel_w(DataChannel * data_channel)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 
CreateSoundclip()466 Soundclip* ChannelManager::CreateSoundclip() {
467   return worker_thread_->Invoke<Soundclip*>(
468       Bind(&ChannelManager::CreateSoundclip_w, this));
469 }
470 
CreateSoundclip_w()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 
DestroySoundclip(Soundclip * soundclip)485 void ChannelManager::DestroySoundclip(Soundclip* soundclip) {
486   if (soundclip) {
487     worker_thread_->Invoke<void>(
488         Bind(&ChannelManager::DestroySoundclip_w, this, soundclip));
489   }
490 }
491 
DestroySoundclip_w(Soundclip * soundclip)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 
GetAudioOptions(std::string * in_name,std::string * out_name,AudioOptions * options)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 
SetAudioOptions(const std::string & in_name,const std::string & out_name,const AudioOptions & options)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 
SetAudioOptions(const std::string & in_name,const std::string & out_name,const AudioOptions & options,int delay_offset)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 
SetAudioOptions_w(const AudioOptions & options,int delay_offset,const Device * in_dev,const Device * out_dev)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 
GetOutputVolume(int * level)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 
SetOutputVolume(int level)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 
IsSameCapturer(const std::string & capturer_name,VideoCapturer * capturer)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 
GetVideoCaptureDevice(Device * device)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 
GetCaptureDevice(std::string * cam_name)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 
SetCaptureDevice(const std::string & cam_name)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 
CreateVideoCapturer()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 
SetCaptureDevice_w(const Device * cam_device)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 
SetDefaultVideoEncoderConfig(const VideoEncoderConfig & c)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 
SetLocalMonitor(bool enable)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 
SetLocalRenderer(VideoRenderer * renderer)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 
SetVoiceLogging(int level,const char * filter)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 
SetVideoLogging(int level,const char * filter)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.
RegisterVideoProcessor(VideoCapturer * capturer,VideoProcessor * processor)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 
RegisterVideoProcessor_w(VideoCapturer * capturer,VideoProcessor * processor)769 bool ChannelManager::RegisterVideoProcessor_w(VideoCapturer* capturer,
770                                               VideoProcessor* processor) {
771   return capture_manager_->AddVideoProcessor(capturer, processor);
772 }
773 
UnregisterVideoProcessor(VideoCapturer * capturer,VideoProcessor * processor)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 
UnregisterVideoProcessor_w(VideoCapturer * capturer,VideoProcessor * processor)781 bool ChannelManager::UnregisterVideoProcessor_w(VideoCapturer* capturer,
782                                                 VideoProcessor* processor) {
783   return capture_manager_->RemoveVideoProcessor(capturer, processor);
784 }
785 
RegisterVoiceProcessor(uint32 ssrc,VoiceProcessor * processor,MediaProcessorDirection direction)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 
UnregisterVoiceProcessor(uint32 ssrc,VoiceProcessor * processor,MediaProcessorDirection direction)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.
StartVideoCapture(VideoCapturer * capturer,const VideoFormat & video_format)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 
MuteToBlackThenPause(VideoCapturer * video_capturer,bool muted)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 
StopVideoCapture(VideoCapturer * capturer,const VideoFormat & video_format)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 
RestartVideoCapture(VideoCapturer * video_capturer,const VideoFormat & previous_format,const VideoFormat & desired_format,CaptureManager::RestartOptions options)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 
AddVideoRenderer(VideoCapturer * capturer,VideoRenderer * renderer)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 
RemoveVideoRenderer(VideoCapturer * capturer,VideoRenderer * renderer)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 
IsScreencastRunning() const856 bool ChannelManager::IsScreencastRunning() const {
857   return initialized_ && worker_thread_->Invoke<bool>(
858       Bind(&ChannelManager::IsScreencastRunning_w, this));
859 }
860 
IsScreencastRunning_w() const861 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 
OnVideoCaptureStateChange(VideoCapturer * capturer,CaptureState result)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 
OnMessage(talk_base::Message * message)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 
GetDeviceNames(const std::vector<Device> & devs,std::vector<std::string> * names)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 
GetAudioInputDevices(std::vector<std::string> * names)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 
GetAudioOutputDevices(std::vector<std::string> * names)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 
GetVideoCaptureDevices(std::vector<std::string> * names)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 
SetVideoCaptureDeviceMaxFormat(const std::string & usb_id,const VideoFormat & max_format)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 
GetStartCaptureFormat()937 VideoFormat ChannelManager::GetStartCaptureFormat() {
938   return worker_thread_->Invoke<VideoFormat>(
939       Bind(&MediaEngineInterface::GetStartCaptureFormat, media_engine_.get()));
940 }
941 
SetAudioOptions(const AudioOptions & options)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