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