blob: a6875f81983fc2717cf597583211d07e0494c1f4 [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "api/call/audio_sink.h"
22#include "media/base/audiosource.h"
23#include "media/base/mediaconstants.h"
24#include "media/base/streamparams.h"
25#include "media/engine/adm_helpers.h"
26#include "media/engine/apm_helpers.h"
27#include "media/engine/payload_type_mapper.h"
28#include "media/engine/webrtcmediaengine.h"
29#include "media/engine/webrtcvoe.h"
30#include "modules/audio_mixer/audio_mixer_impl.h"
31#include "modules/audio_processing/aec_dump/aec_dump_factory.h"
32#include "modules/audio_processing/include/audio_processing.h"
33#include "rtc_base/arraysize.h"
34#include "rtc_base/base64.h"
35#include "rtc_base/byteorder.h"
36#include "rtc_base/constructormagic.h"
37#include "rtc_base/helpers.h"
38#include "rtc_base/logging.h"
39#include "rtc_base/race_checker.h"
40#include "rtc_base/stringencode.h"
41#include "rtc_base/stringutils.h"
42#include "rtc_base/trace_event.h"
43#include "system_wrappers/include/field_trial.h"
44#include "system_wrappers/include/metrics.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020045#include "voice_engine/transmit_mixer.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000046
henrike@webrtc.org28e20752013-07-10 00:45:36 +000047namespace cricket {
solenbergd97ec302015-10-07 01:40:33 -070048namespace {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000049
solenberg418b7d32017-06-13 00:38:27 -070050constexpr size_t kMaxUnsignaledRecvStreams = 4;
solenberg2100c0b2017-03-01 11:29:29 -080051
solenberg971cab02016-06-14 10:02:41 -070052constexpr int kNackRtpHistoryMs = 5000;
minyue@webrtc.org2dc6f312014-10-31 05:33:10 +000053
peah1bcfce52016-08-26 07:16:04 -070054// Check to verify that the define for the intelligibility enhancer is properly
55// set.
56#if !defined(WEBRTC_INTELLIGIBILITY_ENHANCER) || \
57 (WEBRTC_INTELLIGIBILITY_ENHANCER != 0 && \
58 WEBRTC_INTELLIGIBILITY_ENHANCER != 1)
59#error "Set WEBRTC_INTELLIGIBILITY_ENHANCER to either 0 or 1"
60#endif
61
ossu20a4b3f2017-04-27 02:08:52 -070062// For SendSideBwe, Opus bitrate should be in the range between 6000 and 32000.
minyue10cbb462016-11-07 09:29:22 -080063const int kOpusMinBitrateBps = 6000;
ossu20a4b3f2017-04-27 02:08:52 -070064const int kOpusBitrateFbBps = 32000;
deadbeef80346142016-04-27 14:17:10 -070065
wu@webrtc.orgde305012013-10-31 15:40:38 +000066// Default audio dscp value.
67// See http://tools.ietf.org/html/rfc2474 for details.
68// See also http://tools.ietf.org/html/draft-jennings-rtcweb-qos-00
solenbergd97ec302015-10-07 01:40:33 -070069const rtc::DiffServCodePoint kAudioDscpValue = rtc::DSCP_EF;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +000070
Fredrik Solenbergb5727682015-12-04 15:22:19 +010071// Constants from voice_engine_defines.h.
72const int kMinTelephoneEventCode = 0; // RFC4733 (Section 2.3.1)
73const int kMaxTelephoneEventCode = 255;
Fredrik Solenbergb5727682015-12-04 15:22:19 +010074
solenberg31642aa2016-03-14 08:00:37 -070075const int kMinPayloadType = 0;
76const int kMaxPayloadType = 127;
77
deadbeef884f5852016-01-15 09:20:04 -080078class ProxySink : public webrtc::AudioSinkInterface {
79 public:
80 ProxySink(AudioSinkInterface* sink) : sink_(sink) { RTC_DCHECK(sink); }
81
82 void OnData(const Data& audio) override { sink_->OnData(audio); }
83
84 private:
85 webrtc::AudioSinkInterface* sink_;
86};
87
solenberg0b675462015-10-09 01:37:09 -070088bool ValidateStreamParams(const StreamParams& sp) {
89 if (sp.ssrcs.empty()) {
90 LOG(LS_ERROR) << "No SSRCs in stream parameters: " << sp.ToString();
91 return false;
92 }
93 if (sp.ssrcs.size() > 1) {
94 LOG(LS_ERROR) << "Multiple SSRCs in stream parameters: " << sp.ToString();
95 return false;
96 }
97 return true;
98}
99
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000100// Dumps an AudioCodec in RFC 2327-ish format.
solenbergd97ec302015-10-07 01:40:33 -0700101std::string ToString(const AudioCodec& codec) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000102 std::stringstream ss;
ossu20a4b3f2017-04-27 02:08:52 -0700103 ss << codec.name << "/" << codec.clockrate << "/" << codec.channels;
104 if (!codec.params.empty()) {
105 ss << " {";
106 for (const auto& param : codec.params) {
107 ss << " " << param.first << "=" << param.second;
108 }
109 ss << " }";
110 }
111 ss << " (" << codec.id << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000112 return ss.str();
113}
Minyue Li7100dcd2015-03-27 05:05:59 +0100114
solenbergd97ec302015-10-07 01:40:33 -0700115bool IsCodec(const AudioCodec& codec, const char* ref_name) {
Minyue Li7100dcd2015-03-27 05:05:59 +0100116 return (_stricmp(codec.name.c_str(), ref_name) == 0);
117}
118
solenbergd97ec302015-10-07 01:40:33 -0700119bool FindCodec(const std::vector<AudioCodec>& codecs,
solenberg26c8c912015-11-27 04:00:25 -0800120 const AudioCodec& codec,
121 AudioCodec* found_codec) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +0200122 for (const AudioCodec& c : codecs) {
123 if (c.Matches(codec)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000124 if (found_codec != NULL) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +0200125 *found_codec = c;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000126 }
127 return true;
128 }
129 }
130 return false;
131}
wu@webrtc.org1d1ffc92013-10-16 18:12:02 +0000132
solenberg0b675462015-10-09 01:37:09 -0700133bool VerifyUniquePayloadTypes(const std::vector<AudioCodec>& codecs) {
134 if (codecs.empty()) {
135 return true;
136 }
137 std::vector<int> payload_types;
138 for (const AudioCodec& codec : codecs) {
139 payload_types.push_back(codec.id);
140 }
141 std::sort(payload_types.begin(), payload_types.end());
142 auto it = std::unique(payload_types.begin(), payload_types.end());
143 return it == payload_types.end();
144}
145
minyue6b825df2016-10-31 04:08:32 -0700146rtc::Optional<std::string> GetAudioNetworkAdaptorConfig(
147 const AudioOptions& options) {
148 if (options.audio_network_adaptor && *options.audio_network_adaptor &&
149 options.audio_network_adaptor_config) {
150 // Turn on audio network adaptor only when |options_.audio_network_adaptor|
151 // equals true and |options_.audio_network_adaptor_config| has a value.
152 return options.audio_network_adaptor_config;
153 }
154 return rtc::Optional<std::string>();
155}
156
gyzhou95aa9642016-12-13 14:06:26 -0800157webrtc::AudioState::Config MakeAudioStateConfig(
158 VoEWrapper* voe_wrapper,
peaha9cc40b2017-06-29 08:32:09 -0700159 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
160 rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing) {
solenberg566ef242015-11-06 15:34:49 -0800161 webrtc::AudioState::Config config;
162 config.voice_engine = voe_wrapper->engine();
gyzhou95aa9642016-12-13 14:06:26 -0800163 if (audio_mixer) {
164 config.audio_mixer = audio_mixer;
165 } else {
166 config.audio_mixer = webrtc::AudioMixerImpl::Create();
167 }
peaha9cc40b2017-06-29 08:32:09 -0700168 config.audio_processing = audio_processing;
solenberg566ef242015-11-06 15:34:49 -0800169 return config;
170}
171
deadbeefe702b302017-02-04 12:09:01 -0800172// |max_send_bitrate_bps| is the bitrate from "b=" in SDP.
173// |rtp_max_bitrate_bps| is the bitrate from RtpSender::SetParameters.
minyue7a973442016-10-20 03:27:12 -0700174rtc::Optional<int> ComputeSendBitrate(int max_send_bitrate_bps,
deadbeefe702b302017-02-04 12:09:01 -0800175 rtc::Optional<int> rtp_max_bitrate_bps,
ossu20a4b3f2017-04-27 02:08:52 -0700176 const webrtc::AudioCodecSpec& spec) {
deadbeefe702b302017-02-04 12:09:01 -0800177 // If application-configured bitrate is set, take minimum of that and SDP
178 // bitrate.
zsteina5e0df62017-06-14 11:41:48 -0700179 const int bps =
180 rtp_max_bitrate_bps
181 ? webrtc::MinPositive(max_send_bitrate_bps, *rtp_max_bitrate_bps)
182 : max_send_bitrate_bps;
minyue7a973442016-10-20 03:27:12 -0700183 if (bps <= 0) {
ossu20a4b3f2017-04-27 02:08:52 -0700184 return rtc::Optional<int>(spec.info.default_bitrate_bps);
solenberg971cab02016-06-14 10:02:41 -0700185 }
minyue7a973442016-10-20 03:27:12 -0700186
ossu20a4b3f2017-04-27 02:08:52 -0700187 if (bps < spec.info.min_bitrate_bps) {
minyue7a973442016-10-20 03:27:12 -0700188 // If codec is not multi-rate and |bps| is less than the fixed bitrate then
189 // fail. If codec is not multi-rate and |bps| exceeds or equal the fixed
190 // bitrate then ignore.
ossu20a4b3f2017-04-27 02:08:52 -0700191 LOG(LS_ERROR) << "Failed to set codec " << spec.format.name
minyue7a973442016-10-20 03:27:12 -0700192 << " to bitrate " << bps << " bps"
ossu20a4b3f2017-04-27 02:08:52 -0700193 << ", requires at least " << spec.info.min_bitrate_bps
194 << " bps.";
minyue7a973442016-10-20 03:27:12 -0700195 return rtc::Optional<int>();
solenberg971cab02016-06-14 10:02:41 -0700196 }
ossu20a4b3f2017-04-27 02:08:52 -0700197
198 if (spec.info.HasFixedBitrate()) {
199 return rtc::Optional<int>(spec.info.default_bitrate_bps);
200 } else {
201 // If codec is multi-rate then just set the bitrate.
202 return rtc::Optional<int>(std::min(bps, spec.info.max_bitrate_bps));
203 }
solenberg971cab02016-06-14 10:02:41 -0700204}
205
solenberg76377c52017-02-21 00:54:31 -0800206} // namespace
solenberg971cab02016-06-14 10:02:41 -0700207
ossu29b1a8d2016-06-13 07:34:51 -0700208WebRtcVoiceEngine::WebRtcVoiceEngine(
209 webrtc::AudioDeviceModule* adm,
ossueb1fde42017-05-02 06:46:30 -0700210 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -0800211 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
peaha9cc40b2017-06-29 08:32:09 -0700212 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
213 rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing)
ossueb1fde42017-05-02 06:46:30 -0700214 : WebRtcVoiceEngine(adm,
215 encoder_factory,
216 decoder_factory,
217 audio_mixer,
peaha9cc40b2017-06-29 08:32:09 -0700218 audio_processing,
deadbeefeb02c032017-06-15 08:29:25 -0700219 nullptr) {}
solenberg26c8c912015-11-27 04:00:25 -0800220
ossu29b1a8d2016-06-13 07:34:51 -0700221WebRtcVoiceEngine::WebRtcVoiceEngine(
222 webrtc::AudioDeviceModule* adm,
ossueb1fde42017-05-02 06:46:30 -0700223 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory,
ossu29b1a8d2016-06-13 07:34:51 -0700224 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -0800225 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
peaha9cc40b2017-06-29 08:32:09 -0700226 rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing,
ossu29b1a8d2016-06-13 07:34:51 -0700227 VoEWrapper* voe_wrapper)
deadbeefeb02c032017-06-15 08:29:25 -0700228 : adm_(adm),
ossueb1fde42017-05-02 06:46:30 -0700229 encoder_factory_(encoder_factory),
ossu20a4b3f2017-04-27 02:08:52 -0700230 decoder_factory_(decoder_factory),
deadbeefeb02c032017-06-15 08:29:25 -0700231 audio_mixer_(audio_mixer),
peaha9cc40b2017-06-29 08:32:09 -0700232 apm_(audio_processing),
ossu20a4b3f2017-04-27 02:08:52 -0700233 voe_wrapper_(voe_wrapper) {
deadbeefeb02c032017-06-15 08:29:25 -0700234 // This may be called from any thread, so detach thread checkers.
235 worker_thread_checker_.DetachFromThread();
solenberg26c8c912015-11-27 04:00:25 -0800236 signal_thread_checker_.DetachFromThread();
deadbeefeb02c032017-06-15 08:29:25 -0700237 LOG(LS_INFO) << "WebRtcVoiceEngine::WebRtcVoiceEngine";
238 RTC_DCHECK(decoder_factory);
239 RTC_DCHECK(encoder_factory);
peaha9cc40b2017-06-29 08:32:09 -0700240 RTC_DCHECK(audio_processing);
deadbeefeb02c032017-06-15 08:29:25 -0700241 // 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();
deadbeefeb02c032017-06-15 08:29:25 -0700250 }
251}
252
253void WebRtcVoiceEngine::Init() {
254 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
255 LOG(LS_INFO) << "WebRtcVoiceEngine::Init";
256
257 // TaskQueue expects to be created/destroyed on the same thread.
258 low_priority_worker_queue_.reset(
259 new rtc::TaskQueue("rtc-low-prio", rtc::TaskQueue::Priority::LOW));
260
261 // VoEWrapper needs to be created on the worker thread. It's expected to be
262 // null here unless it's being injected for testing.
263 if (!voe_wrapper_) {
264 voe_wrapper_.reset(new VoEWrapper());
265 }
solenberg26c8c912015-11-27 04:00:25 -0800266
ossueb1fde42017-05-02 06:46:30 -0700267 // Load our audio codec lists.
ossuc54071d2016-08-17 02:45:41 -0700268 LOG(LS_INFO) << "Supported send codecs in order of preference:";
ossu20a4b3f2017-04-27 02:08:52 -0700269 send_codecs_ = CollectCodecs(encoder_factory_->GetSupportedEncoders());
ossuc54071d2016-08-17 02:45:41 -0700270 for (const AudioCodec& codec : send_codecs_) {
271 LOG(LS_INFO) << ToString(codec);
272 }
273
274 LOG(LS_INFO) << "Supported recv codecs in order of preference:";
ossu20a4b3f2017-04-27 02:08:52 -0700275 recv_codecs_ = CollectCodecs(decoder_factory_->GetSupportedDecoders());
ossuc54071d2016-08-17 02:45:41 -0700276 for (const AudioCodec& codec : recv_codecs_) {
solenbergff976312016-03-30 23:28:51 -0700277 LOG(LS_INFO) << ToString(codec);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000278 }
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000279
solenberg88499ec2016-09-07 07:34:41 -0700280 channel_config_.enable_voice_pacing = true;
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000281
peaha9cc40b2017-06-29 08:32:09 -0700282 RTC_CHECK_EQ(0,
283 voe_wrapper_->base()->Init(adm_.get(), apm(), decoder_factory_));
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000284
solenbergff976312016-03-30 23:28:51 -0700285 // No ADM supplied? Get the default one from VoE.
286 if (!adm_) {
287 adm_ = voe_wrapper_->base()->audio_device_module();
288 }
289 RTC_DCHECK(adm_);
290
solenberg76377c52017-02-21 00:54:31 -0800291 transmit_mixer_ = voe_wrapper_->base()->transmit_mixer();
292 RTC_DCHECK(transmit_mixer_);
293
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000294 // Save the default AGC configuration settings. This must happen before
solenberg246b8172015-12-08 09:50:23 -0800295 // calling ApplyOptions or the default will be overwritten.
peaha9cc40b2017-06-29 08:32:09 -0700296 default_agc_config_ = webrtc::apm_helpers::GetAgcConfig(apm());
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000297
solenberg0f7d2932016-01-15 01:40:39 -0800298 // Set default engine options.
299 {
300 AudioOptions options;
301 options.echo_cancellation = rtc::Optional<bool>(true);
302 options.auto_gain_control = rtc::Optional<bool>(true);
303 options.noise_suppression = rtc::Optional<bool>(true);
304 options.highpass_filter = rtc::Optional<bool>(true);
305 options.stereo_swapping = rtc::Optional<bool>(false);
306 options.audio_jitter_buffer_max_packets = rtc::Optional<int>(50);
307 options.audio_jitter_buffer_fast_accelerate = rtc::Optional<bool>(false);
308 options.typing_detection = rtc::Optional<bool>(true);
309 options.adjust_agc_delta = rtc::Optional<int>(0);
310 options.experimental_agc = rtc::Optional<bool>(false);
311 options.extended_filter_aec = rtc::Optional<bool>(false);
312 options.delay_agnostic_aec = rtc::Optional<bool>(false);
313 options.experimental_ns = rtc::Optional<bool>(false);
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700314 options.intelligibility_enhancer = rtc::Optional<bool>(false);
peaha3333bf2016-06-30 00:02:34 -0700315 options.level_control = rtc::Optional<bool>(false);
ivocb829d9f2016-11-15 02:34:47 -0800316 options.residual_echo_detector = rtc::Optional<bool>(true);
solenbergff976312016-03-30 23:28:51 -0700317 bool error = ApplyOptions(options);
318 RTC_DCHECK(error);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000319 }
320
solenberg9a5f032222017-03-15 06:14:12 -0700321 // Set default audio devices.
322#if !defined(WEBRTC_IOS)
323 webrtc::adm_helpers::SetRecordingDevice(adm_);
324 apm()->Initialize();
325 webrtc::adm_helpers::SetPlayoutDevice(adm_);
326#endif // !WEBRTC_IOS
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000327
deadbeefeb02c032017-06-15 08:29:25 -0700328 // May be null for VoE injected for testing.
329 if (voe()->engine()) {
peaha9cc40b2017-06-29 08:32:09 -0700330 audio_state_ = webrtc::AudioState::Create(
331 MakeAudioStateConfig(voe(), audio_mixer_, apm_));
deadbeefeb02c032017-06-15 08:29:25 -0700332 }
333
334 initialized_ = true;
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000335}
336
solenberg566ef242015-11-06 15:34:49 -0800337rtc::scoped_refptr<webrtc::AudioState>
338 WebRtcVoiceEngine::GetAudioState() const {
339 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
340 return audio_state_;
341}
342
nisse51542be2016-02-12 02:27:06 -0800343VoiceMediaChannel* WebRtcVoiceEngine::CreateChannel(
344 webrtc::Call* call,
345 const MediaConfig& config,
Jelena Marusicc28a8962015-05-29 15:05:44 +0200346 const AudioOptions& options) {
solenberg566ef242015-11-06 15:34:49 -0800347 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
nisse51542be2016-02-12 02:27:06 -0800348 return new WebRtcVoiceMediaChannel(this, config, options, call);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000349}
350
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000351bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
solenberg566ef242015-11-06 15:34:49 -0800352 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergff976312016-03-30 23:28:51 -0700353 LOG(LS_INFO) << "WebRtcVoiceEngine::ApplyOptions: " << options_in.ToString();
solenberg0f7d2932016-01-15 01:40:39 -0800354 AudioOptions options = options_in; // The options are modified below.
solenberg246b8172015-12-08 09:50:23 -0800355
peah8a8ebd92017-05-22 15:48:47 -0700356 // Set and adjust echo canceller options.
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000357 // kEcConference is AEC with high suppression.
358 webrtc::EcModes ec_mode = webrtc::kEcConference;
kwiberg102c6a62015-10-30 02:47:38 -0700359 if (options.aecm_generate_comfort_noise) {
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000360 LOG(LS_VERBOSE) << "Comfort noise explicitly set to "
kwiberg102c6a62015-10-30 02:47:38 -0700361 << *options.aecm_generate_comfort_noise
362 << " (default is false).";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000363 }
364
kjellanderfcfc8042016-01-14 11:01:09 -0800365#if defined(WEBRTC_IOS)
peah8a8ebd92017-05-22 15:48:47 -0700366 // On iOS, VPIO provides built-in EC.
Karl Wibergbe579832015-11-10 22:34:18 +0100367 options.echo_cancellation = rtc::Optional<bool>(false);
peah8a8ebd92017-05-22 15:48:47 -0700368 options.extended_filter_aec = rtc::Optional<bool>(false);
369 LOG(LS_INFO) << "Always disable AEC on iOS. Use built-in instead.";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000370#elif defined(ANDROID)
371 ec_mode = webrtc::kEcAecm;
Karl Wibergbe579832015-11-10 22:34:18 +0100372 options.extended_filter_aec = rtc::Optional<bool>(false);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000373#endif
374
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100375 // Delay Agnostic AEC automatically turns on EC if not set except on iOS
376 // where the feature is not supported.
377 bool use_delay_agnostic_aec = false;
kjellanderfcfc8042016-01-14 11:01:09 -0800378#if !defined(WEBRTC_IOS)
kwiberg102c6a62015-10-30 02:47:38 -0700379 if (options.delay_agnostic_aec) {
380 use_delay_agnostic_aec = *options.delay_agnostic_aec;
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100381 if (use_delay_agnostic_aec) {
Karl Wibergbe579832015-11-10 22:34:18 +0100382 options.echo_cancellation = rtc::Optional<bool>(true);
383 options.extended_filter_aec = rtc::Optional<bool>(true);
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100384 ec_mode = webrtc::kEcConference;
385 }
386 }
387#endif
388
peah8a8ebd92017-05-22 15:48:47 -0700389// Set and adjust noise suppressor options.
390#if defined(WEBRTC_IOS)
391 // On iOS, VPIO provides built-in NS.
392 options.noise_suppression = rtc::Optional<bool>(false);
393 options.typing_detection = rtc::Optional<bool>(false);
394 options.experimental_ns = rtc::Optional<bool>(false);
395 LOG(LS_INFO) << "Always disable NS on iOS. Use built-in instead.";
396#elif defined(ANDROID)
397 options.typing_detection = rtc::Optional<bool>(false);
398 options.experimental_ns = rtc::Optional<bool>(false);
399#endif
400
401// Set and adjust gain control options.
402#if defined(WEBRTC_IOS)
403 // On iOS, VPIO provides built-in AGC.
404 options.auto_gain_control = rtc::Optional<bool>(false);
405 options.experimental_agc = rtc::Optional<bool>(false);
406 LOG(LS_INFO) << "Always disable AGC on iOS. Use built-in instead.";
407#elif defined(ANDROID)
408 options.experimental_agc = rtc::Optional<bool>(false);
409#endif
410
411#if defined(WEBRTC_IOS) || defined(WEBRTC_ANDROID)
412 // 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).
413 if (webrtc::field_trial::IsEnabled(
414 "WebRTC-Audio-MinimizeResamplingOnMobile")) {
415 options.auto_gain_control = rtc::Optional<bool>(false);
416 LOG(LS_INFO) << "Disable AGC according to field trial.";
417 if (!(options.noise_suppression.value_or(false) or
418 options.echo_cancellation.value_or(false))) {
419 // If possible, turn off the high-pass filter.
420 LOG(LS_INFO) << "Disable high-pass filter in response to field trial.";
421 options.highpass_filter = rtc::Optional<bool>(false);
422 }
423 }
424#endif
425
peah1bcfce52016-08-26 07:16:04 -0700426#if (WEBRTC_INTELLIGIBILITY_ENHANCER == 0)
427 // Hardcode the intelligibility enhancer to be off.
428 options.intelligibility_enhancer = rtc::Optional<bool>(false);
429#endif
430
kwiberg102c6a62015-10-30 02:47:38 -0700431 if (options.echo_cancellation) {
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000432 // Check if platform supports built-in EC. Currently only supported on
433 // Android and in combination with Java based audio layer.
434 // TODO(henrika): investigate possibility to support built-in EC also
435 // in combination with Open SL ES audio.
solenberg5b5129a2016-04-08 05:35:48 -0700436 const bool built_in_aec = adm()->BuiltInAECIsAvailable();
Bjorn Volcker73f72102015-06-03 14:50:15 +0200437 if (built_in_aec) {
Bjorn Volckerccfc9392015-05-07 07:43:17 +0200438 // Built-in EC exists on this device and use_delay_agnostic_aec is not
439 // overriding it. Enable/Disable it according to the echo_cancellation
440 // audio option.
Bjorn Volcker73f72102015-06-03 14:50:15 +0200441 const bool enable_built_in_aec =
kwiberg102c6a62015-10-30 02:47:38 -0700442 *options.echo_cancellation && !use_delay_agnostic_aec;
solenberg5b5129a2016-04-08 05:35:48 -0700443 if (adm()->EnableBuiltInAEC(enable_built_in_aec) == 0 &&
Bjorn Volcker73f72102015-06-03 14:50:15 +0200444 enable_built_in_aec) {
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100445 // Disable internal software EC if built-in EC is enabled,
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000446 // i.e., replace the software EC with the built-in EC.
Karl Wibergbe579832015-11-10 22:34:18 +0100447 options.echo_cancellation = rtc::Optional<bool>(false);
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000448 LOG(LS_INFO) << "Disabling EC since built-in EC will be used instead";
449 }
450 }
solenberg76377c52017-02-21 00:54:31 -0800451 webrtc::apm_helpers::SetEcStatus(
452 apm(), *options.echo_cancellation, ec_mode);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000453#if !defined(ANDROID)
solenberg76377c52017-02-21 00:54:31 -0800454 webrtc::apm_helpers::SetEcMetricsStatus(apm(), *options.echo_cancellation);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000455#endif
456 if (ec_mode == webrtc::kEcAecm) {
kwiberg102c6a62015-10-30 02:47:38 -0700457 bool cn = options.aecm_generate_comfort_noise.value_or(false);
solenberg76377c52017-02-21 00:54:31 -0800458 webrtc::apm_helpers::SetAecmMode(apm(), cn);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000459 }
460 }
461
kwiberg102c6a62015-10-30 02:47:38 -0700462 if (options.auto_gain_control) {
peah72a56452016-08-22 12:08:55 -0700463 bool built_in_agc_avaliable = adm()->BuiltInAGCIsAvailable();
464 if (built_in_agc_avaliable) {
solenberg5b5129a2016-04-08 05:35:48 -0700465 if (adm()->EnableBuiltInAGC(*options.auto_gain_control) == 0 &&
kwiberg102c6a62015-10-30 02:47:38 -0700466 *options.auto_gain_control) {
henrikac14f5ff2015-09-23 14:08:33 +0200467 // Disable internal software AGC if built-in AGC is enabled,
468 // i.e., replace the software AGC with the built-in AGC.
Karl Wibergbe579832015-11-10 22:34:18 +0100469 options.auto_gain_control = rtc::Optional<bool>(false);
henrikac14f5ff2015-09-23 14:08:33 +0200470 LOG(LS_INFO) << "Disabling AGC since built-in AGC will be used instead";
471 }
472 }
solenberg22818a52017-03-16 01:20:23 -0700473 webrtc::apm_helpers::SetAgcStatus(apm(), adm(), *options.auto_gain_control);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000474 }
475
kwiberg102c6a62015-10-30 02:47:38 -0700476 if (options.tx_agc_target_dbov || options.tx_agc_digital_compression_gain ||
solenberg76377c52017-02-21 00:54:31 -0800477 options.tx_agc_limiter || options.adjust_agc_delta) {
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000478 // Override default_agc_config_. Generally, an unset option means "leave
479 // the VoE bits alone" in this function, so we want whatever is set to be
480 // stored as the new "default". If we didn't, then setting e.g.
481 // tx_agc_target_dbov would reset digital compression gain and limiter
482 // settings.
483 // Also, if we don't update default_agc_config_, then adjust_agc_delta
484 // would be an offset from the original values, and not whatever was set
485 // explicitly.
kwiberg102c6a62015-10-30 02:47:38 -0700486 default_agc_config_.targetLeveldBOv = options.tx_agc_target_dbov.value_or(
487 default_agc_config_.targetLeveldBOv);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000488 default_agc_config_.digitalCompressionGaindB =
kwiberg102c6a62015-10-30 02:47:38 -0700489 options.tx_agc_digital_compression_gain.value_or(
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000490 default_agc_config_.digitalCompressionGaindB);
491 default_agc_config_.limiterEnable =
kwiberg102c6a62015-10-30 02:47:38 -0700492 options.tx_agc_limiter.value_or(default_agc_config_.limiterEnable);
solenberg76377c52017-02-21 00:54:31 -0800493
494 webrtc::AgcConfig config = default_agc_config_;
495 if (options.adjust_agc_delta) {
496 config.targetLeveldBOv -= *options.adjust_agc_delta;
497 LOG(LS_INFO) << "Adjusting AGC level from default -"
498 << default_agc_config_.targetLeveldBOv << "dB to -"
499 << config.targetLeveldBOv << "dB";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000500 }
peaha9cc40b2017-06-29 08:32:09 -0700501 webrtc::apm_helpers::SetAgcConfig(apm(), config);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000502 }
503
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700504 if (options.intelligibility_enhancer) {
505 intelligibility_enhancer_ = options.intelligibility_enhancer;
506 }
507 if (intelligibility_enhancer_ && *intelligibility_enhancer_) {
508 LOG(LS_INFO) << "Enabling NS when Intelligibility Enhancer is active.";
509 options.noise_suppression = intelligibility_enhancer_;
510 }
511
kwiberg102c6a62015-10-30 02:47:38 -0700512 if (options.noise_suppression) {
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700513 if (adm()->BuiltInNSIsAvailable()) {
514 bool builtin_ns =
515 *options.noise_suppression &&
516 !(intelligibility_enhancer_ && *intelligibility_enhancer_);
517 if (adm()->EnableBuiltInNS(builtin_ns) == 0 && builtin_ns) {
henrikac14f5ff2015-09-23 14:08:33 +0200518 // Disable internal software NS if built-in NS is enabled,
519 // i.e., replace the software NS with the built-in NS.
Karl Wibergbe579832015-11-10 22:34:18 +0100520 options.noise_suppression = rtc::Optional<bool>(false);
henrikac14f5ff2015-09-23 14:08:33 +0200521 LOG(LS_INFO) << "Disabling NS since built-in NS will be used instead";
522 }
523 }
solenberg76377c52017-02-21 00:54:31 -0800524 webrtc::apm_helpers::SetNsStatus(apm(), *options.noise_suppression);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000525 }
526
kwiberg102c6a62015-10-30 02:47:38 -0700527 if (options.stereo_swapping) {
528 LOG(LS_INFO) << "Stereo swapping enabled? " << *options.stereo_swapping;
solenberg76377c52017-02-21 00:54:31 -0800529 transmit_mixer()->EnableStereoChannelSwapping(*options.stereo_swapping);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000530 }
531
kwiberg102c6a62015-10-30 02:47:38 -0700532 if (options.audio_jitter_buffer_max_packets) {
533 LOG(LS_INFO) << "NetEq capacity is "
534 << *options.audio_jitter_buffer_max_packets;
solenberg88499ec2016-09-07 07:34:41 -0700535 channel_config_.acm_config.neteq_config.max_packets_in_buffer =
536 std::max(20, *options.audio_jitter_buffer_max_packets);
Henrik Lundin64dad832015-05-11 12:44:23 +0200537 }
kwiberg102c6a62015-10-30 02:47:38 -0700538 if (options.audio_jitter_buffer_fast_accelerate) {
539 LOG(LS_INFO) << "NetEq fast mode? "
540 << *options.audio_jitter_buffer_fast_accelerate;
solenberg88499ec2016-09-07 07:34:41 -0700541 channel_config_.acm_config.neteq_config.enable_fast_accelerate =
542 *options.audio_jitter_buffer_fast_accelerate;
Henrik Lundin5263b3c2015-06-01 10:29:41 +0200543 }
544
kwiberg102c6a62015-10-30 02:47:38 -0700545 if (options.typing_detection) {
546 LOG(LS_INFO) << "Typing detection is enabled? "
547 << *options.typing_detection;
solenberg76377c52017-02-21 00:54:31 -0800548 webrtc::apm_helpers::SetTypingDetectionStatus(
549 apm(), *options.typing_detection);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000550 }
551
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000552 webrtc::Config config;
553
kwiberg102c6a62015-10-30 02:47:38 -0700554 if (options.delay_agnostic_aec)
555 delay_agnostic_aec_ = options.delay_agnostic_aec;
556 if (delay_agnostic_aec_) {
557 LOG(LS_INFO) << "Delay agnostic aec is enabled? " << *delay_agnostic_aec_;
henrik.lundin0f133b92015-07-02 00:17:55 -0700558 config.Set<webrtc::DelayAgnostic>(
kwiberg102c6a62015-10-30 02:47:38 -0700559 new webrtc::DelayAgnostic(*delay_agnostic_aec_));
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100560 }
561
kwiberg102c6a62015-10-30 02:47:38 -0700562 if (options.extended_filter_aec) {
563 extended_filter_aec_ = options.extended_filter_aec;
564 }
565 if (extended_filter_aec_) {
566 LOG(LS_INFO) << "Extended filter aec is enabled? " << *extended_filter_aec_;
Henrik Lundin441f6342015-06-09 16:03:13 +0200567 config.Set<webrtc::ExtendedFilter>(
kwiberg102c6a62015-10-30 02:47:38 -0700568 new webrtc::ExtendedFilter(*extended_filter_aec_));
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000569 }
570
kwiberg102c6a62015-10-30 02:47:38 -0700571 if (options.experimental_ns) {
572 experimental_ns_ = options.experimental_ns;
573 }
574 if (experimental_ns_) {
575 LOG(LS_INFO) << "Experimental ns is enabled? " << *experimental_ns_;
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000576 config.Set<webrtc::ExperimentalNs>(
kwiberg102c6a62015-10-30 02:47:38 -0700577 new webrtc::ExperimentalNs(*experimental_ns_));
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000578 }
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000579
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700580 if (intelligibility_enhancer_) {
581 LOG(LS_INFO) << "Intelligibility Enhancer is enabled? "
582 << *intelligibility_enhancer_;
583 config.Set<webrtc::Intelligibility>(
584 new webrtc::Intelligibility(*intelligibility_enhancer_));
585 }
586
peaha3333bf2016-06-30 00:02:34 -0700587 if (options.level_control) {
588 level_control_ = options.level_control;
589 }
590
peahb1c9d1d2017-07-25 15:45:24 -0700591 webrtc::AudioProcessing::Config apm_config = apm()->GetConfig();
592
peaha3333bf2016-06-30 00:02:34 -0700593 LOG(LS_INFO) << "Level control: "
594 << (!!level_control_ ? *level_control_ : -1);
595 if (level_control_) {
peahb1c9d1d2017-07-25 15:45:24 -0700596 apm_config.level_controller.enabled = *level_control_;
aleloie33c5d92016-10-20 01:53:27 -0700597 if (options.level_control_initial_peak_level_dbfs) {
peahb1c9d1d2017-07-25 15:45:24 -0700598 apm_config.level_controller.initial_peak_level_dbfs =
aleloie33c5d92016-10-20 01:53:27 -0700599 *options.level_control_initial_peak_level_dbfs;
600 }
peaha3333bf2016-06-30 00:02:34 -0700601 }
602
peah8271d042016-11-22 07:24:52 -0800603 if (options.highpass_filter) {
peahb1c9d1d2017-07-25 15:45:24 -0700604 apm_config.high_pass_filter.enabled = *options.highpass_filter;
peah8271d042016-11-22 07:24:52 -0800605 }
606
ivoc4ca18692017-02-10 05:11:09 -0800607 if (options.residual_echo_detector) {
peahb1c9d1d2017-07-25 15:45:24 -0700608 apm_config.residual_echo_detector.enabled = *options.residual_echo_detector;
ivoc4ca18692017-02-10 05:11:09 -0800609 }
610
solenberg059fb442016-10-26 05:12:24 -0700611 apm()->SetExtraOptions(config);
peahb1c9d1d2017-07-25 15:45:24 -0700612 apm()->ApplyConfig(apm_config);
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000613
kwiberg102c6a62015-10-30 02:47:38 -0700614 if (options.recording_sample_rate) {
615 LOG(LS_INFO) << "Recording sample rate is "
616 << *options.recording_sample_rate;
solenberg5b5129a2016-04-08 05:35:48 -0700617 if (adm()->SetRecordingSampleRate(*options.recording_sample_rate)) {
solenberg35dee812017-09-18 01:57:01 -0700618 LOG(LS_WARNING) << "SetRecordingSampleRate("
619 << *options.recording_sample_rate << ") failed, err="
620 << adm()->LastError();
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000621 }
622 }
623
kwiberg102c6a62015-10-30 02:47:38 -0700624 if (options.playout_sample_rate) {
625 LOG(LS_INFO) << "Playout sample rate is " << *options.playout_sample_rate;
solenberg5b5129a2016-04-08 05:35:48 -0700626 if (adm()->SetPlayoutSampleRate(*options.playout_sample_rate)) {
solenberg35dee812017-09-18 01:57:01 -0700627 LOG(LS_WARNING) << "SetPlayoutSampleRate("
628 << *options.playout_sample_rate << ") failed, err="
629 << adm()->LastError();
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000630 }
631 }
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000632 return true;
633}
634
solenberg796b8f92017-03-01 17:02:23 -0800635// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000636int WebRtcVoiceEngine::GetInputLevel() {
solenberg566ef242015-11-06 15:34:49 -0800637 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg796b8f92017-03-01 17:02:23 -0800638 int8_t level = transmit_mixer()->AudioLevel();
639 RTC_DCHECK_LE(0, level);
640 return level;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000641}
642
ossudedfd282016-06-14 07:12:39 -0700643const std::vector<AudioCodec>& WebRtcVoiceEngine::send_codecs() const {
644 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
ossuc54071d2016-08-17 02:45:41 -0700645 return send_codecs_;
ossudedfd282016-06-14 07:12:39 -0700646}
647
648const std::vector<AudioCodec>& WebRtcVoiceEngine::recv_codecs() const {
solenberg566ef242015-11-06 15:34:49 -0800649 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
ossuc54071d2016-08-17 02:45:41 -0700650 return recv_codecs_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000651}
652
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100653RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const {
solenberg566ef242015-11-06 15:34:49 -0800654 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100655 RtpCapabilities capabilities;
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100656 capabilities.header_extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -0700657 webrtc::RtpExtension(webrtc::RtpExtension::kAudioLevelUri,
658 webrtc::RtpExtension::kAudioLevelDefaultId));
sprangc1b57a12017-02-28 08:50:47 -0800659 if (webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe")) {
isheriff6f8d6862016-05-26 11:24:55 -0700660 capabilities.header_extensions.push_back(webrtc::RtpExtension(
661 webrtc::RtpExtension::kTransportSequenceNumberUri,
662 webrtc::RtpExtension::kTransportSequenceNumberDefaultId));
stefanba4c0e42016-02-04 04:12:24 -0800663 }
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100664 return capabilities;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000665}
666
solenberg63b34542015-09-29 06:06:31 -0700667void WebRtcVoiceEngine::RegisterChannel(WebRtcVoiceMediaChannel* channel) {
solenberg566ef242015-11-06 15:34:49 -0800668 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
669 RTC_DCHECK(channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000670 channels_.push_back(channel);
671}
672
solenberg63b34542015-09-29 06:06:31 -0700673void WebRtcVoiceEngine::UnregisterChannel(WebRtcVoiceMediaChannel* channel) {
solenberg566ef242015-11-06 15:34:49 -0800674 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg63b34542015-09-29 06:06:31 -0700675 auto it = std::find(channels_.begin(), channels_.end(), channel);
solenberg566ef242015-11-06 15:34:49 -0800676 RTC_DCHECK(it != channels_.end());
677 channels_.erase(it);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000678}
679
ivocd66b44d2016-01-15 03:06:36 -0800680bool WebRtcVoiceEngine::StartAecDump(rtc::PlatformFile file,
681 int64_t max_size_bytes) {
solenberg566ef242015-11-06 15:34:49 -0800682 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeefeb02c032017-06-15 08:29:25 -0700683 auto aec_dump = webrtc::AecDumpFactory::Create(
684 file, max_size_bytes, low_priority_worker_queue_.get());
aleloi048cbdd2017-05-29 02:56:27 -0700685 if (!aec_dump) {
wu@webrtc.orga8910d22014-01-23 22:12:45 +0000686 return false;
687 }
aleloi048cbdd2017-05-29 02:56:27 -0700688 apm()->AttachAecDump(std::move(aec_dump));
wu@webrtc.orga9890802013-12-13 00:21:03 +0000689 return true;
wu@webrtc.orga9890802013-12-13 00:21:03 +0000690}
691
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000692void WebRtcVoiceEngine::StartAecDump(const std::string& filename) {
solenberg566ef242015-11-06 15:34:49 -0800693 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
aleloi048cbdd2017-05-29 02:56:27 -0700694
deadbeefeb02c032017-06-15 08:29:25 -0700695 auto aec_dump = webrtc::AecDumpFactory::Create(
696 filename, -1, low_priority_worker_queue_.get());
aleloi048cbdd2017-05-29 02:56:27 -0700697 if (aec_dump) {
698 apm()->AttachAecDump(std::move(aec_dump));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000699 }
700}
701
702void WebRtcVoiceEngine::StopAecDump() {
solenberg566ef242015-11-06 15:34:49 -0800703 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
aleloi048cbdd2017-05-29 02:56:27 -0700704 apm()->DetachAecDump();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000705}
706
solenberg0a617e22015-10-20 15:49:38 -0700707int WebRtcVoiceEngine::CreateVoEChannel() {
solenberg566ef242015-11-06 15:34:49 -0800708 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg88499ec2016-09-07 07:34:41 -0700709 return voe_wrapper_->base()->CreateChannel(channel_config_);
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000710}
711
solenberg5b5129a2016-04-08 05:35:48 -0700712webrtc::AudioDeviceModule* WebRtcVoiceEngine::adm() {
713 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
714 RTC_DCHECK(adm_);
715 return adm_;
716}
717
peahb1c9d1d2017-07-25 15:45:24 -0700718webrtc::AudioProcessing* WebRtcVoiceEngine::apm() const {
solenberg059fb442016-10-26 05:12:24 -0700719 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
peaha9cc40b2017-06-29 08:32:09 -0700720 return apm_.get();
solenberg059fb442016-10-26 05:12:24 -0700721}
722
solenberg76377c52017-02-21 00:54:31 -0800723webrtc::voe::TransmitMixer* WebRtcVoiceEngine::transmit_mixer() {
724 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
725 RTC_DCHECK(transmit_mixer_);
726 return transmit_mixer_;
727}
728
ossu20a4b3f2017-04-27 02:08:52 -0700729AudioCodecs WebRtcVoiceEngine::CollectCodecs(
730 const std::vector<webrtc::AudioCodecSpec>& specs) const {
ossuc54071d2016-08-17 02:45:41 -0700731 PayloadTypeMapper mapper;
732 AudioCodecs out;
ossuc54071d2016-08-17 02:45:41 -0700733
solenberg2779bab2016-11-17 04:45:19 -0800734 // Only generate CN payload types for these clockrates:
ossuc54071d2016-08-17 02:45:41 -0700735 std::map<int, bool, std::greater<int>> generate_cn = {{ 8000, false },
736 { 16000, false },
737 { 32000, false }};
solenberg2779bab2016-11-17 04:45:19 -0800738 // Only generate telephone-event payload types for these clockrates:
739 std::map<int, bool, std::greater<int>> generate_dtmf = {{ 8000, false },
740 { 16000, false },
741 { 32000, false },
742 { 48000, false }};
ossuc54071d2016-08-17 02:45:41 -0700743
ossu9def8002017-02-09 05:14:32 -0800744 auto map_format = [&mapper](const webrtc::SdpAudioFormat& format,
745 AudioCodecs* out) {
ossuc54071d2016-08-17 02:45:41 -0700746 rtc::Optional<AudioCodec> opt_codec = mapper.ToAudioCodec(format);
ossu9def8002017-02-09 05:14:32 -0800747 if (opt_codec) {
748 if (out) {
749 out->push_back(*opt_codec);
750 }
751 } else {
ossuc54071d2016-08-17 02:45:41 -0700752 LOG(LS_ERROR) << "Unable to assign payload type to format: " << format;
ossuc54071d2016-08-17 02:45:41 -0700753 }
754
ossu9def8002017-02-09 05:14:32 -0800755 return opt_codec;
ossuc54071d2016-08-17 02:45:41 -0700756 };
757
ossud4e9f622016-08-18 02:01:17 -0700758 for (const auto& spec : specs) {
ossu9def8002017-02-09 05:14:32 -0800759 // We need to do some extra stuff before adding the main codecs to out.
760 rtc::Optional<AudioCodec> opt_codec = map_format(spec.format, nullptr);
761 if (opt_codec) {
762 AudioCodec& codec = *opt_codec;
ossua1a040a2017-04-06 10:03:21 -0700763 if (spec.info.supports_network_adaption) {
ossu9def8002017-02-09 05:14:32 -0800764 codec.AddFeedbackParam(
765 FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty));
766 }
767
ossua1a040a2017-04-06 10:03:21 -0700768 if (spec.info.allow_comfort_noise) {
solenberg2779bab2016-11-17 04:45:19 -0800769 // Generate a CN entry if the decoder allows it and we support the
770 // clockrate.
771 auto cn = generate_cn.find(spec.format.clockrate_hz);
772 if (cn != generate_cn.end()) {
773 cn->second = true;
774 }
775 }
776
777 // Generate a telephone-event entry if we support the clockrate.
778 auto dtmf = generate_dtmf.find(spec.format.clockrate_hz);
779 if (dtmf != generate_dtmf.end()) {
780 dtmf->second = true;
ossuc54071d2016-08-17 02:45:41 -0700781 }
ossu9def8002017-02-09 05:14:32 -0800782
783 out.push_back(codec);
ossuc54071d2016-08-17 02:45:41 -0700784 }
785 }
786
solenberg2779bab2016-11-17 04:45:19 -0800787 // Add CN codecs after "proper" audio codecs.
ossuc54071d2016-08-17 02:45:41 -0700788 for (const auto& cn : generate_cn) {
789 if (cn.second) {
ossu9def8002017-02-09 05:14:32 -0800790 map_format({kCnCodecName, cn.first, 1}, &out);
ossuc54071d2016-08-17 02:45:41 -0700791 }
792 }
793
solenberg2779bab2016-11-17 04:45:19 -0800794 // Add telephone-event codecs last.
795 for (const auto& dtmf : generate_dtmf) {
796 if (dtmf.second) {
ossu9def8002017-02-09 05:14:32 -0800797 map_format({kDtmfCodecName, dtmf.first, 1}, &out);
solenberg2779bab2016-11-17 04:45:19 -0800798 }
799 }
ossuc54071d2016-08-17 02:45:41 -0700800
801 return out;
802}
803
solenbergc96df772015-10-21 13:01:53 -0700804class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800805 : public AudioSource::Sink {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000806 public:
minyue7a973442016-10-20 03:27:12 -0700807 WebRtcAudioSendStream(
808 int ch,
809 webrtc::AudioTransport* voe_audio_transport,
810 uint32_t ssrc,
811 const std::string& c_name,
ossu20a4b3f2017-04-27 02:08:52 -0700812 const rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>&
813 send_codec_spec,
minyue7a973442016-10-20 03:27:12 -0700814 const std::vector<webrtc::RtpExtension>& extensions,
815 int max_send_bitrate_bps,
minyue6b825df2016-10-31 04:08:32 -0700816 const rtc::Optional<std::string>& audio_network_adaptor_config,
minyue7a973442016-10-20 03:27:12 -0700817 webrtc::Call* call,
ossu20a4b3f2017-04-27 02:08:52 -0700818 webrtc::Transport* send_transport,
819 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory)
solenberg7add0582015-11-20 09:59:34 -0800820 : voe_audio_transport_(voe_audio_transport),
solenberg3a941542015-11-16 07:34:50 -0800821 call_(call),
mflodman3d7db262016-04-29 00:57:13 -0700822 config_(send_transport),
sprangc1b57a12017-02-28 08:50:47 -0800823 send_side_bwe_with_overhead_(
824 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
minyue7a973442016-10-20 03:27:12 -0700825 max_send_bitrate_bps_(max_send_bitrate_bps),
skvlade0d46372016-04-07 22:59:22 -0700826 rtp_parameters_(CreateRtpParametersWithOneEncoding()) {
solenberg85a04962015-10-27 03:35:21 -0700827 RTC_DCHECK_GE(ch, 0);
828 // TODO(solenberg): Once we're not using FakeWebRtcVoiceEngine anymore:
829 // RTC_DCHECK(voe_audio_transport);
solenbergc96df772015-10-21 13:01:53 -0700830 RTC_DCHECK(call);
ossu20a4b3f2017-04-27 02:08:52 -0700831 RTC_DCHECK(encoder_factory);
solenberg3a941542015-11-16 07:34:50 -0800832 config_.rtp.ssrc = ssrc;
833 config_.rtp.c_name = c_name;
834 config_.voe_channel_id = ch;
solenberg971cab02016-06-14 10:02:41 -0700835 config_.rtp.extensions = extensions;
minyue6b825df2016-10-31 04:08:32 -0700836 config_.audio_network_adaptor_config = audio_network_adaptor_config;
ossu20a4b3f2017-04-27 02:08:52 -0700837 config_.encoder_factory = encoder_factory;
deadbeefcb443432016-12-12 11:12:36 -0800838 rtp_parameters_.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
ossu20a4b3f2017-04-27 02:08:52 -0700839
840 if (send_codec_spec) {
841 UpdateSendCodecSpec(*send_codec_spec);
842 }
843
844 stream_ = call_->CreateAudioSendStream(config_);
solenbergc96df772015-10-21 13:01:53 -0700845 }
solenberg3a941542015-11-16 07:34:50 -0800846
solenbergc96df772015-10-21 13:01:53 -0700847 ~WebRtcAudioSendStream() override {
solenberg566ef242015-11-06 15:34:49 -0800848 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800849 ClearSource();
solenbergc96df772015-10-21 13:01:53 -0700850 call_->DestroyAudioSendStream(stream_);
851 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000852
ossu20a4b3f2017-04-27 02:08:52 -0700853 void SetSendCodecSpec(
minyue7a973442016-10-20 03:27:12 -0700854 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) {
ossu20a4b3f2017-04-27 02:08:52 -0700855 UpdateSendCodecSpec(send_codec_spec);
856 ReconfigureAudioSendStream();
solenberg971cab02016-06-14 10:02:41 -0700857 }
858
ossu20a4b3f2017-04-27 02:08:52 -0700859 void SetRtpExtensions(const std::vector<webrtc::RtpExtension>& extensions) {
solenberg3a941542015-11-16 07:34:50 -0800860 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg3a941542015-11-16 07:34:50 -0800861 config_.rtp.extensions = extensions;
ossu20a4b3f2017-04-27 02:08:52 -0700862 ReconfigureAudioSendStream();
solenberg3a941542015-11-16 07:34:50 -0800863 }
864
ossu20a4b3f2017-04-27 02:08:52 -0700865 void SetAudioNetworkAdaptorConfig(
minyue6b825df2016-10-31 04:08:32 -0700866 const rtc::Optional<std::string>& audio_network_adaptor_config) {
867 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
868 if (config_.audio_network_adaptor_config == audio_network_adaptor_config) {
869 return;
870 }
871 config_.audio_network_adaptor_config = audio_network_adaptor_config;
ossu20a4b3f2017-04-27 02:08:52 -0700872 UpdateAllowedBitrateRange();
873 ReconfigureAudioSendStream();
minyue6b825df2016-10-31 04:08:32 -0700874 }
875
minyue7a973442016-10-20 03:27:12 -0700876 bool SetMaxSendBitrate(int bps) {
877 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
ossu20a4b3f2017-04-27 02:08:52 -0700878 RTC_DCHECK(config_.send_codec_spec);
879 RTC_DCHECK(audio_codec_spec_);
880 auto send_rate = ComputeSendBitrate(
881 bps, rtp_parameters_.encodings[0].max_bitrate_bps, *audio_codec_spec_);
882
minyue7a973442016-10-20 03:27:12 -0700883 if (!send_rate) {
884 return false;
885 }
886
887 max_send_bitrate_bps_ = bps;
888
ossu20a4b3f2017-04-27 02:08:52 -0700889 if (send_rate != config_.send_codec_spec->target_bitrate_bps) {
890 config_.send_codec_spec->target_bitrate_bps = send_rate;
891 ReconfigureAudioSendStream();
minyue7a973442016-10-20 03:27:12 -0700892 }
893 return true;
894 }
895
solenbergffbbcac2016-11-17 05:25:37 -0800896 bool SendTelephoneEvent(int payload_type, int payload_freq, int event,
897 int duration_ms) {
Fredrik Solenbergb5727682015-12-04 15:22:19 +0100898 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
899 RTC_DCHECK(stream_);
solenbergffbbcac2016-11-17 05:25:37 -0800900 return stream_->SendTelephoneEvent(payload_type, payload_freq, event,
901 duration_ms);
Fredrik Solenbergb5727682015-12-04 15:22:19 +0100902 }
903
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800904 void SetSend(bool send) {
905 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
906 send_ = send;
907 UpdateSendState();
908 }
909
solenberg94218532016-06-16 10:53:22 -0700910 void SetMuted(bool muted) {
911 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
912 RTC_DCHECK(stream_);
913 stream_->SetMuted(muted);
914 muted_ = muted;
915 }
916
917 bool muted() const {
918 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
919 return muted_;
920 }
921
solenberg3a941542015-11-16 07:34:50 -0800922 webrtc::AudioSendStream::Stats GetStats() const {
923 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
924 RTC_DCHECK(stream_);
925 return stream_->GetStats();
926 }
927
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800928 // Starts the sending by setting ourselves as a sink to the AudioSource to
929 // get data callbacks.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000930 // This method is called on the libjingle worker thread.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000931 // TODO(xians): Make sure Start() is called only once.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800932 void SetSource(AudioSource* source) {
solenberg566ef242015-11-06 15:34:49 -0800933 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800934 RTC_DCHECK(source);
935 if (source_) {
936 RTC_DCHECK(source_ == source);
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000937 return;
938 }
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800939 source->SetSink(this);
940 source_ = source;
941 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000942 }
943
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800944 // Stops sending by setting the sink of the AudioSource to nullptr. No data
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000945 // callback will be received after this method.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000946 // This method is called on the libjingle worker thread.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800947 void ClearSource() {
solenberg566ef242015-11-06 15:34:49 -0800948 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800949 if (source_) {
950 source_->SetSink(nullptr);
951 source_ = nullptr;
solenberg98c68862015-10-09 03:27:14 -0700952 }
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800953 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000954 }
955
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800956 // AudioSource::Sink implementation.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000957 // This method is called on the audio thread.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000958 void OnData(const void* audio_data,
959 int bits_per_sample,
960 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -0800961 size_t number_of_channels,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700962 size_t number_of_frames) override {
solenberg347ec5c2016-09-23 04:21:47 -0700963 RTC_CHECK_RUNS_SERIALIZED(&audio_capture_race_checker_);
solenbergc96df772015-10-21 13:01:53 -0700964 RTC_DCHECK(voe_audio_transport_);
maxmorin1aee0b52016-08-15 11:46:19 -0700965 voe_audio_transport_->PushCaptureData(config_.voe_channel_id, audio_data,
966 bits_per_sample, sample_rate,
967 number_of_channels, number_of_frames);
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000968 }
969
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800970 // Callback from the |source_| when it is going away. In case Start() has
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000971 // never been called, this callback won't be triggered.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000972 void OnClose() override {
solenberg566ef242015-11-06 15:34:49 -0800973 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800974 // Set |source_| to nullptr to make sure no more callback will get into
975 // the source.
976 source_ = nullptr;
977 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000978 }
979
980 // Accessor to the VoE channel ID.
solenberg85a04962015-10-27 03:35:21 -0700981 int channel() const {
solenberg566ef242015-11-06 15:34:49 -0800982 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7add0582015-11-20 09:59:34 -0800983 return config_.voe_channel_id;
solenberg85a04962015-10-27 03:35:21 -0700984 }
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000985
skvlade0d46372016-04-07 22:59:22 -0700986 const webrtc::RtpParameters& rtp_parameters() const {
987 return rtp_parameters_;
988 }
989
deadbeeffb2aced2017-01-06 23:05:37 -0800990 bool ValidateRtpParameters(const webrtc::RtpParameters& rtp_parameters) {
991 if (rtp_parameters.encodings.size() != 1) {
992 LOG(LS_ERROR)
993 << "Attempted to set RtpParameters without exactly one encoding";
994 return false;
995 }
996 if (rtp_parameters.encodings[0].ssrc != rtp_parameters_.encodings[0].ssrc) {
997 LOG(LS_ERROR) << "Attempted to set RtpParameters with modified SSRC";
998 return false;
999 }
1000 return true;
1001 }
1002
minyue7a973442016-10-20 03:27:12 -07001003 bool SetRtpParameters(const webrtc::RtpParameters& parameters) {
deadbeeffb2aced2017-01-06 23:05:37 -08001004 if (!ValidateRtpParameters(parameters)) {
1005 return false;
1006 }
ossu20a4b3f2017-04-27 02:08:52 -07001007
1008 rtc::Optional<int> send_rate;
1009 if (audio_codec_spec_) {
1010 send_rate = ComputeSendBitrate(max_send_bitrate_bps_,
1011 parameters.encodings[0].max_bitrate_bps,
1012 *audio_codec_spec_);
1013 if (!send_rate) {
1014 return false;
1015 }
minyue7a973442016-10-20 03:27:12 -07001016 }
1017
minyuececec102017-03-27 13:04:25 -07001018 const rtc::Optional<int> old_rtp_max_bitrate =
1019 rtp_parameters_.encodings[0].max_bitrate_bps;
1020
skvlade0d46372016-04-07 22:59:22 -07001021 rtp_parameters_ = parameters;
minyue7a973442016-10-20 03:27:12 -07001022
minyuececec102017-03-27 13:04:25 -07001023 if (rtp_parameters_.encodings[0].max_bitrate_bps != old_rtp_max_bitrate) {
ossu20a4b3f2017-04-27 02:08:52 -07001024 // Reconfigure AudioSendStream with new bit rate.
1025 if (send_rate) {
1026 config_.send_codec_spec->target_bitrate_bps = send_rate;
1027 }
1028 UpdateAllowedBitrateRange();
1029 ReconfigureAudioSendStream();
minyue7a973442016-10-20 03:27:12 -07001030 } else {
1031 // parameters.encodings[0].active could have changed.
1032 UpdateSendState();
1033 }
1034 return true;
skvlade0d46372016-04-07 22:59:22 -07001035 }
1036
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001037 private:
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001038 void UpdateSendState() {
1039 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1040 RTC_DCHECK(stream_);
Taylor Brandstetter55dd7082016-05-03 13:50:11 -07001041 RTC_DCHECK_EQ(1UL, rtp_parameters_.encodings.size());
1042 if (send_ && source_ != nullptr && rtp_parameters_.encodings[0].active) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001043 stream_->Start();
1044 } else { // !send || source_ = nullptr
1045 stream_->Stop();
1046 }
1047 }
1048
ossu20a4b3f2017-04-27 02:08:52 -07001049 void UpdateAllowedBitrateRange() {
michaelt53fe19d2016-10-18 09:39:22 -07001050 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
ossu20a4b3f2017-04-27 02:08:52 -07001051 const bool is_opus =
1052 config_.send_codec_spec &&
1053 !STR_CASE_CMP(config_.send_codec_spec->format.name.c_str(),
1054 kOpusCodecName);
1055 if (is_opus && webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe")) {
stefane9f36d52017-01-24 08:18:45 -08001056 config_.min_bitrate_bps = kOpusMinBitrateBps;
minyuececec102017-03-27 13:04:25 -07001057
1058 // This means that when RtpParameters is reset, we may change the
ossu20a4b3f2017-04-27 02:08:52 -07001059 // encoder's bit rate immediately (through ReconfigureAudioSendStream()),
minyuececec102017-03-27 13:04:25 -07001060 // meanwhile change the cap to the output of BWE.
1061 config_.max_bitrate_bps =
1062 rtp_parameters_.encodings[0].max_bitrate_bps
1063 ? *rtp_parameters_.encodings[0].max_bitrate_bps
1064 : kOpusBitrateFbBps;
1065
michaelt53fe19d2016-10-18 09:39:22 -07001066 // TODO(mflodman): Keep testing this and set proper values.
1067 // Note: This is an early experiment currently only supported by Opus.
elad.alon0fe12162017-01-31 05:48:37 -08001068 if (send_side_bwe_with_overhead_) {
ossu20a4b3f2017-04-27 02:08:52 -07001069 const int max_packet_size_ms =
1070 WEBRTC_OPUS_SUPPORT_120MS_PTIME ? 120 : 60;
michaelt6672b262017-01-11 10:17:59 -08001071
ossu20a4b3f2017-04-27 02:08:52 -07001072 // OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12)
1073 constexpr int kOverheadPerPacket = 20 + 8 + 10 + 12;
michaelt6672b262017-01-11 10:17:59 -08001074
ossu20a4b3f2017-04-27 02:08:52 -07001075 int min_overhead_bps =
1076 kOverheadPerPacket * 8 * 1000 / max_packet_size_ms;
michaelt6672b262017-01-11 10:17:59 -08001077
ossu20a4b3f2017-04-27 02:08:52 -07001078 // We assume that |config_.max_bitrate_bps| before the next line is
1079 // a hard limit on the payload bitrate, so we add min_overhead_bps to
1080 // it to ensure that, when overhead is deducted, the payload rate
1081 // never goes beyond the limit.
1082 // Note: this also means that if a higher overhead is forced, we
1083 // cannot reach the limit.
1084 // TODO(minyue): Reconsider this when the signaling to BWE is done
1085 // through a dedicated API.
1086 config_.max_bitrate_bps += min_overhead_bps;
michaelt6672b262017-01-11 10:17:59 -08001087
ossu20a4b3f2017-04-27 02:08:52 -07001088 // In contrast to max_bitrate_bps, we let min_bitrate_bps always be
1089 // reachable.
1090 config_.min_bitrate_bps += min_overhead_bps;
michaelt6672b262017-01-11 10:17:59 -08001091 }
michaelt53fe19d2016-10-18 09:39:22 -07001092 }
ossu20a4b3f2017-04-27 02:08:52 -07001093 }
1094
1095 void UpdateSendCodecSpec(
1096 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) {
1097 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1098 config_.rtp.nack.rtp_history_ms =
1099 send_codec_spec.nack_enabled ? kNackRtpHistoryMs : 0;
1100 config_.send_codec_spec =
1101 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>(
1102 send_codec_spec);
1103 auto info =
1104 config_.encoder_factory->QueryAudioEncoder(send_codec_spec.format);
1105 RTC_DCHECK(info);
1106 // If a specific target bitrate has been set for the stream, use that as
1107 // the new default bitrate when computing send bitrate.
1108 if (send_codec_spec.target_bitrate_bps) {
1109 info->default_bitrate_bps = std::max(
1110 info->min_bitrate_bps,
1111 std::min(info->max_bitrate_bps, *send_codec_spec.target_bitrate_bps));
1112 }
1113
1114 audio_codec_spec_.emplace(
1115 webrtc::AudioCodecSpec{send_codec_spec.format, *info});
1116
1117 config_.send_codec_spec->target_bitrate_bps = ComputeSendBitrate(
1118 max_send_bitrate_bps_, rtp_parameters_.encodings[0].max_bitrate_bps,
1119 *audio_codec_spec_);
1120
1121 UpdateAllowedBitrateRange();
1122 }
1123
1124 void ReconfigureAudioSendStream() {
1125 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1126 RTC_DCHECK(stream_);
1127 stream_->Reconfigure(config_);
michaelt53fe19d2016-10-18 09:39:22 -07001128 }
1129
solenberg566ef242015-11-06 15:34:49 -08001130 rtc::ThreadChecker worker_thread_checker_;
solenberg347ec5c2016-09-23 04:21:47 -07001131 rtc::RaceChecker audio_capture_race_checker_;
solenbergc96df772015-10-21 13:01:53 -07001132 webrtc::AudioTransport* const voe_audio_transport_ = nullptr;
1133 webrtc::Call* call_ = nullptr;
solenberg3a941542015-11-16 07:34:50 -08001134 webrtc::AudioSendStream::Config config_;
elad.alon0fe12162017-01-31 05:48:37 -08001135 const bool send_side_bwe_with_overhead_;
solenberg3a941542015-11-16 07:34:50 -08001136 // The stream is owned by WebRtcAudioSendStream and may be reallocated if
1137 // configuration changes.
solenbergc96df772015-10-21 13:01:53 -07001138 webrtc::AudioSendStream* stream_ = nullptr;
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001139
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001140 // Raw pointer to AudioSource owned by LocalAudioTrackHandler.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001141 // PeerConnection will make sure invalidating the pointer before the object
1142 // goes away.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001143 AudioSource* source_ = nullptr;
1144 bool send_ = false;
solenberg94218532016-06-16 10:53:22 -07001145 bool muted_ = false;
minyue7a973442016-10-20 03:27:12 -07001146 int max_send_bitrate_bps_;
skvlade0d46372016-04-07 22:59:22 -07001147 webrtc::RtpParameters rtp_parameters_;
ossu20a4b3f2017-04-27 02:08:52 -07001148 rtc::Optional<webrtc::AudioCodecSpec> audio_codec_spec_;
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00001149
solenbergc96df772015-10-21 13:01:53 -07001150 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream);
1151};
1152
1153class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
1154 public:
ossu29b1a8d2016-06-13 07:34:51 -07001155 WebRtcAudioReceiveStream(
1156 int ch,
1157 uint32_t remote_ssrc,
1158 uint32_t local_ssrc,
1159 bool use_transport_cc,
solenberg8189b022016-06-14 12:13:00 -07001160 bool use_nack,
ossu29b1a8d2016-06-13 07:34:51 -07001161 const std::string& sync_group,
1162 const std::vector<webrtc::RtpExtension>& extensions,
1163 webrtc::Call* call,
1164 webrtc::Transport* rtcp_send_transport,
kwiberg1c07c702017-03-27 07:15:49 -07001165 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
1166 const std::map<int, webrtc::SdpAudioFormat>& decoder_map)
stefanba4c0e42016-02-04 04:12:24 -08001167 : call_(call), config_() {
solenberg7add0582015-11-20 09:59:34 -08001168 RTC_DCHECK_GE(ch, 0);
1169 RTC_DCHECK(call);
1170 config_.rtp.remote_ssrc = remote_ssrc;
kwibergd32bf752017-01-19 07:03:59 -08001171 config_.rtp.local_ssrc = local_ssrc;
1172 config_.rtp.transport_cc = use_transport_cc;
1173 config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0;
1174 config_.rtp.extensions = extensions;
solenberg31fec402016-05-06 02:13:12 -07001175 config_.rtcp_send_transport = rtcp_send_transport;
solenberg7add0582015-11-20 09:59:34 -08001176 config_.voe_channel_id = ch;
1177 config_.sync_group = sync_group;
ossu29b1a8d2016-06-13 07:34:51 -07001178 config_.decoder_factory = decoder_factory;
kwiberg1c07c702017-03-27 07:15:49 -07001179 config_.decoder_map = decoder_map;
kwibergd32bf752017-01-19 07:03:59 -08001180 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001181 }
solenbergc96df772015-10-21 13:01:53 -07001182
solenberg7add0582015-11-20 09:59:34 -08001183 ~WebRtcAudioReceiveStream() {
1184 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1185 call_->DestroyAudioReceiveStream(stream_);
1186 }
1187
solenberg4a0f7b52016-06-16 13:07:33 -07001188 void RecreateAudioReceiveStream(uint32_t local_ssrc) {
solenberg7add0582015-11-20 09:59:34 -08001189 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001190 config_.rtp.local_ssrc = local_ssrc;
1191 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001192 }
solenberg8189b022016-06-14 12:13:00 -07001193
1194 void RecreateAudioReceiveStream(bool use_transport_cc, bool use_nack) {
solenberg7add0582015-11-20 09:59:34 -08001195 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001196 config_.rtp.transport_cc = use_transport_cc;
1197 config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0;
1198 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001199 }
1200
solenberg4a0f7b52016-06-16 13:07:33 -07001201 void RecreateAudioReceiveStream(
1202 const std::vector<webrtc::RtpExtension>& extensions) {
1203 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001204 config_.rtp.extensions = extensions;
1205 RecreateAudioReceiveStream();
1206 }
1207
deadbeefcb383672017-04-26 16:28:42 -07001208 // Set a new payload type -> decoder map.
kwibergd32bf752017-01-19 07:03:59 -08001209 void RecreateAudioReceiveStream(
1210 const std::map<int, webrtc::SdpAudioFormat>& decoder_map) {
1211 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001212 config_.decoder_map = decoder_map;
1213 RecreateAudioReceiveStream();
solenberg4a0f7b52016-06-16 13:07:33 -07001214 }
1215
solenberg4904fb62017-02-17 12:01:14 -08001216 void MaybeRecreateAudioReceiveStream(const std::string& sync_group) {
1217 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1218 if (config_.sync_group != sync_group) {
1219 config_.sync_group = sync_group;
1220 RecreateAudioReceiveStream();
1221 }
1222 }
1223
solenberg7add0582015-11-20 09:59:34 -08001224 webrtc::AudioReceiveStream::Stats GetStats() const {
1225 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1226 RTC_DCHECK(stream_);
1227 return stream_->GetStats();
1228 }
1229
solenberg796b8f92017-03-01 17:02:23 -08001230 int GetOutputLevel() const {
1231 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1232 RTC_DCHECK(stream_);
1233 return stream_->GetOutputLevel();
1234 }
1235
solenberg7add0582015-11-20 09:59:34 -08001236 int channel() const {
1237 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1238 return config_.voe_channel_id;
1239 }
solenbergc96df772015-10-21 13:01:53 -07001240
kwiberg686a8ef2016-02-26 03:00:35 -08001241 void SetRawAudioSink(std::unique_ptr<webrtc::AudioSinkInterface> sink) {
Tommif888bb52015-12-12 01:37:01 +01001242 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwiberg686a8ef2016-02-26 03:00:35 -08001243 stream_->SetSink(std::move(sink));
Tommif888bb52015-12-12 01:37:01 +01001244 }
1245
solenberg217fb662016-06-17 08:30:54 -07001246 void SetOutputVolume(double volume) {
1247 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1248 stream_->SetGain(volume);
1249 }
1250
aleloi84ef6152016-08-04 05:28:21 -07001251 void SetPlayout(bool playout) {
1252 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1253 RTC_DCHECK(stream_);
1254 if (playout) {
1255 LOG(LS_INFO) << "Starting playout for channel #" << channel();
1256 stream_->Start();
1257 } else {
1258 LOG(LS_INFO) << "Stopping playout for channel #" << channel();
1259 stream_->Stop();
1260 }
aleloi18e0b672016-10-04 02:45:47 -07001261 playout_ = playout;
aleloi84ef6152016-08-04 05:28:21 -07001262 }
1263
hbos8d609f62017-04-10 07:39:05 -07001264 std::vector<webrtc::RtpSource> GetSources() {
1265 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1266 RTC_DCHECK(stream_);
1267 return stream_->GetSources();
1268 }
1269
solenbergc96df772015-10-21 13:01:53 -07001270 private:
kwibergd32bf752017-01-19 07:03:59 -08001271 void RecreateAudioReceiveStream() {
solenberg7add0582015-11-20 09:59:34 -08001272 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1273 if (stream_) {
1274 call_->DestroyAudioReceiveStream(stream_);
solenberg7add0582015-11-20 09:59:34 -08001275 }
solenberg7add0582015-11-20 09:59:34 -08001276 stream_ = call_->CreateAudioReceiveStream(config_);
1277 RTC_CHECK(stream_);
aleloi18e0b672016-10-04 02:45:47 -07001278 SetPlayout(playout_);
solenberg7add0582015-11-20 09:59:34 -08001279 }
1280
1281 rtc::ThreadChecker worker_thread_checker_;
1282 webrtc::Call* call_ = nullptr;
1283 webrtc::AudioReceiveStream::Config config_;
1284 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if
1285 // configuration changes.
1286 webrtc::AudioReceiveStream* stream_ = nullptr;
aleloi18e0b672016-10-04 02:45:47 -07001287 bool playout_ = false;
solenbergc96df772015-10-21 13:01:53 -07001288
1289 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioReceiveStream);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001290};
1291
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001292WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine,
nisse51542be2016-02-12 02:27:06 -08001293 const MediaConfig& config,
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001294 const AudioOptions& options,
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001295 webrtc::Call* call)
nisse51542be2016-02-12 02:27:06 -08001296 : VoiceMediaChannel(config), engine_(engine), call_(call) {
solenberg0a617e22015-10-20 15:49:38 -07001297 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel";
solenberg566ef242015-11-06 15:34:49 -08001298 RTC_DCHECK(call);
solenberg0a617e22015-10-20 15:49:38 -07001299 engine->RegisterChannel(this);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001300 SetOptions(options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001301}
1302
1303WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() {
solenberg566ef242015-11-06 15:34:49 -08001304 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg0a617e22015-10-20 15:49:38 -07001305 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel";
solenberg7add0582015-11-20 09:59:34 -08001306 // TODO(solenberg): Should be able to delete the streams directly, without
1307 // going through RemoveNnStream(), once stream objects handle
1308 // all (de)configuration.
solenbergc96df772015-10-21 13:01:53 -07001309 while (!send_streams_.empty()) {
1310 RemoveSendStream(send_streams_.begin()->first);
solenbergd97ec302015-10-07 01:40:33 -07001311 }
solenberg7add0582015-11-20 09:59:34 -08001312 while (!recv_streams_.empty()) {
1313 RemoveRecvStream(recv_streams_.begin()->first);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001314 }
solenberg0a617e22015-10-20 15:49:38 -07001315 engine()->UnregisterChannel(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001316}
1317
nisse51542be2016-02-12 02:27:06 -08001318rtc::DiffServCodePoint WebRtcVoiceMediaChannel::PreferredDscp() const {
1319 return kAudioDscpValue;
1320}
1321
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001322bool WebRtcVoiceMediaChannel::SetSendParameters(
1323 const AudioSendParameters& params) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001324 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetSendParameters");
solenberg566ef242015-11-06 15:34:49 -08001325 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7e4e01a2015-12-02 08:05:01 -08001326 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendParameters: "
1327 << params.ToString();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001328 // TODO(pthatcher): Refactor this to be more clean now that we have
1329 // all the information at once.
solenberg3a941542015-11-16 07:34:50 -08001330
1331 if (!SetSendCodecs(params.codecs)) {
1332 return false;
1333 }
1334
solenberg7e4e01a2015-12-02 08:05:01 -08001335 if (!ValidateRtpExtensions(params.extensions)) {
1336 return false;
1337 }
1338 std::vector<webrtc::RtpExtension> filtered_extensions =
1339 FilterRtpExtensions(params.extensions,
1340 webrtc::RtpExtension::IsSupportedForAudio, true);
1341 if (send_rtp_extensions_ != filtered_extensions) {
1342 send_rtp_extensions_.swap(filtered_extensions);
solenberg3a941542015-11-16 07:34:50 -08001343 for (auto& it : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001344 it.second->SetRtpExtensions(send_rtp_extensions_);
solenberg3a941542015-11-16 07:34:50 -08001345 }
1346 }
1347
deadbeef80346142016-04-27 14:17:10 -07001348 if (!SetMaxSendBitrate(params.max_bandwidth_bps)) {
solenberg3a941542015-11-16 07:34:50 -08001349 return false;
1350 }
1351 return SetOptions(params.options);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001352}
1353
1354bool WebRtcVoiceMediaChannel::SetRecvParameters(
1355 const AudioRecvParameters& params) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001356 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetRecvParameters");
solenberg566ef242015-11-06 15:34:49 -08001357 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7e4e01a2015-12-02 08:05:01 -08001358 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetRecvParameters: "
1359 << params.ToString();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001360 // TODO(pthatcher): Refactor this to be more clean now that we have
1361 // all the information at once.
solenberg7add0582015-11-20 09:59:34 -08001362
1363 if (!SetRecvCodecs(params.codecs)) {
1364 return false;
1365 }
1366
solenberg7e4e01a2015-12-02 08:05:01 -08001367 if (!ValidateRtpExtensions(params.extensions)) {
1368 return false;
1369 }
1370 std::vector<webrtc::RtpExtension> filtered_extensions =
1371 FilterRtpExtensions(params.extensions,
1372 webrtc::RtpExtension::IsSupportedForAudio, false);
1373 if (recv_rtp_extensions_ != filtered_extensions) {
1374 recv_rtp_extensions_.swap(filtered_extensions);
solenberg7add0582015-11-20 09:59:34 -08001375 for (auto& it : recv_streams_) {
1376 it.second->RecreateAudioReceiveStream(recv_rtp_extensions_);
1377 }
1378 }
solenberg7add0582015-11-20 09:59:34 -08001379 return true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001380}
1381
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001382webrtc::RtpParameters WebRtcVoiceMediaChannel::GetRtpSendParameters(
skvlade0d46372016-04-07 22:59:22 -07001383 uint32_t ssrc) const {
1384 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1385 auto it = send_streams_.find(ssrc);
1386 if (it == send_streams_.end()) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001387 LOG(LS_WARNING) << "Attempting to get RTP send parameters for stream "
1388 << "with ssrc " << ssrc << " which doesn't exist.";
skvlade0d46372016-04-07 22:59:22 -07001389 return webrtc::RtpParameters();
1390 }
1391
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001392 webrtc::RtpParameters rtp_params = it->second->rtp_parameters();
1393 // Need to add the common list of codecs to the send stream-specific
1394 // RTP parameters.
1395 for (const AudioCodec& codec : send_codecs_) {
1396 rtp_params.codecs.push_back(codec.ToCodecParameters());
1397 }
1398 return rtp_params;
skvlade0d46372016-04-07 22:59:22 -07001399}
1400
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001401bool WebRtcVoiceMediaChannel::SetRtpSendParameters(
skvlade0d46372016-04-07 22:59:22 -07001402 uint32_t ssrc,
1403 const webrtc::RtpParameters& parameters) {
1404 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
skvlade0d46372016-04-07 22:59:22 -07001405 auto it = send_streams_.find(ssrc);
1406 if (it == send_streams_.end()) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001407 LOG(LS_WARNING) << "Attempting to set RTP send parameters for stream "
1408 << "with ssrc " << ssrc << " which doesn't exist.";
skvlade0d46372016-04-07 22:59:22 -07001409 return false;
1410 }
1411
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001412 // TODO(deadbeef): Handle setting parameters with a list of codecs in a
1413 // different order (which should change the send codec).
1414 webrtc::RtpParameters current_parameters = GetRtpSendParameters(ssrc);
1415 if (current_parameters.codecs != parameters.codecs) {
1416 LOG(LS_ERROR) << "Using SetParameters to change the set of codecs "
1417 << "is not currently supported.";
1418 return false;
1419 }
1420
minyue7a973442016-10-20 03:27:12 -07001421 // TODO(minyue): The following legacy actions go into
1422 // |WebRtcAudioSendStream::SetRtpParameters()| which is called at the end,
1423 // though there are two difference:
1424 // 1. |WebRtcVoiceMediaChannel::SetChannelSendParameters()| only calls
1425 // |SetSendCodec| while |WebRtcAudioSendStream::SetRtpParameters()| calls
1426 // |SetSendCodecs|. The outcome should be the same.
1427 // 2. AudioSendStream can be recreated.
1428
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001429 // Codecs are handled at the WebRtcVoiceMediaChannel level.
1430 webrtc::RtpParameters reduced_params = parameters;
1431 reduced_params.codecs.clear();
minyue7a973442016-10-20 03:27:12 -07001432 return it->second->SetRtpParameters(reduced_params);
skvlade0d46372016-04-07 22:59:22 -07001433}
1434
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001435webrtc::RtpParameters WebRtcVoiceMediaChannel::GetRtpReceiveParameters(
1436 uint32_t ssrc) const {
1437 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef3bc15102017-04-20 19:25:07 -07001438 webrtc::RtpParameters rtp_params;
1439 // SSRC of 0 represents the default receive stream.
1440 if (ssrc == 0) {
1441 if (!default_sink_) {
1442 LOG(LS_WARNING) << "Attempting to get RTP parameters for the default, "
1443 "unsignaled audio receive stream, but not yet "
1444 "configured to receive such a stream.";
1445 return rtp_params;
1446 }
1447 rtp_params.encodings.emplace_back();
1448 } else {
1449 auto it = recv_streams_.find(ssrc);
1450 if (it == recv_streams_.end()) {
1451 LOG(LS_WARNING) << "Attempting to get RTP receive parameters for stream "
1452 << "with ssrc " << ssrc << " which doesn't exist.";
1453 return webrtc::RtpParameters();
1454 }
1455 rtp_params.encodings.emplace_back();
1456 // TODO(deadbeef): Return stream-specific parameters.
1457 rtp_params.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001458 }
1459
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001460 for (const AudioCodec& codec : recv_codecs_) {
1461 rtp_params.codecs.push_back(codec.ToCodecParameters());
1462 }
1463 return rtp_params;
1464}
1465
1466bool WebRtcVoiceMediaChannel::SetRtpReceiveParameters(
1467 uint32_t ssrc,
1468 const webrtc::RtpParameters& parameters) {
1469 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef3bc15102017-04-20 19:25:07 -07001470 // SSRC of 0 represents the default receive stream.
1471 if (ssrc == 0) {
1472 if (!default_sink_) {
1473 LOG(LS_WARNING) << "Attempting to set RTP parameters for the default, "
1474 "unsignaled audio receive stream, but not yet "
1475 "configured to receive such a stream.";
1476 return false;
1477 }
1478 } else {
1479 auto it = recv_streams_.find(ssrc);
1480 if (it == recv_streams_.end()) {
1481 LOG(LS_WARNING) << "Attempting to set RTP receive parameters for stream "
1482 << "with ssrc " << ssrc << " which doesn't exist.";
1483 return false;
1484 }
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001485 }
1486
1487 webrtc::RtpParameters current_parameters = GetRtpReceiveParameters(ssrc);
1488 if (current_parameters != parameters) {
1489 LOG(LS_ERROR) << "Changing the RTP receive parameters is currently "
1490 << "unsupported.";
1491 return false;
1492 }
1493 return true;
1494}
1495
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001496bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
solenberg566ef242015-11-06 15:34:49 -08001497 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001498 LOG(LS_INFO) << "Setting voice channel options: "
1499 << options.ToString();
1500
1501 // We retain all of the existing options, and apply the given ones
1502 // on top. This means there is no way to "clear" options such that
1503 // they go back to the engine default.
1504 options_.SetAll(options);
solenberg246b8172015-12-08 09:50:23 -08001505 if (!engine()->ApplyOptions(options_)) {
1506 LOG(LS_WARNING) <<
1507 "Failed to apply engine options during channel SetOptions.";
1508 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001509 }
minyue6b825df2016-10-31 04:08:32 -07001510
ossu20a4b3f2017-04-27 02:08:52 -07001511 rtc::Optional<std::string> audio_network_adaptor_config =
minyue6b825df2016-10-31 04:08:32 -07001512 GetAudioNetworkAdaptorConfig(options_);
1513 for (auto& it : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001514 it.second->SetAudioNetworkAdaptorConfig(audio_network_adaptor_config);
minyue6b825df2016-10-31 04:08:32 -07001515 }
1516
solenberg76377c52017-02-21 00:54:31 -08001517 LOG(LS_INFO) << "Set voice channel options. Current options: "
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001518 << options_.ToString();
1519 return true;
1520}
1521
1522bool WebRtcVoiceMediaChannel::SetRecvCodecs(
1523 const std::vector<AudioCodec>& codecs) {
solenberg566ef242015-11-06 15:34:49 -08001524 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg8fb30c32015-10-13 03:06:58 -07001525
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001526 // Set the payload types to be used for incoming media.
solenberg0b675462015-10-09 01:37:09 -07001527 LOG(LS_INFO) << "Setting receive voice codecs.";
solenberg0b675462015-10-09 01:37:09 -07001528
1529 if (!VerifyUniquePayloadTypes(codecs)) {
1530 LOG(LS_ERROR) << "Codec payload types overlap.";
1531 return false;
1532 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001533
kwibergd32bf752017-01-19 07:03:59 -08001534 // Create a payload type -> SdpAudioFormat map with all the decoders. Fail
1535 // unless the factory claims to support all decoders.
1536 std::map<int, webrtc::SdpAudioFormat> decoder_map;
1537 for (const AudioCodec& codec : codecs) {
deadbeefcb383672017-04-26 16:28:42 -07001538 // Log a warning if a codec's payload type is changing. This used to be
1539 // treated as an error. It's abnormal, but not really illegal.
1540 AudioCodec old_codec;
1541 if (FindCodec(recv_codecs_, codec, &old_codec) &&
1542 old_codec.id != codec.id) {
1543 LOG(LS_WARNING) << codec.name << " mapped to a second payload type ("
1544 << codec.id << ", was already mapped to " << old_codec.id
1545 << ")";
1546 }
kwibergd32bf752017-01-19 07:03:59 -08001547 auto format = AudioCodecToSdpAudioFormat(codec);
1548 if (!IsCodec(codec, "cn") && !IsCodec(codec, "telephone-event") &&
1549 !engine()->decoder_factory_->IsSupportedDecoder(format)) {
1550 LOG(LS_ERROR) << "Unsupported codec: " << format;
1551 return false;
1552 }
deadbeefcb383672017-04-26 16:28:42 -07001553 // We allow adding new codecs but don't allow changing the payload type of
1554 // codecs that are already configured since we might already be receiving
1555 // packets with that payload type. See RFC3264, Section 8.3.2.
1556 // TODO(deadbeef): Also need to check for clashes with previously mapped
1557 // payload types, and not just currently mapped ones. For example, this
1558 // should be illegal:
1559 // 1. {100: opus/48000/2, 101: ISAC/16000}
1560 // 2. {100: opus/48000/2}
1561 // 3. {100: opus/48000/2, 101: ISAC/32000}
1562 // Though this check really should happen at a higher level, since this
1563 // conflict could happen between audio and video codecs.
1564 auto existing = decoder_map_.find(codec.id);
1565 if (existing != decoder_map_.end() && !existing->second.Matches(format)) {
1566 LOG(LS_ERROR) << "Attempting to use payload type " << codec.id << " for "
1567 << codec.name << ", but it is already used for "
1568 << existing->second.name;
1569 return false;
1570 }
kwibergd32bf752017-01-19 07:03:59 -08001571 decoder_map.insert({codec.id, std::move(format)});
1572 }
1573
deadbeefcb383672017-04-26 16:28:42 -07001574 if (decoder_map == decoder_map_) {
1575 // There's nothing new to configure.
1576 return true;
1577 }
1578
kwiberg37b8b112016-11-03 02:46:53 -07001579 if (playout_) {
1580 // Receive codecs can not be changed while playing. So we temporarily
1581 // pause playout.
1582 ChangePlayout(false);
1583 }
1584
kwiberg1c07c702017-03-27 07:15:49 -07001585 decoder_map_ = std::move(decoder_map);
kwibergd32bf752017-01-19 07:03:59 -08001586 for (auto& kv : recv_streams_) {
kwiberg1c07c702017-03-27 07:15:49 -07001587 kv.second->RecreateAudioReceiveStream(decoder_map_);
solenberg26c8c912015-11-27 04:00:25 -08001588 }
kwibergd32bf752017-01-19 07:03:59 -08001589 recv_codecs_ = codecs;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001590
kwiberg37b8b112016-11-03 02:46:53 -07001591 if (desired_playout_ && !playout_) {
1592 ChangePlayout(desired_playout_);
1593 }
kwibergd32bf752017-01-19 07:03:59 -08001594 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001595}
1596
solenberg72e29d22016-03-08 06:35:16 -08001597// Utility function called from SetSendParameters() to extract current send
1598// codec settings from the given list of codecs (originally from SDP). Both send
1599// and receive streams may be reconfigured based on the new settings.
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001600bool WebRtcVoiceMediaChannel::SetSendCodecs(
1601 const std::vector<AudioCodec>& codecs) {
solenberg566ef242015-11-06 15:34:49 -08001602 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenbergb5727682015-12-04 15:22:19 +01001603 dtmf_payload_type_ = rtc::Optional<int>();
solenbergffbbcac2016-11-17 05:25:37 -08001604 dtmf_payload_freq_ = -1;
1605
1606 // Validate supplied codecs list.
1607 for (const AudioCodec& codec : codecs) {
1608 // TODO(solenberg): Validate more aspects of input - that payload types
1609 // don't overlap, remove redundant/unsupported codecs etc -
1610 // the same way it is done for RtpHeaderExtensions.
1611 if (codec.id < kMinPayloadType || codec.id > kMaxPayloadType) {
1612 LOG(LS_WARNING) << "Codec payload type out of range: " << ToString(codec);
1613 return false;
1614 }
1615 }
1616
1617 // Find PT of telephone-event codec with lowest clockrate, as a fallback, in
1618 // case we don't have a DTMF codec with a rate matching the send codec's, or
1619 // if this function returns early.
1620 std::vector<AudioCodec> dtmf_codecs;
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02001621 for (const AudioCodec& codec : codecs) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02001622 if (IsCodec(codec, kDtmfCodecName)) {
solenbergffbbcac2016-11-17 05:25:37 -08001623 dtmf_codecs.push_back(codec);
1624 if (!dtmf_payload_type_ || codec.clockrate < dtmf_payload_freq_) {
1625 dtmf_payload_type_ = rtc::Optional<int>(codec.id);
1626 dtmf_payload_freq_ = codec.clockrate;
solenberg31642aa2016-03-14 08:00:37 -07001627 }
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001628 }
1629 }
1630
ossu20a4b3f2017-04-27 02:08:52 -07001631 // Scan through the list to figure out the codec to use for sending.
1632 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec> send_codec_spec;
stefan1ccf73f2017-03-27 03:51:18 -07001633 webrtc::Call::Config::BitrateConfig bitrate_config;
ossu20a4b3f2017-04-27 02:08:52 -07001634 rtc::Optional<webrtc::AudioCodecInfo> voice_codec_info;
1635 for (const AudioCodec& voice_codec : codecs) {
1636 if (!(IsCodec(voice_codec, kCnCodecName) ||
1637 IsCodec(voice_codec, kDtmfCodecName) ||
1638 IsCodec(voice_codec, kRedCodecName))) {
1639 webrtc::SdpAudioFormat format(voice_codec.name, voice_codec.clockrate,
1640 voice_codec.channels, voice_codec.params);
solenberg72e29d22016-03-08 06:35:16 -08001641
ossu20a4b3f2017-04-27 02:08:52 -07001642 voice_codec_info = engine()->encoder_factory_->QueryAudioEncoder(format);
1643 if (!voice_codec_info) {
1644 LOG(LS_WARNING) << "Unknown codec " << ToString(voice_codec);
solenberg72e29d22016-03-08 06:35:16 -08001645 continue;
1646 }
1647
ossu20a4b3f2017-04-27 02:08:52 -07001648 send_codec_spec =
1649 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>(
1650 {voice_codec.id, format});
1651 if (voice_codec.bitrate > 0) {
1652 send_codec_spec->target_bitrate_bps =
1653 rtc::Optional<int>(voice_codec.bitrate);
1654 }
1655 send_codec_spec->transport_cc_enabled = HasTransportCc(voice_codec);
1656 send_codec_spec->nack_enabled = HasNack(voice_codec);
1657 bitrate_config = GetBitrateConfigForCodec(voice_codec);
1658 break;
1659 }
1660 }
1661
1662 if (!send_codec_spec) {
1663 return false;
1664 }
1665
1666 RTC_DCHECK(voice_codec_info);
1667 if (voice_codec_info->allow_comfort_noise) {
1668 // Loop through the codecs list again to find the CN codec.
1669 // TODO(solenberg): Break out into a separate function?
1670 for (const AudioCodec& cn_codec : codecs) {
ossu0c4b8492017-03-02 11:03:25 -08001671 if (IsCodec(cn_codec, kCnCodecName) &&
ossu20a4b3f2017-04-27 02:08:52 -07001672 cn_codec.clockrate == send_codec_spec->format.clockrate_hz) {
ossu0c4b8492017-03-02 11:03:25 -08001673 switch (cn_codec.clockrate) {
solenberg72e29d22016-03-08 06:35:16 -08001674 case 8000:
1675 case 16000:
1676 case 32000:
ossu20a4b3f2017-04-27 02:08:52 -07001677 send_codec_spec->cng_payload_type = rtc::Optional<int>(cn_codec.id);
solenberg72e29d22016-03-08 06:35:16 -08001678 break;
1679 default:
ossu0c4b8492017-03-02 11:03:25 -08001680 LOG(LS_WARNING) << "CN frequency " << cn_codec.clockrate
solenberg72e29d22016-03-08 06:35:16 -08001681 << " not supported.";
ossu20a4b3f2017-04-27 02:08:52 -07001682 break;
solenberg72e29d22016-03-08 06:35:16 -08001683 }
solenberg72e29d22016-03-08 06:35:16 -08001684 break;
1685 }
1686 }
solenbergffbbcac2016-11-17 05:25:37 -08001687
1688 // Find the telephone-event PT exactly matching the preferred send codec.
1689 for (const AudioCodec& dtmf_codec : dtmf_codecs) {
ossu20a4b3f2017-04-27 02:08:52 -07001690 if (dtmf_codec.clockrate == send_codec_spec->format.clockrate_hz) {
solenbergffbbcac2016-11-17 05:25:37 -08001691 dtmf_payload_type_ = rtc::Optional<int>(dtmf_codec.id);
1692 dtmf_payload_freq_ = dtmf_codec.clockrate;
1693 break;
1694 }
1695 }
solenberg72e29d22016-03-08 06:35:16 -08001696 }
1697
solenberg971cab02016-06-14 10:02:41 -07001698 if (send_codec_spec_ != send_codec_spec) {
1699 send_codec_spec_ = std::move(send_codec_spec);
stefan13f1a0a2016-11-30 07:22:58 -08001700 // Apply new settings to all streams.
solenberg971cab02016-06-14 10:02:41 -07001701 for (const auto& kv : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001702 kv.second->SetSendCodecSpec(*send_codec_spec_);
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001703 }
stefan13f1a0a2016-11-30 07:22:58 -08001704 } else {
1705 // If the codec isn't changing, set the start bitrate to -1 which means
1706 // "unchanged" so that BWE isn't affected.
stefan1ccf73f2017-03-27 03:51:18 -07001707 bitrate_config.start_bitrate_bps = -1;
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001708 }
stefan1ccf73f2017-03-27 03:51:18 -07001709 call_->SetBitrateConfig(bitrate_config);
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001710
solenberg8189b022016-06-14 12:13:00 -07001711 // Check if the transport cc feedback or NACK status has changed on the
1712 // preferred send codec, and in that case reconfigure all receive streams.
ossu20a4b3f2017-04-27 02:08:52 -07001713 if (recv_transport_cc_enabled_ != send_codec_spec_->transport_cc_enabled ||
1714 recv_nack_enabled_ != send_codec_spec_->nack_enabled) {
solenberg72e29d22016-03-08 06:35:16 -08001715 LOG(LS_INFO) << "Recreate all the receive streams because the send "
1716 "codec has changed.";
ossu20a4b3f2017-04-27 02:08:52 -07001717 recv_transport_cc_enabled_ = send_codec_spec_->transport_cc_enabled;
1718 recv_nack_enabled_ = send_codec_spec_->nack_enabled;
solenberg72e29d22016-03-08 06:35:16 -08001719 for (auto& kv : recv_streams_) {
solenberg8189b022016-06-14 12:13:00 -07001720 kv.second->RecreateAudioReceiveStream(recv_transport_cc_enabled_,
1721 recv_nack_enabled_);
solenberg72e29d22016-03-08 06:35:16 -08001722 }
1723 }
1724
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001725 send_codecs_ = codecs;
solenberg72e29d22016-03-08 06:35:16 -08001726 return true;
1727}
1728
aleloi84ef6152016-08-04 05:28:21 -07001729void WebRtcVoiceMediaChannel::SetPlayout(bool playout) {
kwiberg37b8b112016-11-03 02:46:53 -07001730 desired_playout_ = playout;
1731 return ChangePlayout(desired_playout_);
1732}
1733
1734void WebRtcVoiceMediaChannel::ChangePlayout(bool playout) {
1735 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::ChangePlayout");
solenberg566ef242015-11-06 15:34:49 -08001736 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001737 if (playout_ == playout) {
aleloi84ef6152016-08-04 05:28:21 -07001738 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001739 }
1740
aleloi84ef6152016-08-04 05:28:21 -07001741 for (const auto& kv : recv_streams_) {
1742 kv.second->SetPlayout(playout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001743 }
solenberg1ac56142015-10-13 03:58:19 -07001744 playout_ = playout;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001745}
1746
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001747void WebRtcVoiceMediaChannel::SetSend(bool send) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001748 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetSend");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001749 if (send_ == send) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001750 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001751 }
1752
solenbergd53a3f92016-04-14 13:56:37 -07001753 // Apply channel specific options, and initialize the ADM for recording (this
1754 // may take time on some platforms, e.g. Android).
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001755 if (send) {
solenberg63b34542015-09-29 06:06:31 -07001756 engine()->ApplyOptions(options_);
solenbergd53a3f92016-04-14 13:56:37 -07001757
1758 // InitRecording() may return an error if the ADM is already recording.
1759 if (!engine()->adm()->RecordingIsInitialized() &&
1760 !engine()->adm()->Recording()) {
1761 if (engine()->adm()->InitRecording() != 0) {
1762 LOG(LS_WARNING) << "Failed to initialize recording";
1763 }
1764 }
solenberg63b34542015-09-29 06:06:31 -07001765 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001766
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001767 // Change the settings on each send channel.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001768 for (auto& kv : send_streams_) {
1769 kv.second->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001770 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001771
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001772 send_ = send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001773}
1774
Peter Boström0c4e06b2015-10-07 12:23:21 +02001775bool WebRtcVoiceMediaChannel::SetAudioSend(uint32_t ssrc,
1776 bool enable,
solenberg1dd98f32015-09-10 01:57:14 -07001777 const AudioOptions* options,
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001778 AudioSource* source) {
solenberg566ef242015-11-06 15:34:49 -08001779 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg1dd98f32015-09-10 01:57:14 -07001780 // TODO(solenberg): The state change should be fully rolled back if any one of
1781 // these calls fail.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001782 if (!SetLocalSource(ssrc, source)) {
solenberg1dd98f32015-09-10 01:57:14 -07001783 return false;
1784 }
solenbergdfc8f4f2015-10-01 02:31:10 -07001785 if (!MuteStream(ssrc, !enable)) {
solenberg1dd98f32015-09-10 01:57:14 -07001786 return false;
1787 }
solenbergdfc8f4f2015-10-01 02:31:10 -07001788 if (enable && options) {
solenberg1dd98f32015-09-10 01:57:14 -07001789 return SetOptions(*options);
1790 }
1791 return true;
1792}
1793
solenberg0a617e22015-10-20 15:49:38 -07001794int WebRtcVoiceMediaChannel::CreateVoEChannel() {
1795 int id = engine()->CreateVoEChannel();
1796 if (id == -1) {
solenberg35dee812017-09-18 01:57:01 -07001797 LOG(LS_WARNING) << "CreateVoEChannel() failed.";
solenberg0a617e22015-10-20 15:49:38 -07001798 return -1;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001799 }
mflodman3d7db262016-04-29 00:57:13 -07001800
solenberg0a617e22015-10-20 15:49:38 -07001801 return id;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001802}
1803
solenberg7add0582015-11-20 09:59:34 -08001804bool WebRtcVoiceMediaChannel::DeleteVoEChannel(int channel) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001805 if (engine()->voe()->base()->DeleteChannel(channel) == -1) {
solenberg35dee812017-09-18 01:57:01 -07001806 LOG(LS_WARNING) << "DeleteChannel(" << channel << ") failed.";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001807 return false;
1808 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001809 return true;
1810}
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001811
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001812bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001813 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::AddSendStream");
solenberg566ef242015-11-06 15:34:49 -08001814 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg0a617e22015-10-20 15:49:38 -07001815 LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
1816
1817 uint32_t ssrc = sp.first_ssrc();
1818 RTC_DCHECK(0 != ssrc);
1819
1820 if (GetSendChannelId(ssrc) != -1) {
1821 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001822 return false;
1823 }
1824
solenberg0a617e22015-10-20 15:49:38 -07001825 // Create a new channel for sending audio data.
1826 int channel = CreateVoEChannel();
1827 if (channel == -1) {
1828 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001829 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001830
solenbergc96df772015-10-21 13:01:53 -07001831 // Save the channel to send_streams_, so that RemoveSendStream() can still
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001832 // delete the channel in case failure happens below.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001833 webrtc::AudioTransport* audio_transport =
1834 engine()->voe()->base()->audio_transport();
mflodman3d7db262016-04-29 00:57:13 -07001835
minyue6b825df2016-10-31 04:08:32 -07001836 rtc::Optional<std::string> audio_network_adaptor_config =
1837 GetAudioNetworkAdaptorConfig(options_);
skvlade0d46372016-04-07 22:59:22 -07001838 WebRtcAudioSendStream* stream = new WebRtcAudioSendStream(
solenberg971cab02016-06-14 10:02:41 -07001839 channel, audio_transport, ssrc, sp.cname, send_codec_spec_,
minyue6b825df2016-10-31 04:08:32 -07001840 send_rtp_extensions_, max_send_bitrate_bps_, audio_network_adaptor_config,
ossu20a4b3f2017-04-27 02:08:52 -07001841 call_, this, engine()->encoder_factory_);
skvlade0d46372016-04-07 22:59:22 -07001842 send_streams_.insert(std::make_pair(ssrc, stream));
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001843
solenberg4a0f7b52016-06-16 13:07:33 -07001844 // At this point the stream's local SSRC has been updated. If it is the first
1845 // send stream, make sure that all the receive streams are updated with the
1846 // same SSRC in order to send receiver reports.
solenbergc96df772015-10-21 13:01:53 -07001847 if (send_streams_.size() == 1) {
solenberg0a617e22015-10-20 15:49:38 -07001848 receiver_reports_ssrc_ = ssrc;
solenberg4a0f7b52016-06-16 13:07:33 -07001849 for (const auto& kv : recv_streams_) {
1850 // TODO(solenberg): Allow applications to set the RTCP SSRC of receive
1851 // streams instead, so we can avoid recreating the streams here.
1852 kv.second->RecreateAudioReceiveStream(ssrc);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001853 }
1854 }
1855
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001856 send_streams_[ssrc]->SetSend(send_);
1857 return true;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001858}
1859
Peter Boström0c4e06b2015-10-07 12:23:21 +02001860bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001861 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::RemoveSendStream");
solenberg566ef242015-11-06 15:34:49 -08001862 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg3a941542015-11-16 07:34:50 -08001863 LOG(LS_INFO) << "RemoveSendStream: " << ssrc;
1864
solenbergc96df772015-10-21 13:01:53 -07001865 auto it = send_streams_.find(ssrc);
1866 if (it == send_streams_.end()) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001867 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
1868 << " which doesn't exist.";
1869 return false;
1870 }
1871
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001872 it->second->SetSend(false);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001873
solenberg7602aab2016-11-14 11:30:07 -08001874 // TODO(solenberg): If we're removing the receiver_reports_ssrc_ stream, find
1875 // the first active send stream and use that instead, reassociating receive
1876 // streams.
1877
solenberg7add0582015-11-20 09:59:34 -08001878 // Clean up and delete the send stream+channel.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001879 int channel = it->second->channel();
solenberg0a617e22015-10-20 15:49:38 -07001880 LOG(LS_INFO) << "Removing audio send stream " << ssrc
1881 << " with VoiceEngine channel #" << channel << ".";
solenberg7add0582015-11-20 09:59:34 -08001882 delete it->second;
1883 send_streams_.erase(it);
1884 if (!DeleteVoEChannel(channel)) {
solenberg0a617e22015-10-20 15:49:38 -07001885 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001886 }
solenbergc96df772015-10-21 13:01:53 -07001887 if (send_streams_.empty()) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001888 SetSend(false);
solenberg0a617e22015-10-20 15:49:38 -07001889 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001890 return true;
1891}
1892
1893bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001894 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::AddRecvStream");
solenberg566ef242015-11-06 15:34:49 -08001895 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergd97ec302015-10-07 01:40:33 -07001896 LOG(LS_INFO) << "AddRecvStream: " << sp.ToString();
1897
solenberg0b675462015-10-09 01:37:09 -07001898 if (!ValidateStreamParams(sp)) {
wu@webrtc.org78187522013-10-07 23:32:02 +00001899 return false;
1900 }
1901
solenberg7add0582015-11-20 09:59:34 -08001902 const uint32_t ssrc = sp.first_ssrc();
solenberg0b675462015-10-09 01:37:09 -07001903 if (ssrc == 0) {
1904 LOG(LS_WARNING) << "AddRecvStream with ssrc==0 is not supported.";
1905 return false;
1906 }
1907
solenberg2100c0b2017-03-01 11:29:29 -08001908 // If this stream was previously received unsignaled, we promote it, possibly
1909 // recreating the AudioReceiveStream, if sync_label has changed.
1910 if (MaybeDeregisterUnsignaledRecvStream(ssrc)) {
solenberg4904fb62017-02-17 12:01:14 -08001911 recv_streams_[ssrc]->MaybeRecreateAudioReceiveStream(sp.sync_label);
solenberg4904fb62017-02-17 12:01:14 -08001912 return true;
solenberg1ac56142015-10-13 03:58:19 -07001913 }
solenberg0b675462015-10-09 01:37:09 -07001914
solenberg7add0582015-11-20 09:59:34 -08001915 if (GetReceiveChannelId(ssrc) != -1) {
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001916 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001917 return false;
1918 }
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02001919
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001920 // Create a new channel for receiving audio data.
solenberg7add0582015-11-20 09:59:34 -08001921 const int channel = CreateVoEChannel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001922 if (channel == -1) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001923 return false;
1924 }
Minyue2013aec2015-05-13 14:14:42 +02001925
stefanba4c0e42016-02-04 04:12:24 -08001926 recv_streams_.insert(std::make_pair(
kwiberg1c07c702017-03-27 07:15:49 -07001927 ssrc,
1928 new WebRtcAudioReceiveStream(
1929 channel, ssrc, receiver_reports_ssrc_, recv_transport_cc_enabled_,
1930 recv_nack_enabled_, sp.sync_label, recv_rtp_extensions_, call_, this,
1931 engine()->decoder_factory_, decoder_map_)));
aleloi84ef6152016-08-04 05:28:21 -07001932 recv_streams_[ssrc]->SetPlayout(playout_);
solenberg7add0582015-11-20 09:59:34 -08001933
solenberg1ac56142015-10-13 03:58:19 -07001934 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001935}
1936
Peter Boström0c4e06b2015-10-07 12:23:21 +02001937bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001938 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::RemoveRecvStream");
solenberg566ef242015-11-06 15:34:49 -08001939 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergd97ec302015-10-07 01:40:33 -07001940 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
1941
solenberg7add0582015-11-20 09:59:34 -08001942 const auto it = recv_streams_.find(ssrc);
1943 if (it == recv_streams_.end()) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001944 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
1945 << " which doesn't exist.";
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001946 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001947 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001948
solenberg2100c0b2017-03-01 11:29:29 -08001949 MaybeDeregisterUnsignaledRecvStream(ssrc);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001950
solenberg7add0582015-11-20 09:59:34 -08001951 const int channel = it->second->channel();
1952
1953 // Clean up and delete the receive stream+channel.
1954 LOG(LS_INFO) << "Removing audio receive stream " << ssrc
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001955 << " with VoiceEngine channel #" << channel << ".";
Tommif888bb52015-12-12 01:37:01 +01001956 it->second->SetRawAudioSink(nullptr);
solenberg7add0582015-11-20 09:59:34 -08001957 delete it->second;
1958 recv_streams_.erase(it);
1959 return DeleteVoEChannel(channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001960}
1961
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001962bool WebRtcVoiceMediaChannel::SetLocalSource(uint32_t ssrc,
1963 AudioSource* source) {
solenbergc96df772015-10-21 13:01:53 -07001964 auto it = send_streams_.find(ssrc);
1965 if (it == send_streams_.end()) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001966 if (source) {
1967 // Return an error if trying to set a valid source with an invalid ssrc.
1968 LOG(LS_ERROR) << "SetLocalSource failed with ssrc " << ssrc;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001969 return false;
1970 }
1971
1972 // The channel likely has gone away, do nothing.
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001973 return true;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001974 }
1975
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001976 if (source) {
1977 it->second->SetSource(source);
solenberg1ac56142015-10-13 03:58:19 -07001978 } else {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001979 it->second->ClearSource();
solenberg1ac56142015-10-13 03:58:19 -07001980 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001981
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001982 return true;
1983}
1984
solenberg796b8f92017-03-01 17:02:23 -08001985// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001986bool WebRtcVoiceMediaChannel::GetActiveStreams(
1987 AudioInfo::StreamList* actives) {
solenberg566ef242015-11-06 15:34:49 -08001988 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001989 actives->clear();
solenberg7add0582015-11-20 09:59:34 -08001990 for (const auto& ch : recv_streams_) {
solenberg796b8f92017-03-01 17:02:23 -08001991 int level = ch.second->GetOutputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001992 if (level > 0) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02001993 actives->push_back(std::make_pair(ch.first, level));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001994 }
1995 }
1996 return true;
1997}
1998
solenberg796b8f92017-03-01 17:02:23 -08001999// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002000int WebRtcVoiceMediaChannel::GetOutputLevel() {
solenberg566ef242015-11-06 15:34:49 -08002001 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg1ac56142015-10-13 03:58:19 -07002002 int highest = 0;
solenberg7add0582015-11-20 09:59:34 -08002003 for (const auto& ch : recv_streams_) {
solenberg796b8f92017-03-01 17:02:23 -08002004 highest = std::max(ch.second->GetOutputLevel(), highest);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002005 }
2006 return highest;
2007}
2008
solenberg4bac9c52015-10-09 02:32:53 -07002009bool WebRtcVoiceMediaChannel::SetOutputVolume(uint32_t ssrc, double volume) {
solenberg566ef242015-11-06 15:34:49 -08002010 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg2100c0b2017-03-01 11:29:29 -08002011 std::vector<uint32_t> ssrcs(1, ssrc);
deadbeef3bc15102017-04-20 19:25:07 -07002012 // SSRC of 0 represents the default receive stream.
solenberg1ac56142015-10-13 03:58:19 -07002013 if (ssrc == 0) {
2014 default_recv_volume_ = volume;
solenberg2100c0b2017-03-01 11:29:29 -08002015 ssrcs = unsignaled_recv_ssrcs_;
2016 }
2017 for (uint32_t ssrc : ssrcs) {
2018 const auto it = recv_streams_.find(ssrc);
2019 if (it == recv_streams_.end()) {
2020 LOG(LS_WARNING) << "SetOutputVolume: no recv stream " << ssrc;
2021 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002022 }
solenberg2100c0b2017-03-01 11:29:29 -08002023 it->second->SetOutputVolume(volume);
2024 LOG(LS_INFO) << "SetOutputVolume() to " << volume
2025 << " for recv stream with ssrc " << ssrc;
solenberg1ac56142015-10-13 03:58:19 -07002026 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002027 return true;
2028}
2029
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002030bool WebRtcVoiceMediaChannel::CanInsertDtmf() {
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002031 return dtmf_payload_type_ ? true : false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002032}
2033
solenberg1d63dd02015-12-02 12:35:09 -08002034bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, int event,
2035 int duration) {
solenberg566ef242015-11-06 15:34:49 -08002036 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002037 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::InsertDtmf";
2038 if (!dtmf_payload_type_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002039 return false;
2040 }
2041
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002042 // Figure out which WebRtcAudioSendStream to send the event on.
2043 auto it = ssrc != 0 ? send_streams_.find(ssrc) : send_streams_.begin();
2044 if (it == send_streams_.end()) {
2045 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
solenberg1d63dd02015-12-02 12:35:09 -08002046 return false;
2047 }
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002048 if (event < kMinTelephoneEventCode ||
2049 event > kMaxTelephoneEventCode) {
2050 LOG(LS_WARNING) << "DTMF event code " << event << " out of range.";
solenberg1d63dd02015-12-02 12:35:09 -08002051 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002052 }
solenbergffbbcac2016-11-17 05:25:37 -08002053 RTC_DCHECK_NE(-1, dtmf_payload_freq_);
2054 return it->second->SendTelephoneEvent(*dtmf_payload_type_, dtmf_payload_freq_,
2055 event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002056}
2057
wu@webrtc.orga9890802013-12-13 00:21:03 +00002058void WebRtcVoiceMediaChannel::OnPacketReceived(
jbaucheec21bd2016-03-20 06:15:43 -07002059 rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
solenberg566ef242015-11-06 15:34:49 -08002060 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02002061
mflodman3d7db262016-04-29 00:57:13 -07002062 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
2063 packet_time.not_before);
2064 webrtc::PacketReceiver::DeliveryStatus delivery_result =
2065 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
2066 packet->cdata(), packet->size(),
2067 webrtc_packet_time);
mflodman3d7db262016-04-29 00:57:13 -07002068 if (delivery_result != webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC) {
2069 return;
2070 }
2071
solenberg2100c0b2017-03-01 11:29:29 -08002072 // Create an unsignaled receive stream for this previously not received ssrc.
2073 // If there already is N unsignaled receive streams, delete the oldest.
mflodman3d7db262016-04-29 00:57:13 -07002074 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5208
solenberg1ac56142015-10-13 03:58:19 -07002075 uint32_t ssrc = 0;
jbaucheec21bd2016-03-20 06:15:43 -07002076 if (!GetRtpSsrc(packet->cdata(), packet->size(), &ssrc)) {
solenberg1ac56142015-10-13 03:58:19 -07002077 return;
2078 }
solenberg2100c0b2017-03-01 11:29:29 -08002079 RTC_DCHECK(std::find(unsignaled_recv_ssrcs_.begin(),
2080 unsignaled_recv_ssrcs_.end(), ssrc) == unsignaled_recv_ssrcs_.end());
solenberg1ac56142015-10-13 03:58:19 -07002081
solenberg2100c0b2017-03-01 11:29:29 -08002082 // Add new stream.
mflodman3d7db262016-04-29 00:57:13 -07002083 StreamParams sp;
2084 sp.ssrcs.push_back(ssrc);
solenberg2100c0b2017-03-01 11:29:29 -08002085 LOG(LS_INFO) << "Creating unsignaled receive stream for SSRC=" << ssrc;
mflodman3d7db262016-04-29 00:57:13 -07002086 if (!AddRecvStream(sp)) {
solenberg2100c0b2017-03-01 11:29:29 -08002087 LOG(LS_WARNING) << "Could not create unsignaled receive stream.";
mflodman3d7db262016-04-29 00:57:13 -07002088 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002089 }
solenberg2100c0b2017-03-01 11:29:29 -08002090 unsignaled_recv_ssrcs_.push_back(ssrc);
2091 RTC_HISTOGRAM_COUNTS_LINEAR(
2092 "WebRTC.Audio.NumOfUnsignaledStreams", unsignaled_recv_ssrcs_.size(), 1,
2093 100, 101);
solenbergf748ca42017-02-06 13:03:19 -08002094
solenberg2100c0b2017-03-01 11:29:29 -08002095 // Remove oldest unsignaled stream, if we have too many.
2096 if (unsignaled_recv_ssrcs_.size() > kMaxUnsignaledRecvStreams) {
2097 uint32_t remove_ssrc = unsignaled_recv_ssrcs_.front();
2098 LOG(LS_INFO) << "Removing unsignaled receive stream with SSRC="
2099 << remove_ssrc;
2100 RemoveRecvStream(remove_ssrc);
2101 }
2102 RTC_DCHECK_GE(kMaxUnsignaledRecvStreams, unsignaled_recv_ssrcs_.size());
2103
2104 SetOutputVolume(ssrc, default_recv_volume_);
2105
2106 // The default sink can only be attached to one stream at a time, so we hook
2107 // it up to the *latest* unsignaled stream we've seen, in order to support the
2108 // case where the SSRC of one unsignaled stream changes.
mflodman3d7db262016-04-29 00:57:13 -07002109 if (default_sink_) {
solenberg2100c0b2017-03-01 11:29:29 -08002110 for (uint32_t drop_ssrc : unsignaled_recv_ssrcs_) {
2111 auto it = recv_streams_.find(drop_ssrc);
2112 it->second->SetRawAudioSink(nullptr);
2113 }
mflodman3d7db262016-04-29 00:57:13 -07002114 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
2115 new ProxySink(default_sink_.get()));
solenberg2100c0b2017-03-01 11:29:29 -08002116 SetRawAudioSink(ssrc, std::move(proxy_sink));
mflodman3d7db262016-04-29 00:57:13 -07002117 }
solenberg2100c0b2017-03-01 11:29:29 -08002118
mflodman3d7db262016-04-29 00:57:13 -07002119 delivery_result = call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
2120 packet->cdata(),
2121 packet->size(),
2122 webrtc_packet_time);
2123 RTC_DCHECK_NE(webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC, delivery_result);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002124}
2125
wu@webrtc.orga9890802013-12-13 00:21:03 +00002126void WebRtcVoiceMediaChannel::OnRtcpReceived(
jbaucheec21bd2016-03-20 06:15:43 -07002127 rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
solenberg566ef242015-11-06 15:34:49 -08002128 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02002129
Fredrik Solenberg709ed672015-09-15 12:26:33 +02002130 // Forward packet to Call as well.
2131 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
2132 packet_time.not_before);
2133 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
jbaucheec21bd2016-03-20 06:15:43 -07002134 packet->cdata(), packet->size(), webrtc_packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002135}
2136
Honghai Zhangcc411c02016-03-29 17:27:21 -07002137void WebRtcVoiceMediaChannel::OnNetworkRouteChanged(
2138 const std::string& transport_name,
Honghai Zhang0e533ef2016-04-19 15:41:36 -07002139 const rtc::NetworkRoute& network_route) {
2140 call_->OnNetworkRouteChanged(transport_name, network_route);
Honghai Zhangcc411c02016-03-29 17:27:21 -07002141}
2142
Peter Boström0c4e06b2015-10-07 12:23:21 +02002143bool WebRtcVoiceMediaChannel::MuteStream(uint32_t ssrc, bool muted) {
solenberg566ef242015-11-06 15:34:49 -08002144 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg94218532016-06-16 10:53:22 -07002145 const auto it = send_streams_.find(ssrc);
2146 if (it == send_streams_.end()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002147 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
2148 return false;
2149 }
solenberg94218532016-06-16 10:53:22 -07002150 it->second->SetMuted(muted);
2151
2152 // TODO(solenberg):
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002153 // We set the AGC to mute state only when all the channels are muted.
2154 // This implementation is not ideal, instead we should signal the AGC when
2155 // the mic channel is muted/unmuted. We can't do it today because there
2156 // is no good way to know which stream is mapping to the mic channel.
2157 bool all_muted = muted;
solenberg94218532016-06-16 10:53:22 -07002158 for (const auto& kv : send_streams_) {
2159 all_muted = all_muted && kv.second->muted();
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002160 }
solenberg059fb442016-10-26 05:12:24 -07002161 engine()->apm()->set_output_will_be_muted(all_muted);
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002162
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002163 return true;
2164}
2165
deadbeef80346142016-04-27 14:17:10 -07002166bool WebRtcVoiceMediaChannel::SetMaxSendBitrate(int bps) {
2167 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetMaxSendBitrate.";
2168 max_send_bitrate_bps_ = bps;
minyue7a973442016-10-20 03:27:12 -07002169 bool success = true;
skvlade0d46372016-04-07 22:59:22 -07002170 for (const auto& kv : send_streams_) {
minyue7a973442016-10-20 03:27:12 -07002171 if (!kv.second->SetMaxSendBitrate(max_send_bitrate_bps_)) {
2172 success = false;
skvlade0d46372016-04-07 22:59:22 -07002173 }
2174 }
minyue7a973442016-10-20 03:27:12 -07002175 return success;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002176}
2177
skvlad7a43d252016-03-22 15:32:27 -07002178void WebRtcVoiceMediaChannel::OnReadyToSend(bool ready) {
2179 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2180 LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
2181 call_->SignalChannelNetworkState(
2182 webrtc::MediaType::AUDIO,
2183 ready ? webrtc::kNetworkUp : webrtc::kNetworkDown);
2184}
2185
michaelt79e05882016-11-08 02:50:09 -08002186void WebRtcVoiceMediaChannel::OnTransportOverheadChanged(
2187 int transport_overhead_per_packet) {
2188 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2189 call_->OnTransportOverheadChanged(webrtc::MediaType::AUDIO,
2190 transport_overhead_per_packet);
2191}
2192
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002193bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
Peter Boströmca8b4042016-03-08 14:24:13 -08002194 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::GetStats");
solenberg566ef242015-11-06 15:34:49 -08002195 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg85a04962015-10-27 03:35:21 -07002196 RTC_DCHECK(info);
solenbergd97ec302015-10-07 01:40:33 -07002197
solenberg85a04962015-10-27 03:35:21 -07002198 // Get SSRC and stats for each sender.
hbos1acfbd22016-11-17 23:43:29 -08002199 RTC_DCHECK_EQ(info->senders.size(), 0U);
solenberg85a04962015-10-27 03:35:21 -07002200 for (const auto& stream : send_streams_) {
2201 webrtc::AudioSendStream::Stats stats = stream.second->GetStats();
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002202 VoiceSenderInfo sinfo;
solenberg85a04962015-10-27 03:35:21 -07002203 sinfo.add_ssrc(stats.local_ssrc);
2204 sinfo.bytes_sent = stats.bytes_sent;
2205 sinfo.packets_sent = stats.packets_sent;
2206 sinfo.packets_lost = stats.packets_lost;
2207 sinfo.fraction_lost = stats.fraction_lost;
2208 sinfo.codec_name = stats.codec_name;
hbos1acfbd22016-11-17 23:43:29 -08002209 sinfo.codec_payload_type = stats.codec_payload_type;
solenberg85a04962015-10-27 03:35:21 -07002210 sinfo.ext_seqnum = stats.ext_seqnum;
2211 sinfo.jitter_ms = stats.jitter_ms;
2212 sinfo.rtt_ms = stats.rtt_ms;
2213 sinfo.audio_level = stats.audio_level;
zsteine76bd3a2017-07-14 12:17:49 -07002214 sinfo.total_input_energy = stats.total_input_energy;
2215 sinfo.total_input_duration = stats.total_input_duration;
solenberg85a04962015-10-27 03:35:21 -07002216 sinfo.aec_quality_min = stats.aec_quality_min;
2217 sinfo.echo_delay_median_ms = stats.echo_delay_median_ms;
2218 sinfo.echo_delay_std_ms = stats.echo_delay_std_ms;
2219 sinfo.echo_return_loss = stats.echo_return_loss;
2220 sinfo.echo_return_loss_enhancement = stats.echo_return_loss_enhancement;
ivoc8c63a822016-10-21 04:10:03 -07002221 sinfo.residual_echo_likelihood = stats.residual_echo_likelihood;
ivoc4e477a12017-01-15 08:29:46 -08002222 sinfo.residual_echo_likelihood_recent_max =
2223 stats.residual_echo_likelihood_recent_max;
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002224 sinfo.typing_noise_detected = (send_ ? stats.typing_noise_detected : false);
ivoce1198e02017-09-08 08:13:19 -07002225 sinfo.ana_statistics = stats.ana_statistics;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002226 info->senders.push_back(sinfo);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002227 }
2228
solenberg85a04962015-10-27 03:35:21 -07002229 // Get SSRC and stats for each receiver.
hbos1acfbd22016-11-17 23:43:29 -08002230 RTC_DCHECK_EQ(info->receivers.size(), 0U);
solenberg7add0582015-11-20 09:59:34 -08002231 for (const auto& stream : recv_streams_) {
deadbeef4e2deab2017-09-20 13:56:21 -07002232 uint32_t ssrc = stream.first;
2233 // When SSRCs are unsignaled, there's only one audio MediaStreamTrack, but
2234 // multiple RTP streams can be received over time (if the SSRC changes for
2235 // whatever reason). We only want the RTCMediaStreamTrackStats to represent
2236 // the stats for the most recent stream (the one whose audio is actually
2237 // routed to the MediaStreamTrack), so here we ignore any unsignaled SSRCs
2238 // except for the most recent one (last in the vector). This is somewhat of
2239 // a hack, and means you don't get *any* stats for these inactive streams,
2240 // but it's slightly better than the previous behavior, which was "highest
2241 // SSRC wins".
2242 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=8158
2243 if (!unsignaled_recv_ssrcs_.empty()) {
2244 auto end_it = --unsignaled_recv_ssrcs_.end();
2245 if (std::find(unsignaled_recv_ssrcs_.begin(), end_it, ssrc) != end_it) {
2246 continue;
2247 }
2248 }
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002249 webrtc::AudioReceiveStream::Stats stats = stream.second->GetStats();
2250 VoiceReceiverInfo rinfo;
2251 rinfo.add_ssrc(stats.remote_ssrc);
2252 rinfo.bytes_rcvd = stats.bytes_rcvd;
2253 rinfo.packets_rcvd = stats.packets_rcvd;
2254 rinfo.packets_lost = stats.packets_lost;
2255 rinfo.fraction_lost = stats.fraction_lost;
2256 rinfo.codec_name = stats.codec_name;
hbos1acfbd22016-11-17 23:43:29 -08002257 rinfo.codec_payload_type = stats.codec_payload_type;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002258 rinfo.ext_seqnum = stats.ext_seqnum;
2259 rinfo.jitter_ms = stats.jitter_ms;
2260 rinfo.jitter_buffer_ms = stats.jitter_buffer_ms;
2261 rinfo.jitter_buffer_preferred_ms = stats.jitter_buffer_preferred_ms;
2262 rinfo.delay_estimate_ms = stats.delay_estimate_ms;
2263 rinfo.audio_level = stats.audio_level;
zsteine76bd3a2017-07-14 12:17:49 -07002264 rinfo.total_output_energy = stats.total_output_energy;
Steve Anton2dbc69f2017-08-24 17:15:13 -07002265 rinfo.total_samples_received = stats.total_samples_received;
zsteine76bd3a2017-07-14 12:17:49 -07002266 rinfo.total_output_duration = stats.total_output_duration;
Steve Anton2dbc69f2017-08-24 17:15:13 -07002267 rinfo.concealed_samples = stats.concealed_samples;
Gustaf Ullberg9a2e9062017-09-18 09:28:20 +02002268 rinfo.concealment_events = stats.concealment_events;
Gustaf Ullbergb0a02072017-10-02 12:00:34 +02002269 rinfo.jitter_buffer_delay_seconds = stats.jitter_buffer_delay_seconds;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002270 rinfo.expand_rate = stats.expand_rate;
2271 rinfo.speech_expand_rate = stats.speech_expand_rate;
2272 rinfo.secondary_decoded_rate = stats.secondary_decoded_rate;
minyue-webrtc0e320ec2017-08-28 13:51:27 +02002273 rinfo.secondary_discarded_rate = stats.secondary_discarded_rate;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002274 rinfo.accelerate_rate = stats.accelerate_rate;
2275 rinfo.preemptive_expand_rate = stats.preemptive_expand_rate;
2276 rinfo.decoding_calls_to_silence_generator =
2277 stats.decoding_calls_to_silence_generator;
2278 rinfo.decoding_calls_to_neteq = stats.decoding_calls_to_neteq;
2279 rinfo.decoding_normal = stats.decoding_normal;
2280 rinfo.decoding_plc = stats.decoding_plc;
2281 rinfo.decoding_cng = stats.decoding_cng;
2282 rinfo.decoding_plc_cng = stats.decoding_plc_cng;
henrik.lundin63489782016-09-20 01:47:12 -07002283 rinfo.decoding_muted_output = stats.decoding_muted_output;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002284 rinfo.capture_start_ntp_time_ms = stats.capture_start_ntp_time_ms;
2285 info->receivers.push_back(rinfo);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002286 }
2287
hbos1acfbd22016-11-17 23:43:29 -08002288 // Get codec info
2289 for (const AudioCodec& codec : send_codecs_) {
2290 webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
2291 info->send_codecs.insert(
2292 std::make_pair(codec_params.payload_type, std::move(codec_params)));
2293 }
2294 for (const AudioCodec& codec : recv_codecs_) {
2295 webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
2296 info->receive_codecs.insert(
2297 std::make_pair(codec_params.payload_type, std::move(codec_params)));
2298 }
2299
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002300 return true;
2301}
2302
Tommif888bb52015-12-12 01:37:01 +01002303void WebRtcVoiceMediaChannel::SetRawAudioSink(
2304 uint32_t ssrc,
kwiberg686a8ef2016-02-26 03:00:35 -08002305 std::unique_ptr<webrtc::AudioSinkInterface> sink) {
Tommif888bb52015-12-12 01:37:01 +01002306 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef884f5852016-01-15 09:20:04 -08002307 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::SetRawAudioSink: ssrc:" << ssrc
2308 << " " << (sink ? "(ptr)" : "NULL");
2309 if (ssrc == 0) {
solenberg2100c0b2017-03-01 11:29:29 -08002310 if (!unsignaled_recv_ssrcs_.empty()) {
kwiberg686a8ef2016-02-26 03:00:35 -08002311 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
deadbeef884f5852016-01-15 09:20:04 -08002312 sink ? new ProxySink(sink.get()) : nullptr);
solenberg2100c0b2017-03-01 11:29:29 -08002313 SetRawAudioSink(unsignaled_recv_ssrcs_.back(), std::move(proxy_sink));
deadbeef884f5852016-01-15 09:20:04 -08002314 }
2315 default_sink_ = std::move(sink);
2316 return;
2317 }
Tommif888bb52015-12-12 01:37:01 +01002318 const auto it = recv_streams_.find(ssrc);
2319 if (it == recv_streams_.end()) {
solenberg2100c0b2017-03-01 11:29:29 -08002320 LOG(LS_WARNING) << "SetRawAudioSink: no recv stream " << ssrc;
Tommif888bb52015-12-12 01:37:01 +01002321 return;
2322 }
deadbeef2d110be2016-01-13 12:00:26 -08002323 it->second->SetRawAudioSink(std::move(sink));
Tommif888bb52015-12-12 01:37:01 +01002324}
2325
hbos8d609f62017-04-10 07:39:05 -07002326std::vector<webrtc::RtpSource> WebRtcVoiceMediaChannel::GetSources(
2327 uint32_t ssrc) const {
2328 auto it = recv_streams_.find(ssrc);
2329 RTC_DCHECK(it != recv_streams_.end())
2330 << "Attempting to get contributing sources for SSRC:" << ssrc
2331 << " which doesn't exist.";
2332 return it->second->GetSources();
2333}
2334
Peter Boström0c4e06b2015-10-07 12:23:21 +02002335int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
solenberg566ef242015-11-06 15:34:49 -08002336 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7add0582015-11-20 09:59:34 -08002337 const auto it = recv_streams_.find(ssrc);
2338 if (it != recv_streams_.end()) {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002339 return it->second->channel();
solenberg8fb30c32015-10-13 03:06:58 -07002340 }
solenberg1ac56142015-10-13 03:58:19 -07002341 return -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002342}
2343
Peter Boström0c4e06b2015-10-07 12:23:21 +02002344int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const {
solenberg566ef242015-11-06 15:34:49 -08002345 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergc96df772015-10-21 13:01:53 -07002346 const auto it = send_streams_.find(ssrc);
2347 if (it != send_streams_.end()) {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002348 return it->second->channel();
solenberg8fb30c32015-10-13 03:06:58 -07002349 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002350 return -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002351}
solenberg2100c0b2017-03-01 11:29:29 -08002352
2353bool WebRtcVoiceMediaChannel::
2354 MaybeDeregisterUnsignaledRecvStream(uint32_t ssrc) {
2355 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2356 auto it = std::find(unsignaled_recv_ssrcs_.begin(),
2357 unsignaled_recv_ssrcs_.end(),
2358 ssrc);
2359 if (it != unsignaled_recv_ssrcs_.end()) {
2360 unsignaled_recv_ssrcs_.erase(it);
2361 return true;
2362 }
2363 return false;
2364}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002365} // namespace cricket
2366
2367#endif // HAVE_WEBRTC_VOICE