blob: b39be5b2b253e4f853cb731176cf9bbe2a833a66 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellander1afca732016-02-07 20:46:45 -08002 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellander1afca732016-02-07 20:46:45 -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
henrike@webrtc.org28e20752013-07-10 00:45:36 +000011#ifdef HAVE_WEBRTC_VOICE
12
kjellander@webrtc.org5ad12972016-02-12 06:39:40 +010013#include "webrtc/media/engine/webrtcvoiceengine.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000014
15#include <algorithm>
16#include <cstdio>
ossuc54071d2016-08-17 02:45:41 -070017#include <functional>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000018#include <string>
19#include <vector>
20
kjellandera69d9732016-08-31 07:33:05 -070021#include "webrtc/api/call/audio_sink.h"
tfarina5237aaf2015-11-10 23:44:30 -080022#include "webrtc/base/arraysize.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000023#include "webrtc/base/base64.h"
24#include "webrtc/base/byteorder.h"
kwiberg4485ffb2016-04-26 08:14:39 -070025#include "webrtc/base/constructormagic.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000026#include "webrtc/base/helpers.h"
27#include "webrtc/base/logging.h"
solenberg347ec5c2016-09-23 04:21:47 -070028#include "webrtc/base/race_checker.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000029#include "webrtc/base/stringencode.h"
30#include "webrtc/base/stringutils.h"
Peter Boströmca8b4042016-03-08 14:24:13 -080031#include "webrtc/base/trace_event.h"
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -080032#include "webrtc/media/base/audiosource.h"
kjellanderf4752772016-03-02 05:42:30 -080033#include "webrtc/media/base/mediaconstants.h"
kjellandera96e2d72016-02-04 23:52:28 -080034#include "webrtc/media/base/streamparams.h"
solenberg9a5f032222017-03-15 06:14:12 -070035#include "webrtc/media/engine/adm_helpers.h"
solenberg76377c52017-02-21 00:54:31 -080036#include "webrtc/media/engine/apm_helpers.h"
ossuc54071d2016-08-17 02:45:41 -070037#include "webrtc/media/engine/payload_type_mapper.h"
kjellander@webrtc.org5ad12972016-02-12 06:39:40 +010038#include "webrtc/media/engine/webrtcmediaengine.h"
39#include "webrtc/media/engine/webrtcvoe.h"
aleloi10111bc2016-11-17 06:48:48 -080040#include "webrtc/modules/audio_mixer/audio_mixer_impl.h"
aleloi048cbdd2017-05-29 02:56:27 -070041#include "webrtc/modules/audio_processing/aec_dump/aec_dump_factory.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000042#include "webrtc/modules/audio_processing/include/audio_processing.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010043#include "webrtc/system_wrappers/include/field_trial.h"
solenberg2100c0b2017-03-01 11:29:29 -080044#include "webrtc/system_wrappers/include/metrics.h"
solenbergbd138382015-11-20 16:08:07 -080045#include "webrtc/system_wrappers/include/trace.h"
solenberg76377c52017-02-21 00:54:31 -080046#include "webrtc/voice_engine/transmit_mixer.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000047
henrike@webrtc.org28e20752013-07-10 00:45:36 +000048namespace cricket {
solenbergd97ec302015-10-07 01:40:33 -070049namespace {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000050
solenberg418b7d32017-06-13 00:38:27 -070051constexpr size_t kMaxUnsignaledRecvStreams = 4;
solenberg2100c0b2017-03-01 11:29:29 -080052
solenbergbd138382015-11-20 16:08:07 -080053const int kDefaultTraceFilter = webrtc::kTraceNone | webrtc::kTraceTerseInfo |
54 webrtc::kTraceWarning | webrtc::kTraceError |
55 webrtc::kTraceCritical;
56const int kElevatedTraceFilter = kDefaultTraceFilter | webrtc::kTraceStateInfo |
57 webrtc::kTraceInfo;
58
solenberg971cab02016-06-14 10:02:41 -070059constexpr int kNackRtpHistoryMs = 5000;
minyue@webrtc.org2dc6f312014-10-31 05:33:10 +000060
peah1bcfce52016-08-26 07:16:04 -070061// Check to verify that the define for the intelligibility enhancer is properly
62// set.
63#if !defined(WEBRTC_INTELLIGIBILITY_ENHANCER) || \
64 (WEBRTC_INTELLIGIBILITY_ENHANCER != 0 && \
65 WEBRTC_INTELLIGIBILITY_ENHANCER != 1)
66#error "Set WEBRTC_INTELLIGIBILITY_ENHANCER to either 0 or 1"
67#endif
68
ossu20a4b3f2017-04-27 02:08:52 -070069// For SendSideBwe, Opus bitrate should be in the range between 6000 and 32000.
minyue10cbb462016-11-07 09:29:22 -080070const int kOpusMinBitrateBps = 6000;
ossu20a4b3f2017-04-27 02:08:52 -070071const int kOpusBitrateFbBps = 32000;
deadbeef80346142016-04-27 14:17:10 -070072
wu@webrtc.orgde305012013-10-31 15:40:38 +000073// Default audio dscp value.
74// See http://tools.ietf.org/html/rfc2474 for details.
75// See also http://tools.ietf.org/html/draft-jennings-rtcweb-qos-00
solenbergd97ec302015-10-07 01:40:33 -070076const rtc::DiffServCodePoint kAudioDscpValue = rtc::DSCP_EF;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +000077
Fredrik Solenbergb5727682015-12-04 15:22:19 +010078// Constants from voice_engine_defines.h.
79const int kMinTelephoneEventCode = 0; // RFC4733 (Section 2.3.1)
80const int kMaxTelephoneEventCode = 255;
Fredrik Solenbergb5727682015-12-04 15:22:19 +010081
solenberg31642aa2016-03-14 08:00:37 -070082const int kMinPayloadType = 0;
83const int kMaxPayloadType = 127;
84
deadbeef884f5852016-01-15 09:20:04 -080085class ProxySink : public webrtc::AudioSinkInterface {
86 public:
87 ProxySink(AudioSinkInterface* sink) : sink_(sink) { RTC_DCHECK(sink); }
88
89 void OnData(const Data& audio) override { sink_->OnData(audio); }
90
91 private:
92 webrtc::AudioSinkInterface* sink_;
93};
94
solenberg0b675462015-10-09 01:37:09 -070095bool ValidateStreamParams(const StreamParams& sp) {
96 if (sp.ssrcs.empty()) {
97 LOG(LS_ERROR) << "No SSRCs in stream parameters: " << sp.ToString();
98 return false;
99 }
100 if (sp.ssrcs.size() > 1) {
101 LOG(LS_ERROR) << "Multiple SSRCs in stream parameters: " << sp.ToString();
102 return false;
103 }
104 return true;
105}
106
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000107// Dumps an AudioCodec in RFC 2327-ish format.
solenbergd97ec302015-10-07 01:40:33 -0700108std::string ToString(const AudioCodec& codec) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000109 std::stringstream ss;
ossu20a4b3f2017-04-27 02:08:52 -0700110 ss << codec.name << "/" << codec.clockrate << "/" << codec.channels;
111 if (!codec.params.empty()) {
112 ss << " {";
113 for (const auto& param : codec.params) {
114 ss << " " << param.first << "=" << param.second;
115 }
116 ss << " }";
117 }
118 ss << " (" << codec.id << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000119 return ss.str();
120}
Minyue Li7100dcd2015-03-27 05:05:59 +0100121
solenbergd97ec302015-10-07 01:40:33 -0700122bool IsCodec(const AudioCodec& codec, const char* ref_name) {
Minyue Li7100dcd2015-03-27 05:05:59 +0100123 return (_stricmp(codec.name.c_str(), ref_name) == 0);
124}
125
solenbergd97ec302015-10-07 01:40:33 -0700126bool FindCodec(const std::vector<AudioCodec>& codecs,
solenberg26c8c912015-11-27 04:00:25 -0800127 const AudioCodec& codec,
128 AudioCodec* found_codec) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +0200129 for (const AudioCodec& c : codecs) {
130 if (c.Matches(codec)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000131 if (found_codec != NULL) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +0200132 *found_codec = c;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000133 }
134 return true;
135 }
136 }
137 return false;
138}
wu@webrtc.org1d1ffc92013-10-16 18:12:02 +0000139
solenberg0b675462015-10-09 01:37:09 -0700140bool VerifyUniquePayloadTypes(const std::vector<AudioCodec>& codecs) {
141 if (codecs.empty()) {
142 return true;
143 }
144 std::vector<int> payload_types;
145 for (const AudioCodec& codec : codecs) {
146 payload_types.push_back(codec.id);
147 }
148 std::sort(payload_types.begin(), payload_types.end());
149 auto it = std::unique(payload_types.begin(), payload_types.end());
150 return it == payload_types.end();
151}
152
minyue6b825df2016-10-31 04:08:32 -0700153rtc::Optional<std::string> GetAudioNetworkAdaptorConfig(
154 const AudioOptions& options) {
155 if (options.audio_network_adaptor && *options.audio_network_adaptor &&
156 options.audio_network_adaptor_config) {
157 // Turn on audio network adaptor only when |options_.audio_network_adaptor|
158 // equals true and |options_.audio_network_adaptor_config| has a value.
159 return options.audio_network_adaptor_config;
160 }
161 return rtc::Optional<std::string>();
162}
163
gyzhou95aa9642016-12-13 14:06:26 -0800164webrtc::AudioState::Config MakeAudioStateConfig(
165 VoEWrapper* voe_wrapper,
166 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer) {
solenberg566ef242015-11-06 15:34:49 -0800167 webrtc::AudioState::Config config;
168 config.voice_engine = voe_wrapper->engine();
gyzhou95aa9642016-12-13 14:06:26 -0800169 if (audio_mixer) {
170 config.audio_mixer = audio_mixer;
171 } else {
172 config.audio_mixer = webrtc::AudioMixerImpl::Create();
173 }
solenberg566ef242015-11-06 15:34:49 -0800174 return config;
175}
176
deadbeefe702b302017-02-04 12:09:01 -0800177// |max_send_bitrate_bps| is the bitrate from "b=" in SDP.
178// |rtp_max_bitrate_bps| is the bitrate from RtpSender::SetParameters.
minyue7a973442016-10-20 03:27:12 -0700179rtc::Optional<int> ComputeSendBitrate(int max_send_bitrate_bps,
deadbeefe702b302017-02-04 12:09:01 -0800180 rtc::Optional<int> rtp_max_bitrate_bps,
ossu20a4b3f2017-04-27 02:08:52 -0700181 const webrtc::AudioCodecSpec& spec) {
deadbeefe702b302017-02-04 12:09:01 -0800182 // If application-configured bitrate is set, take minimum of that and SDP
183 // bitrate.
zsteina5e0df62017-06-14 11:41:48 -0700184 const int bps =
185 rtp_max_bitrate_bps
186 ? webrtc::MinPositive(max_send_bitrate_bps, *rtp_max_bitrate_bps)
187 : max_send_bitrate_bps;
minyue7a973442016-10-20 03:27:12 -0700188 if (bps <= 0) {
ossu20a4b3f2017-04-27 02:08:52 -0700189 return rtc::Optional<int>(spec.info.default_bitrate_bps);
solenberg971cab02016-06-14 10:02:41 -0700190 }
minyue7a973442016-10-20 03:27:12 -0700191
ossu20a4b3f2017-04-27 02:08:52 -0700192 if (bps < spec.info.min_bitrate_bps) {
minyue7a973442016-10-20 03:27:12 -0700193 // If codec is not multi-rate and |bps| is less than the fixed bitrate then
194 // fail. If codec is not multi-rate and |bps| exceeds or equal the fixed
195 // bitrate then ignore.
ossu20a4b3f2017-04-27 02:08:52 -0700196 LOG(LS_ERROR) << "Failed to set codec " << spec.format.name
minyue7a973442016-10-20 03:27:12 -0700197 << " to bitrate " << bps << " bps"
ossu20a4b3f2017-04-27 02:08:52 -0700198 << ", requires at least " << spec.info.min_bitrate_bps
199 << " bps.";
minyue7a973442016-10-20 03:27:12 -0700200 return rtc::Optional<int>();
solenberg971cab02016-06-14 10:02:41 -0700201 }
ossu20a4b3f2017-04-27 02:08:52 -0700202
203 if (spec.info.HasFixedBitrate()) {
204 return rtc::Optional<int>(spec.info.default_bitrate_bps);
205 } else {
206 // If codec is multi-rate then just set the bitrate.
207 return rtc::Optional<int>(std::min(bps, spec.info.max_bitrate_bps));
208 }
solenberg971cab02016-06-14 10:02:41 -0700209}
210
solenberg76377c52017-02-21 00:54:31 -0800211} // namespace
solenberg971cab02016-06-14 10:02:41 -0700212
ossu29b1a8d2016-06-13 07:34:51 -0700213WebRtcVoiceEngine::WebRtcVoiceEngine(
214 webrtc::AudioDeviceModule* adm,
ossueb1fde42017-05-02 06:46:30 -0700215 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -0800216 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
217 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer)
ossueb1fde42017-05-02 06:46:30 -0700218 : WebRtcVoiceEngine(adm,
219 encoder_factory,
220 decoder_factory,
221 audio_mixer,
deadbeefeb02c032017-06-15 08:29:25 -0700222 nullptr) {}
solenberg26c8c912015-11-27 04:00:25 -0800223
ossu29b1a8d2016-06-13 07:34:51 -0700224WebRtcVoiceEngine::WebRtcVoiceEngine(
225 webrtc::AudioDeviceModule* adm,
ossueb1fde42017-05-02 06:46:30 -0700226 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory,
ossu29b1a8d2016-06-13 07:34:51 -0700227 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -0800228 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
ossu29b1a8d2016-06-13 07:34:51 -0700229 VoEWrapper* voe_wrapper)
deadbeefeb02c032017-06-15 08:29:25 -0700230 : adm_(adm),
ossueb1fde42017-05-02 06:46:30 -0700231 encoder_factory_(encoder_factory),
ossu20a4b3f2017-04-27 02:08:52 -0700232 decoder_factory_(decoder_factory),
deadbeefeb02c032017-06-15 08:29:25 -0700233 audio_mixer_(audio_mixer),
ossu20a4b3f2017-04-27 02:08:52 -0700234 voe_wrapper_(voe_wrapper) {
deadbeefeb02c032017-06-15 08:29:25 -0700235 // This may be called from any thread, so detach thread checkers.
236 worker_thread_checker_.DetachFromThread();
solenberg26c8c912015-11-27 04:00:25 -0800237 signal_thread_checker_.DetachFromThread();
deadbeefeb02c032017-06-15 08:29:25 -0700238 LOG(LS_INFO) << "WebRtcVoiceEngine::WebRtcVoiceEngine";
239 RTC_DCHECK(decoder_factory);
240 RTC_DCHECK(encoder_factory);
241 // The rest of our initialization will happen in Init.
242}
243
244WebRtcVoiceEngine::~WebRtcVoiceEngine() {
245 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
246 LOG(LS_INFO) << "WebRtcVoiceEngine::~WebRtcVoiceEngine";
247 if (initialized_) {
248 StopAecDump();
249 voe_wrapper_->base()->Terminate();
250 webrtc::Trace::SetTraceCallback(nullptr);
251 }
252}
253
254void WebRtcVoiceEngine::Init() {
255 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
256 LOG(LS_INFO) << "WebRtcVoiceEngine::Init";
257
258 // TaskQueue expects to be created/destroyed on the same thread.
259 low_priority_worker_queue_.reset(
260 new rtc::TaskQueue("rtc-low-prio", rtc::TaskQueue::Priority::LOW));
261
262 // VoEWrapper needs to be created on the worker thread. It's expected to be
263 // null here unless it's being injected for testing.
264 if (!voe_wrapper_) {
265 voe_wrapper_.reset(new VoEWrapper());
266 }
solenberg26c8c912015-11-27 04:00:25 -0800267
ossueb1fde42017-05-02 06:46:30 -0700268 // Load our audio codec lists.
ossuc54071d2016-08-17 02:45:41 -0700269 LOG(LS_INFO) << "Supported send codecs in order of preference:";
ossu20a4b3f2017-04-27 02:08:52 -0700270 send_codecs_ = CollectCodecs(encoder_factory_->GetSupportedEncoders());
ossuc54071d2016-08-17 02:45:41 -0700271 for (const AudioCodec& codec : send_codecs_) {
272 LOG(LS_INFO) << ToString(codec);
273 }
274
275 LOG(LS_INFO) << "Supported recv codecs in order of preference:";
ossu20a4b3f2017-04-27 02:08:52 -0700276 recv_codecs_ = CollectCodecs(decoder_factory_->GetSupportedDecoders());
ossuc54071d2016-08-17 02:45:41 -0700277 for (const AudioCodec& codec : recv_codecs_) {
solenbergff976312016-03-30 23:28:51 -0700278 LOG(LS_INFO) << ToString(codec);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000279 }
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000280
solenberg88499ec2016-09-07 07:34:41 -0700281 channel_config_.enable_voice_pacing = true;
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000282
solenbergff976312016-03-30 23:28:51 -0700283 // Temporarily turn logging level up for the Init() call.
284 webrtc::Trace::SetTraceCallback(this);
solenbergbd138382015-11-20 16:08:07 -0800285 webrtc::Trace::set_level_filter(kElevatedTraceFilter);
solenberg2515af22015-12-02 06:19:36 -0800286 LOG(LS_INFO) << webrtc::VoiceEngine::GetVersionString();
ossu29b1a8d2016-06-13 07:34:51 -0700287 RTC_CHECK_EQ(0, voe_wrapper_->base()->Init(adm_.get(), nullptr,
288 decoder_factory_));
solenbergbd138382015-11-20 16:08:07 -0800289 webrtc::Trace::set_level_filter(kDefaultTraceFilter);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000290
solenbergff976312016-03-30 23:28:51 -0700291 // No ADM supplied? Get the default one from VoE.
292 if (!adm_) {
293 adm_ = voe_wrapper_->base()->audio_device_module();
294 }
295 RTC_DCHECK(adm_);
296
solenberg059fb442016-10-26 05:12:24 -0700297 apm_ = voe_wrapper_->base()->audio_processing();
298 RTC_DCHECK(apm_);
299
solenberg76377c52017-02-21 00:54:31 -0800300 transmit_mixer_ = voe_wrapper_->base()->transmit_mixer();
301 RTC_DCHECK(transmit_mixer_);
302
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000303 // Save the default AGC configuration settings. This must happen before
solenberg246b8172015-12-08 09:50:23 -0800304 // calling ApplyOptions or the default will be overwritten.
solenberg76377c52017-02-21 00:54:31 -0800305 default_agc_config_ = webrtc::apm_helpers::GetAgcConfig(apm_);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000306
solenberg0f7d2932016-01-15 01:40:39 -0800307 // Set default engine options.
308 {
309 AudioOptions options;
310 options.echo_cancellation = rtc::Optional<bool>(true);
311 options.auto_gain_control = rtc::Optional<bool>(true);
312 options.noise_suppression = rtc::Optional<bool>(true);
313 options.highpass_filter = rtc::Optional<bool>(true);
314 options.stereo_swapping = rtc::Optional<bool>(false);
315 options.audio_jitter_buffer_max_packets = rtc::Optional<int>(50);
316 options.audio_jitter_buffer_fast_accelerate = rtc::Optional<bool>(false);
317 options.typing_detection = rtc::Optional<bool>(true);
318 options.adjust_agc_delta = rtc::Optional<int>(0);
319 options.experimental_agc = rtc::Optional<bool>(false);
320 options.extended_filter_aec = rtc::Optional<bool>(false);
321 options.delay_agnostic_aec = rtc::Optional<bool>(false);
322 options.experimental_ns = rtc::Optional<bool>(false);
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700323 options.intelligibility_enhancer = rtc::Optional<bool>(false);
peaha3333bf2016-06-30 00:02:34 -0700324 options.level_control = rtc::Optional<bool>(false);
ivocb829d9f2016-11-15 02:34:47 -0800325 options.residual_echo_detector = rtc::Optional<bool>(true);
solenbergff976312016-03-30 23:28:51 -0700326 bool error = ApplyOptions(options);
327 RTC_DCHECK(error);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000328 }
329
solenberg9a5f032222017-03-15 06:14:12 -0700330 // Set default audio devices.
331#if !defined(WEBRTC_IOS)
332 webrtc::adm_helpers::SetRecordingDevice(adm_);
333 apm()->Initialize();
334 webrtc::adm_helpers::SetPlayoutDevice(adm_);
335#endif // !WEBRTC_IOS
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000336
deadbeefeb02c032017-06-15 08:29:25 -0700337 // May be null for VoE injected for testing.
338 if (voe()->engine()) {
339 audio_state_ =
340 webrtc::AudioState::Create(MakeAudioStateConfig(voe(), audio_mixer_));
341 }
342
343 initialized_ = true;
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000344}
345
solenberg566ef242015-11-06 15:34:49 -0800346rtc::scoped_refptr<webrtc::AudioState>
347 WebRtcVoiceEngine::GetAudioState() const {
348 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
349 return audio_state_;
350}
351
nisse51542be2016-02-12 02:27:06 -0800352VoiceMediaChannel* WebRtcVoiceEngine::CreateChannel(
353 webrtc::Call* call,
354 const MediaConfig& config,
Jelena Marusicc28a8962015-05-29 15:05:44 +0200355 const AudioOptions& options) {
solenberg566ef242015-11-06 15:34:49 -0800356 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
nisse51542be2016-02-12 02:27:06 -0800357 return new WebRtcVoiceMediaChannel(this, config, options, call);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000358}
359
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000360bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
solenberg566ef242015-11-06 15:34:49 -0800361 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergff976312016-03-30 23:28:51 -0700362 LOG(LS_INFO) << "WebRtcVoiceEngine::ApplyOptions: " << options_in.ToString();
solenberg0f7d2932016-01-15 01:40:39 -0800363 AudioOptions options = options_in; // The options are modified below.
solenberg246b8172015-12-08 09:50:23 -0800364
peah8a8ebd92017-05-22 15:48:47 -0700365 // Set and adjust echo canceller options.
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000366 // kEcConference is AEC with high suppression.
367 webrtc::EcModes ec_mode = webrtc::kEcConference;
kwiberg102c6a62015-10-30 02:47:38 -0700368 if (options.aecm_generate_comfort_noise) {
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000369 LOG(LS_VERBOSE) << "Comfort noise explicitly set to "
kwiberg102c6a62015-10-30 02:47:38 -0700370 << *options.aecm_generate_comfort_noise
371 << " (default is false).";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000372 }
373
kjellanderfcfc8042016-01-14 11:01:09 -0800374#if defined(WEBRTC_IOS)
peah8a8ebd92017-05-22 15:48:47 -0700375 // On iOS, VPIO provides built-in EC.
Karl Wibergbe579832015-11-10 22:34:18 +0100376 options.echo_cancellation = rtc::Optional<bool>(false);
peah8a8ebd92017-05-22 15:48:47 -0700377 options.extended_filter_aec = rtc::Optional<bool>(false);
378 LOG(LS_INFO) << "Always disable AEC on iOS. Use built-in instead.";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000379#elif defined(ANDROID)
380 ec_mode = webrtc::kEcAecm;
Karl Wibergbe579832015-11-10 22:34:18 +0100381 options.extended_filter_aec = rtc::Optional<bool>(false);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000382#endif
383
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100384 // Delay Agnostic AEC automatically turns on EC if not set except on iOS
385 // where the feature is not supported.
386 bool use_delay_agnostic_aec = false;
kjellanderfcfc8042016-01-14 11:01:09 -0800387#if !defined(WEBRTC_IOS)
kwiberg102c6a62015-10-30 02:47:38 -0700388 if (options.delay_agnostic_aec) {
389 use_delay_agnostic_aec = *options.delay_agnostic_aec;
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100390 if (use_delay_agnostic_aec) {
Karl Wibergbe579832015-11-10 22:34:18 +0100391 options.echo_cancellation = rtc::Optional<bool>(true);
392 options.extended_filter_aec = rtc::Optional<bool>(true);
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100393 ec_mode = webrtc::kEcConference;
394 }
395 }
396#endif
397
peah8a8ebd92017-05-22 15:48:47 -0700398// Set and adjust noise suppressor options.
399#if defined(WEBRTC_IOS)
400 // On iOS, VPIO provides built-in NS.
401 options.noise_suppression = rtc::Optional<bool>(false);
402 options.typing_detection = rtc::Optional<bool>(false);
403 options.experimental_ns = rtc::Optional<bool>(false);
404 LOG(LS_INFO) << "Always disable NS on iOS. Use built-in instead.";
405#elif defined(ANDROID)
406 options.typing_detection = rtc::Optional<bool>(false);
407 options.experimental_ns = rtc::Optional<bool>(false);
408#endif
409
410// Set and adjust gain control options.
411#if defined(WEBRTC_IOS)
412 // On iOS, VPIO provides built-in AGC.
413 options.auto_gain_control = rtc::Optional<bool>(false);
414 options.experimental_agc = rtc::Optional<bool>(false);
415 LOG(LS_INFO) << "Always disable AGC on iOS. Use built-in instead.";
416#elif defined(ANDROID)
417 options.experimental_agc = rtc::Optional<bool>(false);
418#endif
419
420#if defined(WEBRTC_IOS) || defined(WEBRTC_ANDROID)
421 // Turn off the gain control if specified by the field trial. The purpose of the field trial is to reduce the amount of resampling performed inside the audio processing module on mobile platforms by whenever possible turning off the fixed AGC mode and the high-pass filter. (https://bugs.chromium.org/p/webrtc/issues/detail?id=6181).
422 if (webrtc::field_trial::IsEnabled(
423 "WebRTC-Audio-MinimizeResamplingOnMobile")) {
424 options.auto_gain_control = rtc::Optional<bool>(false);
425 LOG(LS_INFO) << "Disable AGC according to field trial.";
426 if (!(options.noise_suppression.value_or(false) or
427 options.echo_cancellation.value_or(false))) {
428 // If possible, turn off the high-pass filter.
429 LOG(LS_INFO) << "Disable high-pass filter in response to field trial.";
430 options.highpass_filter = rtc::Optional<bool>(false);
431 }
432 }
433#endif
434
peah1bcfce52016-08-26 07:16:04 -0700435#if (WEBRTC_INTELLIGIBILITY_ENHANCER == 0)
436 // Hardcode the intelligibility enhancer to be off.
437 options.intelligibility_enhancer = rtc::Optional<bool>(false);
438#endif
439
kwiberg102c6a62015-10-30 02:47:38 -0700440 if (options.echo_cancellation) {
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000441 // Check if platform supports built-in EC. Currently only supported on
442 // Android and in combination with Java based audio layer.
443 // TODO(henrika): investigate possibility to support built-in EC also
444 // in combination with Open SL ES audio.
solenberg5b5129a2016-04-08 05:35:48 -0700445 const bool built_in_aec = adm()->BuiltInAECIsAvailable();
Bjorn Volcker73f72102015-06-03 14:50:15 +0200446 if (built_in_aec) {
Bjorn Volckerccfc9392015-05-07 07:43:17 +0200447 // Built-in EC exists on this device and use_delay_agnostic_aec is not
448 // overriding it. Enable/Disable it according to the echo_cancellation
449 // audio option.
Bjorn Volcker73f72102015-06-03 14:50:15 +0200450 const bool enable_built_in_aec =
kwiberg102c6a62015-10-30 02:47:38 -0700451 *options.echo_cancellation && !use_delay_agnostic_aec;
solenberg5b5129a2016-04-08 05:35:48 -0700452 if (adm()->EnableBuiltInAEC(enable_built_in_aec) == 0 &&
Bjorn Volcker73f72102015-06-03 14:50:15 +0200453 enable_built_in_aec) {
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100454 // Disable internal software EC if built-in EC is enabled,
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000455 // i.e., replace the software EC with the built-in EC.
Karl Wibergbe579832015-11-10 22:34:18 +0100456 options.echo_cancellation = rtc::Optional<bool>(false);
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000457 LOG(LS_INFO) << "Disabling EC since built-in EC will be used instead";
458 }
459 }
solenberg76377c52017-02-21 00:54:31 -0800460 webrtc::apm_helpers::SetEcStatus(
461 apm(), *options.echo_cancellation, ec_mode);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000462#if !defined(ANDROID)
solenberg76377c52017-02-21 00:54:31 -0800463 webrtc::apm_helpers::SetEcMetricsStatus(apm(), *options.echo_cancellation);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000464#endif
465 if (ec_mode == webrtc::kEcAecm) {
kwiberg102c6a62015-10-30 02:47:38 -0700466 bool cn = options.aecm_generate_comfort_noise.value_or(false);
solenberg76377c52017-02-21 00:54:31 -0800467 webrtc::apm_helpers::SetAecmMode(apm(), cn);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000468 }
469 }
470
kwiberg102c6a62015-10-30 02:47:38 -0700471 if (options.auto_gain_control) {
peah72a56452016-08-22 12:08:55 -0700472 bool built_in_agc_avaliable = adm()->BuiltInAGCIsAvailable();
473 if (built_in_agc_avaliable) {
solenberg5b5129a2016-04-08 05:35:48 -0700474 if (adm()->EnableBuiltInAGC(*options.auto_gain_control) == 0 &&
kwiberg102c6a62015-10-30 02:47:38 -0700475 *options.auto_gain_control) {
henrikac14f5ff2015-09-23 14:08:33 +0200476 // Disable internal software AGC if built-in AGC is enabled,
477 // i.e., replace the software AGC with the built-in AGC.
Karl Wibergbe579832015-11-10 22:34:18 +0100478 options.auto_gain_control = rtc::Optional<bool>(false);
henrikac14f5ff2015-09-23 14:08:33 +0200479 LOG(LS_INFO) << "Disabling AGC since built-in AGC will be used instead";
480 }
481 }
solenberg22818a52017-03-16 01:20:23 -0700482 webrtc::apm_helpers::SetAgcStatus(apm(), adm(), *options.auto_gain_control);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000483 }
484
kwiberg102c6a62015-10-30 02:47:38 -0700485 if (options.tx_agc_target_dbov || options.tx_agc_digital_compression_gain ||
solenberg76377c52017-02-21 00:54:31 -0800486 options.tx_agc_limiter || options.adjust_agc_delta) {
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000487 // Override default_agc_config_. Generally, an unset option means "leave
488 // the VoE bits alone" in this function, so we want whatever is set to be
489 // stored as the new "default". If we didn't, then setting e.g.
490 // tx_agc_target_dbov would reset digital compression gain and limiter
491 // settings.
492 // Also, if we don't update default_agc_config_, then adjust_agc_delta
493 // would be an offset from the original values, and not whatever was set
494 // explicitly.
kwiberg102c6a62015-10-30 02:47:38 -0700495 default_agc_config_.targetLeveldBOv = options.tx_agc_target_dbov.value_or(
496 default_agc_config_.targetLeveldBOv);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000497 default_agc_config_.digitalCompressionGaindB =
kwiberg102c6a62015-10-30 02:47:38 -0700498 options.tx_agc_digital_compression_gain.value_or(
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000499 default_agc_config_.digitalCompressionGaindB);
500 default_agc_config_.limiterEnable =
kwiberg102c6a62015-10-30 02:47:38 -0700501 options.tx_agc_limiter.value_or(default_agc_config_.limiterEnable);
solenberg76377c52017-02-21 00:54:31 -0800502
503 webrtc::AgcConfig config = default_agc_config_;
504 if (options.adjust_agc_delta) {
505 config.targetLeveldBOv -= *options.adjust_agc_delta;
506 LOG(LS_INFO) << "Adjusting AGC level from default -"
507 << default_agc_config_.targetLeveldBOv << "dB to -"
508 << config.targetLeveldBOv << "dB";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000509 }
solenberg76377c52017-02-21 00:54:31 -0800510 webrtc::apm_helpers::SetAgcConfig(apm_, config);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000511 }
512
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700513 if (options.intelligibility_enhancer) {
514 intelligibility_enhancer_ = options.intelligibility_enhancer;
515 }
516 if (intelligibility_enhancer_ && *intelligibility_enhancer_) {
517 LOG(LS_INFO) << "Enabling NS when Intelligibility Enhancer is active.";
518 options.noise_suppression = intelligibility_enhancer_;
519 }
520
kwiberg102c6a62015-10-30 02:47:38 -0700521 if (options.noise_suppression) {
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700522 if (adm()->BuiltInNSIsAvailable()) {
523 bool builtin_ns =
524 *options.noise_suppression &&
525 !(intelligibility_enhancer_ && *intelligibility_enhancer_);
526 if (adm()->EnableBuiltInNS(builtin_ns) == 0 && builtin_ns) {
henrikac14f5ff2015-09-23 14:08:33 +0200527 // Disable internal software NS if built-in NS is enabled,
528 // i.e., replace the software NS with the built-in NS.
Karl Wibergbe579832015-11-10 22:34:18 +0100529 options.noise_suppression = rtc::Optional<bool>(false);
henrikac14f5ff2015-09-23 14:08:33 +0200530 LOG(LS_INFO) << "Disabling NS since built-in NS will be used instead";
531 }
532 }
solenberg76377c52017-02-21 00:54:31 -0800533 webrtc::apm_helpers::SetNsStatus(apm(), *options.noise_suppression);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000534 }
535
kwiberg102c6a62015-10-30 02:47:38 -0700536 if (options.stereo_swapping) {
537 LOG(LS_INFO) << "Stereo swapping enabled? " << *options.stereo_swapping;
solenberg76377c52017-02-21 00:54:31 -0800538 transmit_mixer()->EnableStereoChannelSwapping(*options.stereo_swapping);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000539 }
540
kwiberg102c6a62015-10-30 02:47:38 -0700541 if (options.audio_jitter_buffer_max_packets) {
542 LOG(LS_INFO) << "NetEq capacity is "
543 << *options.audio_jitter_buffer_max_packets;
solenberg88499ec2016-09-07 07:34:41 -0700544 channel_config_.acm_config.neteq_config.max_packets_in_buffer =
545 std::max(20, *options.audio_jitter_buffer_max_packets);
Henrik Lundin64dad832015-05-11 12:44:23 +0200546 }
kwiberg102c6a62015-10-30 02:47:38 -0700547 if (options.audio_jitter_buffer_fast_accelerate) {
548 LOG(LS_INFO) << "NetEq fast mode? "
549 << *options.audio_jitter_buffer_fast_accelerate;
solenberg88499ec2016-09-07 07:34:41 -0700550 channel_config_.acm_config.neteq_config.enable_fast_accelerate =
551 *options.audio_jitter_buffer_fast_accelerate;
Henrik Lundin5263b3c2015-06-01 10:29:41 +0200552 }
553
kwiberg102c6a62015-10-30 02:47:38 -0700554 if (options.typing_detection) {
555 LOG(LS_INFO) << "Typing detection is enabled? "
556 << *options.typing_detection;
solenberg76377c52017-02-21 00:54:31 -0800557 webrtc::apm_helpers::SetTypingDetectionStatus(
558 apm(), *options.typing_detection);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000559 }
560
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000561 webrtc::Config config;
562
kwiberg102c6a62015-10-30 02:47:38 -0700563 if (options.delay_agnostic_aec)
564 delay_agnostic_aec_ = options.delay_agnostic_aec;
565 if (delay_agnostic_aec_) {
566 LOG(LS_INFO) << "Delay agnostic aec is enabled? " << *delay_agnostic_aec_;
henrik.lundin0f133b92015-07-02 00:17:55 -0700567 config.Set<webrtc::DelayAgnostic>(
kwiberg102c6a62015-10-30 02:47:38 -0700568 new webrtc::DelayAgnostic(*delay_agnostic_aec_));
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100569 }
570
kwiberg102c6a62015-10-30 02:47:38 -0700571 if (options.extended_filter_aec) {
572 extended_filter_aec_ = options.extended_filter_aec;
573 }
574 if (extended_filter_aec_) {
575 LOG(LS_INFO) << "Extended filter aec is enabled? " << *extended_filter_aec_;
Henrik Lundin441f6342015-06-09 16:03:13 +0200576 config.Set<webrtc::ExtendedFilter>(
kwiberg102c6a62015-10-30 02:47:38 -0700577 new webrtc::ExtendedFilter(*extended_filter_aec_));
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000578 }
579
kwiberg102c6a62015-10-30 02:47:38 -0700580 if (options.experimental_ns) {
581 experimental_ns_ = options.experimental_ns;
582 }
583 if (experimental_ns_) {
584 LOG(LS_INFO) << "Experimental ns is enabled? " << *experimental_ns_;
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000585 config.Set<webrtc::ExperimentalNs>(
kwiberg102c6a62015-10-30 02:47:38 -0700586 new webrtc::ExperimentalNs(*experimental_ns_));
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000587 }
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000588
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700589 if (intelligibility_enhancer_) {
590 LOG(LS_INFO) << "Intelligibility Enhancer is enabled? "
591 << *intelligibility_enhancer_;
592 config.Set<webrtc::Intelligibility>(
593 new webrtc::Intelligibility(*intelligibility_enhancer_));
594 }
595
peaha3333bf2016-06-30 00:02:34 -0700596 if (options.level_control) {
597 level_control_ = options.level_control;
598 }
599
600 LOG(LS_INFO) << "Level control: "
601 << (!!level_control_ ? *level_control_ : -1);
602 if (level_control_) {
peah64d6ff72016-11-21 06:28:14 -0800603 apm_config_.level_controller.enabled = *level_control_;
aleloie33c5d92016-10-20 01:53:27 -0700604 if (options.level_control_initial_peak_level_dbfs) {
peah64d6ff72016-11-21 06:28:14 -0800605 apm_config_.level_controller.initial_peak_level_dbfs =
aleloie33c5d92016-10-20 01:53:27 -0700606 *options.level_control_initial_peak_level_dbfs;
607 }
peaha3333bf2016-06-30 00:02:34 -0700608 }
609
peah8271d042016-11-22 07:24:52 -0800610 if (options.highpass_filter) {
611 apm_config_.high_pass_filter.enabled = *options.highpass_filter;
612 }
613
ivoc4ca18692017-02-10 05:11:09 -0800614 if (options.residual_echo_detector) {
615 apm_config_.residual_echo_detector.enabled =
616 *options.residual_echo_detector;
617 }
618
solenberg059fb442016-10-26 05:12:24 -0700619 apm()->SetExtraOptions(config);
peah64d6ff72016-11-21 06:28:14 -0800620 apm()->ApplyConfig(apm_config_);
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000621
kwiberg102c6a62015-10-30 02:47:38 -0700622 if (options.recording_sample_rate) {
623 LOG(LS_INFO) << "Recording sample rate is "
624 << *options.recording_sample_rate;
solenberg5b5129a2016-04-08 05:35:48 -0700625 if (adm()->SetRecordingSampleRate(*options.recording_sample_rate)) {
kwiberg102c6a62015-10-30 02:47:38 -0700626 LOG_RTCERR1(SetRecordingSampleRate, *options.recording_sample_rate);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000627 }
628 }
629
kwiberg102c6a62015-10-30 02:47:38 -0700630 if (options.playout_sample_rate) {
631 LOG(LS_INFO) << "Playout sample rate is " << *options.playout_sample_rate;
solenberg5b5129a2016-04-08 05:35:48 -0700632 if (adm()->SetPlayoutSampleRate(*options.playout_sample_rate)) {
kwiberg102c6a62015-10-30 02:47:38 -0700633 LOG_RTCERR1(SetPlayoutSampleRate, *options.playout_sample_rate);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000634 }
635 }
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000636 return true;
637}
638
solenberg796b8f92017-03-01 17:02:23 -0800639// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000640int WebRtcVoiceEngine::GetInputLevel() {
solenberg566ef242015-11-06 15:34:49 -0800641 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg796b8f92017-03-01 17:02:23 -0800642 int8_t level = transmit_mixer()->AudioLevel();
643 RTC_DCHECK_LE(0, level);
644 return level;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000645}
646
ossudedfd282016-06-14 07:12:39 -0700647const std::vector<AudioCodec>& WebRtcVoiceEngine::send_codecs() const {
648 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
ossuc54071d2016-08-17 02:45:41 -0700649 return send_codecs_;
ossudedfd282016-06-14 07:12:39 -0700650}
651
652const std::vector<AudioCodec>& WebRtcVoiceEngine::recv_codecs() const {
solenberg566ef242015-11-06 15:34:49 -0800653 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
ossuc54071d2016-08-17 02:45:41 -0700654 return recv_codecs_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000655}
656
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100657RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const {
solenberg566ef242015-11-06 15:34:49 -0800658 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100659 RtpCapabilities capabilities;
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100660 capabilities.header_extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -0700661 webrtc::RtpExtension(webrtc::RtpExtension::kAudioLevelUri,
662 webrtc::RtpExtension::kAudioLevelDefaultId));
sprangc1b57a12017-02-28 08:50:47 -0800663 if (webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe")) {
isheriff6f8d6862016-05-26 11:24:55 -0700664 capabilities.header_extensions.push_back(webrtc::RtpExtension(
665 webrtc::RtpExtension::kTransportSequenceNumberUri,
666 webrtc::RtpExtension::kTransportSequenceNumberDefaultId));
stefanba4c0e42016-02-04 04:12:24 -0800667 }
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100668 return capabilities;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000669}
670
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000671int WebRtcVoiceEngine::GetLastEngineError() {
solenberg566ef242015-11-06 15:34:49 -0800672 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000673 return voe_wrapper_->error();
674}
675
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000676void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
677 int length) {
solenberg566ef242015-11-06 15:34:49 -0800678 // Note: This callback can happen on any thread!
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000679 rtc::LoggingSeverity sev = rtc::LS_VERBOSE;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000680 if (level == webrtc::kTraceError || level == webrtc::kTraceCritical)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000681 sev = rtc::LS_ERROR;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000682 else if (level == webrtc::kTraceWarning)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000683 sev = rtc::LS_WARNING;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000684 else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000685 sev = rtc::LS_INFO;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000686 else if (level == webrtc::kTraceTerseInfo)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000687 sev = rtc::LS_INFO;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000688
solenberg72e29d22016-03-08 06:35:16 -0800689 // Skip past boilerplate prefix text.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000690 if (length < 72) {
691 std::string msg(trace, length);
692 LOG(LS_ERROR) << "Malformed webrtc log message: ";
693 LOG_V(sev) << msg;
694 } else {
695 std::string msg(trace + 71, length - 72);
Peter Boströmd5c75b12015-09-23 13:24:32 +0200696 LOG_V(sev) << "webrtc: " << msg;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000697 }
698}
699
solenberg63b34542015-09-29 06:06:31 -0700700void WebRtcVoiceEngine::RegisterChannel(WebRtcVoiceMediaChannel* channel) {
solenberg566ef242015-11-06 15:34:49 -0800701 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
702 RTC_DCHECK(channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000703 channels_.push_back(channel);
704}
705
solenberg63b34542015-09-29 06:06:31 -0700706void WebRtcVoiceEngine::UnregisterChannel(WebRtcVoiceMediaChannel* channel) {
solenberg566ef242015-11-06 15:34:49 -0800707 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg63b34542015-09-29 06:06:31 -0700708 auto it = std::find(channels_.begin(), channels_.end(), channel);
solenberg566ef242015-11-06 15:34:49 -0800709 RTC_DCHECK(it != channels_.end());
710 channels_.erase(it);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000711}
712
ivocd66b44d2016-01-15 03:06:36 -0800713bool WebRtcVoiceEngine::StartAecDump(rtc::PlatformFile file,
714 int64_t max_size_bytes) {
solenberg566ef242015-11-06 15:34:49 -0800715 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeefeb02c032017-06-15 08:29:25 -0700716 auto aec_dump = webrtc::AecDumpFactory::Create(
717 file, max_size_bytes, low_priority_worker_queue_.get());
aleloi048cbdd2017-05-29 02:56:27 -0700718 if (!aec_dump) {
wu@webrtc.orga8910d22014-01-23 22:12:45 +0000719 return false;
720 }
aleloi048cbdd2017-05-29 02:56:27 -0700721 apm()->AttachAecDump(std::move(aec_dump));
wu@webrtc.orga9890802013-12-13 00:21:03 +0000722 return true;
wu@webrtc.orga9890802013-12-13 00:21:03 +0000723}
724
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000725void WebRtcVoiceEngine::StartAecDump(const std::string& filename) {
solenberg566ef242015-11-06 15:34:49 -0800726 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
aleloi048cbdd2017-05-29 02:56:27 -0700727
deadbeefeb02c032017-06-15 08:29:25 -0700728 auto aec_dump = webrtc::AecDumpFactory::Create(
729 filename, -1, low_priority_worker_queue_.get());
aleloi048cbdd2017-05-29 02:56:27 -0700730 if (aec_dump) {
731 apm()->AttachAecDump(std::move(aec_dump));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000732 }
733}
734
735void WebRtcVoiceEngine::StopAecDump() {
solenberg566ef242015-11-06 15:34:49 -0800736 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
aleloi048cbdd2017-05-29 02:56:27 -0700737 apm()->DetachAecDump();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000738}
739
solenberg0a617e22015-10-20 15:49:38 -0700740int WebRtcVoiceEngine::CreateVoEChannel() {
solenberg566ef242015-11-06 15:34:49 -0800741 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg88499ec2016-09-07 07:34:41 -0700742 return voe_wrapper_->base()->CreateChannel(channel_config_);
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000743}
744
solenberg5b5129a2016-04-08 05:35:48 -0700745webrtc::AudioDeviceModule* WebRtcVoiceEngine::adm() {
746 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
747 RTC_DCHECK(adm_);
748 return adm_;
749}
750
solenberg059fb442016-10-26 05:12:24 -0700751webrtc::AudioProcessing* WebRtcVoiceEngine::apm() {
752 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
753 RTC_DCHECK(apm_);
754 return apm_;
755}
756
solenberg76377c52017-02-21 00:54:31 -0800757webrtc::voe::TransmitMixer* WebRtcVoiceEngine::transmit_mixer() {
758 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
759 RTC_DCHECK(transmit_mixer_);
760 return transmit_mixer_;
761}
762
ossu20a4b3f2017-04-27 02:08:52 -0700763AudioCodecs WebRtcVoiceEngine::CollectCodecs(
764 const std::vector<webrtc::AudioCodecSpec>& specs) const {
ossuc54071d2016-08-17 02:45:41 -0700765 PayloadTypeMapper mapper;
766 AudioCodecs out;
ossuc54071d2016-08-17 02:45:41 -0700767
solenberg2779bab2016-11-17 04:45:19 -0800768 // Only generate CN payload types for these clockrates:
ossuc54071d2016-08-17 02:45:41 -0700769 std::map<int, bool, std::greater<int>> generate_cn = {{ 8000, false },
770 { 16000, false },
771 { 32000, false }};
solenberg2779bab2016-11-17 04:45:19 -0800772 // Only generate telephone-event payload types for these clockrates:
773 std::map<int, bool, std::greater<int>> generate_dtmf = {{ 8000, false },
774 { 16000, false },
775 { 32000, false },
776 { 48000, false }};
ossuc54071d2016-08-17 02:45:41 -0700777
ossu9def8002017-02-09 05:14:32 -0800778 auto map_format = [&mapper](const webrtc::SdpAudioFormat& format,
779 AudioCodecs* out) {
ossuc54071d2016-08-17 02:45:41 -0700780 rtc::Optional<AudioCodec> opt_codec = mapper.ToAudioCodec(format);
ossu9def8002017-02-09 05:14:32 -0800781 if (opt_codec) {
782 if (out) {
783 out->push_back(*opt_codec);
784 }
785 } else {
ossuc54071d2016-08-17 02:45:41 -0700786 LOG(LS_ERROR) << "Unable to assign payload type to format: " << format;
ossuc54071d2016-08-17 02:45:41 -0700787 }
788
ossu9def8002017-02-09 05:14:32 -0800789 return opt_codec;
ossuc54071d2016-08-17 02:45:41 -0700790 };
791
ossud4e9f622016-08-18 02:01:17 -0700792 for (const auto& spec : specs) {
ossu9def8002017-02-09 05:14:32 -0800793 // We need to do some extra stuff before adding the main codecs to out.
794 rtc::Optional<AudioCodec> opt_codec = map_format(spec.format, nullptr);
795 if (opt_codec) {
796 AudioCodec& codec = *opt_codec;
ossua1a040a2017-04-06 10:03:21 -0700797 if (spec.info.supports_network_adaption) {
ossu9def8002017-02-09 05:14:32 -0800798 codec.AddFeedbackParam(
799 FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty));
800 }
801
ossua1a040a2017-04-06 10:03:21 -0700802 if (spec.info.allow_comfort_noise) {
solenberg2779bab2016-11-17 04:45:19 -0800803 // Generate a CN entry if the decoder allows it and we support the
804 // clockrate.
805 auto cn = generate_cn.find(spec.format.clockrate_hz);
806 if (cn != generate_cn.end()) {
807 cn->second = true;
808 }
809 }
810
811 // Generate a telephone-event entry if we support the clockrate.
812 auto dtmf = generate_dtmf.find(spec.format.clockrate_hz);
813 if (dtmf != generate_dtmf.end()) {
814 dtmf->second = true;
ossuc54071d2016-08-17 02:45:41 -0700815 }
ossu9def8002017-02-09 05:14:32 -0800816
817 out.push_back(codec);
ossuc54071d2016-08-17 02:45:41 -0700818 }
819 }
820
solenberg2779bab2016-11-17 04:45:19 -0800821 // Add CN codecs after "proper" audio codecs.
ossuc54071d2016-08-17 02:45:41 -0700822 for (const auto& cn : generate_cn) {
823 if (cn.second) {
ossu9def8002017-02-09 05:14:32 -0800824 map_format({kCnCodecName, cn.first, 1}, &out);
ossuc54071d2016-08-17 02:45:41 -0700825 }
826 }
827
solenberg2779bab2016-11-17 04:45:19 -0800828 // Add telephone-event codecs last.
829 for (const auto& dtmf : generate_dtmf) {
830 if (dtmf.second) {
ossu9def8002017-02-09 05:14:32 -0800831 map_format({kDtmfCodecName, dtmf.first, 1}, &out);
solenberg2779bab2016-11-17 04:45:19 -0800832 }
833 }
ossuc54071d2016-08-17 02:45:41 -0700834
835 return out;
836}
837
solenbergc96df772015-10-21 13:01:53 -0700838class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800839 : public AudioSource::Sink {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000840 public:
minyue7a973442016-10-20 03:27:12 -0700841 WebRtcAudioSendStream(
842 int ch,
843 webrtc::AudioTransport* voe_audio_transport,
844 uint32_t ssrc,
845 const std::string& c_name,
ossu20a4b3f2017-04-27 02:08:52 -0700846 const rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>&
847 send_codec_spec,
minyue7a973442016-10-20 03:27:12 -0700848 const std::vector<webrtc::RtpExtension>& extensions,
849 int max_send_bitrate_bps,
minyue6b825df2016-10-31 04:08:32 -0700850 const rtc::Optional<std::string>& audio_network_adaptor_config,
minyue7a973442016-10-20 03:27:12 -0700851 webrtc::Call* call,
ossu20a4b3f2017-04-27 02:08:52 -0700852 webrtc::Transport* send_transport,
853 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory)
solenberg7add0582015-11-20 09:59:34 -0800854 : voe_audio_transport_(voe_audio_transport),
solenberg3a941542015-11-16 07:34:50 -0800855 call_(call),
mflodman3d7db262016-04-29 00:57:13 -0700856 config_(send_transport),
sprangc1b57a12017-02-28 08:50:47 -0800857 send_side_bwe_with_overhead_(
858 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
minyue7a973442016-10-20 03:27:12 -0700859 max_send_bitrate_bps_(max_send_bitrate_bps),
skvlade0d46372016-04-07 22:59:22 -0700860 rtp_parameters_(CreateRtpParametersWithOneEncoding()) {
solenberg85a04962015-10-27 03:35:21 -0700861 RTC_DCHECK_GE(ch, 0);
862 // TODO(solenberg): Once we're not using FakeWebRtcVoiceEngine anymore:
863 // RTC_DCHECK(voe_audio_transport);
solenbergc96df772015-10-21 13:01:53 -0700864 RTC_DCHECK(call);
ossu20a4b3f2017-04-27 02:08:52 -0700865 RTC_DCHECK(encoder_factory);
solenberg3a941542015-11-16 07:34:50 -0800866 config_.rtp.ssrc = ssrc;
867 config_.rtp.c_name = c_name;
868 config_.voe_channel_id = ch;
solenberg971cab02016-06-14 10:02:41 -0700869 config_.rtp.extensions = extensions;
minyue6b825df2016-10-31 04:08:32 -0700870 config_.audio_network_adaptor_config = audio_network_adaptor_config;
ossu20a4b3f2017-04-27 02:08:52 -0700871 config_.encoder_factory = encoder_factory;
deadbeefcb443432016-12-12 11:12:36 -0800872 rtp_parameters_.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
ossu20a4b3f2017-04-27 02:08:52 -0700873
874 if (send_codec_spec) {
875 UpdateSendCodecSpec(*send_codec_spec);
876 }
877
878 stream_ = call_->CreateAudioSendStream(config_);
solenbergc96df772015-10-21 13:01:53 -0700879 }
solenberg3a941542015-11-16 07:34:50 -0800880
solenbergc96df772015-10-21 13:01:53 -0700881 ~WebRtcAudioSendStream() override {
solenberg566ef242015-11-06 15:34:49 -0800882 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800883 ClearSource();
solenbergc96df772015-10-21 13:01:53 -0700884 call_->DestroyAudioSendStream(stream_);
885 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000886
ossu20a4b3f2017-04-27 02:08:52 -0700887 void SetSendCodecSpec(
minyue7a973442016-10-20 03:27:12 -0700888 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) {
ossu20a4b3f2017-04-27 02:08:52 -0700889 UpdateSendCodecSpec(send_codec_spec);
890 ReconfigureAudioSendStream();
solenberg971cab02016-06-14 10:02:41 -0700891 }
892
ossu20a4b3f2017-04-27 02:08:52 -0700893 void SetRtpExtensions(const std::vector<webrtc::RtpExtension>& extensions) {
solenberg3a941542015-11-16 07:34:50 -0800894 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg3a941542015-11-16 07:34:50 -0800895 config_.rtp.extensions = extensions;
ossu20a4b3f2017-04-27 02:08:52 -0700896 ReconfigureAudioSendStream();
solenberg3a941542015-11-16 07:34:50 -0800897 }
898
ossu20a4b3f2017-04-27 02:08:52 -0700899 void SetAudioNetworkAdaptorConfig(
minyue6b825df2016-10-31 04:08:32 -0700900 const rtc::Optional<std::string>& audio_network_adaptor_config) {
901 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
902 if (config_.audio_network_adaptor_config == audio_network_adaptor_config) {
903 return;
904 }
905 config_.audio_network_adaptor_config = audio_network_adaptor_config;
ossu20a4b3f2017-04-27 02:08:52 -0700906 UpdateAllowedBitrateRange();
907 ReconfigureAudioSendStream();
minyue6b825df2016-10-31 04:08:32 -0700908 }
909
minyue7a973442016-10-20 03:27:12 -0700910 bool SetMaxSendBitrate(int bps) {
911 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
ossu20a4b3f2017-04-27 02:08:52 -0700912 RTC_DCHECK(config_.send_codec_spec);
913 RTC_DCHECK(audio_codec_spec_);
914 auto send_rate = ComputeSendBitrate(
915 bps, rtp_parameters_.encodings[0].max_bitrate_bps, *audio_codec_spec_);
916
minyue7a973442016-10-20 03:27:12 -0700917 if (!send_rate) {
918 return false;
919 }
920
921 max_send_bitrate_bps_ = bps;
922
ossu20a4b3f2017-04-27 02:08:52 -0700923 if (send_rate != config_.send_codec_spec->target_bitrate_bps) {
924 config_.send_codec_spec->target_bitrate_bps = send_rate;
925 ReconfigureAudioSendStream();
minyue7a973442016-10-20 03:27:12 -0700926 }
927 return true;
928 }
929
solenbergffbbcac2016-11-17 05:25:37 -0800930 bool SendTelephoneEvent(int payload_type, int payload_freq, int event,
931 int duration_ms) {
Fredrik Solenbergb5727682015-12-04 15:22:19 +0100932 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
933 RTC_DCHECK(stream_);
solenbergffbbcac2016-11-17 05:25:37 -0800934 return stream_->SendTelephoneEvent(payload_type, payload_freq, event,
935 duration_ms);
Fredrik Solenbergb5727682015-12-04 15:22:19 +0100936 }
937
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800938 void SetSend(bool send) {
939 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
940 send_ = send;
941 UpdateSendState();
942 }
943
solenberg94218532016-06-16 10:53:22 -0700944 void SetMuted(bool muted) {
945 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
946 RTC_DCHECK(stream_);
947 stream_->SetMuted(muted);
948 muted_ = muted;
949 }
950
951 bool muted() const {
952 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
953 return muted_;
954 }
955
solenberg3a941542015-11-16 07:34:50 -0800956 webrtc::AudioSendStream::Stats GetStats() const {
957 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
958 RTC_DCHECK(stream_);
959 return stream_->GetStats();
960 }
961
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800962 // Starts the sending by setting ourselves as a sink to the AudioSource to
963 // get data callbacks.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000964 // This method is called on the libjingle worker thread.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000965 // TODO(xians): Make sure Start() is called only once.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800966 void SetSource(AudioSource* source) {
solenberg566ef242015-11-06 15:34:49 -0800967 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800968 RTC_DCHECK(source);
969 if (source_) {
970 RTC_DCHECK(source_ == source);
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000971 return;
972 }
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800973 source->SetSink(this);
974 source_ = source;
975 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000976 }
977
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800978 // Stops sending by setting the sink of the AudioSource to nullptr. No data
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000979 // callback will be received after this method.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000980 // This method is called on the libjingle worker thread.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800981 void ClearSource() {
solenberg566ef242015-11-06 15:34:49 -0800982 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800983 if (source_) {
984 source_->SetSink(nullptr);
985 source_ = nullptr;
solenberg98c68862015-10-09 03:27:14 -0700986 }
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800987 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000988 }
989
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800990 // AudioSource::Sink implementation.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000991 // This method is called on the audio thread.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000992 void OnData(const void* audio_data,
993 int bits_per_sample,
994 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -0800995 size_t number_of_channels,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700996 size_t number_of_frames) override {
solenberg347ec5c2016-09-23 04:21:47 -0700997 RTC_CHECK_RUNS_SERIALIZED(&audio_capture_race_checker_);
solenbergc96df772015-10-21 13:01:53 -0700998 RTC_DCHECK(voe_audio_transport_);
maxmorin1aee0b52016-08-15 11:46:19 -0700999 voe_audio_transport_->PushCaptureData(config_.voe_channel_id, audio_data,
1000 bits_per_sample, sample_rate,
1001 number_of_channels, number_of_frames);
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00001002 }
1003
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001004 // Callback from the |source_| when it is going away. In case Start() has
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00001005 // never been called, this callback won't be triggered.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001006 void OnClose() override {
solenberg566ef242015-11-06 15:34:49 -08001007 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001008 // Set |source_| to nullptr to make sure no more callback will get into
1009 // the source.
1010 source_ = nullptr;
1011 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001012 }
1013
1014 // Accessor to the VoE channel ID.
solenberg85a04962015-10-27 03:35:21 -07001015 int channel() const {
solenberg566ef242015-11-06 15:34:49 -08001016 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7add0582015-11-20 09:59:34 -08001017 return config_.voe_channel_id;
solenberg85a04962015-10-27 03:35:21 -07001018 }
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001019
skvlade0d46372016-04-07 22:59:22 -07001020 const webrtc::RtpParameters& rtp_parameters() const {
1021 return rtp_parameters_;
1022 }
1023
deadbeeffb2aced2017-01-06 23:05:37 -08001024 bool ValidateRtpParameters(const webrtc::RtpParameters& rtp_parameters) {
1025 if (rtp_parameters.encodings.size() != 1) {
1026 LOG(LS_ERROR)
1027 << "Attempted to set RtpParameters without exactly one encoding";
1028 return false;
1029 }
1030 if (rtp_parameters.encodings[0].ssrc != rtp_parameters_.encodings[0].ssrc) {
1031 LOG(LS_ERROR) << "Attempted to set RtpParameters with modified SSRC";
1032 return false;
1033 }
1034 return true;
1035 }
1036
minyue7a973442016-10-20 03:27:12 -07001037 bool SetRtpParameters(const webrtc::RtpParameters& parameters) {
deadbeeffb2aced2017-01-06 23:05:37 -08001038 if (!ValidateRtpParameters(parameters)) {
1039 return false;
1040 }
ossu20a4b3f2017-04-27 02:08:52 -07001041
1042 rtc::Optional<int> send_rate;
1043 if (audio_codec_spec_) {
1044 send_rate = ComputeSendBitrate(max_send_bitrate_bps_,
1045 parameters.encodings[0].max_bitrate_bps,
1046 *audio_codec_spec_);
1047 if (!send_rate) {
1048 return false;
1049 }
minyue7a973442016-10-20 03:27:12 -07001050 }
1051
minyuececec102017-03-27 13:04:25 -07001052 const rtc::Optional<int> old_rtp_max_bitrate =
1053 rtp_parameters_.encodings[0].max_bitrate_bps;
1054
skvlade0d46372016-04-07 22:59:22 -07001055 rtp_parameters_ = parameters;
minyue7a973442016-10-20 03:27:12 -07001056
minyuececec102017-03-27 13:04:25 -07001057 if (rtp_parameters_.encodings[0].max_bitrate_bps != old_rtp_max_bitrate) {
ossu20a4b3f2017-04-27 02:08:52 -07001058 // Reconfigure AudioSendStream with new bit rate.
1059 if (send_rate) {
1060 config_.send_codec_spec->target_bitrate_bps = send_rate;
1061 }
1062 UpdateAllowedBitrateRange();
1063 ReconfigureAudioSendStream();
minyue7a973442016-10-20 03:27:12 -07001064 } else {
1065 // parameters.encodings[0].active could have changed.
1066 UpdateSendState();
1067 }
1068 return true;
skvlade0d46372016-04-07 22:59:22 -07001069 }
1070
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001071 private:
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001072 void UpdateSendState() {
1073 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1074 RTC_DCHECK(stream_);
Taylor Brandstetter55dd7082016-05-03 13:50:11 -07001075 RTC_DCHECK_EQ(1UL, rtp_parameters_.encodings.size());
1076 if (send_ && source_ != nullptr && rtp_parameters_.encodings[0].active) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001077 stream_->Start();
1078 } else { // !send || source_ = nullptr
1079 stream_->Stop();
1080 }
1081 }
1082
ossu20a4b3f2017-04-27 02:08:52 -07001083 void UpdateAllowedBitrateRange() {
michaelt53fe19d2016-10-18 09:39:22 -07001084 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
ossu20a4b3f2017-04-27 02:08:52 -07001085 const bool is_opus =
1086 config_.send_codec_spec &&
1087 !STR_CASE_CMP(config_.send_codec_spec->format.name.c_str(),
1088 kOpusCodecName);
1089 if (is_opus && webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe")) {
stefane9f36d52017-01-24 08:18:45 -08001090 config_.min_bitrate_bps = kOpusMinBitrateBps;
minyuececec102017-03-27 13:04:25 -07001091
1092 // This means that when RtpParameters is reset, we may change the
ossu20a4b3f2017-04-27 02:08:52 -07001093 // encoder's bit rate immediately (through ReconfigureAudioSendStream()),
minyuececec102017-03-27 13:04:25 -07001094 // meanwhile change the cap to the output of BWE.
1095 config_.max_bitrate_bps =
1096 rtp_parameters_.encodings[0].max_bitrate_bps
1097 ? *rtp_parameters_.encodings[0].max_bitrate_bps
1098 : kOpusBitrateFbBps;
1099
michaelt53fe19d2016-10-18 09:39:22 -07001100 // TODO(mflodman): Keep testing this and set proper values.
1101 // Note: This is an early experiment currently only supported by Opus.
elad.alon0fe12162017-01-31 05:48:37 -08001102 if (send_side_bwe_with_overhead_) {
ossu20a4b3f2017-04-27 02:08:52 -07001103 const int max_packet_size_ms =
1104 WEBRTC_OPUS_SUPPORT_120MS_PTIME ? 120 : 60;
michaelt6672b262017-01-11 10:17:59 -08001105
ossu20a4b3f2017-04-27 02:08:52 -07001106 // OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12)
1107 constexpr int kOverheadPerPacket = 20 + 8 + 10 + 12;
michaelt6672b262017-01-11 10:17:59 -08001108
ossu20a4b3f2017-04-27 02:08:52 -07001109 int min_overhead_bps =
1110 kOverheadPerPacket * 8 * 1000 / max_packet_size_ms;
michaelt6672b262017-01-11 10:17:59 -08001111
ossu20a4b3f2017-04-27 02:08:52 -07001112 // We assume that |config_.max_bitrate_bps| before the next line is
1113 // a hard limit on the payload bitrate, so we add min_overhead_bps to
1114 // it to ensure that, when overhead is deducted, the payload rate
1115 // never goes beyond the limit.
1116 // Note: this also means that if a higher overhead is forced, we
1117 // cannot reach the limit.
1118 // TODO(minyue): Reconsider this when the signaling to BWE is done
1119 // through a dedicated API.
1120 config_.max_bitrate_bps += min_overhead_bps;
michaelt6672b262017-01-11 10:17:59 -08001121
ossu20a4b3f2017-04-27 02:08:52 -07001122 // In contrast to max_bitrate_bps, we let min_bitrate_bps always be
1123 // reachable.
1124 config_.min_bitrate_bps += min_overhead_bps;
michaelt6672b262017-01-11 10:17:59 -08001125 }
michaelt53fe19d2016-10-18 09:39:22 -07001126 }
ossu20a4b3f2017-04-27 02:08:52 -07001127 }
1128
1129 void UpdateSendCodecSpec(
1130 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) {
1131 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1132 config_.rtp.nack.rtp_history_ms =
1133 send_codec_spec.nack_enabled ? kNackRtpHistoryMs : 0;
1134 config_.send_codec_spec =
1135 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>(
1136 send_codec_spec);
1137 auto info =
1138 config_.encoder_factory->QueryAudioEncoder(send_codec_spec.format);
1139 RTC_DCHECK(info);
1140 // If a specific target bitrate has been set for the stream, use that as
1141 // the new default bitrate when computing send bitrate.
1142 if (send_codec_spec.target_bitrate_bps) {
1143 info->default_bitrate_bps = std::max(
1144 info->min_bitrate_bps,
1145 std::min(info->max_bitrate_bps, *send_codec_spec.target_bitrate_bps));
1146 }
1147
1148 audio_codec_spec_.emplace(
1149 webrtc::AudioCodecSpec{send_codec_spec.format, *info});
1150
1151 config_.send_codec_spec->target_bitrate_bps = ComputeSendBitrate(
1152 max_send_bitrate_bps_, rtp_parameters_.encodings[0].max_bitrate_bps,
1153 *audio_codec_spec_);
1154
1155 UpdateAllowedBitrateRange();
1156 }
1157
1158 void ReconfigureAudioSendStream() {
1159 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1160 RTC_DCHECK(stream_);
1161 stream_->Reconfigure(config_);
michaelt53fe19d2016-10-18 09:39:22 -07001162 }
1163
solenberg566ef242015-11-06 15:34:49 -08001164 rtc::ThreadChecker worker_thread_checker_;
solenberg347ec5c2016-09-23 04:21:47 -07001165 rtc::RaceChecker audio_capture_race_checker_;
solenbergc96df772015-10-21 13:01:53 -07001166 webrtc::AudioTransport* const voe_audio_transport_ = nullptr;
1167 webrtc::Call* call_ = nullptr;
solenberg3a941542015-11-16 07:34:50 -08001168 webrtc::AudioSendStream::Config config_;
elad.alon0fe12162017-01-31 05:48:37 -08001169 const bool send_side_bwe_with_overhead_;
solenberg3a941542015-11-16 07:34:50 -08001170 // The stream is owned by WebRtcAudioSendStream and may be reallocated if
1171 // configuration changes.
solenbergc96df772015-10-21 13:01:53 -07001172 webrtc::AudioSendStream* stream_ = nullptr;
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001173
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001174 // Raw pointer to AudioSource owned by LocalAudioTrackHandler.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001175 // PeerConnection will make sure invalidating the pointer before the object
1176 // goes away.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001177 AudioSource* source_ = nullptr;
1178 bool send_ = false;
solenberg94218532016-06-16 10:53:22 -07001179 bool muted_ = false;
minyue7a973442016-10-20 03:27:12 -07001180 int max_send_bitrate_bps_;
skvlade0d46372016-04-07 22:59:22 -07001181 webrtc::RtpParameters rtp_parameters_;
ossu20a4b3f2017-04-27 02:08:52 -07001182 rtc::Optional<webrtc::AudioCodecSpec> audio_codec_spec_;
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00001183
solenbergc96df772015-10-21 13:01:53 -07001184 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream);
1185};
1186
1187class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
1188 public:
ossu29b1a8d2016-06-13 07:34:51 -07001189 WebRtcAudioReceiveStream(
1190 int ch,
1191 uint32_t remote_ssrc,
1192 uint32_t local_ssrc,
1193 bool use_transport_cc,
solenberg8189b022016-06-14 12:13:00 -07001194 bool use_nack,
ossu29b1a8d2016-06-13 07:34:51 -07001195 const std::string& sync_group,
1196 const std::vector<webrtc::RtpExtension>& extensions,
1197 webrtc::Call* call,
1198 webrtc::Transport* rtcp_send_transport,
kwiberg1c07c702017-03-27 07:15:49 -07001199 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
1200 const std::map<int, webrtc::SdpAudioFormat>& decoder_map)
stefanba4c0e42016-02-04 04:12:24 -08001201 : call_(call), config_() {
solenberg7add0582015-11-20 09:59:34 -08001202 RTC_DCHECK_GE(ch, 0);
1203 RTC_DCHECK(call);
1204 config_.rtp.remote_ssrc = remote_ssrc;
kwibergd32bf752017-01-19 07:03:59 -08001205 config_.rtp.local_ssrc = local_ssrc;
1206 config_.rtp.transport_cc = use_transport_cc;
1207 config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0;
1208 config_.rtp.extensions = extensions;
solenberg31fec402016-05-06 02:13:12 -07001209 config_.rtcp_send_transport = rtcp_send_transport;
solenberg7add0582015-11-20 09:59:34 -08001210 config_.voe_channel_id = ch;
1211 config_.sync_group = sync_group;
ossu29b1a8d2016-06-13 07:34:51 -07001212 config_.decoder_factory = decoder_factory;
kwiberg1c07c702017-03-27 07:15:49 -07001213 config_.decoder_map = decoder_map;
kwibergd32bf752017-01-19 07:03:59 -08001214 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001215 }
solenbergc96df772015-10-21 13:01:53 -07001216
solenberg7add0582015-11-20 09:59:34 -08001217 ~WebRtcAudioReceiveStream() {
1218 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1219 call_->DestroyAudioReceiveStream(stream_);
1220 }
1221
solenberg4a0f7b52016-06-16 13:07:33 -07001222 void RecreateAudioReceiveStream(uint32_t local_ssrc) {
solenberg7add0582015-11-20 09:59:34 -08001223 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001224 config_.rtp.local_ssrc = local_ssrc;
1225 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001226 }
solenberg8189b022016-06-14 12:13:00 -07001227
1228 void RecreateAudioReceiveStream(bool use_transport_cc, bool use_nack) {
solenberg7add0582015-11-20 09:59:34 -08001229 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001230 config_.rtp.transport_cc = use_transport_cc;
1231 config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0;
1232 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001233 }
1234
solenberg4a0f7b52016-06-16 13:07:33 -07001235 void RecreateAudioReceiveStream(
1236 const std::vector<webrtc::RtpExtension>& extensions) {
1237 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001238 config_.rtp.extensions = extensions;
1239 RecreateAudioReceiveStream();
1240 }
1241
deadbeefcb383672017-04-26 16:28:42 -07001242 // Set a new payload type -> decoder map.
kwibergd32bf752017-01-19 07:03:59 -08001243 void RecreateAudioReceiveStream(
1244 const std::map<int, webrtc::SdpAudioFormat>& decoder_map) {
1245 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001246 config_.decoder_map = decoder_map;
1247 RecreateAudioReceiveStream();
solenberg4a0f7b52016-06-16 13:07:33 -07001248 }
1249
solenberg4904fb62017-02-17 12:01:14 -08001250 void MaybeRecreateAudioReceiveStream(const std::string& sync_group) {
1251 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1252 if (config_.sync_group != sync_group) {
1253 config_.sync_group = sync_group;
1254 RecreateAudioReceiveStream();
1255 }
1256 }
1257
solenberg7add0582015-11-20 09:59:34 -08001258 webrtc::AudioReceiveStream::Stats GetStats() const {
1259 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1260 RTC_DCHECK(stream_);
1261 return stream_->GetStats();
1262 }
1263
solenberg796b8f92017-03-01 17:02:23 -08001264 int GetOutputLevel() const {
1265 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1266 RTC_DCHECK(stream_);
1267 return stream_->GetOutputLevel();
1268 }
1269
solenberg7add0582015-11-20 09:59:34 -08001270 int channel() const {
1271 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1272 return config_.voe_channel_id;
1273 }
solenbergc96df772015-10-21 13:01:53 -07001274
kwiberg686a8ef2016-02-26 03:00:35 -08001275 void SetRawAudioSink(std::unique_ptr<webrtc::AudioSinkInterface> sink) {
Tommif888bb52015-12-12 01:37:01 +01001276 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwiberg686a8ef2016-02-26 03:00:35 -08001277 stream_->SetSink(std::move(sink));
Tommif888bb52015-12-12 01:37:01 +01001278 }
1279
solenberg217fb662016-06-17 08:30:54 -07001280 void SetOutputVolume(double volume) {
1281 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1282 stream_->SetGain(volume);
1283 }
1284
aleloi84ef6152016-08-04 05:28:21 -07001285 void SetPlayout(bool playout) {
1286 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1287 RTC_DCHECK(stream_);
1288 if (playout) {
1289 LOG(LS_INFO) << "Starting playout for channel #" << channel();
1290 stream_->Start();
1291 } else {
1292 LOG(LS_INFO) << "Stopping playout for channel #" << channel();
1293 stream_->Stop();
1294 }
aleloi18e0b672016-10-04 02:45:47 -07001295 playout_ = playout;
aleloi84ef6152016-08-04 05:28:21 -07001296 }
1297
hbos8d609f62017-04-10 07:39:05 -07001298 std::vector<webrtc::RtpSource> GetSources() {
1299 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1300 RTC_DCHECK(stream_);
1301 return stream_->GetSources();
1302 }
1303
solenbergc96df772015-10-21 13:01:53 -07001304 private:
kwibergd32bf752017-01-19 07:03:59 -08001305 void RecreateAudioReceiveStream() {
solenberg7add0582015-11-20 09:59:34 -08001306 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1307 if (stream_) {
1308 call_->DestroyAudioReceiveStream(stream_);
solenberg7add0582015-11-20 09:59:34 -08001309 }
solenberg7add0582015-11-20 09:59:34 -08001310 stream_ = call_->CreateAudioReceiveStream(config_);
1311 RTC_CHECK(stream_);
aleloi18e0b672016-10-04 02:45:47 -07001312 SetPlayout(playout_);
solenberg7add0582015-11-20 09:59:34 -08001313 }
1314
1315 rtc::ThreadChecker worker_thread_checker_;
1316 webrtc::Call* call_ = nullptr;
1317 webrtc::AudioReceiveStream::Config config_;
1318 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if
1319 // configuration changes.
1320 webrtc::AudioReceiveStream* stream_ = nullptr;
aleloi18e0b672016-10-04 02:45:47 -07001321 bool playout_ = false;
solenbergc96df772015-10-21 13:01:53 -07001322
1323 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioReceiveStream);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001324};
1325
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001326WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine,
nisse51542be2016-02-12 02:27:06 -08001327 const MediaConfig& config,
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001328 const AudioOptions& options,
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001329 webrtc::Call* call)
nisse51542be2016-02-12 02:27:06 -08001330 : VoiceMediaChannel(config), engine_(engine), call_(call) {
solenberg0a617e22015-10-20 15:49:38 -07001331 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel";
solenberg566ef242015-11-06 15:34:49 -08001332 RTC_DCHECK(call);
solenberg0a617e22015-10-20 15:49:38 -07001333 engine->RegisterChannel(this);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001334 SetOptions(options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001335}
1336
1337WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() {
solenberg566ef242015-11-06 15:34:49 -08001338 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg0a617e22015-10-20 15:49:38 -07001339 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel";
solenberg7add0582015-11-20 09:59:34 -08001340 // TODO(solenberg): Should be able to delete the streams directly, without
1341 // going through RemoveNnStream(), once stream objects handle
1342 // all (de)configuration.
solenbergc96df772015-10-21 13:01:53 -07001343 while (!send_streams_.empty()) {
1344 RemoveSendStream(send_streams_.begin()->first);
solenbergd97ec302015-10-07 01:40:33 -07001345 }
solenberg7add0582015-11-20 09:59:34 -08001346 while (!recv_streams_.empty()) {
1347 RemoveRecvStream(recv_streams_.begin()->first);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001348 }
solenberg0a617e22015-10-20 15:49:38 -07001349 engine()->UnregisterChannel(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001350}
1351
nisse51542be2016-02-12 02:27:06 -08001352rtc::DiffServCodePoint WebRtcVoiceMediaChannel::PreferredDscp() const {
1353 return kAudioDscpValue;
1354}
1355
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001356bool WebRtcVoiceMediaChannel::SetSendParameters(
1357 const AudioSendParameters& params) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001358 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetSendParameters");
solenberg566ef242015-11-06 15:34:49 -08001359 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7e4e01a2015-12-02 08:05:01 -08001360 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendParameters: "
1361 << params.ToString();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001362 // TODO(pthatcher): Refactor this to be more clean now that we have
1363 // all the information at once.
solenberg3a941542015-11-16 07:34:50 -08001364
1365 if (!SetSendCodecs(params.codecs)) {
1366 return false;
1367 }
1368
solenberg7e4e01a2015-12-02 08:05:01 -08001369 if (!ValidateRtpExtensions(params.extensions)) {
1370 return false;
1371 }
1372 std::vector<webrtc::RtpExtension> filtered_extensions =
1373 FilterRtpExtensions(params.extensions,
1374 webrtc::RtpExtension::IsSupportedForAudio, true);
1375 if (send_rtp_extensions_ != filtered_extensions) {
1376 send_rtp_extensions_.swap(filtered_extensions);
solenberg3a941542015-11-16 07:34:50 -08001377 for (auto& it : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001378 it.second->SetRtpExtensions(send_rtp_extensions_);
solenberg3a941542015-11-16 07:34:50 -08001379 }
1380 }
1381
deadbeef80346142016-04-27 14:17:10 -07001382 if (!SetMaxSendBitrate(params.max_bandwidth_bps)) {
solenberg3a941542015-11-16 07:34:50 -08001383 return false;
1384 }
1385 return SetOptions(params.options);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001386}
1387
1388bool WebRtcVoiceMediaChannel::SetRecvParameters(
1389 const AudioRecvParameters& params) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001390 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetRecvParameters");
solenberg566ef242015-11-06 15:34:49 -08001391 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7e4e01a2015-12-02 08:05:01 -08001392 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetRecvParameters: "
1393 << params.ToString();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001394 // TODO(pthatcher): Refactor this to be more clean now that we have
1395 // all the information at once.
solenberg7add0582015-11-20 09:59:34 -08001396
1397 if (!SetRecvCodecs(params.codecs)) {
1398 return false;
1399 }
1400
solenberg7e4e01a2015-12-02 08:05:01 -08001401 if (!ValidateRtpExtensions(params.extensions)) {
1402 return false;
1403 }
1404 std::vector<webrtc::RtpExtension> filtered_extensions =
1405 FilterRtpExtensions(params.extensions,
1406 webrtc::RtpExtension::IsSupportedForAudio, false);
1407 if (recv_rtp_extensions_ != filtered_extensions) {
1408 recv_rtp_extensions_.swap(filtered_extensions);
solenberg7add0582015-11-20 09:59:34 -08001409 for (auto& it : recv_streams_) {
1410 it.second->RecreateAudioReceiveStream(recv_rtp_extensions_);
1411 }
1412 }
solenberg7add0582015-11-20 09:59:34 -08001413 return true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001414}
1415
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001416webrtc::RtpParameters WebRtcVoiceMediaChannel::GetRtpSendParameters(
skvlade0d46372016-04-07 22:59:22 -07001417 uint32_t ssrc) const {
1418 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1419 auto it = send_streams_.find(ssrc);
1420 if (it == send_streams_.end()) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001421 LOG(LS_WARNING) << "Attempting to get RTP send parameters for stream "
1422 << "with ssrc " << ssrc << " which doesn't exist.";
skvlade0d46372016-04-07 22:59:22 -07001423 return webrtc::RtpParameters();
1424 }
1425
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001426 webrtc::RtpParameters rtp_params = it->second->rtp_parameters();
1427 // Need to add the common list of codecs to the send stream-specific
1428 // RTP parameters.
1429 for (const AudioCodec& codec : send_codecs_) {
1430 rtp_params.codecs.push_back(codec.ToCodecParameters());
1431 }
1432 return rtp_params;
skvlade0d46372016-04-07 22:59:22 -07001433}
1434
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001435bool WebRtcVoiceMediaChannel::SetRtpSendParameters(
skvlade0d46372016-04-07 22:59:22 -07001436 uint32_t ssrc,
1437 const webrtc::RtpParameters& parameters) {
1438 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
skvlade0d46372016-04-07 22:59:22 -07001439 auto it = send_streams_.find(ssrc);
1440 if (it == send_streams_.end()) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001441 LOG(LS_WARNING) << "Attempting to set RTP send parameters for stream "
1442 << "with ssrc " << ssrc << " which doesn't exist.";
skvlade0d46372016-04-07 22:59:22 -07001443 return false;
1444 }
1445
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001446 // TODO(deadbeef): Handle setting parameters with a list of codecs in a
1447 // different order (which should change the send codec).
1448 webrtc::RtpParameters current_parameters = GetRtpSendParameters(ssrc);
1449 if (current_parameters.codecs != parameters.codecs) {
1450 LOG(LS_ERROR) << "Using SetParameters to change the set of codecs "
1451 << "is not currently supported.";
1452 return false;
1453 }
1454
minyue7a973442016-10-20 03:27:12 -07001455 // TODO(minyue): The following legacy actions go into
1456 // |WebRtcAudioSendStream::SetRtpParameters()| which is called at the end,
1457 // though there are two difference:
1458 // 1. |WebRtcVoiceMediaChannel::SetChannelSendParameters()| only calls
1459 // |SetSendCodec| while |WebRtcAudioSendStream::SetRtpParameters()| calls
1460 // |SetSendCodecs|. The outcome should be the same.
1461 // 2. AudioSendStream can be recreated.
1462
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001463 // Codecs are handled at the WebRtcVoiceMediaChannel level.
1464 webrtc::RtpParameters reduced_params = parameters;
1465 reduced_params.codecs.clear();
minyue7a973442016-10-20 03:27:12 -07001466 return it->second->SetRtpParameters(reduced_params);
skvlade0d46372016-04-07 22:59:22 -07001467}
1468
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001469webrtc::RtpParameters WebRtcVoiceMediaChannel::GetRtpReceiveParameters(
1470 uint32_t ssrc) const {
1471 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef3bc15102017-04-20 19:25:07 -07001472 webrtc::RtpParameters rtp_params;
1473 // SSRC of 0 represents the default receive stream.
1474 if (ssrc == 0) {
1475 if (!default_sink_) {
1476 LOG(LS_WARNING) << "Attempting to get RTP parameters for the default, "
1477 "unsignaled audio receive stream, but not yet "
1478 "configured to receive such a stream.";
1479 return rtp_params;
1480 }
1481 rtp_params.encodings.emplace_back();
1482 } else {
1483 auto it = recv_streams_.find(ssrc);
1484 if (it == recv_streams_.end()) {
1485 LOG(LS_WARNING) << "Attempting to get RTP receive parameters for stream "
1486 << "with ssrc " << ssrc << " which doesn't exist.";
1487 return webrtc::RtpParameters();
1488 }
1489 rtp_params.encodings.emplace_back();
1490 // TODO(deadbeef): Return stream-specific parameters.
1491 rtp_params.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001492 }
1493
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001494 for (const AudioCodec& codec : recv_codecs_) {
1495 rtp_params.codecs.push_back(codec.ToCodecParameters());
1496 }
1497 return rtp_params;
1498}
1499
1500bool WebRtcVoiceMediaChannel::SetRtpReceiveParameters(
1501 uint32_t ssrc,
1502 const webrtc::RtpParameters& parameters) {
1503 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef3bc15102017-04-20 19:25:07 -07001504 // SSRC of 0 represents the default receive stream.
1505 if (ssrc == 0) {
1506 if (!default_sink_) {
1507 LOG(LS_WARNING) << "Attempting to set RTP parameters for the default, "
1508 "unsignaled audio receive stream, but not yet "
1509 "configured to receive such a stream.";
1510 return false;
1511 }
1512 } else {
1513 auto it = recv_streams_.find(ssrc);
1514 if (it == recv_streams_.end()) {
1515 LOG(LS_WARNING) << "Attempting to set RTP receive parameters for stream "
1516 << "with ssrc " << ssrc << " which doesn't exist.";
1517 return false;
1518 }
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001519 }
1520
1521 webrtc::RtpParameters current_parameters = GetRtpReceiveParameters(ssrc);
1522 if (current_parameters != parameters) {
1523 LOG(LS_ERROR) << "Changing the RTP receive parameters is currently "
1524 << "unsupported.";
1525 return false;
1526 }
1527 return true;
1528}
1529
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001530bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
solenberg566ef242015-11-06 15:34:49 -08001531 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001532 LOG(LS_INFO) << "Setting voice channel options: "
1533 << options.ToString();
1534
1535 // We retain all of the existing options, and apply the given ones
1536 // on top. This means there is no way to "clear" options such that
1537 // they go back to the engine default.
1538 options_.SetAll(options);
solenberg246b8172015-12-08 09:50:23 -08001539 if (!engine()->ApplyOptions(options_)) {
1540 LOG(LS_WARNING) <<
1541 "Failed to apply engine options during channel SetOptions.";
1542 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001543 }
minyue6b825df2016-10-31 04:08:32 -07001544
ossu20a4b3f2017-04-27 02:08:52 -07001545 rtc::Optional<std::string> audio_network_adaptor_config =
minyue6b825df2016-10-31 04:08:32 -07001546 GetAudioNetworkAdaptorConfig(options_);
1547 for (auto& it : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001548 it.second->SetAudioNetworkAdaptorConfig(audio_network_adaptor_config);
minyue6b825df2016-10-31 04:08:32 -07001549 }
1550
solenberg76377c52017-02-21 00:54:31 -08001551 LOG(LS_INFO) << "Set voice channel options. Current options: "
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001552 << options_.ToString();
1553 return true;
1554}
1555
1556bool WebRtcVoiceMediaChannel::SetRecvCodecs(
1557 const std::vector<AudioCodec>& codecs) {
solenberg566ef242015-11-06 15:34:49 -08001558 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg8fb30c32015-10-13 03:06:58 -07001559
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001560 // Set the payload types to be used for incoming media.
solenberg0b675462015-10-09 01:37:09 -07001561 LOG(LS_INFO) << "Setting receive voice codecs.";
solenberg0b675462015-10-09 01:37:09 -07001562
1563 if (!VerifyUniquePayloadTypes(codecs)) {
1564 LOG(LS_ERROR) << "Codec payload types overlap.";
1565 return false;
1566 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001567
kwibergd32bf752017-01-19 07:03:59 -08001568 // Create a payload type -> SdpAudioFormat map with all the decoders. Fail
1569 // unless the factory claims to support all decoders.
1570 std::map<int, webrtc::SdpAudioFormat> decoder_map;
1571 for (const AudioCodec& codec : codecs) {
deadbeefcb383672017-04-26 16:28:42 -07001572 // Log a warning if a codec's payload type is changing. This used to be
1573 // treated as an error. It's abnormal, but not really illegal.
1574 AudioCodec old_codec;
1575 if (FindCodec(recv_codecs_, codec, &old_codec) &&
1576 old_codec.id != codec.id) {
1577 LOG(LS_WARNING) << codec.name << " mapped to a second payload type ("
1578 << codec.id << ", was already mapped to " << old_codec.id
1579 << ")";
1580 }
kwibergd32bf752017-01-19 07:03:59 -08001581 auto format = AudioCodecToSdpAudioFormat(codec);
1582 if (!IsCodec(codec, "cn") && !IsCodec(codec, "telephone-event") &&
1583 !engine()->decoder_factory_->IsSupportedDecoder(format)) {
1584 LOG(LS_ERROR) << "Unsupported codec: " << format;
1585 return false;
1586 }
deadbeefcb383672017-04-26 16:28:42 -07001587 // We allow adding new codecs but don't allow changing the payload type of
1588 // codecs that are already configured since we might already be receiving
1589 // packets with that payload type. See RFC3264, Section 8.3.2.
1590 // TODO(deadbeef): Also need to check for clashes with previously mapped
1591 // payload types, and not just currently mapped ones. For example, this
1592 // should be illegal:
1593 // 1. {100: opus/48000/2, 101: ISAC/16000}
1594 // 2. {100: opus/48000/2}
1595 // 3. {100: opus/48000/2, 101: ISAC/32000}
1596 // Though this check really should happen at a higher level, since this
1597 // conflict could happen between audio and video codecs.
1598 auto existing = decoder_map_.find(codec.id);
1599 if (existing != decoder_map_.end() && !existing->second.Matches(format)) {
1600 LOG(LS_ERROR) << "Attempting to use payload type " << codec.id << " for "
1601 << codec.name << ", but it is already used for "
1602 << existing->second.name;
1603 return false;
1604 }
kwibergd32bf752017-01-19 07:03:59 -08001605 decoder_map.insert({codec.id, std::move(format)});
1606 }
1607
deadbeefcb383672017-04-26 16:28:42 -07001608 if (decoder_map == decoder_map_) {
1609 // There's nothing new to configure.
1610 return true;
1611 }
1612
kwiberg37b8b112016-11-03 02:46:53 -07001613 if (playout_) {
1614 // Receive codecs can not be changed while playing. So we temporarily
1615 // pause playout.
1616 ChangePlayout(false);
1617 }
1618
kwiberg1c07c702017-03-27 07:15:49 -07001619 decoder_map_ = std::move(decoder_map);
kwibergd32bf752017-01-19 07:03:59 -08001620 for (auto& kv : recv_streams_) {
kwiberg1c07c702017-03-27 07:15:49 -07001621 kv.second->RecreateAudioReceiveStream(decoder_map_);
solenberg26c8c912015-11-27 04:00:25 -08001622 }
kwibergd32bf752017-01-19 07:03:59 -08001623 recv_codecs_ = codecs;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001624
kwiberg37b8b112016-11-03 02:46:53 -07001625 if (desired_playout_ && !playout_) {
1626 ChangePlayout(desired_playout_);
1627 }
kwibergd32bf752017-01-19 07:03:59 -08001628 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001629}
1630
solenberg72e29d22016-03-08 06:35:16 -08001631// Utility function called from SetSendParameters() to extract current send
1632// codec settings from the given list of codecs (originally from SDP). Both send
1633// and receive streams may be reconfigured based on the new settings.
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001634bool WebRtcVoiceMediaChannel::SetSendCodecs(
1635 const std::vector<AudioCodec>& codecs) {
solenberg566ef242015-11-06 15:34:49 -08001636 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenbergb5727682015-12-04 15:22:19 +01001637 dtmf_payload_type_ = rtc::Optional<int>();
solenbergffbbcac2016-11-17 05:25:37 -08001638 dtmf_payload_freq_ = -1;
1639
1640 // Validate supplied codecs list.
1641 for (const AudioCodec& codec : codecs) {
1642 // TODO(solenberg): Validate more aspects of input - that payload types
1643 // don't overlap, remove redundant/unsupported codecs etc -
1644 // the same way it is done for RtpHeaderExtensions.
1645 if (codec.id < kMinPayloadType || codec.id > kMaxPayloadType) {
1646 LOG(LS_WARNING) << "Codec payload type out of range: " << ToString(codec);
1647 return false;
1648 }
1649 }
1650
1651 // Find PT of telephone-event codec with lowest clockrate, as a fallback, in
1652 // case we don't have a DTMF codec with a rate matching the send codec's, or
1653 // if this function returns early.
1654 std::vector<AudioCodec> dtmf_codecs;
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02001655 for (const AudioCodec& codec : codecs) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02001656 if (IsCodec(codec, kDtmfCodecName)) {
solenbergffbbcac2016-11-17 05:25:37 -08001657 dtmf_codecs.push_back(codec);
1658 if (!dtmf_payload_type_ || codec.clockrate < dtmf_payload_freq_) {
1659 dtmf_payload_type_ = rtc::Optional<int>(codec.id);
1660 dtmf_payload_freq_ = codec.clockrate;
solenberg31642aa2016-03-14 08:00:37 -07001661 }
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001662 }
1663 }
1664
ossu20a4b3f2017-04-27 02:08:52 -07001665 // Scan through the list to figure out the codec to use for sending.
1666 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec> send_codec_spec;
stefan1ccf73f2017-03-27 03:51:18 -07001667 webrtc::Call::Config::BitrateConfig bitrate_config;
ossu20a4b3f2017-04-27 02:08:52 -07001668 rtc::Optional<webrtc::AudioCodecInfo> voice_codec_info;
1669 for (const AudioCodec& voice_codec : codecs) {
1670 if (!(IsCodec(voice_codec, kCnCodecName) ||
1671 IsCodec(voice_codec, kDtmfCodecName) ||
1672 IsCodec(voice_codec, kRedCodecName))) {
1673 webrtc::SdpAudioFormat format(voice_codec.name, voice_codec.clockrate,
1674 voice_codec.channels, voice_codec.params);
solenberg72e29d22016-03-08 06:35:16 -08001675
ossu20a4b3f2017-04-27 02:08:52 -07001676 voice_codec_info = engine()->encoder_factory_->QueryAudioEncoder(format);
1677 if (!voice_codec_info) {
1678 LOG(LS_WARNING) << "Unknown codec " << ToString(voice_codec);
solenberg72e29d22016-03-08 06:35:16 -08001679 continue;
1680 }
1681
ossu20a4b3f2017-04-27 02:08:52 -07001682 send_codec_spec =
1683 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>(
1684 {voice_codec.id, format});
1685 if (voice_codec.bitrate > 0) {
1686 send_codec_spec->target_bitrate_bps =
1687 rtc::Optional<int>(voice_codec.bitrate);
1688 }
1689 send_codec_spec->transport_cc_enabled = HasTransportCc(voice_codec);
1690 send_codec_spec->nack_enabled = HasNack(voice_codec);
1691 bitrate_config = GetBitrateConfigForCodec(voice_codec);
1692 break;
1693 }
1694 }
1695
1696 if (!send_codec_spec) {
1697 return false;
1698 }
1699
1700 RTC_DCHECK(voice_codec_info);
1701 if (voice_codec_info->allow_comfort_noise) {
1702 // Loop through the codecs list again to find the CN codec.
1703 // TODO(solenberg): Break out into a separate function?
1704 for (const AudioCodec& cn_codec : codecs) {
ossu0c4b8492017-03-02 11:03:25 -08001705 if (IsCodec(cn_codec, kCnCodecName) &&
ossu20a4b3f2017-04-27 02:08:52 -07001706 cn_codec.clockrate == send_codec_spec->format.clockrate_hz) {
ossu0c4b8492017-03-02 11:03:25 -08001707 switch (cn_codec.clockrate) {
solenberg72e29d22016-03-08 06:35:16 -08001708 case 8000:
1709 case 16000:
1710 case 32000:
ossu20a4b3f2017-04-27 02:08:52 -07001711 send_codec_spec->cng_payload_type = rtc::Optional<int>(cn_codec.id);
solenberg72e29d22016-03-08 06:35:16 -08001712 break;
1713 default:
ossu0c4b8492017-03-02 11:03:25 -08001714 LOG(LS_WARNING) << "CN frequency " << cn_codec.clockrate
solenberg72e29d22016-03-08 06:35:16 -08001715 << " not supported.";
ossu20a4b3f2017-04-27 02:08:52 -07001716 break;
solenberg72e29d22016-03-08 06:35:16 -08001717 }
solenberg72e29d22016-03-08 06:35:16 -08001718 break;
1719 }
1720 }
solenbergffbbcac2016-11-17 05:25:37 -08001721
1722 // Find the telephone-event PT exactly matching the preferred send codec.
1723 for (const AudioCodec& dtmf_codec : dtmf_codecs) {
ossu20a4b3f2017-04-27 02:08:52 -07001724 if (dtmf_codec.clockrate == send_codec_spec->format.clockrate_hz) {
solenbergffbbcac2016-11-17 05:25:37 -08001725 dtmf_payload_type_ = rtc::Optional<int>(dtmf_codec.id);
1726 dtmf_payload_freq_ = dtmf_codec.clockrate;
1727 break;
1728 }
1729 }
solenberg72e29d22016-03-08 06:35:16 -08001730 }
1731
solenberg971cab02016-06-14 10:02:41 -07001732 if (send_codec_spec_ != send_codec_spec) {
1733 send_codec_spec_ = std::move(send_codec_spec);
stefan13f1a0a2016-11-30 07:22:58 -08001734 // Apply new settings to all streams.
solenberg971cab02016-06-14 10:02:41 -07001735 for (const auto& kv : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001736 kv.second->SetSendCodecSpec(*send_codec_spec_);
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001737 }
stefan13f1a0a2016-11-30 07:22:58 -08001738 } else {
1739 // If the codec isn't changing, set the start bitrate to -1 which means
1740 // "unchanged" so that BWE isn't affected.
stefan1ccf73f2017-03-27 03:51:18 -07001741 bitrate_config.start_bitrate_bps = -1;
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001742 }
stefan1ccf73f2017-03-27 03:51:18 -07001743 call_->SetBitrateConfig(bitrate_config);
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001744
solenberg8189b022016-06-14 12:13:00 -07001745 // Check if the transport cc feedback or NACK status has changed on the
1746 // preferred send codec, and in that case reconfigure all receive streams.
ossu20a4b3f2017-04-27 02:08:52 -07001747 if (recv_transport_cc_enabled_ != send_codec_spec_->transport_cc_enabled ||
1748 recv_nack_enabled_ != send_codec_spec_->nack_enabled) {
solenberg72e29d22016-03-08 06:35:16 -08001749 LOG(LS_INFO) << "Recreate all the receive streams because the send "
1750 "codec has changed.";
ossu20a4b3f2017-04-27 02:08:52 -07001751 recv_transport_cc_enabled_ = send_codec_spec_->transport_cc_enabled;
1752 recv_nack_enabled_ = send_codec_spec_->nack_enabled;
solenberg72e29d22016-03-08 06:35:16 -08001753 for (auto& kv : recv_streams_) {
solenberg8189b022016-06-14 12:13:00 -07001754 kv.second->RecreateAudioReceiveStream(recv_transport_cc_enabled_,
1755 recv_nack_enabled_);
solenberg72e29d22016-03-08 06:35:16 -08001756 }
1757 }
1758
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001759 send_codecs_ = codecs;
solenberg72e29d22016-03-08 06:35:16 -08001760 return true;
1761}
1762
aleloi84ef6152016-08-04 05:28:21 -07001763void WebRtcVoiceMediaChannel::SetPlayout(bool playout) {
kwiberg37b8b112016-11-03 02:46:53 -07001764 desired_playout_ = playout;
1765 return ChangePlayout(desired_playout_);
1766}
1767
1768void WebRtcVoiceMediaChannel::ChangePlayout(bool playout) {
1769 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::ChangePlayout");
solenberg566ef242015-11-06 15:34:49 -08001770 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001771 if (playout_ == playout) {
aleloi84ef6152016-08-04 05:28:21 -07001772 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001773 }
1774
aleloi84ef6152016-08-04 05:28:21 -07001775 for (const auto& kv : recv_streams_) {
1776 kv.second->SetPlayout(playout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001777 }
solenberg1ac56142015-10-13 03:58:19 -07001778 playout_ = playout;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001779}
1780
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001781void WebRtcVoiceMediaChannel::SetSend(bool send) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001782 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetSend");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001783 if (send_ == send) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001784 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001785 }
1786
solenbergd53a3f92016-04-14 13:56:37 -07001787 // Apply channel specific options, and initialize the ADM for recording (this
1788 // may take time on some platforms, e.g. Android).
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001789 if (send) {
solenberg63b34542015-09-29 06:06:31 -07001790 engine()->ApplyOptions(options_);
solenbergd53a3f92016-04-14 13:56:37 -07001791
1792 // InitRecording() may return an error if the ADM is already recording.
1793 if (!engine()->adm()->RecordingIsInitialized() &&
1794 !engine()->adm()->Recording()) {
1795 if (engine()->adm()->InitRecording() != 0) {
1796 LOG(LS_WARNING) << "Failed to initialize recording";
1797 }
1798 }
solenberg63b34542015-09-29 06:06:31 -07001799 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001800
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001801 // Change the settings on each send channel.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001802 for (auto& kv : send_streams_) {
1803 kv.second->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001804 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001805
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001806 send_ = send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001807}
1808
Peter Boström0c4e06b2015-10-07 12:23:21 +02001809bool WebRtcVoiceMediaChannel::SetAudioSend(uint32_t ssrc,
1810 bool enable,
solenberg1dd98f32015-09-10 01:57:14 -07001811 const AudioOptions* options,
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001812 AudioSource* source) {
solenberg566ef242015-11-06 15:34:49 -08001813 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg1dd98f32015-09-10 01:57:14 -07001814 // TODO(solenberg): The state change should be fully rolled back if any one of
1815 // these calls fail.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001816 if (!SetLocalSource(ssrc, source)) {
solenberg1dd98f32015-09-10 01:57:14 -07001817 return false;
1818 }
solenbergdfc8f4f2015-10-01 02:31:10 -07001819 if (!MuteStream(ssrc, !enable)) {
solenberg1dd98f32015-09-10 01:57:14 -07001820 return false;
1821 }
solenbergdfc8f4f2015-10-01 02:31:10 -07001822 if (enable && options) {
solenberg1dd98f32015-09-10 01:57:14 -07001823 return SetOptions(*options);
1824 }
1825 return true;
1826}
1827
solenberg0a617e22015-10-20 15:49:38 -07001828int WebRtcVoiceMediaChannel::CreateVoEChannel() {
1829 int id = engine()->CreateVoEChannel();
1830 if (id == -1) {
1831 LOG_RTCERR0(CreateVoEChannel);
1832 return -1;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001833 }
mflodman3d7db262016-04-29 00:57:13 -07001834
solenberg0a617e22015-10-20 15:49:38 -07001835 return id;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001836}
1837
solenberg7add0582015-11-20 09:59:34 -08001838bool WebRtcVoiceMediaChannel::DeleteVoEChannel(int channel) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001839 if (engine()->voe()->base()->DeleteChannel(channel) == -1) {
1840 LOG_RTCERR1(DeleteChannel, channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001841 return false;
1842 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001843 return true;
1844}
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001845
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001846bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001847 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::AddSendStream");
solenberg566ef242015-11-06 15:34:49 -08001848 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg0a617e22015-10-20 15:49:38 -07001849 LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
1850
1851 uint32_t ssrc = sp.first_ssrc();
1852 RTC_DCHECK(0 != ssrc);
1853
1854 if (GetSendChannelId(ssrc) != -1) {
1855 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001856 return false;
1857 }
1858
solenberg0a617e22015-10-20 15:49:38 -07001859 // Create a new channel for sending audio data.
1860 int channel = CreateVoEChannel();
1861 if (channel == -1) {
1862 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001863 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001864
solenbergc96df772015-10-21 13:01:53 -07001865 // Save the channel to send_streams_, so that RemoveSendStream() can still
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001866 // delete the channel in case failure happens below.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001867 webrtc::AudioTransport* audio_transport =
1868 engine()->voe()->base()->audio_transport();
mflodman3d7db262016-04-29 00:57:13 -07001869
minyue6b825df2016-10-31 04:08:32 -07001870 rtc::Optional<std::string> audio_network_adaptor_config =
1871 GetAudioNetworkAdaptorConfig(options_);
skvlade0d46372016-04-07 22:59:22 -07001872 WebRtcAudioSendStream* stream = new WebRtcAudioSendStream(
solenberg971cab02016-06-14 10:02:41 -07001873 channel, audio_transport, ssrc, sp.cname, send_codec_spec_,
minyue6b825df2016-10-31 04:08:32 -07001874 send_rtp_extensions_, max_send_bitrate_bps_, audio_network_adaptor_config,
ossu20a4b3f2017-04-27 02:08:52 -07001875 call_, this, engine()->encoder_factory_);
skvlade0d46372016-04-07 22:59:22 -07001876 send_streams_.insert(std::make_pair(ssrc, stream));
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001877
solenberg4a0f7b52016-06-16 13:07:33 -07001878 // At this point the stream's local SSRC has been updated. If it is the first
1879 // send stream, make sure that all the receive streams are updated with the
1880 // same SSRC in order to send receiver reports.
solenbergc96df772015-10-21 13:01:53 -07001881 if (send_streams_.size() == 1) {
solenberg0a617e22015-10-20 15:49:38 -07001882 receiver_reports_ssrc_ = ssrc;
solenberg4a0f7b52016-06-16 13:07:33 -07001883 for (const auto& kv : recv_streams_) {
1884 // TODO(solenberg): Allow applications to set the RTCP SSRC of receive
1885 // streams instead, so we can avoid recreating the streams here.
1886 kv.second->RecreateAudioReceiveStream(ssrc);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001887 }
1888 }
1889
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001890 send_streams_[ssrc]->SetSend(send_);
1891 return true;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001892}
1893
Peter Boström0c4e06b2015-10-07 12:23:21 +02001894bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001895 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::RemoveSendStream");
solenberg566ef242015-11-06 15:34:49 -08001896 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg3a941542015-11-16 07:34:50 -08001897 LOG(LS_INFO) << "RemoveSendStream: " << ssrc;
1898
solenbergc96df772015-10-21 13:01:53 -07001899 auto it = send_streams_.find(ssrc);
1900 if (it == send_streams_.end()) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001901 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
1902 << " which doesn't exist.";
1903 return false;
1904 }
1905
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001906 it->second->SetSend(false);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001907
solenberg7602aab2016-11-14 11:30:07 -08001908 // TODO(solenberg): If we're removing the receiver_reports_ssrc_ stream, find
1909 // the first active send stream and use that instead, reassociating receive
1910 // streams.
1911
solenberg7add0582015-11-20 09:59:34 -08001912 // Clean up and delete the send stream+channel.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001913 int channel = it->second->channel();
solenberg0a617e22015-10-20 15:49:38 -07001914 LOG(LS_INFO) << "Removing audio send stream " << ssrc
1915 << " with VoiceEngine channel #" << channel << ".";
solenberg7add0582015-11-20 09:59:34 -08001916 delete it->second;
1917 send_streams_.erase(it);
1918 if (!DeleteVoEChannel(channel)) {
solenberg0a617e22015-10-20 15:49:38 -07001919 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001920 }
solenbergc96df772015-10-21 13:01:53 -07001921 if (send_streams_.empty()) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001922 SetSend(false);
solenberg0a617e22015-10-20 15:49:38 -07001923 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001924 return true;
1925}
1926
1927bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001928 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::AddRecvStream");
solenberg566ef242015-11-06 15:34:49 -08001929 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergd97ec302015-10-07 01:40:33 -07001930 LOG(LS_INFO) << "AddRecvStream: " << sp.ToString();
1931
solenberg0b675462015-10-09 01:37:09 -07001932 if (!ValidateStreamParams(sp)) {
wu@webrtc.org78187522013-10-07 23:32:02 +00001933 return false;
1934 }
1935
solenberg7add0582015-11-20 09:59:34 -08001936 const uint32_t ssrc = sp.first_ssrc();
solenberg0b675462015-10-09 01:37:09 -07001937 if (ssrc == 0) {
1938 LOG(LS_WARNING) << "AddRecvStream with ssrc==0 is not supported.";
1939 return false;
1940 }
1941
solenberg2100c0b2017-03-01 11:29:29 -08001942 // If this stream was previously received unsignaled, we promote it, possibly
1943 // recreating the AudioReceiveStream, if sync_label has changed.
1944 if (MaybeDeregisterUnsignaledRecvStream(ssrc)) {
solenberg4904fb62017-02-17 12:01:14 -08001945 recv_streams_[ssrc]->MaybeRecreateAudioReceiveStream(sp.sync_label);
solenberg4904fb62017-02-17 12:01:14 -08001946 return true;
solenberg1ac56142015-10-13 03:58:19 -07001947 }
solenberg0b675462015-10-09 01:37:09 -07001948
solenberg7add0582015-11-20 09:59:34 -08001949 if (GetReceiveChannelId(ssrc) != -1) {
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001950 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001951 return false;
1952 }
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02001953
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001954 // Create a new channel for receiving audio data.
solenberg7add0582015-11-20 09:59:34 -08001955 const int channel = CreateVoEChannel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001956 if (channel == -1) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001957 return false;
1958 }
Minyue2013aec2015-05-13 14:14:42 +02001959
stefanba4c0e42016-02-04 04:12:24 -08001960 recv_streams_.insert(std::make_pair(
kwiberg1c07c702017-03-27 07:15:49 -07001961 ssrc,
1962 new WebRtcAudioReceiveStream(
1963 channel, ssrc, receiver_reports_ssrc_, recv_transport_cc_enabled_,
1964 recv_nack_enabled_, sp.sync_label, recv_rtp_extensions_, call_, this,
1965 engine()->decoder_factory_, decoder_map_)));
aleloi84ef6152016-08-04 05:28:21 -07001966 recv_streams_[ssrc]->SetPlayout(playout_);
solenberg7add0582015-11-20 09:59:34 -08001967
solenberg1ac56142015-10-13 03:58:19 -07001968 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001969}
1970
Peter Boström0c4e06b2015-10-07 12:23:21 +02001971bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001972 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::RemoveRecvStream");
solenberg566ef242015-11-06 15:34:49 -08001973 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergd97ec302015-10-07 01:40:33 -07001974 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
1975
solenberg7add0582015-11-20 09:59:34 -08001976 const auto it = recv_streams_.find(ssrc);
1977 if (it == recv_streams_.end()) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001978 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
1979 << " which doesn't exist.";
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001980 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001981 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001982
solenberg2100c0b2017-03-01 11:29:29 -08001983 MaybeDeregisterUnsignaledRecvStream(ssrc);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001984
solenberg7add0582015-11-20 09:59:34 -08001985 const int channel = it->second->channel();
1986
1987 // Clean up and delete the receive stream+channel.
1988 LOG(LS_INFO) << "Removing audio receive stream " << ssrc
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001989 << " with VoiceEngine channel #" << channel << ".";
Tommif888bb52015-12-12 01:37:01 +01001990 it->second->SetRawAudioSink(nullptr);
solenberg7add0582015-11-20 09:59:34 -08001991 delete it->second;
1992 recv_streams_.erase(it);
1993 return DeleteVoEChannel(channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001994}
1995
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001996bool WebRtcVoiceMediaChannel::SetLocalSource(uint32_t ssrc,
1997 AudioSource* source) {
solenbergc96df772015-10-21 13:01:53 -07001998 auto it = send_streams_.find(ssrc);
1999 if (it == send_streams_.end()) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002000 if (source) {
2001 // Return an error if trying to set a valid source with an invalid ssrc.
2002 LOG(LS_ERROR) << "SetLocalSource failed with ssrc " << ssrc;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002003 return false;
2004 }
2005
2006 // The channel likely has gone away, do nothing.
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002007 return true;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002008 }
2009
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002010 if (source) {
2011 it->second->SetSource(source);
solenberg1ac56142015-10-13 03:58:19 -07002012 } else {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002013 it->second->ClearSource();
solenberg1ac56142015-10-13 03:58:19 -07002014 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002015
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002016 return true;
2017}
2018
solenberg796b8f92017-03-01 17:02:23 -08002019// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002020bool WebRtcVoiceMediaChannel::GetActiveStreams(
2021 AudioInfo::StreamList* actives) {
solenberg566ef242015-11-06 15:34:49 -08002022 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002023 actives->clear();
solenberg7add0582015-11-20 09:59:34 -08002024 for (const auto& ch : recv_streams_) {
solenberg796b8f92017-03-01 17:02:23 -08002025 int level = ch.second->GetOutputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002026 if (level > 0) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02002027 actives->push_back(std::make_pair(ch.first, level));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002028 }
2029 }
2030 return true;
2031}
2032
solenberg796b8f92017-03-01 17:02:23 -08002033// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002034int WebRtcVoiceMediaChannel::GetOutputLevel() {
solenberg566ef242015-11-06 15:34:49 -08002035 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg1ac56142015-10-13 03:58:19 -07002036 int highest = 0;
solenberg7add0582015-11-20 09:59:34 -08002037 for (const auto& ch : recv_streams_) {
solenberg796b8f92017-03-01 17:02:23 -08002038 highest = std::max(ch.second->GetOutputLevel(), highest);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002039 }
2040 return highest;
2041}
2042
solenberg4bac9c52015-10-09 02:32:53 -07002043bool WebRtcVoiceMediaChannel::SetOutputVolume(uint32_t ssrc, double volume) {
solenberg566ef242015-11-06 15:34:49 -08002044 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg2100c0b2017-03-01 11:29:29 -08002045 std::vector<uint32_t> ssrcs(1, ssrc);
deadbeef3bc15102017-04-20 19:25:07 -07002046 // SSRC of 0 represents the default receive stream.
solenberg1ac56142015-10-13 03:58:19 -07002047 if (ssrc == 0) {
2048 default_recv_volume_ = volume;
solenberg2100c0b2017-03-01 11:29:29 -08002049 ssrcs = unsignaled_recv_ssrcs_;
2050 }
2051 for (uint32_t ssrc : ssrcs) {
2052 const auto it = recv_streams_.find(ssrc);
2053 if (it == recv_streams_.end()) {
2054 LOG(LS_WARNING) << "SetOutputVolume: no recv stream " << ssrc;
2055 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002056 }
solenberg2100c0b2017-03-01 11:29:29 -08002057 it->second->SetOutputVolume(volume);
2058 LOG(LS_INFO) << "SetOutputVolume() to " << volume
2059 << " for recv stream with ssrc " << ssrc;
solenberg1ac56142015-10-13 03:58:19 -07002060 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002061 return true;
2062}
2063
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002064bool WebRtcVoiceMediaChannel::CanInsertDtmf() {
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002065 return dtmf_payload_type_ ? true : false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002066}
2067
solenberg1d63dd02015-12-02 12:35:09 -08002068bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, int event,
2069 int duration) {
solenberg566ef242015-11-06 15:34:49 -08002070 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002071 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::InsertDtmf";
2072 if (!dtmf_payload_type_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002073 return false;
2074 }
2075
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002076 // Figure out which WebRtcAudioSendStream to send the event on.
2077 auto it = ssrc != 0 ? send_streams_.find(ssrc) : send_streams_.begin();
2078 if (it == send_streams_.end()) {
2079 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
solenberg1d63dd02015-12-02 12:35:09 -08002080 return false;
2081 }
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002082 if (event < kMinTelephoneEventCode ||
2083 event > kMaxTelephoneEventCode) {
2084 LOG(LS_WARNING) << "DTMF event code " << event << " out of range.";
solenberg1d63dd02015-12-02 12:35:09 -08002085 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002086 }
solenbergffbbcac2016-11-17 05:25:37 -08002087 RTC_DCHECK_NE(-1, dtmf_payload_freq_);
2088 return it->second->SendTelephoneEvent(*dtmf_payload_type_, dtmf_payload_freq_,
2089 event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002090}
2091
wu@webrtc.orga9890802013-12-13 00:21:03 +00002092void WebRtcVoiceMediaChannel::OnPacketReceived(
jbaucheec21bd2016-03-20 06:15:43 -07002093 rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
solenberg566ef242015-11-06 15:34:49 -08002094 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02002095
mflodman3d7db262016-04-29 00:57:13 -07002096 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
2097 packet_time.not_before);
2098 webrtc::PacketReceiver::DeliveryStatus delivery_result =
2099 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
2100 packet->cdata(), packet->size(),
2101 webrtc_packet_time);
mflodman3d7db262016-04-29 00:57:13 -07002102 if (delivery_result != webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC) {
2103 return;
2104 }
2105
solenberg2100c0b2017-03-01 11:29:29 -08002106 // Create an unsignaled receive stream for this previously not received ssrc.
2107 // If there already is N unsignaled receive streams, delete the oldest.
mflodman3d7db262016-04-29 00:57:13 -07002108 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5208
solenberg1ac56142015-10-13 03:58:19 -07002109 uint32_t ssrc = 0;
jbaucheec21bd2016-03-20 06:15:43 -07002110 if (!GetRtpSsrc(packet->cdata(), packet->size(), &ssrc)) {
solenberg1ac56142015-10-13 03:58:19 -07002111 return;
2112 }
solenberg2100c0b2017-03-01 11:29:29 -08002113 RTC_DCHECK(std::find(unsignaled_recv_ssrcs_.begin(),
2114 unsignaled_recv_ssrcs_.end(), ssrc) == unsignaled_recv_ssrcs_.end());
solenberg1ac56142015-10-13 03:58:19 -07002115
solenberg2100c0b2017-03-01 11:29:29 -08002116 // Add new stream.
mflodman3d7db262016-04-29 00:57:13 -07002117 StreamParams sp;
2118 sp.ssrcs.push_back(ssrc);
solenberg2100c0b2017-03-01 11:29:29 -08002119 LOG(LS_INFO) << "Creating unsignaled receive stream for SSRC=" << ssrc;
mflodman3d7db262016-04-29 00:57:13 -07002120 if (!AddRecvStream(sp)) {
solenberg2100c0b2017-03-01 11:29:29 -08002121 LOG(LS_WARNING) << "Could not create unsignaled receive stream.";
mflodman3d7db262016-04-29 00:57:13 -07002122 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002123 }
solenberg2100c0b2017-03-01 11:29:29 -08002124 unsignaled_recv_ssrcs_.push_back(ssrc);
2125 RTC_HISTOGRAM_COUNTS_LINEAR(
2126 "WebRTC.Audio.NumOfUnsignaledStreams", unsignaled_recv_ssrcs_.size(), 1,
2127 100, 101);
solenbergf748ca42017-02-06 13:03:19 -08002128
solenberg2100c0b2017-03-01 11:29:29 -08002129 // Remove oldest unsignaled stream, if we have too many.
2130 if (unsignaled_recv_ssrcs_.size() > kMaxUnsignaledRecvStreams) {
2131 uint32_t remove_ssrc = unsignaled_recv_ssrcs_.front();
2132 LOG(LS_INFO) << "Removing unsignaled receive stream with SSRC="
2133 << remove_ssrc;
2134 RemoveRecvStream(remove_ssrc);
2135 }
2136 RTC_DCHECK_GE(kMaxUnsignaledRecvStreams, unsignaled_recv_ssrcs_.size());
2137
2138 SetOutputVolume(ssrc, default_recv_volume_);
2139
2140 // The default sink can only be attached to one stream at a time, so we hook
2141 // it up to the *latest* unsignaled stream we've seen, in order to support the
2142 // case where the SSRC of one unsignaled stream changes.
mflodman3d7db262016-04-29 00:57:13 -07002143 if (default_sink_) {
solenberg2100c0b2017-03-01 11:29:29 -08002144 for (uint32_t drop_ssrc : unsignaled_recv_ssrcs_) {
2145 auto it = recv_streams_.find(drop_ssrc);
2146 it->second->SetRawAudioSink(nullptr);
2147 }
mflodman3d7db262016-04-29 00:57:13 -07002148 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
2149 new ProxySink(default_sink_.get()));
solenberg2100c0b2017-03-01 11:29:29 -08002150 SetRawAudioSink(ssrc, std::move(proxy_sink));
mflodman3d7db262016-04-29 00:57:13 -07002151 }
solenberg2100c0b2017-03-01 11:29:29 -08002152
mflodman3d7db262016-04-29 00:57:13 -07002153 delivery_result = call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
2154 packet->cdata(),
2155 packet->size(),
2156 webrtc_packet_time);
2157 RTC_DCHECK_NE(webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC, delivery_result);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002158}
2159
wu@webrtc.orga9890802013-12-13 00:21:03 +00002160void WebRtcVoiceMediaChannel::OnRtcpReceived(
jbaucheec21bd2016-03-20 06:15:43 -07002161 rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
solenberg566ef242015-11-06 15:34:49 -08002162 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02002163
Fredrik Solenberg709ed672015-09-15 12:26:33 +02002164 // Forward packet to Call as well.
2165 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
2166 packet_time.not_before);
2167 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
jbaucheec21bd2016-03-20 06:15:43 -07002168 packet->cdata(), packet->size(), webrtc_packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002169}
2170
Honghai Zhangcc411c02016-03-29 17:27:21 -07002171void WebRtcVoiceMediaChannel::OnNetworkRouteChanged(
2172 const std::string& transport_name,
Honghai Zhang0e533ef2016-04-19 15:41:36 -07002173 const rtc::NetworkRoute& network_route) {
2174 call_->OnNetworkRouteChanged(transport_name, network_route);
Honghai Zhangcc411c02016-03-29 17:27:21 -07002175}
2176
Peter Boström0c4e06b2015-10-07 12:23:21 +02002177bool WebRtcVoiceMediaChannel::MuteStream(uint32_t ssrc, bool muted) {
solenberg566ef242015-11-06 15:34:49 -08002178 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg94218532016-06-16 10:53:22 -07002179 const auto it = send_streams_.find(ssrc);
2180 if (it == send_streams_.end()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002181 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
2182 return false;
2183 }
solenberg94218532016-06-16 10:53:22 -07002184 it->second->SetMuted(muted);
2185
2186 // TODO(solenberg):
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002187 // We set the AGC to mute state only when all the channels are muted.
2188 // This implementation is not ideal, instead we should signal the AGC when
2189 // the mic channel is muted/unmuted. We can't do it today because there
2190 // is no good way to know which stream is mapping to the mic channel.
2191 bool all_muted = muted;
solenberg94218532016-06-16 10:53:22 -07002192 for (const auto& kv : send_streams_) {
2193 all_muted = all_muted && kv.second->muted();
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002194 }
solenberg059fb442016-10-26 05:12:24 -07002195 engine()->apm()->set_output_will_be_muted(all_muted);
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002196
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002197 return true;
2198}
2199
deadbeef80346142016-04-27 14:17:10 -07002200bool WebRtcVoiceMediaChannel::SetMaxSendBitrate(int bps) {
2201 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetMaxSendBitrate.";
2202 max_send_bitrate_bps_ = bps;
minyue7a973442016-10-20 03:27:12 -07002203 bool success = true;
skvlade0d46372016-04-07 22:59:22 -07002204 for (const auto& kv : send_streams_) {
minyue7a973442016-10-20 03:27:12 -07002205 if (!kv.second->SetMaxSendBitrate(max_send_bitrate_bps_)) {
2206 success = false;
skvlade0d46372016-04-07 22:59:22 -07002207 }
2208 }
minyue7a973442016-10-20 03:27:12 -07002209 return success;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002210}
2211
skvlad7a43d252016-03-22 15:32:27 -07002212void WebRtcVoiceMediaChannel::OnReadyToSend(bool ready) {
2213 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2214 LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
2215 call_->SignalChannelNetworkState(
2216 webrtc::MediaType::AUDIO,
2217 ready ? webrtc::kNetworkUp : webrtc::kNetworkDown);
2218}
2219
michaelt79e05882016-11-08 02:50:09 -08002220void WebRtcVoiceMediaChannel::OnTransportOverheadChanged(
2221 int transport_overhead_per_packet) {
2222 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2223 call_->OnTransportOverheadChanged(webrtc::MediaType::AUDIO,
2224 transport_overhead_per_packet);
2225}
2226
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002227bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
Peter Boströmca8b4042016-03-08 14:24:13 -08002228 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::GetStats");
solenberg566ef242015-11-06 15:34:49 -08002229 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg85a04962015-10-27 03:35:21 -07002230 RTC_DCHECK(info);
solenbergd97ec302015-10-07 01:40:33 -07002231
solenberg85a04962015-10-27 03:35:21 -07002232 // Get SSRC and stats for each sender.
hbos1acfbd22016-11-17 23:43:29 -08002233 RTC_DCHECK_EQ(info->senders.size(), 0U);
solenberg85a04962015-10-27 03:35:21 -07002234 for (const auto& stream : send_streams_) {
2235 webrtc::AudioSendStream::Stats stats = stream.second->GetStats();
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002236 VoiceSenderInfo sinfo;
solenberg85a04962015-10-27 03:35:21 -07002237 sinfo.add_ssrc(stats.local_ssrc);
2238 sinfo.bytes_sent = stats.bytes_sent;
2239 sinfo.packets_sent = stats.packets_sent;
2240 sinfo.packets_lost = stats.packets_lost;
2241 sinfo.fraction_lost = stats.fraction_lost;
2242 sinfo.codec_name = stats.codec_name;
hbos1acfbd22016-11-17 23:43:29 -08002243 sinfo.codec_payload_type = stats.codec_payload_type;
solenberg85a04962015-10-27 03:35:21 -07002244 sinfo.ext_seqnum = stats.ext_seqnum;
2245 sinfo.jitter_ms = stats.jitter_ms;
2246 sinfo.rtt_ms = stats.rtt_ms;
2247 sinfo.audio_level = stats.audio_level;
2248 sinfo.aec_quality_min = stats.aec_quality_min;
2249 sinfo.echo_delay_median_ms = stats.echo_delay_median_ms;
2250 sinfo.echo_delay_std_ms = stats.echo_delay_std_ms;
2251 sinfo.echo_return_loss = stats.echo_return_loss;
2252 sinfo.echo_return_loss_enhancement = stats.echo_return_loss_enhancement;
ivoc8c63a822016-10-21 04:10:03 -07002253 sinfo.residual_echo_likelihood = stats.residual_echo_likelihood;
ivoc4e477a12017-01-15 08:29:46 -08002254 sinfo.residual_echo_likelihood_recent_max =
2255 stats.residual_echo_likelihood_recent_max;
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002256 sinfo.typing_noise_detected = (send_ ? stats.typing_noise_detected : false);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002257 info->senders.push_back(sinfo);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002258 }
2259
solenberg85a04962015-10-27 03:35:21 -07002260 // Get SSRC and stats for each receiver.
hbos1acfbd22016-11-17 23:43:29 -08002261 RTC_DCHECK_EQ(info->receivers.size(), 0U);
solenberg7add0582015-11-20 09:59:34 -08002262 for (const auto& stream : recv_streams_) {
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002263 webrtc::AudioReceiveStream::Stats stats = stream.second->GetStats();
2264 VoiceReceiverInfo rinfo;
2265 rinfo.add_ssrc(stats.remote_ssrc);
2266 rinfo.bytes_rcvd = stats.bytes_rcvd;
2267 rinfo.packets_rcvd = stats.packets_rcvd;
2268 rinfo.packets_lost = stats.packets_lost;
2269 rinfo.fraction_lost = stats.fraction_lost;
2270 rinfo.codec_name = stats.codec_name;
hbos1acfbd22016-11-17 23:43:29 -08002271 rinfo.codec_payload_type = stats.codec_payload_type;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002272 rinfo.ext_seqnum = stats.ext_seqnum;
2273 rinfo.jitter_ms = stats.jitter_ms;
2274 rinfo.jitter_buffer_ms = stats.jitter_buffer_ms;
2275 rinfo.jitter_buffer_preferred_ms = stats.jitter_buffer_preferred_ms;
2276 rinfo.delay_estimate_ms = stats.delay_estimate_ms;
2277 rinfo.audio_level = stats.audio_level;
2278 rinfo.expand_rate = stats.expand_rate;
2279 rinfo.speech_expand_rate = stats.speech_expand_rate;
2280 rinfo.secondary_decoded_rate = stats.secondary_decoded_rate;
2281 rinfo.accelerate_rate = stats.accelerate_rate;
2282 rinfo.preemptive_expand_rate = stats.preemptive_expand_rate;
2283 rinfo.decoding_calls_to_silence_generator =
2284 stats.decoding_calls_to_silence_generator;
2285 rinfo.decoding_calls_to_neteq = stats.decoding_calls_to_neteq;
2286 rinfo.decoding_normal = stats.decoding_normal;
2287 rinfo.decoding_plc = stats.decoding_plc;
2288 rinfo.decoding_cng = stats.decoding_cng;
2289 rinfo.decoding_plc_cng = stats.decoding_plc_cng;
henrik.lundin63489782016-09-20 01:47:12 -07002290 rinfo.decoding_muted_output = stats.decoding_muted_output;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002291 rinfo.capture_start_ntp_time_ms = stats.capture_start_ntp_time_ms;
2292 info->receivers.push_back(rinfo);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002293 }
2294
hbos1acfbd22016-11-17 23:43:29 -08002295 // Get codec info
2296 for (const AudioCodec& codec : send_codecs_) {
2297 webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
2298 info->send_codecs.insert(
2299 std::make_pair(codec_params.payload_type, std::move(codec_params)));
2300 }
2301 for (const AudioCodec& codec : recv_codecs_) {
2302 webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
2303 info->receive_codecs.insert(
2304 std::make_pair(codec_params.payload_type, std::move(codec_params)));
2305 }
2306
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002307 return true;
2308}
2309
Tommif888bb52015-12-12 01:37:01 +01002310void WebRtcVoiceMediaChannel::SetRawAudioSink(
2311 uint32_t ssrc,
kwiberg686a8ef2016-02-26 03:00:35 -08002312 std::unique_ptr<webrtc::AudioSinkInterface> sink) {
Tommif888bb52015-12-12 01:37:01 +01002313 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef884f5852016-01-15 09:20:04 -08002314 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::SetRawAudioSink: ssrc:" << ssrc
2315 << " " << (sink ? "(ptr)" : "NULL");
2316 if (ssrc == 0) {
solenberg2100c0b2017-03-01 11:29:29 -08002317 if (!unsignaled_recv_ssrcs_.empty()) {
kwiberg686a8ef2016-02-26 03:00:35 -08002318 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
deadbeef884f5852016-01-15 09:20:04 -08002319 sink ? new ProxySink(sink.get()) : nullptr);
solenberg2100c0b2017-03-01 11:29:29 -08002320 SetRawAudioSink(unsignaled_recv_ssrcs_.back(), std::move(proxy_sink));
deadbeef884f5852016-01-15 09:20:04 -08002321 }
2322 default_sink_ = std::move(sink);
2323 return;
2324 }
Tommif888bb52015-12-12 01:37:01 +01002325 const auto it = recv_streams_.find(ssrc);
2326 if (it == recv_streams_.end()) {
solenberg2100c0b2017-03-01 11:29:29 -08002327 LOG(LS_WARNING) << "SetRawAudioSink: no recv stream " << ssrc;
Tommif888bb52015-12-12 01:37:01 +01002328 return;
2329 }
deadbeef2d110be2016-01-13 12:00:26 -08002330 it->second->SetRawAudioSink(std::move(sink));
Tommif888bb52015-12-12 01:37:01 +01002331}
2332
hbos8d609f62017-04-10 07:39:05 -07002333std::vector<webrtc::RtpSource> WebRtcVoiceMediaChannel::GetSources(
2334 uint32_t ssrc) const {
2335 auto it = recv_streams_.find(ssrc);
2336 RTC_DCHECK(it != recv_streams_.end())
2337 << "Attempting to get contributing sources for SSRC:" << ssrc
2338 << " which doesn't exist.";
2339 return it->second->GetSources();
2340}
2341
Peter Boström0c4e06b2015-10-07 12:23:21 +02002342int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
solenberg566ef242015-11-06 15:34:49 -08002343 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7add0582015-11-20 09:59:34 -08002344 const auto it = recv_streams_.find(ssrc);
2345 if (it != recv_streams_.end()) {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002346 return it->second->channel();
solenberg8fb30c32015-10-13 03:06:58 -07002347 }
solenberg1ac56142015-10-13 03:58:19 -07002348 return -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002349}
2350
Peter Boström0c4e06b2015-10-07 12:23:21 +02002351int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const {
solenberg566ef242015-11-06 15:34:49 -08002352 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergc96df772015-10-21 13:01:53 -07002353 const auto it = send_streams_.find(ssrc);
2354 if (it != send_streams_.end()) {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002355 return it->second->channel();
solenberg8fb30c32015-10-13 03:06:58 -07002356 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002357 return -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002358}
solenberg2100c0b2017-03-01 11:29:29 -08002359
2360bool WebRtcVoiceMediaChannel::
2361 MaybeDeregisterUnsignaledRecvStream(uint32_t ssrc) {
2362 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2363 auto it = std::find(unsignaled_recv_ssrcs_.begin(),
2364 unsignaled_recv_ssrcs_.end(),
2365 ssrc);
2366 if (it != unsignaled_recv_ssrcs_.end()) {
2367 unsignaled_recv_ssrcs_.erase(it);
2368 return true;
2369 }
2370 return false;
2371}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002372} // namespace cricket
2373
2374#endif // HAVE_WEBRTC_VOICE