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