blob: bd89a41328cb345728bdec0912b4f230a3242a94 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
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
Fredrik Solenberg709ed672015-09-15 12:26:33 +020036#include "talk/app/webrtc/mediacontroller.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000037#include "talk/media/base/capturemanager.h"
solenbergfacbbec2015-09-24 00:41:50 -070038#include "talk/media/base/device.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000039#include "talk/media/base/hybriddataengine.h"
40#include "talk/media/base/rtpdataengine.h"
41#include "talk/media/base/videocapturer.h"
42#ifdef HAVE_SCTP
43#include "talk/media/sctp/sctpdataengine.h"
44#endif
wu@webrtc.org9dba5252013-08-05 20:36:57 +000045#include "talk/session/media/srtpfilter.h"
buildbot@webrtc.org65b98d12014-08-07 22:09:08 +000046#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"
Peter Boström1a9d6152015-12-08 22:15:17 +010052#include "webrtc/base/trace_event.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000053
54namespace cricket {
55
56enum {
57 MSG_VIDEOCAPTURESTATE = 1,
58};
59
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000060using rtc::Bind;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000061
62static const int kNotSetOutputVolume = -1;
63
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000064struct CaptureStateParams : public rtc::MessageData {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000065 CaptureStateParams(cricket::VideoCapturer* c, cricket::CaptureState s)
66 : capturer(c),
67 state(s) {}
68 cricket::VideoCapturer* capturer;
69 cricket::CaptureState state;
70};
71
72static DataEngineInterface* ConstructDataEngine() {
73#ifdef HAVE_SCTP
74 return new HybridDataEngine(new RtpDataEngine(), new SctpDataEngine());
75#else
76 return new RtpDataEngine();
77#endif
78}
79
henrike@webrtc.org28e20752013-07-10 00:45:36 +000080ChannelManager::ChannelManager(MediaEngineInterface* me,
81 DataEngineInterface* dme,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000082 CaptureManager* cm,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000083 rtc::Thread* worker_thread) {
solenbergfacbbec2015-09-24 00:41:50 -070084 Construct(me, dme, cm, worker_thread);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000085}
86
87ChannelManager::ChannelManager(MediaEngineInterface* me,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000088 rtc::Thread* worker_thread) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000089 Construct(me,
90 ConstructDataEngine(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000091 new CaptureManager(),
92 worker_thread);
93}
94
95void ChannelManager::Construct(MediaEngineInterface* me,
96 DataEngineInterface* dme,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000097 CaptureManager* cm,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000098 rtc::Thread* worker_thread) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000099 media_engine_.reset(me);
100 data_media_engine_.reset(dme);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000101 capture_manager_.reset(cm);
102 initialized_ = false;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000103 main_thread_ = rtc::Thread::Current();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000104 worker_thread_ = worker_thread;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000105 audio_output_volume_ = kNotSetOutputVolume;
106 local_renderer_ = NULL;
107 capturing_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000108 enable_rtx_ = false;
109
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000110 capture_manager_->SignalCapturerStateChange.connect(
111 this, &ChannelManager::OnVideoCaptureStateChange);
112}
113
114ChannelManager::~ChannelManager() {
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000115 if (initialized_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000116 Terminate();
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000117 // If srtp is initialized (done by the Channel) then we must call
118 // srtp_shutdown to free all crypto kernel lists. But we need to make sure
119 // shutdown always called at the end, after channels are destroyed.
120 // ChannelManager d'tor is always called last, it's safe place to call
121 // shutdown.
122 ShutdownSrtp();
123 }
hbos@webrtc.org4aef5fe2015-02-25 10:09:05 +0000124 // Some deletes need to be on the worker thread for thread safe destruction,
125 // this includes the media engine and capture manager.
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000126 worker_thread_->Invoke<void>(Bind(
hbos@webrtc.org4aef5fe2015-02-25 10:09:05 +0000127 &ChannelManager::DestructorDeletes_w, this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000128}
129
130bool ChannelManager::SetVideoRtxEnabled(bool enable) {
131 // To be safe, this call is only allowed before initialization. Apps like
132 // Flute only have a singleton ChannelManager and we don't want this flag to
133 // be toggled between calls or when there's concurrent calls. We expect apps
134 // to enable this at startup and retain that setting for the lifetime of the
135 // app.
136 if (!initialized_) {
137 enable_rtx_ = enable;
138 return true;
139 } else {
140 LOG(LS_WARNING) << "Cannot toggle rtx after initialization!";
141 return false;
142 }
143}
144
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000145void ChannelManager::GetSupportedAudioCodecs(
146 std::vector<AudioCodec>* codecs) const {
147 codecs->clear();
148
149 for (std::vector<AudioCodec>::const_iterator it =
150 media_engine_->audio_codecs().begin();
151 it != media_engine_->audio_codecs().end(); ++it) {
152 codecs->push_back(*it);
153 }
154}
155
156void ChannelManager::GetSupportedAudioRtpHeaderExtensions(
157 RtpHeaderExtensions* ext) const {
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100158 *ext = media_engine_->GetAudioCapabilities().header_extensions;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000159}
160
161void ChannelManager::GetSupportedVideoCodecs(
162 std::vector<VideoCodec>* codecs) const {
163 codecs->clear();
164
165 std::vector<VideoCodec>::const_iterator it;
166 for (it = media_engine_->video_codecs().begin();
167 it != media_engine_->video_codecs().end(); ++it) {
168 if (!enable_rtx_ && _stricmp(kRtxCodecName, it->name.c_str()) == 0) {
169 continue;
170 }
171 codecs->push_back(*it);
172 }
173}
174
175void ChannelManager::GetSupportedVideoRtpHeaderExtensions(
176 RtpHeaderExtensions* ext) const {
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100177 *ext = media_engine_->GetVideoCapabilities().header_extensions;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000178}
179
180void ChannelManager::GetSupportedDataCodecs(
181 std::vector<DataCodec>* codecs) const {
182 *codecs = data_media_engine_->data_codecs();
183}
184
185bool ChannelManager::Init() {
186 ASSERT(!initialized_);
187 if (initialized_) {
188 return false;
189 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000190 ASSERT(worker_thread_ != NULL);
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000191 if (!worker_thread_) {
192 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000193 }
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000194 if (worker_thread_ != rtc::Thread::Current()) {
195 // Do not allow invoking calls to other threads on the worker thread.
196 worker_thread_->Invoke<bool>(rtc::Bind(
197 &rtc::Thread::SetAllowBlockingCalls, worker_thread_, false));
198 }
199
200 initialized_ = worker_thread_->Invoke<bool>(Bind(
201 &ChannelManager::InitMediaEngine_w, this));
202 ASSERT(initialized_);
203 if (!initialized_) {
204 return false;
205 }
206
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000207 // If audio_output_volume_ has been set via SetOutputVolume(), set the
208 // audio output volume of the engine.
209 if (kNotSetOutputVolume != audio_output_volume_ &&
210 !SetOutputVolume(audio_output_volume_)) {
211 LOG(LS_WARNING) << "Failed to SetOutputVolume to "
212 << audio_output_volume_;
213 }
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000214
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000215 return initialized_;
216}
217
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000218bool ChannelManager::InitMediaEngine_w() {
219 ASSERT(worker_thread_ == rtc::Thread::Current());
220 return (media_engine_->Init(worker_thread_));
221}
222
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000223void ChannelManager::Terminate() {
224 ASSERT(initialized_);
225 if (!initialized_) {
226 return;
227 }
228 worker_thread_->Invoke<void>(Bind(&ChannelManager::Terminate_w, this));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000229 initialized_ = false;
230}
231
hbos@webrtc.org4aef5fe2015-02-25 10:09:05 +0000232void ChannelManager::DestructorDeletes_w() {
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000233 ASSERT(worker_thread_ == rtc::Thread::Current());
234 media_engine_.reset(NULL);
hbos@webrtc.org4aef5fe2015-02-25 10:09:05 +0000235 capture_manager_.reset(NULL);
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000236}
237
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000238void ChannelManager::Terminate_w() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000239 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000240 // Need to destroy the voice/video channels
241 while (!video_channels_.empty()) {
242 DestroyVideoChannel_w(video_channels_.back());
243 }
244 while (!voice_channels_.empty()) {
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200245 DestroyVoiceChannel_w(voice_channels_.back());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000246 }
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000247 media_engine_->Terminate();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000248}
249
250VoiceChannel* ChannelManager::CreateVoiceChannel(
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200251 webrtc::MediaControllerInterface* media_controller,
deadbeefcbecd352015-09-23 11:50:27 -0700252 TransportController* transport_controller,
Jelena Marusicc28a8962015-05-29 15:05:44 +0200253 const std::string& content_name,
254 bool rtcp,
255 const AudioOptions& options) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000256 return worker_thread_->Invoke<VoiceChannel*>(
deadbeefcbecd352015-09-23 11:50:27 -0700257 Bind(&ChannelManager::CreateVoiceChannel_w, this, media_controller,
258 transport_controller, content_name, rtcp, options));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000259}
260
261VoiceChannel* ChannelManager::CreateVoiceChannel_w(
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200262 webrtc::MediaControllerInterface* media_controller,
deadbeefcbecd352015-09-23 11:50:27 -0700263 TransportController* transport_controller,
Jelena Marusicc28a8962015-05-29 15:05:44 +0200264 const std::string& content_name,
265 bool rtcp,
266 const AudioOptions& options) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000267 ASSERT(initialized_);
Fredrik Solenberg4b60c732015-05-07 14:07:48 +0200268 ASSERT(worker_thread_ == rtc::Thread::Current());
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200269 ASSERT(nullptr != media_controller);
270 VoiceMediaChannel* media_channel =
271 media_engine_->CreateChannel(media_controller->call_w(), options);
Jelena Marusicc28a8962015-05-29 15:05:44 +0200272 if (!media_channel)
273 return nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000274
deadbeefcbecd352015-09-23 11:50:27 -0700275 VoiceChannel* voice_channel =
276 new VoiceChannel(worker_thread_, media_engine_.get(), media_channel,
277 transport_controller, content_name, rtcp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000278 if (!voice_channel->Init()) {
279 delete voice_channel;
Jelena Marusicc28a8962015-05-29 15:05:44 +0200280 return nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000281 }
282 voice_channels_.push_back(voice_channel);
283 return voice_channel;
284}
285
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200286void ChannelManager::DestroyVoiceChannel(VoiceChannel* voice_channel) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100287 TRACE_EVENT0("webrtc", "ChannelManager::DestroyVoiceChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000288 if (voice_channel) {
289 worker_thread_->Invoke<void>(
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200290 Bind(&ChannelManager::DestroyVoiceChannel_w, this, voice_channel));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000291 }
292}
293
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200294void ChannelManager::DestroyVoiceChannel_w(VoiceChannel* voice_channel) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100295 TRACE_EVENT0("webrtc", "ChannelManager::DestroyVoiceChannel_w");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000296 // Destroy voice channel.
297 ASSERT(initialized_);
Fredrik Solenberg4b60c732015-05-07 14:07:48 +0200298 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000299 VoiceChannels::iterator it = std::find(voice_channels_.begin(),
300 voice_channels_.end(), voice_channel);
301 ASSERT(it != voice_channels_.end());
302 if (it == voice_channels_.end())
303 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000304 voice_channels_.erase(it);
305 delete voice_channel;
306}
307
308VideoChannel* ChannelManager::CreateVideoChannel(
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200309 webrtc::MediaControllerInterface* media_controller,
deadbeefcbecd352015-09-23 11:50:27 -0700310 TransportController* transport_controller,
buildbot@webrtc.org1ecbe452014-10-14 20:29:28 +0000311 const std::string& content_name,
312 bool rtcp,
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200313 const VideoOptions& options) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000314 return worker_thread_->Invoke<VideoChannel*>(
deadbeefcbecd352015-09-23 11:50:27 -0700315 Bind(&ChannelManager::CreateVideoChannel_w, this, media_controller,
316 transport_controller, content_name, rtcp, options));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000317}
318
319VideoChannel* ChannelManager::CreateVideoChannel_w(
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200320 webrtc::MediaControllerInterface* media_controller,
deadbeefcbecd352015-09-23 11:50:27 -0700321 TransportController* transport_controller,
buildbot@webrtc.org1ecbe452014-10-14 20:29:28 +0000322 const std::string& content_name,
323 bool rtcp,
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200324 const VideoOptions& options) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000325 ASSERT(initialized_);
Fredrik Solenberg4b60c732015-05-07 14:07:48 +0200326 ASSERT(worker_thread_ == rtc::Thread::Current());
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200327 ASSERT(nullptr != media_controller);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000328 VideoMediaChannel* media_channel =
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200329 media_engine_->CreateVideoChannel(media_controller->call_w(), options);
deadbeefcbecd352015-09-23 11:50:27 -0700330 if (media_channel == NULL) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000331 return NULL;
deadbeefcbecd352015-09-23 11:50:27 -0700332 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000333
334 VideoChannel* video_channel = new VideoChannel(
deadbeefcbecd352015-09-23 11:50:27 -0700335 worker_thread_, media_channel, transport_controller, content_name, rtcp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000336 if (!video_channel->Init()) {
337 delete video_channel;
338 return NULL;
339 }
340 video_channels_.push_back(video_channel);
341 return video_channel;
342}
343
344void ChannelManager::DestroyVideoChannel(VideoChannel* video_channel) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100345 TRACE_EVENT0("webrtc", "ChannelManager::DestroyVideoChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000346 if (video_channel) {
347 worker_thread_->Invoke<void>(
348 Bind(&ChannelManager::DestroyVideoChannel_w, this, video_channel));
349 }
350}
351
352void ChannelManager::DestroyVideoChannel_w(VideoChannel* video_channel) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100353 TRACE_EVENT0("webrtc", "ChannelManager::DestroyVideoChannel_w");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000354 // Destroy video channel.
355 ASSERT(initialized_);
Fredrik Solenberg4b60c732015-05-07 14:07:48 +0200356 ASSERT(worker_thread_ == rtc::Thread::Current());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000357 VideoChannels::iterator it = std::find(video_channels_.begin(),
358 video_channels_.end(), video_channel);
359 ASSERT(it != video_channels_.end());
360 if (it == video_channels_.end())
361 return;
362
363 video_channels_.erase(it);
364 delete video_channel;
365}
366
367DataChannel* ChannelManager::CreateDataChannel(
deadbeefcbecd352015-09-23 11:50:27 -0700368 TransportController* transport_controller,
369 const std::string& content_name,
370 bool rtcp,
371 DataChannelType channel_type) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000372 return worker_thread_->Invoke<DataChannel*>(
deadbeefcbecd352015-09-23 11:50:27 -0700373 Bind(&ChannelManager::CreateDataChannel_w, this, transport_controller,
374 content_name, rtcp, channel_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000375}
376
377DataChannel* ChannelManager::CreateDataChannel_w(
deadbeefcbecd352015-09-23 11:50:27 -0700378 TransportController* transport_controller,
379 const std::string& content_name,
380 bool rtcp,
381 DataChannelType data_channel_type) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000382 // This is ok to alloc from a thread other than the worker thread.
383 ASSERT(initialized_);
384 DataMediaChannel* media_channel = data_media_engine_->CreateChannel(
385 data_channel_type);
386 if (!media_channel) {
387 LOG(LS_WARNING) << "Failed to create data channel of type "
388 << data_channel_type;
389 return NULL;
390 }
391
392 DataChannel* data_channel = new DataChannel(
deadbeefcbecd352015-09-23 11:50:27 -0700393 worker_thread_, media_channel, transport_controller, content_name, rtcp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000394 if (!data_channel->Init()) {
395 LOG(LS_WARNING) << "Failed to init data channel.";
396 delete data_channel;
397 return NULL;
398 }
399 data_channels_.push_back(data_channel);
400 return data_channel;
401}
402
403void ChannelManager::DestroyDataChannel(DataChannel* data_channel) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100404 TRACE_EVENT0("webrtc", "ChannelManager::DestroyDataChannel");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000405 if (data_channel) {
406 worker_thread_->Invoke<void>(
407 Bind(&ChannelManager::DestroyDataChannel_w, this, data_channel));
408 }
409}
410
411void ChannelManager::DestroyDataChannel_w(DataChannel* data_channel) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100412 TRACE_EVENT0("webrtc", "ChannelManager::DestroyDataChannel_w");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000413 // Destroy data channel.
414 ASSERT(initialized_);
415 DataChannels::iterator it = std::find(data_channels_.begin(),
416 data_channels_.end(), data_channel);
417 ASSERT(it != data_channels_.end());
418 if (it == data_channels_.end())
419 return;
420
421 data_channels_.erase(it);
422 delete data_channel;
423}
424
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000425bool ChannelManager::GetOutputVolume(int* level) {
426 if (!initialized_) {
427 return false;
428 }
429 return worker_thread_->Invoke<bool>(
430 Bind(&MediaEngineInterface::GetOutputVolume, media_engine_.get(), level));
431}
432
433bool ChannelManager::SetOutputVolume(int level) {
434 bool ret = level >= 0 && level <= 255;
435 if (initialized_) {
436 ret &= worker_thread_->Invoke<bool>(
437 Bind(&MediaEngineInterface::SetOutputVolume,
438 media_engine_.get(), level));
439 }
440
441 if (ret) {
442 audio_output_volume_ = level;
443 }
444
445 return ret;
446}
447
hbos@webrtc.org1e642632015-02-25 09:49:41 +0000448std::vector<cricket::VideoFormat> ChannelManager::GetSupportedFormats(
449 VideoCapturer* capturer) const {
450 ASSERT(capturer != NULL);
451 std::vector<VideoFormat> formats;
452 worker_thread_->Invoke<void>(rtc::Bind(&ChannelManager::GetSupportedFormats_w,
453 this, capturer, &formats));
454 return formats;
455}
456
457void ChannelManager::GetSupportedFormats_w(
458 VideoCapturer* capturer,
459 std::vector<cricket::VideoFormat>* out_formats) const {
460 const std::vector<VideoFormat>* formats = capturer->GetSupportedFormats();
461 if (formats != NULL)
462 *out_formats = *formats;
463}
464
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000465// The following are done in the new "CaptureManager" style that
466// all local video capturers, processors, and managers should move
467// to.
468// TODO(pthatcher): Add more of the CaptureManager interface.
469bool ChannelManager::StartVideoCapture(
470 VideoCapturer* capturer, const VideoFormat& video_format) {
471 return initialized_ && worker_thread_->Invoke<bool>(
472 Bind(&CaptureManager::StartVideoCapture,
473 capture_manager_.get(), capturer, video_format));
474}
475
476bool ChannelManager::MuteToBlackThenPause(
477 VideoCapturer* video_capturer, bool muted) {
478 if (!initialized_) {
479 return false;
480 }
481 worker_thread_->Invoke<void>(
482 Bind(&VideoCapturer::MuteToBlackThenPause, video_capturer, muted));
483 return true;
484}
485
486bool ChannelManager::StopVideoCapture(
487 VideoCapturer* capturer, const VideoFormat& video_format) {
488 return initialized_ && worker_thread_->Invoke<bool>(
489 Bind(&CaptureManager::StopVideoCapture,
490 capture_manager_.get(), capturer, video_format));
491}
492
493bool ChannelManager::RestartVideoCapture(
494 VideoCapturer* video_capturer,
495 const VideoFormat& previous_format,
496 const VideoFormat& desired_format,
497 CaptureManager::RestartOptions options) {
498 return initialized_ && worker_thread_->Invoke<bool>(
499 Bind(&CaptureManager::RestartVideoCapture, capture_manager_.get(),
500 video_capturer, previous_format, desired_format, options));
501}
502
503bool ChannelManager::AddVideoRenderer(
504 VideoCapturer* capturer, VideoRenderer* renderer) {
505 return initialized_ && worker_thread_->Invoke<bool>(
506 Bind(&CaptureManager::AddVideoRenderer,
507 capture_manager_.get(), capturer, renderer));
508}
509
510bool ChannelManager::RemoveVideoRenderer(
511 VideoCapturer* capturer, VideoRenderer* renderer) {
512 return initialized_ && worker_thread_->Invoke<bool>(
513 Bind(&CaptureManager::RemoveVideoRenderer,
514 capture_manager_.get(), capturer, renderer));
515}
516
517bool ChannelManager::IsScreencastRunning() const {
518 return initialized_ && worker_thread_->Invoke<bool>(
519 Bind(&ChannelManager::IsScreencastRunning_w, this));
520}
521
522bool ChannelManager::IsScreencastRunning_w() const {
523 VideoChannels::const_iterator it = video_channels_.begin();
524 for ( ; it != video_channels_.end(); ++it) {
525 if ((*it) && (*it)->IsScreencasting()) {
526 return true;
527 }
528 }
529 return false;
530}
531
532void ChannelManager::OnVideoCaptureStateChange(VideoCapturer* capturer,
533 CaptureState result) {
534 // TODO(whyuan): Check capturer and signal failure only for camera video, not
535 // screencast.
536 capturing_ = result == CS_RUNNING;
537 main_thread_->Post(this, MSG_VIDEOCAPTURESTATE,
538 new CaptureStateParams(capturer, result));
539}
540
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000541void ChannelManager::OnMessage(rtc::Message* message) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000542 switch (message->message_id) {
543 case MSG_VIDEOCAPTURESTATE: {
544 CaptureStateParams* data =
545 static_cast<CaptureStateParams*>(message->pdata);
546 SignalVideoCaptureStateChange(data->capturer, data->state);
547 delete data;
548 break;
549 }
550 }
551}
552
ivocd66b44d2016-01-15 03:06:36 -0800553bool ChannelManager::StartAecDump(rtc::PlatformFile file,
554 int64_t max_size_bytes) {
555 return worker_thread_->Invoke<bool>(Bind(&MediaEngineInterface::StartAecDump,
556 media_engine_.get(), file,
557 max_size_bytes));
wu@webrtc.orga9890802013-12-13 00:21:03 +0000558}
559
ivoc797ef122015-10-22 03:25:41 -0700560void ChannelManager::StopAecDump() {
561 worker_thread_->Invoke<void>(
562 Bind(&MediaEngineInterface::StopAecDump, media_engine_.get()));
563}
564
ivoc112a3d82015-10-16 02:22:18 -0700565bool ChannelManager::StartRtcEventLog(rtc::PlatformFile file) {
566 return worker_thread_->Invoke<bool>(
567 Bind(&MediaEngineInterface::StartRtcEventLog, media_engine_.get(), file));
568}
569
570void ChannelManager::StopRtcEventLog() {
571 worker_thread_->Invoke<void>(
572 Bind(&MediaEngineInterface::StopRtcEventLog, media_engine_.get()));
573}
574
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000575} // namespace cricket