blob: 17e47512b43680ab782e5c5e0c24ff657b05979c [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellander65c7f672016-02-12 00:05:01 -08002 * Copyright 2004 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellander65c7f672016-02-12 00:05:01 -08004 * 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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
Steve Anton10542f22019-01-11 09:11:00 -080011#include "pc/channel_manager.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012
Steve Anton36b29d12017-10-30 09:57:42 -070013#include <utility>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000014
Steve Anton64b626b2019-01-28 17:25:26 -080015#include "absl/algorithm/container.h"
Karl Wiberg918f50c2018-07-05 11:40:33 +020016#include "absl/memory/memory.h"
Niels Möller3c7d5992018-10-19 15:29:54 +020017#include "absl/strings/match.h"
Steve Anton10542f22019-01-11 09:11:00 -080018#include "media/base/media_constants.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "rtc_base/checks.h"
Yves Gerey3e707812018-11-28 16:47:49 +010020#include "rtc_base/location.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "rtc_base/logging.h"
Yves Gerey3e707812018-11-28 16:47:49 +010022#include "rtc_base/thread_checker.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "rtc_base/trace_event.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000024
25namespace cricket {
26
Steve Antonc9e15602017-11-06 15:40:09 -080027ChannelManager::ChannelManager(
28 std::unique_ptr<MediaEngineInterface> media_engine,
29 std::unique_ptr<DataEngineInterface> data_engine,
30 rtc::Thread* worker_thread,
31 rtc::Thread* network_thread)
32 : media_engine_(std::move(media_engine)),
33 data_engine_(std::move(data_engine)),
34 main_thread_(rtc::Thread::Current()),
35 worker_thread_(worker_thread),
36 network_thread_(network_thread) {
37 RTC_DCHECK(data_engine_);
38 RTC_DCHECK(worker_thread_);
39 RTC_DCHECK(network_thread_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000040}
41
42ChannelManager::~ChannelManager() {
wu@webrtc.org9dba5252013-08-05 20:36:57 +000043 if (initialized_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000044 Terminate();
wu@webrtc.org9dba5252013-08-05 20:36:57 +000045 }
perkjc11b1842016-03-07 17:34:13 -080046 // The media engine needs to be deleted on the worker thread for thread safe
47 // destruction,
Steve Antonc9e15602017-11-06 15:40:09 -080048 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] { media_engine_.reset(); });
henrike@webrtc.org28e20752013-07-10 00:45:36 +000049}
50
51bool ChannelManager::SetVideoRtxEnabled(bool enable) {
52 // To be safe, this call is only allowed before initialization. Apps like
53 // Flute only have a singleton ChannelManager and we don't want this flag to
54 // be toggled between calls or when there's concurrent calls. We expect apps
55 // to enable this at startup and retain that setting for the lifetime of the
56 // app.
57 if (!initialized_) {
58 enable_rtx_ = enable;
59 return true;
60 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +010061 RTC_LOG(LS_WARNING) << "Cannot toggle rtx after initialization!";
henrike@webrtc.org28e20752013-07-10 00:45:36 +000062 return false;
63 }
64}
65
ossudedfd282016-06-14 07:12:39 -070066void ChannelManager::GetSupportedAudioSendCodecs(
henrike@webrtc.org28e20752013-07-10 00:45:36 +000067 std::vector<AudioCodec>* codecs) const {
zhihuang38ede132017-06-15 12:52:32 -070068 if (!media_engine_) {
69 return;
70 }
Sebastian Jansson6eb8a162018-11-16 11:29:55 +010071 *codecs = media_engine_->voice().send_codecs();
ossudedfd282016-06-14 07:12:39 -070072}
henrike@webrtc.org28e20752013-07-10 00:45:36 +000073
ossudedfd282016-06-14 07:12:39 -070074void ChannelManager::GetSupportedAudioReceiveCodecs(
75 std::vector<AudioCodec>* codecs) const {
zhihuang38ede132017-06-15 12:52:32 -070076 if (!media_engine_) {
77 return;
78 }
Sebastian Jansson6eb8a162018-11-16 11:29:55 +010079 *codecs = media_engine_->voice().recv_codecs();
henrike@webrtc.org28e20752013-07-10 00:45:36 +000080}
81
Johannes Kron8e8b36a2020-02-07 14:23:45 +000082void ChannelManager::GetSupportedVideoCodecs(
magjed3cf8ece2016-11-10 03:36:53 -080083 std::vector<VideoCodec>* codecs) const {
zhihuang38ede132017-06-15 12:52:32 -070084 if (!media_engine_) {
85 return;
86 }
magjed3cf8ece2016-11-10 03:36:53 -080087 codecs->clear();
88
Johannes Kron8e8b36a2020-02-07 14:23:45 +000089 std::vector<VideoCodec> video_codecs = media_engine_->video().codecs();
brandtrffc61182016-11-28 06:02:22 -080090 for (const auto& video_codec : video_codecs) {
91 if (!enable_rtx_ &&
Niels Möller3c7d5992018-10-19 15:29:54 +020092 absl::EqualsIgnoreCase(kRtxCodecName, video_codec.name)) {
magjed3cf8ece2016-11-10 03:36:53 -080093 continue;
94 }
brandtrffc61182016-11-28 06:02:22 -080095 codecs->push_back(video_codec);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000096 }
97}
98
henrike@webrtc.org28e20752013-07-10 00:45:36 +000099void ChannelManager::GetSupportedDataCodecs(
100 std::vector<DataCodec>* codecs) const {
Steve Antonc9e15602017-11-06 15:40:09 -0800101 *codecs = data_engine_->data_codecs();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000102}
103
104bool ChannelManager::Init() {
nisseede5da42017-01-12 05:15:36 -0800105 RTC_DCHECK(!initialized_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000106 if (initialized_) {
107 return false;
108 }
Danil Chapovalov33b01f22016-05-11 19:55:27 +0200109 RTC_DCHECK(network_thread_);
110 RTC_DCHECK(worker_thread_);
111 if (!network_thread_->IsCurrent()) {
112 // Do not allow invoking calls to other threads on the network thread.
Steve Antonc9e15602017-11-06 15:40:09 -0800113 network_thread_->Invoke<void>(
Karl Wiberg32562252019-02-21 13:38:30 +0100114 RTC_FROM_HERE, [&] { network_thread_->DisallowBlockingCalls(); });
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000115 }
116
zhihuang38ede132017-06-15 12:52:32 -0700117 if (media_engine_) {
Steve Antonc9e15602017-11-06 15:40:09 -0800118 initialized_ = worker_thread_->Invoke<bool>(
119 RTC_FROM_HERE, [&] { return media_engine_->Init(); });
120 RTC_DCHECK(initialized_);
121 } else {
122 initialized_ = true;
zhihuang38ede132017-06-15 12:52:32 -0700123 }
Steve Antonc9e15602017-11-06 15:40:09 -0800124 return initialized_;
henrika@webrtc.org62f6e752015-02-11 08:38:35 +0000125}
126
Markus Handell0357b3e2020-03-16 13:40:51 +0100127RtpHeaderExtensions ChannelManager::GetDefaultEnabledAudioRtpHeaderExtensions()
128 const {
129 if (!media_engine_)
130 return {};
131 return GetDefaultEnabledRtpHeaderExtensions(media_engine_->voice());
132}
133
134std::vector<webrtc::RtpHeaderExtensionCapability>
135ChannelManager::GetSupportedAudioRtpHeaderExtensions() const {
136 if (!media_engine_)
137 return {};
138 return media_engine_->voice().GetRtpHeaderExtensions();
139}
140
141RtpHeaderExtensions ChannelManager::GetDefaultEnabledVideoRtpHeaderExtensions()
142 const {
143 if (!media_engine_)
144 return {};
145 return GetDefaultEnabledRtpHeaderExtensions(media_engine_->video());
146}
147
148std::vector<webrtc::RtpHeaderExtensionCapability>
149ChannelManager::GetSupportedVideoRtpHeaderExtensions() const {
150 if (!media_engine_)
151 return {};
152 return media_engine_->video().GetRtpHeaderExtensions();
153}
154
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000155void ChannelManager::Terminate() {
nisseede5da42017-01-12 05:15:36 -0800156 RTC_DCHECK(initialized_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000157 if (!initialized_) {
158 return;
159 }
Steve Antonc9e15602017-11-06 15:40:09 -0800160 // Need to destroy the channels on the worker thread.
161 worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
162 video_channels_.clear();
163 voice_channels_.clear();
164 data_channels_.clear();
165 });
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000166 initialized_ = false;
167}
168
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000169VoiceChannel* ChannelManager::CreateVoiceChannel(
nisseeaabdf62017-05-05 02:23:02 -0700170 webrtc::Call* call,
171 const cricket::MediaConfig& media_config,
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800172 webrtc::RtpTransportInternal* rtp_transport,
Anton Sukhanov4f08faa2019-05-21 11:12:57 -0700173 const webrtc::MediaTransportConfig& media_transport_config,
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800174 rtc::Thread* signaling_thread,
175 const std::string& content_name,
176 bool srtp_required,
Benjamin Wrighta54daf12018-10-11 15:33:17 -0700177 const webrtc::CryptoOptions& crypto_options,
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800178 rtc::UniqueRandomIdGenerator* ssrc_generator,
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800179 const AudioOptions& options) {
180 if (!worker_thread_->IsCurrent()) {
181 return worker_thread_->Invoke<VoiceChannel*>(RTC_FROM_HERE, [&] {
Anton Sukhanov4f08faa2019-05-21 11:12:57 -0700182 return CreateVoiceChannel(call, media_config, rtp_transport,
183 media_transport_config, signaling_thread,
184 content_name, srtp_required, crypto_options,
185 ssrc_generator, options);
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800186 });
187 }
188
189 RTC_DCHECK_RUN_ON(worker_thread_);
190 RTC_DCHECK(initialized_);
191 RTC_DCHECK(call);
192 if (!media_engine_) {
193 return nullptr;
194 }
195
Sebastian Jansson6eb8a162018-11-16 11:29:55 +0100196 VoiceMediaChannel* media_channel = media_engine_->voice().CreateMediaChannel(
197 call, media_config, options, crypto_options);
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800198 if (!media_channel) {
199 return nullptr;
200 }
201
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200202 auto voice_channel = std::make_unique<VoiceChannel>(
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800203 worker_thread_, network_thread_, signaling_thread,
Karl Wiberg918f50c2018-07-05 11:40:33 +0200204 absl::WrapUnique(media_channel), content_name, srtp_required,
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800205 crypto_options, ssrc_generator);
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800206
Anton Sukhanov4f08faa2019-05-21 11:12:57 -0700207 voice_channel->Init_w(rtp_transport, media_transport_config);
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800208
209 VoiceChannel* voice_channel_ptr = voice_channel.get();
210 voice_channels_.push_back(std::move(voice_channel));
211 return voice_channel_ptr;
212}
213
Fredrik Solenberg709ed672015-09-15 12:26:33 +0200214void ChannelManager::DestroyVoiceChannel(VoiceChannel* voice_channel) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100215 TRACE_EVENT0("webrtc", "ChannelManager::DestroyVoiceChannel");
Steve Antonc9e15602017-11-06 15:40:09 -0800216 if (!voice_channel) {
217 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000218 }
Steve Antonc9e15602017-11-06 15:40:09 -0800219 if (!worker_thread_->IsCurrent()) {
220 worker_thread_->Invoke<void>(RTC_FROM_HERE,
221 [&] { DestroyVoiceChannel(voice_channel); });
222 return;
223 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000224
nisseede5da42017-01-12 05:15:36 -0800225 RTC_DCHECK(initialized_);
Steve Anton774115c2017-08-30 10:48:46 -0700226
Steve Anton64b626b2019-01-28 17:25:26 -0800227 auto it = absl::c_find_if(voice_channels_,
228 [&](const std::unique_ptr<VoiceChannel>& p) {
229 return p.get() == voice_channel;
230 });
nisseede5da42017-01-12 05:15:36 -0800231 RTC_DCHECK(it != voice_channels_.end());
Steve Antonc9e15602017-11-06 15:40:09 -0800232 if (it == voice_channels_.end()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000233 return;
Steve Antonc9e15602017-11-06 15:40:09 -0800234 }
235
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000236 voice_channels_.erase(it);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000237}
238
239VideoChannel* ChannelManager::CreateVideoChannel(
nisseeaabdf62017-05-05 02:23:02 -0700240 webrtc::Call* call,
241 const cricket::MediaConfig& media_config,
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800242 webrtc::RtpTransportInternal* rtp_transport,
Anton Sukhanov4f08faa2019-05-21 11:12:57 -0700243 const webrtc::MediaTransportConfig& media_transport_config,
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800244 rtc::Thread* signaling_thread,
245 const std::string& content_name,
246 bool srtp_required,
Benjamin Wrighta54daf12018-10-11 15:33:17 -0700247 const webrtc::CryptoOptions& crypto_options,
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800248 rtc::UniqueRandomIdGenerator* ssrc_generator,
Jonas Orelanda3aa9bd2019-04-17 07:38:40 +0200249 const VideoOptions& options,
250 webrtc::VideoBitrateAllocatorFactory* video_bitrate_allocator_factory) {
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800251 if (!worker_thread_->IsCurrent()) {
252 return worker_thread_->Invoke<VideoChannel*>(RTC_FROM_HERE, [&] {
Anton Sukhanov4f08faa2019-05-21 11:12:57 -0700253 return CreateVideoChannel(
254 call, media_config, rtp_transport, media_transport_config,
255 signaling_thread, content_name, srtp_required, crypto_options,
256 ssrc_generator, options, video_bitrate_allocator_factory);
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800257 });
258 }
259
260 RTC_DCHECK_RUN_ON(worker_thread_);
261 RTC_DCHECK(initialized_);
262 RTC_DCHECK(call);
263 if (!media_engine_) {
264 return nullptr;
265 }
266
Sebastian Jansson6eb8a162018-11-16 11:29:55 +0100267 VideoMediaChannel* media_channel = media_engine_->video().CreateMediaChannel(
Jonas Orelanda3aa9bd2019-04-17 07:38:40 +0200268 call, media_config, options, crypto_options,
269 video_bitrate_allocator_factory);
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800270 if (!media_channel) {
271 return nullptr;
272 }
273
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200274 auto video_channel = std::make_unique<VideoChannel>(
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800275 worker_thread_, network_thread_, signaling_thread,
Karl Wiberg918f50c2018-07-05 11:40:33 +0200276 absl::WrapUnique(media_channel), content_name, srtp_required,
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800277 crypto_options, ssrc_generator);
Anton Sukhanov98a462c2018-10-17 13:15:42 -0700278
Anton Sukhanov4f08faa2019-05-21 11:12:57 -0700279 video_channel->Init_w(rtp_transport, media_transport_config);
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800280
281 VideoChannel* video_channel_ptr = video_channel.get();
282 video_channels_.push_back(std::move(video_channel));
283 return video_channel_ptr;
284}
285
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000286void ChannelManager::DestroyVideoChannel(VideoChannel* video_channel) {
Peter Boström1a9d6152015-12-08 22:15:17 +0100287 TRACE_EVENT0("webrtc", "ChannelManager::DestroyVideoChannel");
Steve Antonc9e15602017-11-06 15:40:09 -0800288 if (!video_channel) {
289 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000290 }
Steve Antonc9e15602017-11-06 15:40:09 -0800291 if (!worker_thread_->IsCurrent()) {
292 worker_thread_->Invoke<void>(RTC_FROM_HERE,
293 [&] { DestroyVideoChannel(video_channel); });
294 return;
295 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000296
nisseede5da42017-01-12 05:15:36 -0800297 RTC_DCHECK(initialized_);
Steve Anton774115c2017-08-30 10:48:46 -0700298
Steve Anton64b626b2019-01-28 17:25:26 -0800299 auto it = absl::c_find_if(video_channels_,
300 [&](const std::unique_ptr<VideoChannel>& p) {
301 return p.get() == video_channel;
302 });
nisseede5da42017-01-12 05:15:36 -0800303 RTC_DCHECK(it != video_channels_.end());
Steve Antonc9e15602017-11-06 15:40:09 -0800304 if (it == video_channels_.end()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000305 return;
Steve Antonc9e15602017-11-06 15:40:09 -0800306 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000307
308 video_channels_.erase(it);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000309}
310
deadbeef953c2ce2017-01-09 14:53:41 -0800311RtpDataChannel* ChannelManager::CreateRtpDataChannel(
nisseeaabdf62017-05-05 02:23:02 -0700312 const cricket::MediaConfig& media_config,
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800313 webrtc::RtpTransportInternal* rtp_transport,
314 rtc::Thread* signaling_thread,
315 const std::string& content_name,
Zhi Huange830e682018-03-30 10:48:35 -0700316 bool srtp_required,
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800317 const webrtc::CryptoOptions& crypto_options,
318 rtc::UniqueRandomIdGenerator* ssrc_generator) {
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800319 if (!worker_thread_->IsCurrent()) {
320 return worker_thread_->Invoke<RtpDataChannel*>(RTC_FROM_HERE, [&] {
321 return CreateRtpDataChannel(media_config, rtp_transport, signaling_thread,
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800322 content_name, srtp_required, crypto_options,
323 ssrc_generator);
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800324 });
325 }
326
327 // This is ok to alloc from a thread other than the worker thread.
328 RTC_DCHECK(initialized_);
329 DataMediaChannel* media_channel = data_engine_->CreateChannel(media_config);
330 if (!media_channel) {
331 RTC_LOG(LS_WARNING) << "Failed to create RTP data channel.";
332 return nullptr;
333 }
334
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200335 auto data_channel = std::make_unique<RtpDataChannel>(
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800336 worker_thread_, network_thread_, signaling_thread,
Karl Wiberg918f50c2018-07-05 11:40:33 +0200337 absl::WrapUnique(media_channel), content_name, srtp_required,
Amit Hilbuchbcd39d42019-01-25 17:13:56 -0800338 crypto_options, ssrc_generator);
Anton Sukhanov4f08faa2019-05-21 11:12:57 -0700339
340 // Media Transports are not supported with Rtp Data Channel.
341 data_channel->Init_w(rtp_transport, webrtc::MediaTransportConfig());
Zhi Huang2dfc42d2017-12-04 13:38:48 -0800342
343 RtpDataChannel* data_channel_ptr = data_channel.get();
344 data_channels_.push_back(std::move(data_channel));
345 return data_channel_ptr;
346}
347
deadbeef953c2ce2017-01-09 14:53:41 -0800348void ChannelManager::DestroyRtpDataChannel(RtpDataChannel* data_channel) {
349 TRACE_EVENT0("webrtc", "ChannelManager::DestroyRtpDataChannel");
Steve Antonc9e15602017-11-06 15:40:09 -0800350 if (!data_channel) {
351 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000352 }
Steve Antonc9e15602017-11-06 15:40:09 -0800353 if (!worker_thread_->IsCurrent()) {
354 worker_thread_->Invoke<void>(
355 RTC_FROM_HERE, [&] { return DestroyRtpDataChannel(data_channel); });
356 return;
357 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000358
nisseede5da42017-01-12 05:15:36 -0800359 RTC_DCHECK(initialized_);
Steve Anton774115c2017-08-30 10:48:46 -0700360
Steve Anton64b626b2019-01-28 17:25:26 -0800361 auto it = absl::c_find_if(data_channels_,
362 [&](const std::unique_ptr<RtpDataChannel>& p) {
363 return p.get() == data_channel;
364 });
nisseede5da42017-01-12 05:15:36 -0800365 RTC_DCHECK(it != data_channels_.end());
Steve Antonc9e15602017-11-06 15:40:09 -0800366 if (it == data_channels_.end()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000367 return;
Steve Antonc9e15602017-11-06 15:40:09 -0800368 }
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000369
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000370 data_channels_.erase(it);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000371}
372
Niels Möllere8e4dc42019-06-11 14:04:16 +0200373bool ChannelManager::StartAecDump(webrtc::FileWrapper file,
ivocd66b44d2016-01-15 03:06:36 -0800374 int64_t max_size_bytes) {
Steve Antonc9e15602017-11-06 15:40:09 -0800375 return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
Niels Möllere8e4dc42019-06-11 14:04:16 +0200376 return media_engine_->voice().StartAecDump(std::move(file), max_size_bytes);
Steve Antonc9e15602017-11-06 15:40:09 -0800377 });
wu@webrtc.orga9890802013-12-13 00:21:03 +0000378}
379
ivoc797ef122015-10-22 03:25:41 -0700380void ChannelManager::StopAecDump() {
Steve Antonc9e15602017-11-06 15:40:09 -0800381 worker_thread_->Invoke<void>(RTC_FROM_HERE,
Sebastian Jansson6eb8a162018-11-16 11:29:55 +0100382 [&] { media_engine_->voice().StopAecDump(); });
ivoc797ef122015-10-22 03:25:41 -0700383}
384
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000385} // namespace cricket