1 /*
2 * libjingle
3 * Copyright 2004--2008, 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/phone/channelmanager.h"
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include <algorithm>
35
36 #include "talk/base/common.h"
37 #include "talk/base/logging.h"
38 #include "talk/base/sigslotrepeater.h"
39 #include "talk/base/stringencode.h"
40 #include "talk/session/phone/dataengine.h"
41 #include "talk/session/phone/soundclip.h"
42
43 namespace cricket {
44
45 enum {
46 MSG_CREATEVOICECHANNEL = 1,
47 MSG_DESTROYVOICECHANNEL = 2,
48 MSG_SETAUDIOOPTIONS = 3,
49 MSG_GETOUTPUTVOLUME = 4,
50 MSG_SETOUTPUTVOLUME = 5,
51 MSG_SETLOCALMONITOR = 6,
52 MSG_SETVOICELOGGING = 7,
53 MSG_CREATEVIDEOCHANNEL = 11,
54 MSG_DESTROYVIDEOCHANNEL = 12,
55 MSG_SETVIDEOOPTIONS = 13,
56 MSG_SETLOCALRENDERER = 14,
57 MSG_SETDEFAULTVIDEOENCODERCONFIG = 15,
58 MSG_SETVIDEOLOGGING = 16,
59 MSG_CREATESOUNDCLIP = 17,
60 MSG_DESTROYSOUNDCLIP = 18,
61 MSG_CAMERASTARTED = 19,
62 MSG_SETVIDEOCAPTURE = 20,
63 MSG_TERMINATE = 21,
64 MSG_REGISTERVIDEOPROCESSOR = 22,
65 MSG_UNREGISTERVIDEOPROCESSOR = 23,
66 MSG_REGISTERVOICEPROCESSOR = 24,
67 MSG_UNREGISTERVOICEPROCESSOR = 25,
68 MSG_SETVIDEOCAPTURER = 26,
69 MSG_CREATEDATACHANNEL = 27,
70 MSG_DESTROYDATACHANNEL = 28,
71 };
72
73 static const int kNotSetOutputVolume = -1;
74
75 struct CreationParams : public talk_base::MessageData {
CreationParamscricket::CreationParams76 CreationParams(BaseSession* session, const std::string& content_name,
77 bool rtcp, VoiceChannel* voice_channel)
78 : session(session),
79 content_name(content_name),
80 rtcp(rtcp),
81 voice_channel(voice_channel),
82 video_channel(NULL),
83 data_channel(NULL) {
84 }
85 BaseSession* session;
86 std::string content_name;
87 bool rtcp;
88 VoiceChannel* voice_channel;
89 VideoChannel* video_channel;
90 DataChannel* data_channel;
91 };
92
93 struct AudioOptions : public talk_base::MessageData {
AudioOptionscricket::AudioOptions94 AudioOptions(int o, const Device* in, const Device* out)
95 : options(o), in_device(in), out_device(out) {}
96 int options;
97 const Device* in_device;
98 const Device* out_device;
99 bool result;
100 };
101
102 struct VolumeLevel : public talk_base::MessageData {
VolumeLevelcricket::VolumeLevel103 VolumeLevel() : level(-1), result(false) {}
VolumeLevelcricket::VolumeLevel104 explicit VolumeLevel(int l) : level(l), result(false) {}
105 int level;
106 bool result;
107 };
108
109 struct VideoOptions : public talk_base::MessageData {
VideoOptionscricket::VideoOptions110 explicit VideoOptions(const Device* d) : cam_device(d), result(false) {}
111 const Device* cam_device;
112 bool result;
113 };
114
115 struct DefaultVideoEncoderConfig : public talk_base::MessageData {
DefaultVideoEncoderConfigcricket::DefaultVideoEncoderConfig116 explicit DefaultVideoEncoderConfig(const VideoEncoderConfig& c)
117 : config(c), result(false) {}
118 VideoEncoderConfig config;
119 bool result;
120 };
121
122 struct LocalMonitor : public talk_base::MessageData {
LocalMonitorcricket::LocalMonitor123 explicit LocalMonitor(bool e) : enable(e), result(false) {}
124 bool enable;
125 bool result;
126 };
127
128 struct LocalRenderer : public talk_base::MessageData {
LocalRenderercricket::LocalRenderer129 explicit LocalRenderer(VideoRenderer* r) : renderer(r), result(false) {}
130 VideoRenderer* renderer;
131 bool result;
132 };
133
134 struct Capturer : public talk_base::MessageData {
Capturercricket::Capturer135 Capturer(VideoCapturer* c, uint32 s)
136 : capturer(c),
137 ssrc(s),
138 result(false) {}
139 VideoCapturer* capturer;
140 uint32 ssrc;
141 bool result;
142 };
143
144 struct LoggingOptions : public talk_base::MessageData {
LoggingOptionscricket::LoggingOptions145 explicit LoggingOptions(int lev, const char* f) : level(lev), filter(f) {}
146 int level;
147 std::string filter;
148 };
149
150 struct CaptureParams : public talk_base::MessageData {
CaptureParamscricket::CaptureParams151 explicit CaptureParams(bool c) : capture(c), result(CR_FAILURE) {}
152 bool capture;
153 CaptureResult result;
154 };
155
156 struct VideoProcessorParams : public talk_base::MessageData {
VideoProcessorParamscricket::VideoProcessorParams157 VideoProcessorParams(uint32 s, VideoProcessor* p)
158 : ssrc(s), processor(p), result(false) {}
159 uint32 ssrc;
160 VideoProcessor* processor;
161 bool result;
162 };
163
164 struct VoiceProcessorParams : public talk_base::MessageData {
VoiceProcessorParamscricket::VoiceProcessorParams165 VoiceProcessorParams(uint32 c, VoiceProcessor* p, MediaProcessorDirection d)
166 : ssrc(c), direction(d), processor(p), result(false) {}
167 uint32 ssrc;
168 MediaProcessorDirection direction;
169 VoiceProcessor* processor;
170 bool result;
171 };
172
ChannelManager(talk_base::Thread * worker_thread)173 ChannelManager::ChannelManager(talk_base::Thread* worker_thread) {
174 Construct(MediaEngineFactory::Create(),
175 new DataEngine(),
176 cricket::DeviceManagerFactory::Create(),
177 worker_thread);
178 }
179
ChannelManager(MediaEngineInterface * me,DataEngineInterface * dme,DeviceManagerInterface * dm,talk_base::Thread * worker_thread)180 ChannelManager::ChannelManager(MediaEngineInterface* me,
181 DataEngineInterface* dme,
182 DeviceManagerInterface* dm,
183 talk_base::Thread* worker_thread) {
184 Construct(me, dme, dm, worker_thread);
185 }
186
ChannelManager(MediaEngineInterface * me,DeviceManagerInterface * dm,talk_base::Thread * worker_thread)187 ChannelManager::ChannelManager(MediaEngineInterface* me,
188 DeviceManagerInterface* dm,
189 talk_base::Thread* worker_thread) {
190 Construct(me, new DataEngine(), dm, worker_thread);
191 }
192
Construct(MediaEngineInterface * me,DataEngineInterface * dme,DeviceManagerInterface * dm,talk_base::Thread * worker_thread)193 void ChannelManager::Construct(MediaEngineInterface* me,
194 DataEngineInterface* dme,
195 DeviceManagerInterface* dm,
196 talk_base::Thread* worker_thread) {
197 media_engine_.reset(me);
198 data_media_engine_.reset(dme);
199 device_manager_.reset(dm);
200 initialized_ = false;
201 main_thread_ = talk_base::Thread::Current();
202 worker_thread_ = worker_thread;
203 audio_in_device_ = DeviceManagerInterface::kDefaultDeviceName;
204 audio_out_device_ = DeviceManagerInterface::kDefaultDeviceName;
205 audio_options_ = MediaEngineInterface::DEFAULT_AUDIO_OPTIONS;
206 audio_output_volume_ = kNotSetOutputVolume;
207 local_renderer_ = NULL;
208 capturing_ = false;
209 monitoring_ = false;
210
211 // Init the device manager immediately, and set up our default video device.
212 SignalDevicesChange.repeat(device_manager_->SignalDevicesChange);
213 device_manager_->Init();
214
215 // Camera is started asynchronously, request callbacks when startup
216 // completes to be able to forward them to the rendering manager.
217 media_engine_->SignalVideoCaptureResult.connect(
218 this, &ChannelManager::OnVideoCaptureResult);
219 }
220
~ChannelManager()221 ChannelManager::~ChannelManager() {
222 if (initialized_)
223 Terminate();
224 }
225
GetCapabilities()226 int ChannelManager::GetCapabilities() {
227 return media_engine_->GetCapabilities() & device_manager_->GetCapabilities();
228 }
229
GetSupportedAudioCodecs(std::vector<AudioCodec> * codecs) const230 void ChannelManager::GetSupportedAudioCodecs(
231 std::vector<AudioCodec>* codecs) const {
232 codecs->clear();
233
234 for (std::vector<AudioCodec>::const_iterator it =
235 media_engine_->audio_codecs().begin();
236 it != media_engine_->audio_codecs().end(); ++it) {
237 codecs->push_back(*it);
238 }
239 }
240
GetSupportedVideoCodecs(std::vector<VideoCodec> * codecs) const241 void ChannelManager::GetSupportedVideoCodecs(
242 std::vector<VideoCodec>* codecs) const {
243 codecs->clear();
244
245 std::vector<VideoCodec>::const_iterator it;
246 for (it = media_engine_->video_codecs().begin();
247 it != media_engine_->video_codecs().end(); ++it) {
248 codecs->push_back(*it);
249 }
250 }
251
GetSupportedDataCodecs(std::vector<DataCodec> * codecs) const252 void ChannelManager::GetSupportedDataCodecs(
253 std::vector<DataCodec>* codecs) const {
254 *codecs = data_media_engine_->data_codecs();
255 }
256
Init()257 bool ChannelManager::Init() {
258 ASSERT(!initialized_);
259 if (initialized_) {
260 return false;
261 }
262
263 ASSERT(worker_thread_ != NULL);
264 if (worker_thread_ && worker_thread_->started()) {
265 if (media_engine_->Init()) {
266 initialized_ = true;
267
268 // Now that we're initialized, apply any stored preferences. A preferred
269 // device might have been unplugged. In this case, we fallback to the
270 // default device but keep the user preferences. The preferences are
271 // changed only when the Javascript FE changes them.
272 const std::string preferred_audio_in_device = audio_in_device_;
273 const std::string preferred_audio_out_device = audio_out_device_;
274 const std::string preferred_camera_device = camera_device_;
275 Device device;
276 if (!device_manager_->GetAudioInputDevice(audio_in_device_, &device)) {
277 LOG(LS_WARNING) << "The preferred microphone '" << audio_in_device_
278 << "' is unavailable. Fall back to the default.";
279 audio_in_device_ = DeviceManagerInterface::kDefaultDeviceName;
280 }
281 if (!device_manager_->GetAudioOutputDevice(audio_out_device_, &device)) {
282 LOG(LS_WARNING) << "The preferred speaker '" << audio_out_device_
283 << "' is unavailable. Fall back to the default.";
284 audio_out_device_ = DeviceManagerInterface::kDefaultDeviceName;
285 }
286 if (!device_manager_->GetVideoCaptureDevice(camera_device_, &device)) {
287 if (!camera_device_.empty()) {
288 LOG(LS_WARNING) << "The preferred camera '" << camera_device_
289 << "' is unavailable. Fall back to the default.";
290 }
291 camera_device_ = DeviceManagerInterface::kDefaultDeviceName;
292 }
293
294 if (!SetAudioOptions(audio_in_device_, audio_out_device_,
295 audio_options_)) {
296 LOG(LS_WARNING) << "Failed to SetAudioOptions with"
297 << " microphone: " << audio_in_device_
298 << " speaker: " << audio_out_device_
299 << " options: " << audio_options_;
300 }
301
302 // If audio_output_volume_ has been set via SetOutputVolume(), set the
303 // audio output volume of the engine.
304 if (kNotSetOutputVolume != audio_output_volume_ &&
305 !SetOutputVolume(audio_output_volume_)) {
306 LOG(LS_WARNING) << "Failed to SetOutputVolume to "
307 << audio_output_volume_;
308 }
309 if (!SetVideoOptions(camera_device_) && !camera_device_.empty()) {
310 LOG(LS_WARNING) << "Failed to SetVideoOptions with camera: "
311 << camera_device_;
312 }
313
314 // Restore the user preferences.
315 audio_in_device_ = preferred_audio_in_device;
316 audio_out_device_ = preferred_audio_out_device;
317 camera_device_ = preferred_camera_device;
318
319 // Now apply the default video codec that has been set earlier.
320 if (default_video_encoder_config_.max_codec.id != 0) {
321 SetDefaultVideoEncoderConfig(default_video_encoder_config_);
322 }
323 // And the local renderer.
324 if (local_renderer_) {
325 SetLocalRenderer(local_renderer_);
326 }
327 }
328 }
329 return initialized_;
330 }
331
Terminate()332 void ChannelManager::Terminate() {
333 ASSERT(initialized_);
334 if (!initialized_) {
335 return;
336 }
337 Send(MSG_TERMINATE, NULL);
338 media_engine_->Terminate();
339 initialized_ = false;
340 }
341
Terminate_w()342 void ChannelManager::Terminate_w() {
343 ASSERT(worker_thread_ == talk_base::Thread::Current());
344 // Need to destroy the voice/video channels
345 while (!video_channels_.empty()) {
346 DestroyVideoChannel_w(video_channels_.back());
347 }
348 while (!voice_channels_.empty()) {
349 DestroyVoiceChannel_w(voice_channels_.back());
350 }
351 while (!soundclips_.empty()) {
352 DestroySoundclip_w(soundclips_.back());
353 }
354 }
355
CreateVoiceChannel(BaseSession * session,const std::string & content_name,bool rtcp)356 VoiceChannel* ChannelManager::CreateVoiceChannel(
357 BaseSession* session, const std::string& content_name, bool rtcp) {
358 CreationParams params(session, content_name, rtcp, NULL);
359 return (Send(MSG_CREATEVOICECHANNEL, ¶ms)) ? params.voice_channel : NULL;
360 }
361
CreateVoiceChannel_w(BaseSession * session,const std::string & content_name,bool rtcp)362 VoiceChannel* ChannelManager::CreateVoiceChannel_w(
363 BaseSession* session, const std::string& content_name, bool rtcp) {
364 // This is ok to alloc from a thread other than the worker thread
365 ASSERT(initialized_);
366 VoiceMediaChannel* media_channel = media_engine_->CreateChannel();
367 if (media_channel == NULL)
368 return NULL;
369
370 VoiceChannel* voice_channel = new VoiceChannel(
371 worker_thread_, media_engine_.get(), media_channel,
372 session, content_name, rtcp);
373 if (!voice_channel->Init()) {
374 delete voice_channel;
375 return NULL;
376 }
377 voice_channels_.push_back(voice_channel);
378 return voice_channel;
379 }
380
DestroyVoiceChannel(VoiceChannel * voice_channel)381 void ChannelManager::DestroyVoiceChannel(VoiceChannel* voice_channel) {
382 if (voice_channel) {
383 talk_base::TypedMessageData<VoiceChannel*> data(voice_channel);
384 Send(MSG_DESTROYVOICECHANNEL, &data);
385 }
386 }
387
DestroyVoiceChannel_w(VoiceChannel * voice_channel)388 void ChannelManager::DestroyVoiceChannel_w(VoiceChannel* voice_channel) {
389 // Destroy voice channel.
390 ASSERT(initialized_);
391 VoiceChannels::iterator it = std::find(voice_channels_.begin(),
392 voice_channels_.end(), voice_channel);
393 ASSERT(it != voice_channels_.end());
394 if (it == voice_channels_.end())
395 return;
396
397 voice_channels_.erase(it);
398 delete voice_channel;
399 }
400
CreateVideoChannel(BaseSession * session,const std::string & content_name,bool rtcp,VoiceChannel * voice_channel)401 VideoChannel* ChannelManager::CreateVideoChannel(
402 BaseSession* session, const std::string& content_name, bool rtcp,
403 VoiceChannel* voice_channel) {
404 CreationParams params(session, content_name, rtcp, voice_channel);
405 return (Send(MSG_CREATEVIDEOCHANNEL, ¶ms)) ? params.video_channel : NULL;
406 }
407
CreateVideoChannel_w(BaseSession * session,const std::string & content_name,bool rtcp,VoiceChannel * voice_channel)408 VideoChannel* ChannelManager::CreateVideoChannel_w(
409 BaseSession* session, const std::string& content_name, bool rtcp,
410 VoiceChannel* voice_channel) {
411 // This is ok to alloc from a thread other than the worker thread
412 ASSERT(initialized_);
413 VideoMediaChannel* media_channel =
414 // voice_channel can be NULL in case of NullVoiceEngine.
415 media_engine_->CreateVideoChannel(voice_channel ?
416 voice_channel->media_channel() : NULL);
417 if (media_channel == NULL)
418 return NULL;
419
420 VideoChannel* video_channel = new VideoChannel(
421 worker_thread_, media_engine_.get(), media_channel,
422 session, content_name, rtcp, voice_channel);
423 if (!video_channel->Init()) {
424 delete video_channel;
425 return NULL;
426 }
427 video_channels_.push_back(video_channel);
428 return video_channel;
429 }
430
DestroyVideoChannel(VideoChannel * video_channel)431 void ChannelManager::DestroyVideoChannel(VideoChannel* video_channel) {
432 if (video_channel) {
433 talk_base::TypedMessageData<VideoChannel*> data(video_channel);
434 Send(MSG_DESTROYVIDEOCHANNEL, &data);
435 }
436 }
437
DestroyVideoChannel_w(VideoChannel * video_channel)438 void ChannelManager::DestroyVideoChannel_w(VideoChannel* video_channel) {
439 // Destroy video channel.
440 ASSERT(initialized_);
441 VideoChannels::iterator it = std::find(video_channels_.begin(),
442 video_channels_.end(), video_channel);
443 ASSERT(it != video_channels_.end());
444 if (it == video_channels_.end())
445 return;
446
447 video_channels_.erase(it);
448 delete video_channel;
449 }
450
CreateDataChannel(BaseSession * session,const std::string & content_name,bool rtcp)451 DataChannel* ChannelManager::CreateDataChannel(
452 BaseSession* session, const std::string& content_name, bool rtcp) {
453 CreationParams params(session, content_name, rtcp, NULL);
454 return (Send(MSG_CREATEDATACHANNEL, ¶ms)) ? params.data_channel : NULL;
455 }
456
CreateDataChannel_w(BaseSession * session,const std::string & content_name,bool rtcp)457 DataChannel* ChannelManager::CreateDataChannel_w(
458 BaseSession* session, const std::string& content_name, bool rtcp) {
459 // This is ok to alloc from a thread other than the worker thread.
460 ASSERT(initialized_);
461 DataMediaChannel* media_channel = data_media_engine_->CreateChannel();
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.";
467 delete data_channel;
468 return NULL;
469 }
470 data_channels_.push_back(data_channel);
471 return data_channel;
472 }
473
DestroyDataChannel(DataChannel * data_channel)474 void ChannelManager::DestroyDataChannel(DataChannel* data_channel) {
475 if (data_channel) {
476 talk_base::TypedMessageData<DataChannel*> data(data_channel);
477 Send(MSG_DESTROYDATACHANNEL, &data);
478 }
479 }
480
DestroyDataChannel_w(DataChannel * 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())
488 return;
489
490 data_channels_.erase(it);
491 delete data_channel;
492 }
493
CreateSoundclip()494 Soundclip* ChannelManager::CreateSoundclip() {
495 talk_base::TypedMessageData<Soundclip*> data(NULL);
496 Send(MSG_CREATESOUNDCLIP, &data);
497 return data.data();
498 }
499
CreateSoundclip_w()500 Soundclip* ChannelManager::CreateSoundclip_w() {
501 ASSERT(initialized_);
502 ASSERT(worker_thread_ == talk_base::Thread::Current());
503
504 SoundclipMedia* soundclip_media = media_engine_->CreateSoundclip();
505 if (!soundclip_media) {
506 return NULL;
507 }
508
509 Soundclip* soundclip = new Soundclip(worker_thread_, soundclip_media);
510 soundclips_.push_back(soundclip);
511 return soundclip;
512 }
513
DestroySoundclip(Soundclip * soundclip)514 void ChannelManager::DestroySoundclip(Soundclip* soundclip) {
515 if (soundclip) {
516 talk_base::TypedMessageData<Soundclip*> data(soundclip);
517 Send(MSG_DESTROYSOUNDCLIP, &data);
518 }
519 }
520
DestroySoundclip_w(Soundclip * soundclip)521 void ChannelManager::DestroySoundclip_w(Soundclip* soundclip) {
522 // Destroy soundclip.
523 ASSERT(initialized_);
524 Soundclips::iterator it = std::find(soundclips_.begin(),
525 soundclips_.end(), soundclip);
526 ASSERT(it != soundclips_.end());
527 if (it == soundclips_.end())
528 return;
529
530 soundclips_.erase(it);
531 delete soundclip;
532 }
533
GetAudioOptions(std::string * in_name,std::string * out_name,int * opts)534 bool ChannelManager::GetAudioOptions(std::string* in_name,
535 std::string* out_name, int* opts) {
536 *in_name = audio_in_device_;
537 *out_name = audio_out_device_;
538 *opts = audio_options_;
539 return true;
540 }
541
SetAudioOptions(const std::string & in_name,const std::string & out_name,int opts)542 bool ChannelManager::SetAudioOptions(const std::string& in_name,
543 const std::string& out_name, int opts) {
544 // Get device ids from DeviceManager.
545 Device in_dev, out_dev;
546 if (!device_manager_->GetAudioInputDevice(in_name, &in_dev)) {
547 LOG(LS_WARNING) << "Failed to GetAudioInputDevice: " << in_name;
548 return false;
549 }
550 if (!device_manager_->GetAudioOutputDevice(out_name, &out_dev)) {
551 LOG(LS_WARNING) << "Failed to GetAudioOutputDevice: " << out_name;
552 return false;
553 }
554
555 // If we're initialized, pass the settings to the media engine.
556 bool ret = true;
557 if (initialized_) {
558 AudioOptions options(opts, &in_dev, &out_dev);
559 ret = (Send(MSG_SETAUDIOOPTIONS, &options) && options.result);
560 }
561
562 // If all worked well, save the values for use in GetAudioOptions.
563 if (ret) {
564 audio_options_ = opts;
565 audio_in_device_ = in_name;
566 audio_out_device_ = out_name;
567 }
568 return ret;
569 }
570
SetAudioOptions_w(int opts,const Device * in_dev,const Device * out_dev)571 bool ChannelManager::SetAudioOptions_w(int opts, const Device* in_dev,
572 const Device* out_dev) {
573 ASSERT(worker_thread_ == talk_base::Thread::Current());
574 ASSERT(initialized_);
575
576 // Set audio options
577 bool ret = media_engine_->SetAudioOptions(opts);
578
579 // Set the audio devices
580 if (ret) {
581 ret = media_engine_->SetSoundDevices(in_dev, out_dev);
582 }
583
584 return ret;
585 }
586
GetOutputVolume(int * level)587 bool ChannelManager::GetOutputVolume(int* level) {
588 VolumeLevel volume;
589 if (!Send(MSG_GETOUTPUTVOLUME, &volume) || !volume.result) {
590 return false;
591 }
592
593 *level = volume.level;
594 return true;
595 }
596
GetOutputVolume_w(int * level)597 bool ChannelManager::GetOutputVolume_w(int* level) {
598 ASSERT(worker_thread_ == talk_base::Thread::Current());
599 ASSERT(initialized_);
600 return media_engine_->GetOutputVolume(level);
601 }
602
SetOutputVolume(int level)603 bool ChannelManager::SetOutputVolume(int level) {
604 bool ret = level >= 0 && level <= 255;
605 if (initialized_) {
606 VolumeLevel volume(level);
607 ret &= Send(MSG_SETOUTPUTVOLUME, &volume) && volume.result;
608 }
609
610 if (ret) {
611 audio_output_volume_ = level;
612 }
613
614 return ret;
615 }
616
SetOutputVolume_w(int level)617 bool ChannelManager::SetOutputVolume_w(int level) {
618 ASSERT(worker_thread_ == talk_base::Thread::Current());
619 ASSERT(initialized_);
620 return media_engine_->SetOutputVolume(level);
621 }
622
GetVideoOptions(std::string * cam_name)623 bool ChannelManager::GetVideoOptions(std::string* cam_name) {
624 if (camera_device_.empty()) {
625 // Initialize camera_device_ with default.
626 Device device;
627 if (!device_manager_->GetVideoCaptureDevice(
628 DeviceManagerInterface::kDefaultDeviceName, &device)) {
629 LOG(LS_WARNING) << "Device manager can't find default camera: " <<
630 DeviceManagerInterface::kDefaultDeviceName;
631 return false;
632 }
633 camera_device_ = device.name;
634 }
635 *cam_name = camera_device_;
636 return true;
637 }
638
SetVideoOptions(const std::string & cam_name)639 bool ChannelManager::SetVideoOptions(const std::string& cam_name) {
640 Device device;
641 bool ret = true;
642 if (!device_manager_->GetVideoCaptureDevice(cam_name, &device)) {
643 if (!cam_name.empty()) {
644 LOG(LS_WARNING) << "Device manager can't find camera: " << cam_name;
645 }
646 ret = false;
647 }
648
649 // If we're running, tell the media engine about it.
650 if (initialized_ && ret) {
651 VideoOptions options(&device);
652 ret = (Send(MSG_SETVIDEOOPTIONS, &options) && options.result);
653 }
654
655 // If everything worked, retain the name of the selected camera.
656 if (ret) {
657 camera_device_ = device.name;
658 } else if (camera_device_.empty()) {
659 // When video option setting fails, we still want camera_device_ to be in a
660 // good state, so we initialize it with default if it's empty.
661 Device default_device;
662 if (!device_manager_->GetVideoCaptureDevice(
663 DeviceManagerInterface::kDefaultDeviceName, &default_device)) {
664 LOG(LS_WARNING) << "Device manager can't find default camera: " <<
665 DeviceManagerInterface::kDefaultDeviceName;
666 }
667 camera_device_ = default_device.name;
668 }
669
670 return ret;
671 }
672
SetVideoOptions_w(const Device * cam_device)673 bool ChannelManager::SetVideoOptions_w(const Device* cam_device) {
674 ASSERT(worker_thread_ == talk_base::Thread::Current());
675 ASSERT(initialized_);
676
677 // Set the video input device
678 return media_engine_->SetVideoCaptureDevice(cam_device);
679 }
680
SetDefaultVideoEncoderConfig(const VideoEncoderConfig & c)681 bool ChannelManager::SetDefaultVideoEncoderConfig(const VideoEncoderConfig& c) {
682 bool ret = true;
683 if (initialized_) {
684 DefaultVideoEncoderConfig config(c);
685 ret = Send(MSG_SETDEFAULTVIDEOENCODERCONFIG, &config) && config.result;
686 }
687 if (ret) {
688 default_video_encoder_config_ = c;
689 }
690 return ret;
691 }
692
SetDefaultVideoEncoderConfig_w(const VideoEncoderConfig & c)693 bool ChannelManager::SetDefaultVideoEncoderConfig_w(
694 const VideoEncoderConfig& c) {
695 ASSERT(worker_thread_ == talk_base::Thread::Current());
696 ASSERT(initialized_);
697 return media_engine_->SetDefaultVideoEncoderConfig(c);
698 }
699
SetLocalMonitor(bool enable)700 bool ChannelManager::SetLocalMonitor(bool enable) {
701 LocalMonitor monitor(enable);
702 bool ret = Send(MSG_SETLOCALMONITOR, &monitor) && monitor.result;
703 if (ret) {
704 monitoring_ = enable;
705 }
706 return ret;
707 }
708
SetLocalMonitor_w(bool enable)709 bool ChannelManager::SetLocalMonitor_w(bool enable) {
710 ASSERT(worker_thread_ == talk_base::Thread::Current());
711 ASSERT(initialized_);
712 return media_engine_->SetLocalMonitor(enable);
713 }
714
SetLocalRenderer(VideoRenderer * renderer)715 bool ChannelManager::SetLocalRenderer(VideoRenderer* renderer) {
716 bool ret = true;
717 if (initialized_) {
718 LocalRenderer local(renderer);
719 ret = (Send(MSG_SETLOCALRENDERER, &local) && local.result);
720 }
721 if (ret) {
722 local_renderer_ = renderer;
723 }
724 return ret;
725 }
726
SetLocalRenderer_w(VideoRenderer * renderer)727 bool ChannelManager::SetLocalRenderer_w(VideoRenderer* renderer) {
728 ASSERT(worker_thread_ == talk_base::Thread::Current());
729 ASSERT(initialized_);
730 return media_engine_->SetLocalRenderer(renderer);
731 }
732
SetVideoCapturer(VideoCapturer * capturer,uint32 ssrc)733 bool ChannelManager::SetVideoCapturer(VideoCapturer* capturer, uint32 ssrc) {
734 bool ret = true;
735 if (initialized_) {
736 Capturer capture(capturer, ssrc);
737 ret = (Send(MSG_SETVIDEOCAPTURER, &capture) && capture.result);
738 }
739 return ret;
740 }
741
SetVideoCapturer_w(VideoCapturer * capturer,uint32 ssrc)742 bool ChannelManager::SetVideoCapturer_w(VideoCapturer* capturer, uint32 ssrc) {
743 ASSERT(worker_thread_ == talk_base::Thread::Current());
744 ASSERT(initialized_);
745 return media_engine_->SetVideoCapturer(capturer, ssrc);
746 }
747
SetVideoCapture(bool capture)748 CaptureResult ChannelManager::SetVideoCapture(bool capture) {
749 bool ret;
750 CaptureParams capture_params(capture);
751 ret = (Send(MSG_SETVIDEOCAPTURE, &capture_params) &&
752 (capture_params.result != CR_FAILURE));
753 if (ret) {
754 capturing_ = capture;
755 }
756 return capture_params.result;
757 }
758
SetVideoCapture_w(bool capture)759 CaptureResult ChannelManager::SetVideoCapture_w(bool capture) {
760 ASSERT(worker_thread_ == talk_base::Thread::Current());
761 ASSERT(initialized_);
762 return media_engine_->SetVideoCapture(capture);
763 }
764
SetVoiceLogging(int level,const char * filter)765 void ChannelManager::SetVoiceLogging(int level, const char* filter) {
766 SetMediaLogging(false, level, filter);
767 }
768
SetVideoLogging(int level,const char * filter)769 void ChannelManager::SetVideoLogging(int level, const char* filter) {
770 SetMediaLogging(true, level, filter);
771 }
772
SetMediaLogging(bool video,int level,const char * filter)773 void ChannelManager::SetMediaLogging(bool video, int level,
774 const char* filter) {
775 // Can be called before initialization; in this case, the worker function
776 // is simply called on the main thread.
777 if (initialized_) {
778 LoggingOptions options(level, filter);
779 Send((video) ? MSG_SETVIDEOLOGGING : MSG_SETVOICELOGGING, &options);
780 } else {
781 SetMediaLogging_w(video, level, filter);
782 }
783 }
784
SetMediaLogging_w(bool video,int level,const char * filter)785 void ChannelManager::SetMediaLogging_w(bool video, int level,
786 const char* filter) {
787 // Can be called before initialization
788 ASSERT(worker_thread_ == talk_base::Thread::Current() || !initialized_);
789 if (video) {
790 media_engine_->SetVideoLogging(level, filter);
791 } else {
792 media_engine_->SetVoiceLogging(level, filter);
793 }
794 }
795
796 // TODO: For now pass this request through the mediaengine to the
797 // voice and video engines to do the real work. Once the capturer refactoring
798 // is done, we will access the capturer using the ssrc (similar to how the
799 // renderer is accessed today) and register with it directly.
RegisterVideoProcessor(uint32 ssrc,VideoProcessor * processor)800 bool ChannelManager::RegisterVideoProcessor(uint32 ssrc,
801 VideoProcessor* processor) {
802 VideoProcessorParams processor_params(ssrc, processor);
803 return (Send(MSG_REGISTERVIDEOPROCESSOR, &processor_params) &&
804 processor_params.result);
805 }
RegisterVideoProcessor_w(uint32 ssrc,VideoProcessor * processor)806 bool ChannelManager::RegisterVideoProcessor_w(uint32 ssrc,
807 VideoProcessor* processor) {
808 return media_engine_->RegisterVideoProcessor(processor);
809 }
810
UnregisterVideoProcessor(uint32 ssrc,VideoProcessor * processor)811 bool ChannelManager::UnregisterVideoProcessor(uint32 ssrc,
812 VideoProcessor* processor) {
813 VideoProcessorParams processor_params(ssrc, processor);
814 return (Send(MSG_UNREGISTERVIDEOPROCESSOR, &processor_params) &&
815 processor_params.result);
816 }
UnregisterVideoProcessor_w(uint32 ssrc,VideoProcessor * processor)817 bool ChannelManager::UnregisterVideoProcessor_w(uint32 ssrc,
818 VideoProcessor* processor) {
819 return media_engine_->UnregisterVideoProcessor(processor);
820 }
821
RegisterVoiceProcessor(uint32 ssrc,VoiceProcessor * processor,MediaProcessorDirection direction)822 bool ChannelManager::RegisterVoiceProcessor(
823 uint32 ssrc,
824 VoiceProcessor* processor,
825 MediaProcessorDirection direction) {
826 VoiceProcessorParams processor_params(ssrc, processor, direction);
827 return (Send(MSG_REGISTERVOICEPROCESSOR, &processor_params) &&
828 processor_params.result);
829 }
RegisterVoiceProcessor_w(uint32 ssrc,VoiceProcessor * processor,MediaProcessorDirection direction)830 bool ChannelManager::RegisterVoiceProcessor_w(
831 uint32 ssrc,
832 VoiceProcessor* processor,
833 MediaProcessorDirection direction) {
834 return media_engine_->RegisterVoiceProcessor(ssrc, processor, direction);
835 }
836
UnregisterVoiceProcessor(uint32 ssrc,VoiceProcessor * processor,MediaProcessorDirection direction)837 bool ChannelManager::UnregisterVoiceProcessor(
838 uint32 ssrc,
839 VoiceProcessor* processor,
840 MediaProcessorDirection direction) {
841 VoiceProcessorParams processor_params(ssrc, processor, direction);
842 return (Send(MSG_UNREGISTERVOICEPROCESSOR, &processor_params) &&
843 processor_params.result);
844 }
UnregisterVoiceProcessor_w(uint32 ssrc,VoiceProcessor * processor,MediaProcessorDirection direction)845 bool ChannelManager::UnregisterVoiceProcessor_w(
846 uint32 ssrc,
847 VoiceProcessor* processor,
848 MediaProcessorDirection direction) {
849 return media_engine_->UnregisterVoiceProcessor(ssrc, processor, direction);
850 }
851
Send(uint32 id,talk_base::MessageData * data)852 bool ChannelManager::Send(uint32 id, talk_base::MessageData* data) {
853 if (!worker_thread_ || !initialized_) return false;
854 worker_thread_->Send(this, id, data);
855 return true;
856 }
857
OnVideoCaptureResult(VideoCapturer * capturer,CaptureResult result)858 void ChannelManager::OnVideoCaptureResult(VideoCapturer* capturer,
859 CaptureResult result) {
860 // TODO: Check capturer and signal failure only for camera video, not
861 // screencast.
862 capturing_ = result == CR_SUCCESS;
863 main_thread_->Post(this, MSG_CAMERASTARTED,
864 new talk_base::TypedMessageData<CaptureResult>(result));
865 }
866
OnMessage(talk_base::Message * message)867 void ChannelManager::OnMessage(talk_base::Message* message) {
868 talk_base::MessageData* data = message->pdata;
869 switch (message->message_id) {
870 case MSG_CREATEVOICECHANNEL: {
871 CreationParams* p = static_cast<CreationParams*>(data);
872 p->voice_channel =
873 CreateVoiceChannel_w(p->session, p->content_name, p->rtcp);
874 break;
875 }
876 case MSG_DESTROYVOICECHANNEL: {
877 VoiceChannel* p = static_cast<talk_base::TypedMessageData<VoiceChannel*>*>
878 (data)->data();
879 DestroyVoiceChannel_w(p);
880 break;
881 }
882 case MSG_CREATEVIDEOCHANNEL: {
883 CreationParams* p = static_cast<CreationParams*>(data);
884 p->video_channel = CreateVideoChannel_w(p->session, p->content_name,
885 p->rtcp, p->voice_channel);
886 break;
887 }
888 case MSG_DESTROYVIDEOCHANNEL: {
889 VideoChannel* p = static_cast<talk_base::TypedMessageData<VideoChannel*>*>
890 (data)->data();
891 DestroyVideoChannel_w(p);
892 break;
893 }
894 case MSG_CREATEDATACHANNEL: {
895 CreationParams* p = static_cast<CreationParams*>(data);
896 p->data_channel =
897 CreateDataChannel_w(p->session, p->content_name, p->rtcp);
898 break;
899 }
900 case MSG_DESTROYDATACHANNEL: {
901 DataChannel* p = static_cast<talk_base::TypedMessageData<DataChannel*>*>
902 (data)->data();
903 DestroyDataChannel_w(p);
904 break;
905 }
906 case MSG_CREATESOUNDCLIP: {
907 talk_base::TypedMessageData<Soundclip*> *p =
908 static_cast<talk_base::TypedMessageData<Soundclip*>*>(data);
909 p->data() = CreateSoundclip_w();
910 break;
911 }
912 case MSG_DESTROYSOUNDCLIP: {
913 talk_base::TypedMessageData<Soundclip*> *p =
914 static_cast<talk_base::TypedMessageData<Soundclip*>*>(data);
915 DestroySoundclip_w(p->data());
916 break;
917 }
918 case MSG_SETAUDIOOPTIONS: {
919 AudioOptions* p = static_cast<AudioOptions*>(data);
920 p->result = SetAudioOptions_w(p->options,
921 p->in_device, p->out_device);
922 break;
923 }
924 case MSG_GETOUTPUTVOLUME: {
925 VolumeLevel* p = static_cast<VolumeLevel*>(data);
926 p->result = GetOutputVolume_w(&p->level);
927 break;
928 }
929 case MSG_SETOUTPUTVOLUME: {
930 VolumeLevel* p = static_cast<VolumeLevel*>(data);
931 p->result = SetOutputVolume_w(p->level);
932 break;
933 }
934 case MSG_SETLOCALMONITOR: {
935 LocalMonitor* p = static_cast<LocalMonitor*>(data);
936 p->result = SetLocalMonitor_w(p->enable);
937 break;
938 }
939 case MSG_SETVIDEOOPTIONS: {
940 VideoOptions* p = static_cast<VideoOptions*>(data);
941 p->result = SetVideoOptions_w(p->cam_device);
942 break;
943 }
944 case MSG_SETDEFAULTVIDEOENCODERCONFIG: {
945 DefaultVideoEncoderConfig* p =
946 static_cast<DefaultVideoEncoderConfig*>(data);
947 p->result = SetDefaultVideoEncoderConfig_w(p->config);
948 break;
949 }
950 case MSG_SETLOCALRENDERER: {
951 LocalRenderer* p = static_cast<LocalRenderer*>(data);
952 p->result = SetLocalRenderer_w(p->renderer);
953 break;
954 }
955 case MSG_SETVIDEOCAPTURER: {
956 Capturer* p = static_cast<Capturer*>(data);
957 p->result = SetVideoCapturer_w(p->capturer, p->ssrc);
958 break;
959 }
960 case MSG_SETVIDEOCAPTURE: {
961 CaptureParams* p = static_cast<CaptureParams*>(data);
962 p->result = SetVideoCapture_w(p->capture);
963 break;
964 }
965 case MSG_SETVOICELOGGING:
966 case MSG_SETVIDEOLOGGING: {
967 LoggingOptions* p = static_cast<LoggingOptions*>(data);
968 bool video = (message->message_id == MSG_SETVIDEOLOGGING);
969 SetMediaLogging_w(video, p->level, p->filter.c_str());
970 break;
971 }
972 case MSG_CAMERASTARTED: {
973 talk_base::TypedMessageData<CaptureResult>* data =
974 static_cast<talk_base::TypedMessageData<CaptureResult>*>(
975 message->pdata);
976 SignalVideoCaptureResult(data->data());
977 delete data;
978 break;
979 }
980 case MSG_TERMINATE: {
981 Terminate_w();
982 break;
983 }
984 case MSG_REGISTERVIDEOPROCESSOR: {
985 VideoProcessorParams* data =
986 static_cast<VideoProcessorParams*>(message->pdata);
987 data->result = RegisterVideoProcessor_w(data->ssrc, data->processor);
988 break;
989 }
990 case MSG_UNREGISTERVIDEOPROCESSOR: {
991 VideoProcessorParams* data =
992 static_cast<VideoProcessorParams*>(message->pdata);
993 data->result = UnregisterVideoProcessor_w(data->ssrc, data->processor);
994 break;
995 }
996 case MSG_REGISTERVOICEPROCESSOR: {
997 VoiceProcessorParams* data =
998 static_cast<VoiceProcessorParams*>(message->pdata);
999 data->result = RegisterVoiceProcessor_w(data->ssrc,
1000 data->processor,
1001 data->direction);
1002 break;
1003 }
1004 case MSG_UNREGISTERVOICEPROCESSOR: {
1005 VoiceProcessorParams* data =
1006 static_cast<VoiceProcessorParams*>(message->pdata);
1007 data->result = UnregisterVoiceProcessor_w(data->ssrc,
1008 data->processor,
1009 data->direction);
1010 break;
1011 }
1012 }
1013 }
1014
GetDeviceNames(const std::vector<Device> & devs,std::vector<std::string> * names)1015 static void GetDeviceNames(const std::vector<Device>& devs,
1016 std::vector<std::string>* names) {
1017 names->clear();
1018 for (size_t i = 0; i < devs.size(); ++i) {
1019 names->push_back(devs[i].name);
1020 }
1021 }
1022
GetAudioInputDevices(std::vector<std::string> * names)1023 bool ChannelManager::GetAudioInputDevices(std::vector<std::string>* names) {
1024 names->clear();
1025 std::vector<Device> devs;
1026 bool ret = device_manager_->GetAudioInputDevices(&devs);
1027 if (ret)
1028 GetDeviceNames(devs, names);
1029
1030 return ret;
1031 }
1032
GetAudioOutputDevices(std::vector<std::string> * names)1033 bool ChannelManager::GetAudioOutputDevices(std::vector<std::string>* names) {
1034 names->clear();
1035 std::vector<Device> devs;
1036 bool ret = device_manager_->GetAudioOutputDevices(&devs);
1037 if (ret)
1038 GetDeviceNames(devs, names);
1039
1040 return ret;
1041 }
1042
GetVideoCaptureDevices(std::vector<std::string> * names)1043 bool ChannelManager::GetVideoCaptureDevices(std::vector<std::string>* names) {
1044 names->clear();
1045 std::vector<Device> devs;
1046 bool ret = device_manager_->GetVideoCaptureDevices(&devs);
1047 if (ret)
1048 GetDeviceNames(devs, names);
1049
1050 return ret;
1051 }
1052
1053 } // namespace cricket
1054