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