1 /* 2 * libjingle 3 * Copyright 2004 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/session/media/channelmanager.h" 29 30 #ifdef HAVE_CONFIG_H 31 #include <config.h> 32 #endif 33 34 #include <algorithm> 35 36 #include "talk/base/bind.h" 37 #include "talk/base/common.h" 38 #include "talk/base/logging.h" 39 #include "talk/base/sigslotrepeater.h" 40 #include "talk/base/stringencode.h" 41 #include "talk/base/stringutils.h" 42 #include "talk/media/base/capturemanager.h" 43 #include "talk/media/base/hybriddataengine.h" 44 #include "talk/media/base/rtpdataengine.h" 45 #include "talk/media/base/videocapturer.h" 46 #include "talk/media/devices/devicemanager.h" 47 #ifdef HAVE_SCTP 48 #include "talk/media/sctp/sctpdataengine.h" 49 #endif 50 #include "talk/session/media/soundclip.h" 51 #include "talk/session/media/srtpfilter.h" 52 53 namespace cricket { 54 55 enum { 56 MSG_VIDEOCAPTURESTATE = 1, 57 }; 58 59 using talk_base::Bind; 60 61 static const int kNotSetOutputVolume = -1; 62 63 struct CaptureStateParams : public talk_base::MessageData { 64 CaptureStateParams(cricket::VideoCapturer* c, cricket::CaptureState s) 65 : capturer(c), 66 state(s) {} 67 cricket::VideoCapturer* capturer; 68 cricket::CaptureState state; 69 }; 70 71 static DataEngineInterface* ConstructDataEngine() { 72 #ifdef HAVE_SCTP 73 return new HybridDataEngine(new RtpDataEngine(), new SctpDataEngine()); 74 #else 75 return new RtpDataEngine(); 76 #endif 77 } 78 79 #if !defined(DISABLE_MEDIA_ENGINE_FACTORY) 80 ChannelManager::ChannelManager(talk_base::Thread* worker_thread) { 81 Construct(MediaEngineFactory::Create(), 82 ConstructDataEngine(), 83 cricket::DeviceManagerFactory::Create(), 84 new CaptureManager(), 85 worker_thread); 86 } 87 #endif 88 89 ChannelManager::ChannelManager(MediaEngineInterface* me, 90 DataEngineInterface* dme, 91 DeviceManagerInterface* dm, 92 CaptureManager* cm, 93 talk_base::Thread* worker_thread) { 94 Construct(me, dme, dm, cm, worker_thread); 95 } 96 97 ChannelManager::ChannelManager(MediaEngineInterface* me, 98 DeviceManagerInterface* dm, 99 talk_base::Thread* worker_thread) { 100 Construct(me, 101 ConstructDataEngine(), 102 dm, 103 new CaptureManager(), 104 worker_thread); 105 } 106 107 void ChannelManager::Construct(MediaEngineInterface* me, 108 DataEngineInterface* dme, 109 DeviceManagerInterface* dm, 110 CaptureManager* cm, 111 talk_base::Thread* worker_thread) { 112 media_engine_.reset(me); 113 data_media_engine_.reset(dme); 114 device_manager_.reset(dm); 115 capture_manager_.reset(cm); 116 initialized_ = false; 117 main_thread_ = talk_base::Thread::Current(); 118 worker_thread_ = worker_thread; 119 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 141 ChannelManager::~ChannelManager() { 142 if (initialized_) { 143 Terminate(); 144 // 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 } 151 } 152 153 bool 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 168 int ChannelManager::GetCapabilities() { 169 return media_engine_->GetCapabilities() & device_manager_->GetCapabilities(); 170 } 171 172 void 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 183 void ChannelManager::GetSupportedAudioRtpHeaderExtensions( 184 RtpHeaderExtensions* ext) const { 185 *ext = media_engine_->audio_rtp_header_extensions(); 186 } 187 188 void 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 202 void ChannelManager::GetSupportedVideoRtpHeaderExtensions( 203 RtpHeaderExtensions* ext) const { 204 *ext = media_engine_->video_rtp_header_extensions(); 205 } 206 207 void ChannelManager::GetSupportedDataCodecs( 208 std::vector<DataCodec>* codecs) const { 209 *codecs = data_media_engine_->data_codecs(); 210 } 211 212 bool 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 288 void 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 298 void 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 315 VoiceChannel* 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 322 VoiceChannel* 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 341 void 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 348 void 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 361 VideoChannel* 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 369 VideoChannel* 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 392 void 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 399 void 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 412 DataChannel* 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 420 DataChannel* 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 445 void 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 452 void 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 465 Soundclip* ChannelManager::CreateSoundclip() { 466 return worker_thread_->Invoke<Soundclip*>( 467 Bind(&ChannelManager::CreateSoundclip_w, this)); 468 } 469 470 Soundclip* 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 484 void ChannelManager::DestroySoundclip(Soundclip* soundclip) { 485 if (soundclip) { 486 worker_thread_->Invoke<void>( 487 Bind(&ChannelManager::DestroySoundclip_w, this, soundclip)); 488 } 489 } 490 491 void 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 504 bool 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 515 bool 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 520 bool 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 552 bool 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 572 bool 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 580 bool 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 595 bool 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 607 bool 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 615 bool 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 631 bool 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 665 VideoCapturer* 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 676 bool 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 688 bool 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 701 bool 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 711 bool 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 724 void 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 734 void 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. 748 bool 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 755 bool ChannelManager::RegisterVideoProcessor_w(VideoCapturer* capturer, 756 VideoProcessor* processor) { 757 return capture_manager_->AddVideoProcessor(capturer, processor); 758 } 759 760 bool 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 767 bool ChannelManager::UnregisterVideoProcessor_w(VideoCapturer* capturer, 768 VideoProcessor* processor) { 769 return capture_manager_->RemoveVideoProcessor(capturer, processor); 770 } 771 772 bool 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 781 bool 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. 794 bool 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 801 bool 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 811 bool 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 818 bool 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 828 bool 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 835 bool 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 842 bool ChannelManager::IsScreencastRunning() const { 843 return initialized_ && worker_thread_->Invoke<bool>( 844 Bind(&ChannelManager::IsScreencastRunning_w, this)); 845 } 846 847 bool 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 857 void 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 866 void 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 879 static 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 887 bool 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 897 bool 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 907 bool 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 917 void ChannelManager::SetVideoCaptureDeviceMaxFormat( 918 const std::string& usb_id, 919 const VideoFormat& max_format) { 920 device_manager_->SetVideoCaptureDeviceMaxFormat(usb_id, max_format); 921 } 922 923 VideoFormat ChannelManager::GetStartCaptureFormat() { 924 return worker_thread_->Invoke<VideoFormat>( 925 Bind(&MediaEngineInterface::GetStartCaptureFormat, media_engine_.get())); 926 } 927 928 } // namespace cricket 929