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