3 * Copyright 2004 Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
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.
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.
28 #include "talk/session/media/channelmanager.h"
36 #include "talk/media/base/capturemanager.h"
37 #include "talk/media/base/hybriddataengine.h"
38 #include "talk/media/base/rtpdataengine.h"
39 #include "talk/media/base/videocapturer.h"
40 #include "talk/media/devices/devicemanager.h"
42 #include "talk/media/sctp/sctpdataengine.h"
44 #include "talk/session/media/soundclip.h"
45 #include "talk/session/media/srtpfilter.h"
46 #include "webrtc/base/bind.h"
47 #include "webrtc/base/common.h"
48 #include "webrtc/base/logging.h"
49 #include "webrtc/base/sigslotrepeater.h"
50 #include "webrtc/base/stringencode.h"
51 #include "webrtc/base/stringutils.h"
56 MSG_VIDEOCAPTURESTATE = 1,
61 static const int kNotSetOutputVolume = -1;
63 struct CaptureStateParams : public rtc::MessageData {
64 CaptureStateParams(cricket::VideoCapturer* c, cricket::CaptureState s)
67 cricket::VideoCapturer* capturer;
68 cricket::CaptureState state;
71 static DataEngineInterface* ConstructDataEngine() {
73 return new HybridDataEngine(new RtpDataEngine(), new SctpDataEngine());
75 return new RtpDataEngine();
79 #if !defined(DISABLE_MEDIA_ENGINE_FACTORY)
80 ChannelManager::ChannelManager(rtc::Thread* worker_thread) {
81 Construct(MediaEngineFactory::Create(),
82 ConstructDataEngine(),
83 cricket::DeviceManagerFactory::Create(),
89 ChannelManager::ChannelManager(MediaEngineInterface* me,
90 DataEngineInterface* dme,
91 DeviceManagerInterface* dm,
93 rtc::Thread* worker_thread) {
94 Construct(me, dme, dm, cm, worker_thread);
97 ChannelManager::ChannelManager(MediaEngineInterface* me,
98 DeviceManagerInterface* dm,
99 rtc::Thread* worker_thread) {
101 ConstructDataEngine(),
103 new CaptureManager(),
107 void ChannelManager::Construct(MediaEngineInterface* me,
108 DataEngineInterface* dme,
109 DeviceManagerInterface* dm,
111 rtc::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_ = rtc::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_ = kDefaultAudioDelayOffset;
124 audio_output_volume_ = kNotSetOutputVolume;
125 local_renderer_ = NULL;
130 // Init the device manager immediately, and set up our default video device.
131 SignalDevicesChange.repeat(device_manager_->SignalDevicesChange);
132 device_manager_->Init();
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);
142 ChannelManager::~ChannelManager() {
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
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
161 enable_rtx_ = enable;
164 LOG(LS_WARNING) << "Cannot toggle rtx after initialization!";
169 int ChannelManager::GetCapabilities() {
170 return media_engine_->GetCapabilities() & device_manager_->GetCapabilities();
173 void ChannelManager::GetSupportedAudioCodecs(
174 std::vector<AudioCodec>* codecs) const {
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);
184 void ChannelManager::GetSupportedAudioRtpHeaderExtensions(
185 RtpHeaderExtensions* ext) const {
186 *ext = media_engine_->audio_rtp_header_extensions();
189 void ChannelManager::GetSupportedVideoCodecs(
190 std::vector<VideoCodec>* codecs) const {
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) {
199 codecs->push_back(*it);
203 void ChannelManager::GetSupportedVideoRtpHeaderExtensions(
204 RtpHeaderExtensions* ext) const {
205 *ext = media_engine_->video_rtp_header_extensions();
208 void ChannelManager::GetSupportedDataCodecs(
209 std::vector<DataCodec>* codecs) const {
210 *codecs = data_media_engine_->data_codecs();
213 bool ChannelManager::Init() {
214 ASSERT(!initialized_);
219 ASSERT(worker_thread_ != NULL);
220 if (worker_thread_) {
221 if (worker_thread_ != rtc::Thread::Current()) {
222 // Do not allow invoking calls to other threads on the worker thread.
223 worker_thread_->Invoke<bool>(rtc::Bind(
224 &rtc::Thread::SetAllowBlockingCalls, worker_thread_, false));
227 if (media_engine_->Init(worker_thread_)) {
230 // Now that we're initialized, apply any stored preferences. A preferred
231 // device might have been unplugged. In this case, we fallback to the
232 // default device but keep the user preferences. The preferences are
233 // changed only when the Javascript FE changes them.
234 const std::string preferred_audio_in_device = audio_in_device_;
235 const std::string preferred_audio_out_device = audio_out_device_;
236 const std::string preferred_camera_device = camera_device_;
238 if (!device_manager_->GetAudioInputDevice(audio_in_device_, &device)) {
239 LOG(LS_WARNING) << "The preferred microphone '" << audio_in_device_
240 << "' is unavailable. Fall back to the default.";
241 audio_in_device_ = DeviceManagerInterface::kDefaultDeviceName;
243 if (!device_manager_->GetAudioOutputDevice(audio_out_device_, &device)) {
244 LOG(LS_WARNING) << "The preferred speaker '" << audio_out_device_
245 << "' is unavailable. Fall back to the default.";
246 audio_out_device_ = DeviceManagerInterface::kDefaultDeviceName;
248 if (!device_manager_->GetVideoCaptureDevice(camera_device_, &device)) {
249 if (!camera_device_.empty()) {
250 LOG(LS_WARNING) << "The preferred camera '" << camera_device_
251 << "' is unavailable. Fall back to the default.";
253 camera_device_ = DeviceManagerInterface::kDefaultDeviceName;
256 if (!SetAudioOptions(audio_in_device_, audio_out_device_,
257 audio_options_, audio_delay_offset_)) {
258 LOG(LS_WARNING) << "Failed to SetAudioOptions with"
259 << " microphone: " << audio_in_device_
260 << " speaker: " << audio_out_device_
261 << " options: " << audio_options_.ToString()
262 << " delay: " << audio_delay_offset_;
265 // If audio_output_volume_ has been set via SetOutputVolume(), set the
266 // audio output volume of the engine.
267 if (kNotSetOutputVolume != audio_output_volume_ &&
268 !SetOutputVolume(audio_output_volume_)) {
269 LOG(LS_WARNING) << "Failed to SetOutputVolume to "
270 << audio_output_volume_;
272 if (!SetCaptureDevice(camera_device_) && !camera_device_.empty()) {
273 LOG(LS_WARNING) << "Failed to SetCaptureDevice with camera: "
277 // Restore the user preferences.
278 audio_in_device_ = preferred_audio_in_device;
279 audio_out_device_ = preferred_audio_out_device;
280 camera_device_ = preferred_camera_device;
282 // Now apply the default video codec that has been set earlier.
283 if (default_video_encoder_config_.max_codec.id != 0) {
284 SetDefaultVideoEncoderConfig(default_video_encoder_config_);
291 void ChannelManager::Terminate() {
292 ASSERT(initialized_);
296 worker_thread_->Invoke<void>(Bind(&ChannelManager::Terminate_w, this));
297 media_engine_->Terminate();
298 initialized_ = false;
301 void ChannelManager::Terminate_w() {
302 ASSERT(worker_thread_ == rtc::Thread::Current());
303 // Need to destroy the voice/video channels
304 while (!video_channels_.empty()) {
305 DestroyVideoChannel_w(video_channels_.back());
307 while (!voice_channels_.empty()) {
308 DestroyVoiceChannel_w(voice_channels_.back());
310 while (!soundclips_.empty()) {
311 DestroySoundclip_w(soundclips_.back());
313 if (!SetCaptureDevice_w(NULL)) {
314 LOG(LS_WARNING) << "failed to delete video capturer";
318 VoiceChannel* ChannelManager::CreateVoiceChannel(
319 BaseSession* session, const std::string& content_name, bool rtcp) {
320 return worker_thread_->Invoke<VoiceChannel*>(
321 Bind(&ChannelManager::CreateVoiceChannel_w, this,
322 session, content_name, rtcp));
325 VoiceChannel* ChannelManager::CreateVoiceChannel_w(
326 BaseSession* session, const std::string& content_name, bool rtcp) {
327 // This is ok to alloc from a thread other than the worker thread
328 ASSERT(initialized_);
329 VoiceMediaChannel* media_channel = media_engine_->CreateChannel();
330 if (media_channel == NULL)
333 VoiceChannel* voice_channel = new VoiceChannel(
334 worker_thread_, media_engine_.get(), media_channel,
335 session, content_name, rtcp);
336 if (!voice_channel->Init()) {
337 delete voice_channel;
340 voice_channels_.push_back(voice_channel);
341 return voice_channel;
344 void ChannelManager::DestroyVoiceChannel(VoiceChannel* voice_channel) {
346 worker_thread_->Invoke<void>(
347 Bind(&ChannelManager::DestroyVoiceChannel_w, this, voice_channel));
351 void ChannelManager::DestroyVoiceChannel_w(VoiceChannel* voice_channel) {
352 // Destroy voice channel.
353 ASSERT(initialized_);
354 VoiceChannels::iterator it = std::find(voice_channels_.begin(),
355 voice_channels_.end(), voice_channel);
356 ASSERT(it != voice_channels_.end());
357 if (it == voice_channels_.end())
360 voice_channels_.erase(it);
361 delete voice_channel;
364 VideoChannel* ChannelManager::CreateVideoChannel(
365 BaseSession* session,
366 const std::string& content_name,
368 VoiceChannel* voice_channel) {
369 return worker_thread_->Invoke<VideoChannel*>(
370 Bind(&ChannelManager::CreateVideoChannel_w,
379 VideoChannel* ChannelManager::CreateVideoChannel(
380 BaseSession* session,
381 const std::string& content_name,
383 const VideoOptions& options,
384 VoiceChannel* voice_channel) {
385 return worker_thread_->Invoke<VideoChannel*>(
386 Bind(&ChannelManager::CreateVideoChannel_w,
395 VideoChannel* ChannelManager::CreateVideoChannel_w(
396 BaseSession* session,
397 const std::string& content_name,
399 const VideoOptions& options,
400 VoiceChannel* voice_channel) {
401 // This is ok to alloc from a thread other than the worker thread
402 ASSERT(initialized_);
403 VideoMediaChannel* media_channel =
404 // voice_channel can be NULL in case of NullVoiceEngine.
405 media_engine_->CreateVideoChannel(
406 options, voice_channel ? voice_channel->media_channel() : NULL);
407 if (media_channel == NULL)
410 VideoChannel* video_channel = new VideoChannel(
411 worker_thread_, media_engine_.get(), media_channel,
412 session, content_name, rtcp, voice_channel);
413 if (!video_channel->Init()) {
414 delete video_channel;
417 video_channels_.push_back(video_channel);
418 return video_channel;
421 void ChannelManager::DestroyVideoChannel(VideoChannel* video_channel) {
423 worker_thread_->Invoke<void>(
424 Bind(&ChannelManager::DestroyVideoChannel_w, this, video_channel));
428 void ChannelManager::DestroyVideoChannel_w(VideoChannel* video_channel) {
429 // Destroy video channel.
430 ASSERT(initialized_);
431 VideoChannels::iterator it = std::find(video_channels_.begin(),
432 video_channels_.end(), video_channel);
433 ASSERT(it != video_channels_.end());
434 if (it == video_channels_.end())
437 video_channels_.erase(it);
438 delete video_channel;
441 DataChannel* ChannelManager::CreateDataChannel(
442 BaseSession* session, const std::string& content_name,
443 bool rtcp, DataChannelType channel_type) {
444 return worker_thread_->Invoke<DataChannel*>(
445 Bind(&ChannelManager::CreateDataChannel_w, this, session, content_name,
446 rtcp, channel_type));
449 DataChannel* ChannelManager::CreateDataChannel_w(
450 BaseSession* session, const std::string& content_name,
451 bool rtcp, DataChannelType data_channel_type) {
452 // This is ok to alloc from a thread other than the worker thread.
453 ASSERT(initialized_);
454 DataMediaChannel* media_channel = data_media_engine_->CreateChannel(
456 if (!media_channel) {
457 LOG(LS_WARNING) << "Failed to create data channel of type "
458 << data_channel_type;
462 DataChannel* data_channel = new DataChannel(
463 worker_thread_, media_channel,
464 session, content_name, rtcp);
465 if (!data_channel->Init()) {
466 LOG(LS_WARNING) << "Failed to init data channel.";
470 data_channels_.push_back(data_channel);
474 void ChannelManager::DestroyDataChannel(DataChannel* data_channel) {
476 worker_thread_->Invoke<void>(
477 Bind(&ChannelManager::DestroyDataChannel_w, this, data_channel));
481 void ChannelManager::DestroyDataChannel_w(DataChannel* data_channel) {
482 // Destroy data channel.
483 ASSERT(initialized_);
484 DataChannels::iterator it = std::find(data_channels_.begin(),
485 data_channels_.end(), data_channel);
486 ASSERT(it != data_channels_.end());
487 if (it == data_channels_.end())
490 data_channels_.erase(it);
494 Soundclip* ChannelManager::CreateSoundclip() {
495 return worker_thread_->Invoke<Soundclip*>(
496 Bind(&ChannelManager::CreateSoundclip_w, this));
499 Soundclip* ChannelManager::CreateSoundclip_w() {
500 ASSERT(initialized_);
501 ASSERT(worker_thread_ == rtc::Thread::Current());
503 SoundclipMedia* soundclip_media = media_engine_->CreateSoundclip();
504 if (!soundclip_media) {
508 Soundclip* soundclip = new Soundclip(worker_thread_, soundclip_media);
509 soundclips_.push_back(soundclip);
513 void ChannelManager::DestroySoundclip(Soundclip* soundclip) {
515 worker_thread_->Invoke<void>(
516 Bind(&ChannelManager::DestroySoundclip_w, this, soundclip));
520 void ChannelManager::DestroySoundclip_w(Soundclip* soundclip) {
521 // Destroy soundclip.
522 ASSERT(initialized_);
523 Soundclips::iterator it = std::find(soundclips_.begin(),
524 soundclips_.end(), soundclip);
525 ASSERT(it != soundclips_.end());
526 if (it == soundclips_.end())
529 soundclips_.erase(it);
533 bool ChannelManager::GetAudioOptions(std::string* in_name,
534 std::string* out_name,
535 AudioOptions* options) {
537 *in_name = audio_in_device_;
539 *out_name = audio_out_device_;
541 *options = audio_options_;
545 bool ChannelManager::SetAudioOptions(const std::string& in_name,
546 const std::string& out_name,
547 const AudioOptions& options) {
548 return SetAudioOptions(in_name, out_name, options, audio_delay_offset_);
551 bool ChannelManager::SetAudioOptions(const std::string& in_name,
552 const std::string& out_name,
553 const AudioOptions& options,
555 // Get device ids from DeviceManager.
556 Device in_dev, out_dev;
557 if (!device_manager_->GetAudioInputDevice(in_name, &in_dev)) {
558 LOG(LS_WARNING) << "Failed to GetAudioInputDevice: " << in_name;
561 if (!device_manager_->GetAudioOutputDevice(out_name, &out_dev)) {
562 LOG(LS_WARNING) << "Failed to GetAudioOutputDevice: " << out_name;
566 // If we're initialized, pass the settings to the media engine.
569 ret = worker_thread_->Invoke<bool>(
570 Bind(&ChannelManager::SetAudioOptions_w, this,
571 options, delay_offset, &in_dev, &out_dev));
574 // If all worked well, save the values for use in GetAudioOptions.
576 audio_options_ = options;
577 audio_in_device_ = in_name;
578 audio_out_device_ = out_name;
579 audio_delay_offset_ = delay_offset;
584 bool ChannelManager::SetAudioOptions_w(
585 const AudioOptions& options, int delay_offset,
586 const Device* in_dev, const Device* out_dev) {
587 ASSERT(worker_thread_ == rtc::Thread::Current());
588 ASSERT(initialized_);
591 bool ret = media_engine_->SetAudioOptions(options);
594 ret = media_engine_->SetAudioDelayOffset(delay_offset);
597 // Set the audio devices
599 ret = media_engine_->SetSoundDevices(in_dev, out_dev);
605 // Sets Engine-specific audio options according to enabled experiments.
606 bool ChannelManager::SetEngineAudioOptions(const AudioOptions& options) {
607 // If we're initialized, pass the settings to the media engine.
610 ret = worker_thread_->Invoke<bool>(
611 Bind(&ChannelManager::SetEngineAudioOptions_w, this, options));
614 // If all worked well, save the audio options.
616 audio_options_ = options;
621 bool ChannelManager::SetEngineAudioOptions_w(const AudioOptions& options) {
622 ASSERT(worker_thread_ == rtc::Thread::Current());
623 ASSERT(initialized_);
625 return media_engine_->SetAudioOptions(options);
628 bool ChannelManager::GetOutputVolume(int* level) {
632 return worker_thread_->Invoke<bool>(
633 Bind(&MediaEngineInterface::GetOutputVolume, media_engine_.get(), level));
636 bool ChannelManager::SetOutputVolume(int level) {
637 bool ret = level >= 0 && level <= 255;
639 ret &= worker_thread_->Invoke<bool>(
640 Bind(&MediaEngineInterface::SetOutputVolume,
641 media_engine_.get(), level));
645 audio_output_volume_ = level;
651 bool ChannelManager::IsSameCapturer(const std::string& capturer_name,
652 VideoCapturer* capturer) {
653 if (capturer == NULL) {
657 if (!device_manager_->GetVideoCaptureDevice(capturer_name, &device)) {
660 return capturer->GetId() == device.id;
663 bool ChannelManager::GetVideoCaptureDevice(Device* device) {
664 std::string device_name;
665 if (!GetCaptureDevice(&device_name)) {
668 return device_manager_->GetVideoCaptureDevice(device_name, device);
671 bool ChannelManager::GetCaptureDevice(std::string* cam_name) {
672 if (camera_device_.empty()) {
673 // Initialize camera_device_ with default.
675 if (!device_manager_->GetVideoCaptureDevice(
676 DeviceManagerInterface::kDefaultDeviceName, &device)) {
677 LOG(LS_WARNING) << "Device manager can't find default camera: " <<
678 DeviceManagerInterface::kDefaultDeviceName;
681 camera_device_ = device.name;
683 *cam_name = camera_device_;
687 bool ChannelManager::SetCaptureDevice(const std::string& cam_name) {
690 if (!device_manager_->GetVideoCaptureDevice(cam_name, &device)) {
691 if (!cam_name.empty()) {
692 LOG(LS_WARNING) << "Device manager can't find camera: " << cam_name;
697 // If we're running, tell the media engine about it.
698 if (initialized_ && ret) {
699 ret = worker_thread_->Invoke<bool>(
700 Bind(&ChannelManager::SetCaptureDevice_w, this, &device));
703 // If everything worked, retain the name of the selected camera.
705 camera_device_ = device.name;
706 } else if (camera_device_.empty()) {
707 // When video option setting fails, we still want camera_device_ to be in a
708 // good state, so we initialize it with default if it's empty.
709 Device default_device;
710 if (!device_manager_->GetVideoCaptureDevice(
711 DeviceManagerInterface::kDefaultDeviceName, &default_device)) {
712 LOG(LS_WARNING) << "Device manager can't find default camera: " <<
713 DeviceManagerInterface::kDefaultDeviceName;
715 camera_device_ = default_device.name;
721 VideoCapturer* ChannelManager::CreateVideoCapturer() {
723 if (!device_manager_->GetVideoCaptureDevice(camera_device_, &device)) {
724 if (!camera_device_.empty()) {
725 LOG(LS_WARNING) << "Device manager can't find camera: " << camera_device_;
729 VideoCapturer* capturer = device_manager_->CreateVideoCapturer(device);
730 if (capturer && default_video_encoder_config_.max_codec.id != 0) {
731 // For now, use the aspect ratio of the default_video_encoder_config_,
732 // which may be different than the native aspect ratio of the start
733 // format the camera may use.
734 capturer->UpdateAspectRatio(
735 default_video_encoder_config_.max_codec.width,
736 default_video_encoder_config_.max_codec.height);
741 VideoCapturer* ChannelManager::CreateScreenCapturer(
742 const ScreencastId& screenid) {
743 return device_manager_->CreateScreenCapturer(screenid);
746 bool ChannelManager::SetCaptureDevice_w(const Device* cam_device) {
747 ASSERT(worker_thread_ == rtc::Thread::Current());
748 ASSERT(initialized_);
751 video_device_name_.clear();
754 video_device_name_ = cam_device->name;
758 bool ChannelManager::SetDefaultVideoEncoderConfig(const VideoEncoderConfig& c) {
761 ret = worker_thread_->Invoke<bool>(
762 Bind(&MediaEngineInterface::SetDefaultVideoEncoderConfig,
763 media_engine_.get(), c));
766 default_video_encoder_config_ = c;
771 bool ChannelManager::SetLocalMonitor(bool enable) {
772 bool ret = initialized_ && worker_thread_->Invoke<bool>(
773 Bind(&MediaEngineInterface::SetLocalMonitor,
774 media_engine_.get(), enable));
776 monitoring_ = enable;
781 void ChannelManager::SetVoiceLogging(int level, const char* filter) {
783 worker_thread_->Invoke<void>(
784 Bind(&MediaEngineInterface::SetVoiceLogging,
785 media_engine_.get(), level, filter));
787 media_engine_->SetVoiceLogging(level, filter);
791 void ChannelManager::SetVideoLogging(int level, const char* filter) {
793 worker_thread_->Invoke<void>(
794 Bind(&MediaEngineInterface::SetVideoLogging,
795 media_engine_.get(), level, filter));
797 media_engine_->SetVideoLogging(level, filter);
801 // TODO(janahan): For now pass this request through the mediaengine to the
802 // voice and video engines to do the real work. Once the capturer refactoring
803 // is done, we will access the capturer using the ssrc (similar to how the
804 // renderer is accessed today) and register with it directly.
805 bool ChannelManager::RegisterVideoProcessor(VideoCapturer* capturer,
806 VideoProcessor* processor) {
807 return initialized_ && worker_thread_->Invoke<bool>(
808 Bind(&ChannelManager::RegisterVideoProcessor_w, this,
809 capturer, processor));
812 bool ChannelManager::RegisterVideoProcessor_w(VideoCapturer* capturer,
813 VideoProcessor* processor) {
814 return capture_manager_->AddVideoProcessor(capturer, processor);
817 bool ChannelManager::UnregisterVideoProcessor(VideoCapturer* capturer,
818 VideoProcessor* processor) {
819 return initialized_ && worker_thread_->Invoke<bool>(
820 Bind(&ChannelManager::UnregisterVideoProcessor_w, this,
821 capturer, processor));
824 bool ChannelManager::UnregisterVideoProcessor_w(VideoCapturer* capturer,
825 VideoProcessor* processor) {
826 return capture_manager_->RemoveVideoProcessor(capturer, processor);
829 bool ChannelManager::RegisterVoiceProcessor(
831 VoiceProcessor* processor,
832 MediaProcessorDirection direction) {
833 return initialized_ && worker_thread_->Invoke<bool>(
834 Bind(&MediaEngineInterface::RegisterVoiceProcessor, media_engine_.get(),
835 ssrc, processor, direction));
838 bool ChannelManager::UnregisterVoiceProcessor(
840 VoiceProcessor* processor,
841 MediaProcessorDirection direction) {
842 return initialized_ && worker_thread_->Invoke<bool>(
843 Bind(&MediaEngineInterface::UnregisterVoiceProcessor,
844 media_engine_.get(), ssrc, processor, direction));
847 // The following are done in the new "CaptureManager" style that
848 // all local video capturers, processors, and managers should move
850 // TODO(pthatcher): Add more of the CaptureManager interface.
851 bool ChannelManager::StartVideoCapture(
852 VideoCapturer* capturer, const VideoFormat& video_format) {
853 return initialized_ && worker_thread_->Invoke<bool>(
854 Bind(&CaptureManager::StartVideoCapture,
855 capture_manager_.get(), capturer, video_format));
858 bool ChannelManager::MuteToBlackThenPause(
859 VideoCapturer* video_capturer, bool muted) {
863 worker_thread_->Invoke<void>(
864 Bind(&VideoCapturer::MuteToBlackThenPause, video_capturer, muted));
868 bool ChannelManager::StopVideoCapture(
869 VideoCapturer* capturer, const VideoFormat& video_format) {
870 return initialized_ && worker_thread_->Invoke<bool>(
871 Bind(&CaptureManager::StopVideoCapture,
872 capture_manager_.get(), capturer, video_format));
875 bool ChannelManager::RestartVideoCapture(
876 VideoCapturer* video_capturer,
877 const VideoFormat& previous_format,
878 const VideoFormat& desired_format,
879 CaptureManager::RestartOptions options) {
880 return initialized_ && worker_thread_->Invoke<bool>(
881 Bind(&CaptureManager::RestartVideoCapture, capture_manager_.get(),
882 video_capturer, previous_format, desired_format, options));
885 bool ChannelManager::AddVideoRenderer(
886 VideoCapturer* capturer, VideoRenderer* renderer) {
887 return initialized_ && worker_thread_->Invoke<bool>(
888 Bind(&CaptureManager::AddVideoRenderer,
889 capture_manager_.get(), capturer, renderer));
892 bool ChannelManager::RemoveVideoRenderer(
893 VideoCapturer* capturer, VideoRenderer* renderer) {
894 return initialized_ && worker_thread_->Invoke<bool>(
895 Bind(&CaptureManager::RemoveVideoRenderer,
896 capture_manager_.get(), capturer, renderer));
899 bool ChannelManager::IsScreencastRunning() const {
900 return initialized_ && worker_thread_->Invoke<bool>(
901 Bind(&ChannelManager::IsScreencastRunning_w, this));
904 bool ChannelManager::IsScreencastRunning_w() const {
905 VideoChannels::const_iterator it = video_channels_.begin();
906 for ( ; it != video_channels_.end(); ++it) {
907 if ((*it) && (*it)->IsScreencasting()) {
914 void ChannelManager::OnVideoCaptureStateChange(VideoCapturer* capturer,
915 CaptureState result) {
916 // TODO(whyuan): Check capturer and signal failure only for camera video, not
918 capturing_ = result == CS_RUNNING;
919 main_thread_->Post(this, MSG_VIDEOCAPTURESTATE,
920 new CaptureStateParams(capturer, result));
923 void ChannelManager::OnMessage(rtc::Message* message) {
924 switch (message->message_id) {
925 case MSG_VIDEOCAPTURESTATE: {
926 CaptureStateParams* data =
927 static_cast<CaptureStateParams*>(message->pdata);
928 SignalVideoCaptureStateChange(data->capturer, data->state);
936 static void GetDeviceNames(const std::vector<Device>& devs,
937 std::vector<std::string>* names) {
939 for (size_t i = 0; i < devs.size(); ++i) {
940 names->push_back(devs[i].name);
944 bool ChannelManager::GetAudioInputDevices(std::vector<std::string>* names) {
946 std::vector<Device> devs;
947 bool ret = device_manager_->GetAudioInputDevices(&devs);
949 GetDeviceNames(devs, names);
954 bool ChannelManager::GetAudioOutputDevices(std::vector<std::string>* names) {
956 std::vector<Device> devs;
957 bool ret = device_manager_->GetAudioOutputDevices(&devs);
959 GetDeviceNames(devs, names);
964 bool ChannelManager::GetVideoCaptureDevices(std::vector<std::string>* names) {
966 std::vector<Device> devs;
967 bool ret = device_manager_->GetVideoCaptureDevices(&devs);
969 GetDeviceNames(devs, names);
974 void ChannelManager::SetVideoCaptureDeviceMaxFormat(
975 const std::string& usb_id,
976 const VideoFormat& max_format) {
977 device_manager_->SetVideoCaptureDeviceMaxFormat(usb_id, max_format);
980 VideoFormat ChannelManager::GetStartCaptureFormat() {
981 return worker_thread_->Invoke<VideoFormat>(
982 Bind(&MediaEngineInterface::GetStartCaptureFormat, media_engine_.get()));
985 bool ChannelManager::StartAecDump(rtc::PlatformFile file) {
986 return worker_thread_->Invoke<bool>(
987 Bind(&MediaEngineInterface::StartAecDump, media_engine_.get(), file));
990 } // namespace cricket