OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2004 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2004 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/pc/channelmanager.h" | 11 #include "webrtc/pc/channelmanager.h" |
12 | 12 |
13 #ifdef HAVE_CONFIG_H | 13 #ifdef HAVE_CONFIG_H |
14 #include <config.h> | 14 #include <config.h> |
15 #endif | 15 #endif |
16 | 16 |
17 #include <algorithm> | 17 #include <algorithm> |
18 | 18 |
19 #include "webrtc/api/mediacontroller.h" | 19 #include "webrtc/api/mediacontroller.h" |
20 #include "webrtc/base/bind.h" | 20 #include "webrtc/base/bind.h" |
21 #include "webrtc/base/common.h" | 21 #include "webrtc/base/common.h" |
22 #include "webrtc/base/logging.h" | 22 #include "webrtc/base/logging.h" |
23 #include "webrtc/base/sigslotrepeater.h" | |
24 #include "webrtc/base/stringencode.h" | 23 #include "webrtc/base/stringencode.h" |
25 #include "webrtc/base/stringutils.h" | 24 #include "webrtc/base/stringutils.h" |
26 #include "webrtc/base/trace_event.h" | 25 #include "webrtc/base/trace_event.h" |
27 #include "webrtc/media/base/capturemanager.h" | |
28 #include "webrtc/media/base/device.h" | 26 #include "webrtc/media/base/device.h" |
29 #include "webrtc/media/base/hybriddataengine.h" | 27 #include "webrtc/media/base/hybriddataengine.h" |
30 #include "webrtc/media/base/rtpdataengine.h" | 28 #include "webrtc/media/base/rtpdataengine.h" |
31 #include "webrtc/media/base/videocapturer.h" | |
32 #ifdef HAVE_SCTP | 29 #ifdef HAVE_SCTP |
33 #include "webrtc/media/sctp/sctpdataengine.h" | 30 #include "webrtc/media/sctp/sctpdataengine.h" |
34 #endif | 31 #endif |
35 #include "webrtc/pc/srtpfilter.h" | 32 #include "webrtc/pc/srtpfilter.h" |
36 | 33 |
37 namespace cricket { | 34 namespace cricket { |
38 | 35 |
39 enum { | |
40 MSG_VIDEOCAPTURESTATE = 1, | |
41 }; | |
42 | 36 |
43 using rtc::Bind; | 37 using rtc::Bind; |
44 | 38 |
45 static const int kNotSetOutputVolume = -1; | 39 static const int kNotSetOutputVolume = -1; |
46 | 40 |
47 struct CaptureStateParams : public rtc::MessageData { | |
48 CaptureStateParams(cricket::VideoCapturer* c, cricket::CaptureState s) | |
49 : capturer(c), | |
50 state(s) {} | |
51 cricket::VideoCapturer* capturer; | |
52 cricket::CaptureState state; | |
53 }; | |
54 | |
55 static DataEngineInterface* ConstructDataEngine() { | 41 static DataEngineInterface* ConstructDataEngine() { |
56 #ifdef HAVE_SCTP | 42 #ifdef HAVE_SCTP |
57 return new HybridDataEngine(new RtpDataEngine(), new SctpDataEngine()); | 43 return new HybridDataEngine(new RtpDataEngine(), new SctpDataEngine()); |
58 #else | 44 #else |
59 return new RtpDataEngine(); | 45 return new RtpDataEngine(); |
60 #endif | 46 #endif |
61 } | 47 } |
62 | 48 |
63 ChannelManager::ChannelManager(MediaEngineInterface* me, | 49 ChannelManager::ChannelManager(MediaEngineInterface* me, |
64 DataEngineInterface* dme, | 50 DataEngineInterface* dme, |
65 CaptureManager* cm, | |
66 rtc::Thread* worker_thread) { | 51 rtc::Thread* worker_thread) { |
67 Construct(me, dme, cm, worker_thread); | 52 Construct(me, dme, worker_thread); |
68 } | 53 } |
69 | 54 |
70 ChannelManager::ChannelManager(MediaEngineInterface* me, | 55 ChannelManager::ChannelManager(MediaEngineInterface* me, |
71 rtc::Thread* worker_thread) { | 56 rtc::Thread* worker_thread) { |
72 Construct(me, | 57 Construct(me, |
73 ConstructDataEngine(), | 58 ConstructDataEngine(), |
74 new CaptureManager(), | |
75 worker_thread); | 59 worker_thread); |
76 } | 60 } |
77 | 61 |
78 void ChannelManager::Construct(MediaEngineInterface* me, | 62 void ChannelManager::Construct(MediaEngineInterface* me, |
79 DataEngineInterface* dme, | 63 DataEngineInterface* dme, |
80 CaptureManager* cm, | |
81 rtc::Thread* worker_thread) { | 64 rtc::Thread* worker_thread) { |
82 media_engine_.reset(me); | 65 media_engine_.reset(me); |
83 data_media_engine_.reset(dme); | 66 data_media_engine_.reset(dme); |
84 capture_manager_.reset(cm); | |
85 initialized_ = false; | 67 initialized_ = false; |
86 main_thread_ = rtc::Thread::Current(); | 68 main_thread_ = rtc::Thread::Current(); |
87 worker_thread_ = worker_thread; | 69 worker_thread_ = worker_thread; |
88 audio_output_volume_ = kNotSetOutputVolume; | 70 audio_output_volume_ = kNotSetOutputVolume; |
89 capturing_ = false; | 71 capturing_ = false; |
90 enable_rtx_ = false; | 72 enable_rtx_ = false; |
91 | |
92 capture_manager_->SignalCapturerStateChange.connect( | |
93 this, &ChannelManager::OnVideoCaptureStateChange); | |
94 } | 73 } |
95 | 74 |
96 ChannelManager::~ChannelManager() { | 75 ChannelManager::~ChannelManager() { |
97 if (initialized_) { | 76 if (initialized_) { |
98 Terminate(); | 77 Terminate(); |
99 // If srtp is initialized (done by the Channel) then we must call | 78 // If srtp is initialized (done by the Channel) then we must call |
100 // srtp_shutdown to free all crypto kernel lists. But we need to make sure | 79 // srtp_shutdown to free all crypto kernel lists. But we need to make sure |
101 // shutdown always called at the end, after channels are destroyed. | 80 // shutdown always called at the end, after channels are destroyed. |
102 // ChannelManager d'tor is always called last, it's safe place to call | 81 // ChannelManager d'tor is always called last, it's safe place to call |
103 // shutdown. | 82 // shutdown. |
104 ShutdownSrtp(); | 83 ShutdownSrtp(); |
105 } | 84 } |
106 // Some deletes need to be on the worker thread for thread safe destruction, | 85 // The media engine needs to be deleted on the worker thread for thread safe |
107 // this includes the media engine and capture manager. | 86 // destruction, |
108 worker_thread_->Invoke<void>(Bind( | 87 worker_thread_->Invoke<void>(Bind( |
109 &ChannelManager::DestructorDeletes_w, this)); | 88 &ChannelManager::DestructorDeletes_w, this)); |
110 } | 89 } |
111 | 90 |
112 bool ChannelManager::SetVideoRtxEnabled(bool enable) { | 91 bool ChannelManager::SetVideoRtxEnabled(bool enable) { |
113 // To be safe, this call is only allowed before initialization. Apps like | 92 // To be safe, this call is only allowed before initialization. Apps like |
114 // Flute only have a singleton ChannelManager and we don't want this flag to | 93 // Flute only have a singleton ChannelManager and we don't want this flag to |
115 // be toggled between calls or when there's concurrent calls. We expect apps | 94 // be toggled between calls or when there's concurrent calls. We expect apps |
116 // to enable this at startup and retain that setting for the lifetime of the | 95 // to enable this at startup and retain that setting for the lifetime of the |
117 // app. | 96 // app. |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 if (!initialized_) { | 186 if (!initialized_) { |
208 return; | 187 return; |
209 } | 188 } |
210 worker_thread_->Invoke<void>(Bind(&ChannelManager::Terminate_w, this)); | 189 worker_thread_->Invoke<void>(Bind(&ChannelManager::Terminate_w, this)); |
211 initialized_ = false; | 190 initialized_ = false; |
212 } | 191 } |
213 | 192 |
214 void ChannelManager::DestructorDeletes_w() { | 193 void ChannelManager::DestructorDeletes_w() { |
215 ASSERT(worker_thread_ == rtc::Thread::Current()); | 194 ASSERT(worker_thread_ == rtc::Thread::Current()); |
216 media_engine_.reset(NULL); | 195 media_engine_.reset(NULL); |
217 capture_manager_.reset(NULL); | |
218 } | 196 } |
219 | 197 |
220 void ChannelManager::Terminate_w() { | 198 void ChannelManager::Terminate_w() { |
221 ASSERT(worker_thread_ == rtc::Thread::Current()); | 199 ASSERT(worker_thread_ == rtc::Thread::Current()); |
222 // Need to destroy the voice/video channels | 200 // Need to destroy the voice/video channels |
223 while (!video_channels_.empty()) { | 201 while (!video_channels_.empty()) { |
224 DestroyVideoChannel_w(video_channels_.back()); | 202 DestroyVideoChannel_w(video_channels_.back()); |
225 } | 203 } |
226 while (!voice_channels_.empty()) { | 204 while (!voice_channels_.empty()) { |
227 DestroyVoiceChannel_w(voice_channels_.back()); | 205 DestroyVoiceChannel_w(voice_channels_.back()); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 media_engine_.get(), level)); | 398 media_engine_.get(), level)); |
421 } | 399 } |
422 | 400 |
423 if (ret) { | 401 if (ret) { |
424 audio_output_volume_ = level; | 402 audio_output_volume_ = level; |
425 } | 403 } |
426 | 404 |
427 return ret; | 405 return ret; |
428 } | 406 } |
429 | 407 |
430 std::vector<cricket::VideoFormat> ChannelManager::GetSupportedFormats( | |
431 VideoCapturer* capturer) const { | |
432 ASSERT(capturer != NULL); | |
433 std::vector<VideoFormat> formats; | |
434 worker_thread_->Invoke<void>(rtc::Bind(&ChannelManager::GetSupportedFormats_w, | |
435 this, capturer, &formats)); | |
436 return formats; | |
437 } | |
438 | |
439 void ChannelManager::GetSupportedFormats_w( | |
440 VideoCapturer* capturer, | |
441 std::vector<cricket::VideoFormat>* out_formats) const { | |
442 const std::vector<VideoFormat>* formats = capturer->GetSupportedFormats(); | |
443 if (formats != NULL) | |
444 *out_formats = *formats; | |
445 } | |
446 | |
447 // The following are done in the new "CaptureManager" style that | |
448 // all local video capturers, processors, and managers should move | |
449 // to. | |
450 // TODO(pthatcher): Add more of the CaptureManager interface. | |
451 bool ChannelManager::StartVideoCapture( | |
452 VideoCapturer* capturer, const VideoFormat& video_format) { | |
453 return initialized_ && worker_thread_->Invoke<bool>( | |
454 Bind(&CaptureManager::StartVideoCapture, | |
455 capture_manager_.get(), capturer, video_format)); | |
456 } | |
457 | |
458 bool ChannelManager::StopVideoCapture( | |
459 VideoCapturer* capturer, const VideoFormat& video_format) { | |
460 return initialized_ && worker_thread_->Invoke<bool>( | |
461 Bind(&CaptureManager::StopVideoCapture, | |
462 capture_manager_.get(), capturer, video_format)); | |
463 } | |
464 | |
465 void ChannelManager::AddVideoSink( | |
466 VideoCapturer* capturer, rtc::VideoSinkInterface<VideoFrame>* sink) { | |
467 if (initialized_) | |
468 worker_thread_->Invoke<void>( | |
469 Bind(&CaptureManager::AddVideoSink, | |
470 capture_manager_.get(), capturer, sink)); | |
471 } | |
472 | |
473 void ChannelManager::RemoveVideoSink( | |
474 VideoCapturer* capturer, rtc::VideoSinkInterface<VideoFrame>* sink) { | |
475 if (initialized_) | |
476 worker_thread_->Invoke<void>( | |
477 Bind(&CaptureManager::RemoveVideoSink, | |
478 capture_manager_.get(), capturer, sink)); | |
479 } | |
480 | |
481 bool ChannelManager::IsScreencastRunning() const { | |
482 return initialized_ && worker_thread_->Invoke<bool>( | |
483 Bind(&ChannelManager::IsScreencastRunning_w, this)); | |
484 } | |
485 | |
486 bool ChannelManager::IsScreencastRunning_w() const { | |
487 VideoChannels::const_iterator it = video_channels_.begin(); | |
488 for ( ; it != video_channels_.end(); ++it) { | |
489 if ((*it) && (*it)->IsScreencasting()) { | |
490 return true; | |
491 } | |
492 } | |
493 return false; | |
494 } | |
495 | |
496 void ChannelManager::OnVideoCaptureStateChange(VideoCapturer* capturer, | |
497 CaptureState result) { | |
498 // TODO(whyuan): Check capturer and signal failure only for camera video, not | |
499 // screencast. | |
500 capturing_ = result == CS_RUNNING; | |
501 main_thread_->Post(this, MSG_VIDEOCAPTURESTATE, | |
502 new CaptureStateParams(capturer, result)); | |
503 } | |
504 | |
505 void ChannelManager::OnMessage(rtc::Message* message) { | |
506 switch (message->message_id) { | |
507 case MSG_VIDEOCAPTURESTATE: { | |
508 CaptureStateParams* data = | |
509 static_cast<CaptureStateParams*>(message->pdata); | |
510 SignalVideoCaptureStateChange(data->capturer, data->state); | |
511 delete data; | |
512 break; | |
513 } | |
514 } | |
515 } | |
516 | 408 |
517 bool ChannelManager::StartAecDump(rtc::PlatformFile file, | 409 bool ChannelManager::StartAecDump(rtc::PlatformFile file, |
518 int64_t max_size_bytes) { | 410 int64_t max_size_bytes) { |
519 return worker_thread_->Invoke<bool>(Bind(&MediaEngineInterface::StartAecDump, | 411 return worker_thread_->Invoke<bool>(Bind(&MediaEngineInterface::StartAecDump, |
520 media_engine_.get(), file, | 412 media_engine_.get(), file, |
521 max_size_bytes)); | 413 max_size_bytes)); |
522 } | 414 } |
523 | 415 |
524 void ChannelManager::StopAecDump() { | 416 void ChannelManager::StopAecDump() { |
525 worker_thread_->Invoke<void>( | 417 worker_thread_->Invoke<void>( |
526 Bind(&MediaEngineInterface::StopAecDump, media_engine_.get())); | 418 Bind(&MediaEngineInterface::StopAecDump, media_engine_.get())); |
527 } | 419 } |
528 | 420 |
529 bool ChannelManager::StartRtcEventLog(rtc::PlatformFile file) { | 421 bool ChannelManager::StartRtcEventLog(rtc::PlatformFile file) { |
530 return worker_thread_->Invoke<bool>( | 422 return worker_thread_->Invoke<bool>( |
531 Bind(&MediaEngineInterface::StartRtcEventLog, media_engine_.get(), file)); | 423 Bind(&MediaEngineInterface::StartRtcEventLog, media_engine_.get(), file)); |
532 } | 424 } |
533 | 425 |
534 void ChannelManager::StopRtcEventLog() { | 426 void ChannelManager::StopRtcEventLog() { |
535 worker_thread_->Invoke<void>( | 427 worker_thread_->Invoke<void>( |
536 Bind(&MediaEngineInterface::StopRtcEventLog, media_engine_.get())); | 428 Bind(&MediaEngineInterface::StopRtcEventLog, media_engine_.get())); |
537 } | 429 } |
538 | 430 |
539 } // namespace cricket | 431 } // namespace cricket |
OLD | NEW |