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