blob: 0fef4fd0a8aa66ee8133193644a86da3ea003cf7 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellander1afca732016-02-07 20:46:45 -08002 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellander1afca732016-02-07 20:46:45 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
henrike@webrtc.org28e20752013-07-10 00:45:36 +000011#ifdef HAVE_WEBRTC_VOICE
12
kjellander@webrtc.org5ad12972016-02-12 06:39:40 +010013#include "webrtc/media/engine/webrtcvoiceengine.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000014
15#include <algorithm>
16#include <cstdio>
ossuc54071d2016-08-17 02:45:41 -070017#include <functional>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000018#include <string>
19#include <vector>
20
kjellandera69d9732016-08-31 07:33:05 -070021#include "webrtc/api/call/audio_sink.h"
tfarina5237aaf2015-11-10 23:44:30 -080022#include "webrtc/base/arraysize.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000023#include "webrtc/base/base64.h"
24#include "webrtc/base/byteorder.h"
kwiberg4485ffb2016-04-26 08:14:39 -070025#include "webrtc/base/constructormagic.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000026#include "webrtc/base/helpers.h"
27#include "webrtc/base/logging.h"
solenberg347ec5c2016-09-23 04:21:47 -070028#include "webrtc/base/race_checker.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000029#include "webrtc/base/stringencode.h"
30#include "webrtc/base/stringutils.h"
Peter Boströmca8b4042016-03-08 14:24:13 -080031#include "webrtc/base/trace_event.h"
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -080032#include "webrtc/media/base/audiosource.h"
kjellanderf4752772016-03-02 05:42:30 -080033#include "webrtc/media/base/mediaconstants.h"
kjellandera96e2d72016-02-04 23:52:28 -080034#include "webrtc/media/base/streamparams.h"
solenberg9a5f032222017-03-15 06:14:12 -070035#include "webrtc/media/engine/adm_helpers.h"
solenberg76377c52017-02-21 00:54:31 -080036#include "webrtc/media/engine/apm_helpers.h"
ossuc54071d2016-08-17 02:45:41 -070037#include "webrtc/media/engine/payload_type_mapper.h"
kjellander@webrtc.org5ad12972016-02-12 06:39:40 +010038#include "webrtc/media/engine/webrtcmediaengine.h"
39#include "webrtc/media/engine/webrtcvoe.h"
aleloi10111bc2016-11-17 06:48:48 -080040#include "webrtc/modules/audio_mixer/audio_mixer_impl.h"
aleloi048cbdd2017-05-29 02:56:27 -070041#include "webrtc/modules/audio_processing/aec_dump/aec_dump_factory.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000042#include "webrtc/modules/audio_processing/include/audio_processing.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010043#include "webrtc/system_wrappers/include/field_trial.h"
solenberg2100c0b2017-03-01 11:29:29 -080044#include "webrtc/system_wrappers/include/metrics.h"
solenbergbd138382015-11-20 16:08:07 -080045#include "webrtc/system_wrappers/include/trace.h"
solenberg76377c52017-02-21 00:54:31 -080046#include "webrtc/voice_engine/transmit_mixer.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000047
henrike@webrtc.org28e20752013-07-10 00:45:36 +000048namespace cricket {
solenbergd97ec302015-10-07 01:40:33 -070049namespace {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000050
solenberg418b7d32017-06-13 00:38:27 -070051constexpr size_t kMaxUnsignaledRecvStreams = 4;
solenberg2100c0b2017-03-01 11:29:29 -080052
solenbergbd138382015-11-20 16:08:07 -080053const int kDefaultTraceFilter = webrtc::kTraceNone | webrtc::kTraceTerseInfo |
54 webrtc::kTraceWarning | webrtc::kTraceError |
55 webrtc::kTraceCritical;
56const int kElevatedTraceFilter = kDefaultTraceFilter | webrtc::kTraceStateInfo |
57 webrtc::kTraceInfo;
58
solenberg971cab02016-06-14 10:02:41 -070059constexpr int kNackRtpHistoryMs = 5000;
minyue@webrtc.org2dc6f312014-10-31 05:33:10 +000060
peah1bcfce52016-08-26 07:16:04 -070061// Check to verify that the define for the intelligibility enhancer is properly
62// set.
63#if !defined(WEBRTC_INTELLIGIBILITY_ENHANCER) || \
64 (WEBRTC_INTELLIGIBILITY_ENHANCER != 0 && \
65 WEBRTC_INTELLIGIBILITY_ENHANCER != 1)
66#error "Set WEBRTC_INTELLIGIBILITY_ENHANCER to either 0 or 1"
67#endif
68
ossu20a4b3f2017-04-27 02:08:52 -070069// For SendSideBwe, Opus bitrate should be in the range between 6000 and 32000.
minyue10cbb462016-11-07 09:29:22 -080070const int kOpusMinBitrateBps = 6000;
ossu20a4b3f2017-04-27 02:08:52 -070071const int kOpusBitrateFbBps = 32000;
deadbeef80346142016-04-27 14:17:10 -070072
wu@webrtc.orgde305012013-10-31 15:40:38 +000073// Default audio dscp value.
74// See http://tools.ietf.org/html/rfc2474 for details.
75// See also http://tools.ietf.org/html/draft-jennings-rtcweb-qos-00
solenbergd97ec302015-10-07 01:40:33 -070076const rtc::DiffServCodePoint kAudioDscpValue = rtc::DSCP_EF;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +000077
Fredrik Solenbergb5727682015-12-04 15:22:19 +010078// Constants from voice_engine_defines.h.
79const int kMinTelephoneEventCode = 0; // RFC4733 (Section 2.3.1)
80const int kMaxTelephoneEventCode = 255;
Fredrik Solenbergb5727682015-12-04 15:22:19 +010081
solenberg31642aa2016-03-14 08:00:37 -070082const int kMinPayloadType = 0;
83const int kMaxPayloadType = 127;
84
deadbeef884f5852016-01-15 09:20:04 -080085class ProxySink : public webrtc::AudioSinkInterface {
86 public:
87 ProxySink(AudioSinkInterface* sink) : sink_(sink) { RTC_DCHECK(sink); }
88
89 void OnData(const Data& audio) override { sink_->OnData(audio); }
90
91 private:
92 webrtc::AudioSinkInterface* sink_;
93};
94
solenberg0b675462015-10-09 01:37:09 -070095bool ValidateStreamParams(const StreamParams& sp) {
96 if (sp.ssrcs.empty()) {
97 LOG(LS_ERROR) << "No SSRCs in stream parameters: " << sp.ToString();
98 return false;
99 }
100 if (sp.ssrcs.size() > 1) {
101 LOG(LS_ERROR) << "Multiple SSRCs in stream parameters: " << sp.ToString();
102 return false;
103 }
104 return true;
105}
106
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000107// Dumps an AudioCodec in RFC 2327-ish format.
solenbergd97ec302015-10-07 01:40:33 -0700108std::string ToString(const AudioCodec& codec) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000109 std::stringstream ss;
ossu20a4b3f2017-04-27 02:08:52 -0700110 ss << codec.name << "/" << codec.clockrate << "/" << codec.channels;
111 if (!codec.params.empty()) {
112 ss << " {";
113 for (const auto& param : codec.params) {
114 ss << " " << param.first << "=" << param.second;
115 }
116 ss << " }";
117 }
118 ss << " (" << codec.id << ")";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000119 return ss.str();
120}
Minyue Li7100dcd2015-03-27 05:05:59 +0100121
solenbergd97ec302015-10-07 01:40:33 -0700122bool IsCodec(const AudioCodec& codec, const char* ref_name) {
Minyue Li7100dcd2015-03-27 05:05:59 +0100123 return (_stricmp(codec.name.c_str(), ref_name) == 0);
124}
125
solenbergd97ec302015-10-07 01:40:33 -0700126bool FindCodec(const std::vector<AudioCodec>& codecs,
solenberg26c8c912015-11-27 04:00:25 -0800127 const AudioCodec& codec,
128 AudioCodec* found_codec) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +0200129 for (const AudioCodec& c : codecs) {
130 if (c.Matches(codec)) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000131 if (found_codec != NULL) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +0200132 *found_codec = c;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000133 }
134 return true;
135 }
136 }
137 return false;
138}
wu@webrtc.org1d1ffc92013-10-16 18:12:02 +0000139
solenberg0b675462015-10-09 01:37:09 -0700140bool VerifyUniquePayloadTypes(const std::vector<AudioCodec>& codecs) {
141 if (codecs.empty()) {
142 return true;
143 }
144 std::vector<int> payload_types;
145 for (const AudioCodec& codec : codecs) {
146 payload_types.push_back(codec.id);
147 }
148 std::sort(payload_types.begin(), payload_types.end());
149 auto it = std::unique(payload_types.begin(), payload_types.end());
150 return it == payload_types.end();
151}
152
minyue6b825df2016-10-31 04:08:32 -0700153rtc::Optional<std::string> GetAudioNetworkAdaptorConfig(
154 const AudioOptions& options) {
155 if (options.audio_network_adaptor && *options.audio_network_adaptor &&
156 options.audio_network_adaptor_config) {
157 // Turn on audio network adaptor only when |options_.audio_network_adaptor|
158 // equals true and |options_.audio_network_adaptor_config| has a value.
159 return options.audio_network_adaptor_config;
160 }
161 return rtc::Optional<std::string>();
162}
163
gyzhou95aa9642016-12-13 14:06:26 -0800164webrtc::AudioState::Config MakeAudioStateConfig(
165 VoEWrapper* voe_wrapper,
166 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer) {
solenberg566ef242015-11-06 15:34:49 -0800167 webrtc::AudioState::Config config;
168 config.voice_engine = voe_wrapper->engine();
gyzhou95aa9642016-12-13 14:06:26 -0800169 if (audio_mixer) {
170 config.audio_mixer = audio_mixer;
171 } else {
172 config.audio_mixer = webrtc::AudioMixerImpl::Create();
173 }
solenberg566ef242015-11-06 15:34:49 -0800174 return config;
175}
176
deadbeefe702b302017-02-04 12:09:01 -0800177// |max_send_bitrate_bps| is the bitrate from "b=" in SDP.
178// |rtp_max_bitrate_bps| is the bitrate from RtpSender::SetParameters.
minyue7a973442016-10-20 03:27:12 -0700179rtc::Optional<int> ComputeSendBitrate(int max_send_bitrate_bps,
deadbeefe702b302017-02-04 12:09:01 -0800180 rtc::Optional<int> rtp_max_bitrate_bps,
ossu20a4b3f2017-04-27 02:08:52 -0700181 const webrtc::AudioCodecSpec& spec) {
deadbeefe702b302017-02-04 12:09:01 -0800182 // If application-configured bitrate is set, take minimum of that and SDP
183 // bitrate.
zsteina5e0df62017-06-14 11:41:48 -0700184 const int bps =
185 rtp_max_bitrate_bps
186 ? webrtc::MinPositive(max_send_bitrate_bps, *rtp_max_bitrate_bps)
187 : max_send_bitrate_bps;
minyue7a973442016-10-20 03:27:12 -0700188 if (bps <= 0) {
ossu20a4b3f2017-04-27 02:08:52 -0700189 return rtc::Optional<int>(spec.info.default_bitrate_bps);
solenberg971cab02016-06-14 10:02:41 -0700190 }
minyue7a973442016-10-20 03:27:12 -0700191
ossu20a4b3f2017-04-27 02:08:52 -0700192 if (bps < spec.info.min_bitrate_bps) {
minyue7a973442016-10-20 03:27:12 -0700193 // If codec is not multi-rate and |bps| is less than the fixed bitrate then
194 // fail. If codec is not multi-rate and |bps| exceeds or equal the fixed
195 // bitrate then ignore.
ossu20a4b3f2017-04-27 02:08:52 -0700196 LOG(LS_ERROR) << "Failed to set codec " << spec.format.name
minyue7a973442016-10-20 03:27:12 -0700197 << " to bitrate " << bps << " bps"
ossu20a4b3f2017-04-27 02:08:52 -0700198 << ", requires at least " << spec.info.min_bitrate_bps
199 << " bps.";
minyue7a973442016-10-20 03:27:12 -0700200 return rtc::Optional<int>();
solenberg971cab02016-06-14 10:02:41 -0700201 }
ossu20a4b3f2017-04-27 02:08:52 -0700202
203 if (spec.info.HasFixedBitrate()) {
204 return rtc::Optional<int>(spec.info.default_bitrate_bps);
205 } else {
206 // If codec is multi-rate then just set the bitrate.
207 return rtc::Optional<int>(std::min(bps, spec.info.max_bitrate_bps));
208 }
solenberg971cab02016-06-14 10:02:41 -0700209}
210
solenberg76377c52017-02-21 00:54:31 -0800211} // namespace
solenberg971cab02016-06-14 10:02:41 -0700212
ossu29b1a8d2016-06-13 07:34:51 -0700213WebRtcVoiceEngine::WebRtcVoiceEngine(
214 webrtc::AudioDeviceModule* adm,
ossueb1fde42017-05-02 06:46:30 -0700215 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -0800216 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
217 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer)
ossueb1fde42017-05-02 06:46:30 -0700218 : WebRtcVoiceEngine(adm,
219 encoder_factory,
220 decoder_factory,
221 audio_mixer,
222 new VoEWrapper()) {
gyzhou95aa9642016-12-13 14:06:26 -0800223 audio_state_ =
224 webrtc::AudioState::Create(MakeAudioStateConfig(voe(), audio_mixer));
solenberg26c8c912015-11-27 04:00:25 -0800225}
226
ossu29b1a8d2016-06-13 07:34:51 -0700227WebRtcVoiceEngine::WebRtcVoiceEngine(
228 webrtc::AudioDeviceModule* adm,
ossueb1fde42017-05-02 06:46:30 -0700229 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory,
ossu29b1a8d2016-06-13 07:34:51 -0700230 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -0800231 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
ossu29b1a8d2016-06-13 07:34:51 -0700232 VoEWrapper* voe_wrapper)
aleloi048cbdd2017-05-29 02:56:27 -0700233 : low_priority_worker_queue_("rtc-low-prio", rtc::TaskQueue::Priority::LOW),
234 adm_(adm),
ossueb1fde42017-05-02 06:46:30 -0700235 encoder_factory_(encoder_factory),
ossu20a4b3f2017-04-27 02:08:52 -0700236 decoder_factory_(decoder_factory),
237 voe_wrapper_(voe_wrapper) {
solenberg26c8c912015-11-27 04:00:25 -0800238 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergff976312016-03-30 23:28:51 -0700239 LOG(LS_INFO) << "WebRtcVoiceEngine::WebRtcVoiceEngine";
240 RTC_DCHECK(voe_wrapper);
ossuc54071d2016-08-17 02:45:41 -0700241 RTC_DCHECK(decoder_factory);
solenberg26c8c912015-11-27 04:00:25 -0800242
243 signal_thread_checker_.DetachFromThread();
solenberg26c8c912015-11-27 04:00:25 -0800244
ossueb1fde42017-05-02 06:46:30 -0700245 // Load our audio codec lists.
ossuc54071d2016-08-17 02:45:41 -0700246 LOG(LS_INFO) << "Supported send codecs in order of preference:";
ossu20a4b3f2017-04-27 02:08:52 -0700247 send_codecs_ = CollectCodecs(encoder_factory_->GetSupportedEncoders());
ossuc54071d2016-08-17 02:45:41 -0700248 for (const AudioCodec& codec : send_codecs_) {
249 LOG(LS_INFO) << ToString(codec);
250 }
251
252 LOG(LS_INFO) << "Supported recv codecs in order of preference:";
ossu20a4b3f2017-04-27 02:08:52 -0700253 recv_codecs_ = CollectCodecs(decoder_factory_->GetSupportedDecoders());
ossuc54071d2016-08-17 02:45:41 -0700254 for (const AudioCodec& codec : recv_codecs_) {
solenbergff976312016-03-30 23:28:51 -0700255 LOG(LS_INFO) << ToString(codec);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000256 }
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000257
solenberg88499ec2016-09-07 07:34:41 -0700258 channel_config_.enable_voice_pacing = true;
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000259
solenbergff976312016-03-30 23:28:51 -0700260 // Temporarily turn logging level up for the Init() call.
261 webrtc::Trace::SetTraceCallback(this);
solenbergbd138382015-11-20 16:08:07 -0800262 webrtc::Trace::set_level_filter(kElevatedTraceFilter);
solenberg2515af22015-12-02 06:19:36 -0800263 LOG(LS_INFO) << webrtc::VoiceEngine::GetVersionString();
ossu29b1a8d2016-06-13 07:34:51 -0700264 RTC_CHECK_EQ(0, voe_wrapper_->base()->Init(adm_.get(), nullptr,
265 decoder_factory_));
solenbergbd138382015-11-20 16:08:07 -0800266 webrtc::Trace::set_level_filter(kDefaultTraceFilter);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000267
solenbergff976312016-03-30 23:28:51 -0700268 // No ADM supplied? Get the default one from VoE.
269 if (!adm_) {
270 adm_ = voe_wrapper_->base()->audio_device_module();
271 }
272 RTC_DCHECK(adm_);
273
solenberg059fb442016-10-26 05:12:24 -0700274 apm_ = voe_wrapper_->base()->audio_processing();
275 RTC_DCHECK(apm_);
276
solenberg76377c52017-02-21 00:54:31 -0800277 transmit_mixer_ = voe_wrapper_->base()->transmit_mixer();
278 RTC_DCHECK(transmit_mixer_);
279
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000280 // Save the default AGC configuration settings. This must happen before
solenberg246b8172015-12-08 09:50:23 -0800281 // calling ApplyOptions or the default will be overwritten.
solenberg76377c52017-02-21 00:54:31 -0800282 default_agc_config_ = webrtc::apm_helpers::GetAgcConfig(apm_);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000283
solenberg0f7d2932016-01-15 01:40:39 -0800284 // Set default engine options.
285 {
286 AudioOptions options;
287 options.echo_cancellation = rtc::Optional<bool>(true);
288 options.auto_gain_control = rtc::Optional<bool>(true);
289 options.noise_suppression = rtc::Optional<bool>(true);
290 options.highpass_filter = rtc::Optional<bool>(true);
291 options.stereo_swapping = rtc::Optional<bool>(false);
292 options.audio_jitter_buffer_max_packets = rtc::Optional<int>(50);
293 options.audio_jitter_buffer_fast_accelerate = rtc::Optional<bool>(false);
294 options.typing_detection = rtc::Optional<bool>(true);
295 options.adjust_agc_delta = rtc::Optional<int>(0);
296 options.experimental_agc = rtc::Optional<bool>(false);
297 options.extended_filter_aec = rtc::Optional<bool>(false);
298 options.delay_agnostic_aec = rtc::Optional<bool>(false);
299 options.experimental_ns = rtc::Optional<bool>(false);
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700300 options.intelligibility_enhancer = rtc::Optional<bool>(false);
peaha3333bf2016-06-30 00:02:34 -0700301 options.level_control = rtc::Optional<bool>(false);
ivocb829d9f2016-11-15 02:34:47 -0800302 options.residual_echo_detector = rtc::Optional<bool>(true);
solenbergff976312016-03-30 23:28:51 -0700303 bool error = ApplyOptions(options);
304 RTC_DCHECK(error);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000305 }
306
solenberg9a5f032222017-03-15 06:14:12 -0700307 // Set default audio devices.
308#if !defined(WEBRTC_IOS)
309 webrtc::adm_helpers::SetRecordingDevice(adm_);
310 apm()->Initialize();
311 webrtc::adm_helpers::SetPlayoutDevice(adm_);
312#endif // !WEBRTC_IOS
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000313}
314
solenbergff976312016-03-30 23:28:51 -0700315WebRtcVoiceEngine::~WebRtcVoiceEngine() {
solenberg566ef242015-11-06 15:34:49 -0800316 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergff976312016-03-30 23:28:51 -0700317 LOG(LS_INFO) << "WebRtcVoiceEngine::~WebRtcVoiceEngine";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000318 StopAecDump();
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000319 voe_wrapper_->base()->Terminate();
solenbergff976312016-03-30 23:28:51 -0700320 webrtc::Trace::SetTraceCallback(nullptr);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000321}
322
solenberg566ef242015-11-06 15:34:49 -0800323rtc::scoped_refptr<webrtc::AudioState>
324 WebRtcVoiceEngine::GetAudioState() const {
325 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
326 return audio_state_;
327}
328
nisse51542be2016-02-12 02:27:06 -0800329VoiceMediaChannel* WebRtcVoiceEngine::CreateChannel(
330 webrtc::Call* call,
331 const MediaConfig& config,
Jelena Marusicc28a8962015-05-29 15:05:44 +0200332 const AudioOptions& options) {
solenberg566ef242015-11-06 15:34:49 -0800333 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
nisse51542be2016-02-12 02:27:06 -0800334 return new WebRtcVoiceMediaChannel(this, config, options, call);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000335}
336
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000337bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
solenberg566ef242015-11-06 15:34:49 -0800338 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergff976312016-03-30 23:28:51 -0700339 LOG(LS_INFO) << "WebRtcVoiceEngine::ApplyOptions: " << options_in.ToString();
solenberg0f7d2932016-01-15 01:40:39 -0800340 AudioOptions options = options_in; // The options are modified below.
solenberg246b8172015-12-08 09:50:23 -0800341
peah8a8ebd92017-05-22 15:48:47 -0700342 // Set and adjust echo canceller options.
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000343 // kEcConference is AEC with high suppression.
344 webrtc::EcModes ec_mode = webrtc::kEcConference;
kwiberg102c6a62015-10-30 02:47:38 -0700345 if (options.aecm_generate_comfort_noise) {
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000346 LOG(LS_VERBOSE) << "Comfort noise explicitly set to "
kwiberg102c6a62015-10-30 02:47:38 -0700347 << *options.aecm_generate_comfort_noise
348 << " (default is false).";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000349 }
350
kjellanderfcfc8042016-01-14 11:01:09 -0800351#if defined(WEBRTC_IOS)
peah8a8ebd92017-05-22 15:48:47 -0700352 // On iOS, VPIO provides built-in EC.
Karl Wibergbe579832015-11-10 22:34:18 +0100353 options.echo_cancellation = rtc::Optional<bool>(false);
peah8a8ebd92017-05-22 15:48:47 -0700354 options.extended_filter_aec = rtc::Optional<bool>(false);
355 LOG(LS_INFO) << "Always disable AEC on iOS. Use built-in instead.";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000356#elif defined(ANDROID)
357 ec_mode = webrtc::kEcAecm;
Karl Wibergbe579832015-11-10 22:34:18 +0100358 options.extended_filter_aec = rtc::Optional<bool>(false);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000359#endif
360
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100361 // Delay Agnostic AEC automatically turns on EC if not set except on iOS
362 // where the feature is not supported.
363 bool use_delay_agnostic_aec = false;
kjellanderfcfc8042016-01-14 11:01:09 -0800364#if !defined(WEBRTC_IOS)
kwiberg102c6a62015-10-30 02:47:38 -0700365 if (options.delay_agnostic_aec) {
366 use_delay_agnostic_aec = *options.delay_agnostic_aec;
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100367 if (use_delay_agnostic_aec) {
Karl Wibergbe579832015-11-10 22:34:18 +0100368 options.echo_cancellation = rtc::Optional<bool>(true);
369 options.extended_filter_aec = rtc::Optional<bool>(true);
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100370 ec_mode = webrtc::kEcConference;
371 }
372 }
373#endif
374
peah8a8ebd92017-05-22 15:48:47 -0700375// Set and adjust noise suppressor options.
376#if defined(WEBRTC_IOS)
377 // On iOS, VPIO provides built-in NS.
378 options.noise_suppression = rtc::Optional<bool>(false);
379 options.typing_detection = rtc::Optional<bool>(false);
380 options.experimental_ns = rtc::Optional<bool>(false);
381 LOG(LS_INFO) << "Always disable NS on iOS. Use built-in instead.";
382#elif defined(ANDROID)
383 options.typing_detection = rtc::Optional<bool>(false);
384 options.experimental_ns = rtc::Optional<bool>(false);
385#endif
386
387// Set and adjust gain control options.
388#if defined(WEBRTC_IOS)
389 // On iOS, VPIO provides built-in AGC.
390 options.auto_gain_control = rtc::Optional<bool>(false);
391 options.experimental_agc = rtc::Optional<bool>(false);
392 LOG(LS_INFO) << "Always disable AGC on iOS. Use built-in instead.";
393#elif defined(ANDROID)
394 options.experimental_agc = rtc::Optional<bool>(false);
395#endif
396
397#if defined(WEBRTC_IOS) || defined(WEBRTC_ANDROID)
398 // 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).
399 if (webrtc::field_trial::IsEnabled(
400 "WebRTC-Audio-MinimizeResamplingOnMobile")) {
401 options.auto_gain_control = rtc::Optional<bool>(false);
402 LOG(LS_INFO) << "Disable AGC according to field trial.";
403 if (!(options.noise_suppression.value_or(false) or
404 options.echo_cancellation.value_or(false))) {
405 // If possible, turn off the high-pass filter.
406 LOG(LS_INFO) << "Disable high-pass filter in response to field trial.";
407 options.highpass_filter = rtc::Optional<bool>(false);
408 }
409 }
410#endif
411
peah1bcfce52016-08-26 07:16:04 -0700412#if (WEBRTC_INTELLIGIBILITY_ENHANCER == 0)
413 // Hardcode the intelligibility enhancer to be off.
414 options.intelligibility_enhancer = rtc::Optional<bool>(false);
415#endif
416
kwiberg102c6a62015-10-30 02:47:38 -0700417 if (options.echo_cancellation) {
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000418 // Check if platform supports built-in EC. Currently only supported on
419 // Android and in combination with Java based audio layer.
420 // TODO(henrika): investigate possibility to support built-in EC also
421 // in combination with Open SL ES audio.
solenberg5b5129a2016-04-08 05:35:48 -0700422 const bool built_in_aec = adm()->BuiltInAECIsAvailable();
Bjorn Volcker73f72102015-06-03 14:50:15 +0200423 if (built_in_aec) {
Bjorn Volckerccfc9392015-05-07 07:43:17 +0200424 // Built-in EC exists on this device and use_delay_agnostic_aec is not
425 // overriding it. Enable/Disable it according to the echo_cancellation
426 // audio option.
Bjorn Volcker73f72102015-06-03 14:50:15 +0200427 const bool enable_built_in_aec =
kwiberg102c6a62015-10-30 02:47:38 -0700428 *options.echo_cancellation && !use_delay_agnostic_aec;
solenberg5b5129a2016-04-08 05:35:48 -0700429 if (adm()->EnableBuiltInAEC(enable_built_in_aec) == 0 &&
Bjorn Volcker73f72102015-06-03 14:50:15 +0200430 enable_built_in_aec) {
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100431 // Disable internal software EC if built-in EC is enabled,
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000432 // i.e., replace the software EC with the built-in EC.
Karl Wibergbe579832015-11-10 22:34:18 +0100433 options.echo_cancellation = rtc::Optional<bool>(false);
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000434 LOG(LS_INFO) << "Disabling EC since built-in EC will be used instead";
435 }
436 }
solenberg76377c52017-02-21 00:54:31 -0800437 webrtc::apm_helpers::SetEcStatus(
438 apm(), *options.echo_cancellation, ec_mode);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000439#if !defined(ANDROID)
solenberg76377c52017-02-21 00:54:31 -0800440 webrtc::apm_helpers::SetEcMetricsStatus(apm(), *options.echo_cancellation);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000441#endif
442 if (ec_mode == webrtc::kEcAecm) {
kwiberg102c6a62015-10-30 02:47:38 -0700443 bool cn = options.aecm_generate_comfort_noise.value_or(false);
solenberg76377c52017-02-21 00:54:31 -0800444 webrtc::apm_helpers::SetAecmMode(apm(), cn);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000445 }
446 }
447
kwiberg102c6a62015-10-30 02:47:38 -0700448 if (options.auto_gain_control) {
peah72a56452016-08-22 12:08:55 -0700449 bool built_in_agc_avaliable = adm()->BuiltInAGCIsAvailable();
450 if (built_in_agc_avaliable) {
solenberg5b5129a2016-04-08 05:35:48 -0700451 if (adm()->EnableBuiltInAGC(*options.auto_gain_control) == 0 &&
kwiberg102c6a62015-10-30 02:47:38 -0700452 *options.auto_gain_control) {
henrikac14f5ff2015-09-23 14:08:33 +0200453 // Disable internal software AGC if built-in AGC is enabled,
454 // i.e., replace the software AGC with the built-in AGC.
Karl Wibergbe579832015-11-10 22:34:18 +0100455 options.auto_gain_control = rtc::Optional<bool>(false);
henrikac14f5ff2015-09-23 14:08:33 +0200456 LOG(LS_INFO) << "Disabling AGC since built-in AGC will be used instead";
457 }
458 }
solenberg22818a52017-03-16 01:20:23 -0700459 webrtc::apm_helpers::SetAgcStatus(apm(), adm(), *options.auto_gain_control);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000460 }
461
kwiberg102c6a62015-10-30 02:47:38 -0700462 if (options.tx_agc_target_dbov || options.tx_agc_digital_compression_gain ||
solenberg76377c52017-02-21 00:54:31 -0800463 options.tx_agc_limiter || options.adjust_agc_delta) {
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000464 // Override default_agc_config_. Generally, an unset option means "leave
465 // the VoE bits alone" in this function, so we want whatever is set to be
466 // stored as the new "default". If we didn't, then setting e.g.
467 // tx_agc_target_dbov would reset digital compression gain and limiter
468 // settings.
469 // Also, if we don't update default_agc_config_, then adjust_agc_delta
470 // would be an offset from the original values, and not whatever was set
471 // explicitly.
kwiberg102c6a62015-10-30 02:47:38 -0700472 default_agc_config_.targetLeveldBOv = options.tx_agc_target_dbov.value_or(
473 default_agc_config_.targetLeveldBOv);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000474 default_agc_config_.digitalCompressionGaindB =
kwiberg102c6a62015-10-30 02:47:38 -0700475 options.tx_agc_digital_compression_gain.value_or(
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000476 default_agc_config_.digitalCompressionGaindB);
477 default_agc_config_.limiterEnable =
kwiberg102c6a62015-10-30 02:47:38 -0700478 options.tx_agc_limiter.value_or(default_agc_config_.limiterEnable);
solenberg76377c52017-02-21 00:54:31 -0800479
480 webrtc::AgcConfig config = default_agc_config_;
481 if (options.adjust_agc_delta) {
482 config.targetLeveldBOv -= *options.adjust_agc_delta;
483 LOG(LS_INFO) << "Adjusting AGC level from default -"
484 << default_agc_config_.targetLeveldBOv << "dB to -"
485 << config.targetLeveldBOv << "dB";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000486 }
solenberg76377c52017-02-21 00:54:31 -0800487 webrtc::apm_helpers::SetAgcConfig(apm_, config);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000488 }
489
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700490 if (options.intelligibility_enhancer) {
491 intelligibility_enhancer_ = options.intelligibility_enhancer;
492 }
493 if (intelligibility_enhancer_ && *intelligibility_enhancer_) {
494 LOG(LS_INFO) << "Enabling NS when Intelligibility Enhancer is active.";
495 options.noise_suppression = intelligibility_enhancer_;
496 }
497
kwiberg102c6a62015-10-30 02:47:38 -0700498 if (options.noise_suppression) {
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700499 if (adm()->BuiltInNSIsAvailable()) {
500 bool builtin_ns =
501 *options.noise_suppression &&
502 !(intelligibility_enhancer_ && *intelligibility_enhancer_);
503 if (adm()->EnableBuiltInNS(builtin_ns) == 0 && builtin_ns) {
henrikac14f5ff2015-09-23 14:08:33 +0200504 // Disable internal software NS if built-in NS is enabled,
505 // i.e., replace the software NS with the built-in NS.
Karl Wibergbe579832015-11-10 22:34:18 +0100506 options.noise_suppression = rtc::Optional<bool>(false);
henrikac14f5ff2015-09-23 14:08:33 +0200507 LOG(LS_INFO) << "Disabling NS since built-in NS will be used instead";
508 }
509 }
solenberg76377c52017-02-21 00:54:31 -0800510 webrtc::apm_helpers::SetNsStatus(apm(), *options.noise_suppression);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000511 }
512
kwiberg102c6a62015-10-30 02:47:38 -0700513 if (options.stereo_swapping) {
514 LOG(LS_INFO) << "Stereo swapping enabled? " << *options.stereo_swapping;
solenberg76377c52017-02-21 00:54:31 -0800515 transmit_mixer()->EnableStereoChannelSwapping(*options.stereo_swapping);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000516 }
517
kwiberg102c6a62015-10-30 02:47:38 -0700518 if (options.audio_jitter_buffer_max_packets) {
519 LOG(LS_INFO) << "NetEq capacity is "
520 << *options.audio_jitter_buffer_max_packets;
solenberg88499ec2016-09-07 07:34:41 -0700521 channel_config_.acm_config.neteq_config.max_packets_in_buffer =
522 std::max(20, *options.audio_jitter_buffer_max_packets);
Henrik Lundin64dad832015-05-11 12:44:23 +0200523 }
kwiberg102c6a62015-10-30 02:47:38 -0700524 if (options.audio_jitter_buffer_fast_accelerate) {
525 LOG(LS_INFO) << "NetEq fast mode? "
526 << *options.audio_jitter_buffer_fast_accelerate;
solenberg88499ec2016-09-07 07:34:41 -0700527 channel_config_.acm_config.neteq_config.enable_fast_accelerate =
528 *options.audio_jitter_buffer_fast_accelerate;
Henrik Lundin5263b3c2015-06-01 10:29:41 +0200529 }
530
kwiberg102c6a62015-10-30 02:47:38 -0700531 if (options.typing_detection) {
532 LOG(LS_INFO) << "Typing detection is enabled? "
533 << *options.typing_detection;
solenberg76377c52017-02-21 00:54:31 -0800534 webrtc::apm_helpers::SetTypingDetectionStatus(
535 apm(), *options.typing_detection);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000536 }
537
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000538 webrtc::Config config;
539
kwiberg102c6a62015-10-30 02:47:38 -0700540 if (options.delay_agnostic_aec)
541 delay_agnostic_aec_ = options.delay_agnostic_aec;
542 if (delay_agnostic_aec_) {
543 LOG(LS_INFO) << "Delay agnostic aec is enabled? " << *delay_agnostic_aec_;
henrik.lundin0f133b92015-07-02 00:17:55 -0700544 config.Set<webrtc::DelayAgnostic>(
kwiberg102c6a62015-10-30 02:47:38 -0700545 new webrtc::DelayAgnostic(*delay_agnostic_aec_));
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100546 }
547
kwiberg102c6a62015-10-30 02:47:38 -0700548 if (options.extended_filter_aec) {
549 extended_filter_aec_ = options.extended_filter_aec;
550 }
551 if (extended_filter_aec_) {
552 LOG(LS_INFO) << "Extended filter aec is enabled? " << *extended_filter_aec_;
Henrik Lundin441f6342015-06-09 16:03:13 +0200553 config.Set<webrtc::ExtendedFilter>(
kwiberg102c6a62015-10-30 02:47:38 -0700554 new webrtc::ExtendedFilter(*extended_filter_aec_));
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000555 }
556
kwiberg102c6a62015-10-30 02:47:38 -0700557 if (options.experimental_ns) {
558 experimental_ns_ = options.experimental_ns;
559 }
560 if (experimental_ns_) {
561 LOG(LS_INFO) << "Experimental ns is enabled? " << *experimental_ns_;
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000562 config.Set<webrtc::ExperimentalNs>(
kwiberg102c6a62015-10-30 02:47:38 -0700563 new webrtc::ExperimentalNs(*experimental_ns_));
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000564 }
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000565
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700566 if (intelligibility_enhancer_) {
567 LOG(LS_INFO) << "Intelligibility Enhancer is enabled? "
568 << *intelligibility_enhancer_;
569 config.Set<webrtc::Intelligibility>(
570 new webrtc::Intelligibility(*intelligibility_enhancer_));
571 }
572
peaha3333bf2016-06-30 00:02:34 -0700573 if (options.level_control) {
574 level_control_ = options.level_control;
575 }
576
577 LOG(LS_INFO) << "Level control: "
578 << (!!level_control_ ? *level_control_ : -1);
579 if (level_control_) {
peah64d6ff72016-11-21 06:28:14 -0800580 apm_config_.level_controller.enabled = *level_control_;
aleloie33c5d92016-10-20 01:53:27 -0700581 if (options.level_control_initial_peak_level_dbfs) {
peah64d6ff72016-11-21 06:28:14 -0800582 apm_config_.level_controller.initial_peak_level_dbfs =
aleloie33c5d92016-10-20 01:53:27 -0700583 *options.level_control_initial_peak_level_dbfs;
584 }
peaha3333bf2016-06-30 00:02:34 -0700585 }
586
peah8271d042016-11-22 07:24:52 -0800587 if (options.highpass_filter) {
588 apm_config_.high_pass_filter.enabled = *options.highpass_filter;
589 }
590
ivoc4ca18692017-02-10 05:11:09 -0800591 if (options.residual_echo_detector) {
592 apm_config_.residual_echo_detector.enabled =
593 *options.residual_echo_detector;
594 }
595
solenberg059fb442016-10-26 05:12:24 -0700596 apm()->SetExtraOptions(config);
peah64d6ff72016-11-21 06:28:14 -0800597 apm()->ApplyConfig(apm_config_);
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000598
kwiberg102c6a62015-10-30 02:47:38 -0700599 if (options.recording_sample_rate) {
600 LOG(LS_INFO) << "Recording sample rate is "
601 << *options.recording_sample_rate;
solenberg5b5129a2016-04-08 05:35:48 -0700602 if (adm()->SetRecordingSampleRate(*options.recording_sample_rate)) {
kwiberg102c6a62015-10-30 02:47:38 -0700603 LOG_RTCERR1(SetRecordingSampleRate, *options.recording_sample_rate);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000604 }
605 }
606
kwiberg102c6a62015-10-30 02:47:38 -0700607 if (options.playout_sample_rate) {
608 LOG(LS_INFO) << "Playout sample rate is " << *options.playout_sample_rate;
solenberg5b5129a2016-04-08 05:35:48 -0700609 if (adm()->SetPlayoutSampleRate(*options.playout_sample_rate)) {
kwiberg102c6a62015-10-30 02:47:38 -0700610 LOG_RTCERR1(SetPlayoutSampleRate, *options.playout_sample_rate);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000611 }
612 }
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000613 return true;
614}
615
solenberg796b8f92017-03-01 17:02:23 -0800616// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000617int WebRtcVoiceEngine::GetInputLevel() {
solenberg566ef242015-11-06 15:34:49 -0800618 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg796b8f92017-03-01 17:02:23 -0800619 int8_t level = transmit_mixer()->AudioLevel();
620 RTC_DCHECK_LE(0, level);
621 return level;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000622}
623
ossudedfd282016-06-14 07:12:39 -0700624const std::vector<AudioCodec>& WebRtcVoiceEngine::send_codecs() const {
625 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
ossuc54071d2016-08-17 02:45:41 -0700626 return send_codecs_;
ossudedfd282016-06-14 07:12:39 -0700627}
628
629const std::vector<AudioCodec>& WebRtcVoiceEngine::recv_codecs() const {
solenberg566ef242015-11-06 15:34:49 -0800630 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
ossuc54071d2016-08-17 02:45:41 -0700631 return recv_codecs_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000632}
633
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100634RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const {
solenberg566ef242015-11-06 15:34:49 -0800635 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100636 RtpCapabilities capabilities;
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100637 capabilities.header_extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -0700638 webrtc::RtpExtension(webrtc::RtpExtension::kAudioLevelUri,
639 webrtc::RtpExtension::kAudioLevelDefaultId));
sprangc1b57a12017-02-28 08:50:47 -0800640 if (webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe")) {
isheriff6f8d6862016-05-26 11:24:55 -0700641 capabilities.header_extensions.push_back(webrtc::RtpExtension(
642 webrtc::RtpExtension::kTransportSequenceNumberUri,
643 webrtc::RtpExtension::kTransportSequenceNumberDefaultId));
stefanba4c0e42016-02-04 04:12:24 -0800644 }
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100645 return capabilities;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000646}
647
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000648int WebRtcVoiceEngine::GetLastEngineError() {
solenberg566ef242015-11-06 15:34:49 -0800649 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000650 return voe_wrapper_->error();
651}
652
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000653void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
654 int length) {
solenberg566ef242015-11-06 15:34:49 -0800655 // Note: This callback can happen on any thread!
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000656 rtc::LoggingSeverity sev = rtc::LS_VERBOSE;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000657 if (level == webrtc::kTraceError || level == webrtc::kTraceCritical)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000658 sev = rtc::LS_ERROR;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000659 else if (level == webrtc::kTraceWarning)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000660 sev = rtc::LS_WARNING;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000661 else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000662 sev = rtc::LS_INFO;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000663 else if (level == webrtc::kTraceTerseInfo)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000664 sev = rtc::LS_INFO;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000665
solenberg72e29d22016-03-08 06:35:16 -0800666 // Skip past boilerplate prefix text.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000667 if (length < 72) {
668 std::string msg(trace, length);
669 LOG(LS_ERROR) << "Malformed webrtc log message: ";
670 LOG_V(sev) << msg;
671 } else {
672 std::string msg(trace + 71, length - 72);
Peter Boströmd5c75b12015-09-23 13:24:32 +0200673 LOG_V(sev) << "webrtc: " << msg;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000674 }
675}
676
solenberg63b34542015-09-29 06:06:31 -0700677void WebRtcVoiceEngine::RegisterChannel(WebRtcVoiceMediaChannel* channel) {
solenberg566ef242015-11-06 15:34:49 -0800678 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
679 RTC_DCHECK(channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000680 channels_.push_back(channel);
681}
682
solenberg63b34542015-09-29 06:06:31 -0700683void WebRtcVoiceEngine::UnregisterChannel(WebRtcVoiceMediaChannel* channel) {
solenberg566ef242015-11-06 15:34:49 -0800684 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg63b34542015-09-29 06:06:31 -0700685 auto it = std::find(channels_.begin(), channels_.end(), channel);
solenberg566ef242015-11-06 15:34:49 -0800686 RTC_DCHECK(it != channels_.end());
687 channels_.erase(it);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000688}
689
ivocd66b44d2016-01-15 03:06:36 -0800690bool WebRtcVoiceEngine::StartAecDump(rtc::PlatformFile file,
691 int64_t max_size_bytes) {
solenberg566ef242015-11-06 15:34:49 -0800692 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
aleloi048cbdd2017-05-29 02:56:27 -0700693 auto aec_dump = webrtc::AecDumpFactory::Create(file, max_size_bytes,
694 &low_priority_worker_queue_);
695 if (!aec_dump) {
wu@webrtc.orga8910d22014-01-23 22:12:45 +0000696 return false;
697 }
aleloi048cbdd2017-05-29 02:56:27 -0700698 apm()->AttachAecDump(std::move(aec_dump));
wu@webrtc.orga9890802013-12-13 00:21:03 +0000699 return true;
wu@webrtc.orga9890802013-12-13 00:21:03 +0000700}
701
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000702void WebRtcVoiceEngine::StartAecDump(const std::string& filename) {
solenberg566ef242015-11-06 15:34:49 -0800703 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
aleloi048cbdd2017-05-29 02:56:27 -0700704
705 auto aec_dump =
706 webrtc::AecDumpFactory::Create(filename, -1, &low_priority_worker_queue_);
707 if (aec_dump) {
708 apm()->AttachAecDump(std::move(aec_dump));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000709 }
710}
711
712void WebRtcVoiceEngine::StopAecDump() {
solenberg566ef242015-11-06 15:34:49 -0800713 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
aleloi048cbdd2017-05-29 02:56:27 -0700714 apm()->DetachAecDump();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000715}
716
solenberg0a617e22015-10-20 15:49:38 -0700717int WebRtcVoiceEngine::CreateVoEChannel() {
solenberg566ef242015-11-06 15:34:49 -0800718 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg88499ec2016-09-07 07:34:41 -0700719 return voe_wrapper_->base()->CreateChannel(channel_config_);
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000720}
721
solenberg5b5129a2016-04-08 05:35:48 -0700722webrtc::AudioDeviceModule* WebRtcVoiceEngine::adm() {
723 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
724 RTC_DCHECK(adm_);
725 return adm_;
726}
727
solenberg059fb442016-10-26 05:12:24 -0700728webrtc::AudioProcessing* WebRtcVoiceEngine::apm() {
729 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
730 RTC_DCHECK(apm_);
731 return apm_;
732}
733
solenberg76377c52017-02-21 00:54:31 -0800734webrtc::voe::TransmitMixer* WebRtcVoiceEngine::transmit_mixer() {
735 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
736 RTC_DCHECK(transmit_mixer_);
737 return transmit_mixer_;
738}
739
ossu20a4b3f2017-04-27 02:08:52 -0700740AudioCodecs WebRtcVoiceEngine::CollectCodecs(
741 const std::vector<webrtc::AudioCodecSpec>& specs) const {
ossuc54071d2016-08-17 02:45:41 -0700742 PayloadTypeMapper mapper;
743 AudioCodecs out;
ossuc54071d2016-08-17 02:45:41 -0700744
solenberg2779bab2016-11-17 04:45:19 -0800745 // Only generate CN payload types for these clockrates:
ossuc54071d2016-08-17 02:45:41 -0700746 std::map<int, bool, std::greater<int>> generate_cn = {{ 8000, false },
747 { 16000, false },
748 { 32000, false }};
solenberg2779bab2016-11-17 04:45:19 -0800749 // Only generate telephone-event payload types for these clockrates:
750 std::map<int, bool, std::greater<int>> generate_dtmf = {{ 8000, false },
751 { 16000, false },
752 { 32000, false },
753 { 48000, false }};
ossuc54071d2016-08-17 02:45:41 -0700754
ossu9def8002017-02-09 05:14:32 -0800755 auto map_format = [&mapper](const webrtc::SdpAudioFormat& format,
756 AudioCodecs* out) {
ossuc54071d2016-08-17 02:45:41 -0700757 rtc::Optional<AudioCodec> opt_codec = mapper.ToAudioCodec(format);
ossu9def8002017-02-09 05:14:32 -0800758 if (opt_codec) {
759 if (out) {
760 out->push_back(*opt_codec);
761 }
762 } else {
ossuc54071d2016-08-17 02:45:41 -0700763 LOG(LS_ERROR) << "Unable to assign payload type to format: " << format;
ossuc54071d2016-08-17 02:45:41 -0700764 }
765
ossu9def8002017-02-09 05:14:32 -0800766 return opt_codec;
ossuc54071d2016-08-17 02:45:41 -0700767 };
768
ossud4e9f622016-08-18 02:01:17 -0700769 for (const auto& spec : specs) {
ossu9def8002017-02-09 05:14:32 -0800770 // We need to do some extra stuff before adding the main codecs to out.
771 rtc::Optional<AudioCodec> opt_codec = map_format(spec.format, nullptr);
772 if (opt_codec) {
773 AudioCodec& codec = *opt_codec;
ossua1a040a2017-04-06 10:03:21 -0700774 if (spec.info.supports_network_adaption) {
ossu9def8002017-02-09 05:14:32 -0800775 codec.AddFeedbackParam(
776 FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty));
777 }
778
ossua1a040a2017-04-06 10:03:21 -0700779 if (spec.info.allow_comfort_noise) {
solenberg2779bab2016-11-17 04:45:19 -0800780 // Generate a CN entry if the decoder allows it and we support the
781 // clockrate.
782 auto cn = generate_cn.find(spec.format.clockrate_hz);
783 if (cn != generate_cn.end()) {
784 cn->second = true;
785 }
786 }
787
788 // Generate a telephone-event entry if we support the clockrate.
789 auto dtmf = generate_dtmf.find(spec.format.clockrate_hz);
790 if (dtmf != generate_dtmf.end()) {
791 dtmf->second = true;
ossuc54071d2016-08-17 02:45:41 -0700792 }
ossu9def8002017-02-09 05:14:32 -0800793
794 out.push_back(codec);
ossuc54071d2016-08-17 02:45:41 -0700795 }
796 }
797
solenberg2779bab2016-11-17 04:45:19 -0800798 // Add CN codecs after "proper" audio codecs.
ossuc54071d2016-08-17 02:45:41 -0700799 for (const auto& cn : generate_cn) {
800 if (cn.second) {
ossu9def8002017-02-09 05:14:32 -0800801 map_format({kCnCodecName, cn.first, 1}, &out);
ossuc54071d2016-08-17 02:45:41 -0700802 }
803 }
804
solenberg2779bab2016-11-17 04:45:19 -0800805 // Add telephone-event codecs last.
806 for (const auto& dtmf : generate_dtmf) {
807 if (dtmf.second) {
ossu9def8002017-02-09 05:14:32 -0800808 map_format({kDtmfCodecName, dtmf.first, 1}, &out);
solenberg2779bab2016-11-17 04:45:19 -0800809 }
810 }
ossuc54071d2016-08-17 02:45:41 -0700811
812 return out;
813}
814
solenbergc96df772015-10-21 13:01:53 -0700815class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800816 : public AudioSource::Sink {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000817 public:
minyue7a973442016-10-20 03:27:12 -0700818 WebRtcAudioSendStream(
819 int ch,
820 webrtc::AudioTransport* voe_audio_transport,
821 uint32_t ssrc,
822 const std::string& c_name,
ossu20a4b3f2017-04-27 02:08:52 -0700823 const rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>&
824 send_codec_spec,
minyue7a973442016-10-20 03:27:12 -0700825 const std::vector<webrtc::RtpExtension>& extensions,
826 int max_send_bitrate_bps,
minyue6b825df2016-10-31 04:08:32 -0700827 const rtc::Optional<std::string>& audio_network_adaptor_config,
minyue7a973442016-10-20 03:27:12 -0700828 webrtc::Call* call,
ossu20a4b3f2017-04-27 02:08:52 -0700829 webrtc::Transport* send_transport,
830 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory)
solenberg7add0582015-11-20 09:59:34 -0800831 : voe_audio_transport_(voe_audio_transport),
solenberg3a941542015-11-16 07:34:50 -0800832 call_(call),
mflodman3d7db262016-04-29 00:57:13 -0700833 config_(send_transport),
sprangc1b57a12017-02-28 08:50:47 -0800834 send_side_bwe_with_overhead_(
835 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
minyue7a973442016-10-20 03:27:12 -0700836 max_send_bitrate_bps_(max_send_bitrate_bps),
skvlade0d46372016-04-07 22:59:22 -0700837 rtp_parameters_(CreateRtpParametersWithOneEncoding()) {
solenberg85a04962015-10-27 03:35:21 -0700838 RTC_DCHECK_GE(ch, 0);
839 // TODO(solenberg): Once we're not using FakeWebRtcVoiceEngine anymore:
840 // RTC_DCHECK(voe_audio_transport);
solenbergc96df772015-10-21 13:01:53 -0700841 RTC_DCHECK(call);
ossu20a4b3f2017-04-27 02:08:52 -0700842 RTC_DCHECK(encoder_factory);
solenberg3a941542015-11-16 07:34:50 -0800843 config_.rtp.ssrc = ssrc;
844 config_.rtp.c_name = c_name;
845 config_.voe_channel_id = ch;
solenberg971cab02016-06-14 10:02:41 -0700846 config_.rtp.extensions = extensions;
minyue6b825df2016-10-31 04:08:32 -0700847 config_.audio_network_adaptor_config = audio_network_adaptor_config;
ossu20a4b3f2017-04-27 02:08:52 -0700848 config_.encoder_factory = encoder_factory;
deadbeefcb443432016-12-12 11:12:36 -0800849 rtp_parameters_.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
ossu20a4b3f2017-04-27 02:08:52 -0700850
851 if (send_codec_spec) {
852 UpdateSendCodecSpec(*send_codec_spec);
853 }
854
855 stream_ = call_->CreateAudioSendStream(config_);
solenbergc96df772015-10-21 13:01:53 -0700856 }
solenberg3a941542015-11-16 07:34:50 -0800857
solenbergc96df772015-10-21 13:01:53 -0700858 ~WebRtcAudioSendStream() override {
solenberg566ef242015-11-06 15:34:49 -0800859 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800860 ClearSource();
solenbergc96df772015-10-21 13:01:53 -0700861 call_->DestroyAudioSendStream(stream_);
862 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000863
ossu20a4b3f2017-04-27 02:08:52 -0700864 void SetSendCodecSpec(
minyue7a973442016-10-20 03:27:12 -0700865 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) {
ossu20a4b3f2017-04-27 02:08:52 -0700866 UpdateSendCodecSpec(send_codec_spec);
867 ReconfigureAudioSendStream();
solenberg971cab02016-06-14 10:02:41 -0700868 }
869
ossu20a4b3f2017-04-27 02:08:52 -0700870 void SetRtpExtensions(const std::vector<webrtc::RtpExtension>& extensions) {
solenberg3a941542015-11-16 07:34:50 -0800871 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg3a941542015-11-16 07:34:50 -0800872 config_.rtp.extensions = extensions;
ossu20a4b3f2017-04-27 02:08:52 -0700873 ReconfigureAudioSendStream();
solenberg3a941542015-11-16 07:34:50 -0800874 }
875
ossu20a4b3f2017-04-27 02:08:52 -0700876 void SetAudioNetworkAdaptorConfig(
minyue6b825df2016-10-31 04:08:32 -0700877 const rtc::Optional<std::string>& audio_network_adaptor_config) {
878 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
879 if (config_.audio_network_adaptor_config == audio_network_adaptor_config) {
880 return;
881 }
882 config_.audio_network_adaptor_config = audio_network_adaptor_config;
ossu20a4b3f2017-04-27 02:08:52 -0700883 UpdateAllowedBitrateRange();
884 ReconfigureAudioSendStream();
minyue6b825df2016-10-31 04:08:32 -0700885 }
886
minyue7a973442016-10-20 03:27:12 -0700887 bool SetMaxSendBitrate(int bps) {
888 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
ossu20a4b3f2017-04-27 02:08:52 -0700889 RTC_DCHECK(config_.send_codec_spec);
890 RTC_DCHECK(audio_codec_spec_);
891 auto send_rate = ComputeSendBitrate(
892 bps, rtp_parameters_.encodings[0].max_bitrate_bps, *audio_codec_spec_);
893
minyue7a973442016-10-20 03:27:12 -0700894 if (!send_rate) {
895 return false;
896 }
897
898 max_send_bitrate_bps_ = bps;
899
ossu20a4b3f2017-04-27 02:08:52 -0700900 if (send_rate != config_.send_codec_spec->target_bitrate_bps) {
901 config_.send_codec_spec->target_bitrate_bps = send_rate;
902 ReconfigureAudioSendStream();
minyue7a973442016-10-20 03:27:12 -0700903 }
904 return true;
905 }
906
solenbergffbbcac2016-11-17 05:25:37 -0800907 bool SendTelephoneEvent(int payload_type, int payload_freq, int event,
908 int duration_ms) {
Fredrik Solenbergb5727682015-12-04 15:22:19 +0100909 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
910 RTC_DCHECK(stream_);
solenbergffbbcac2016-11-17 05:25:37 -0800911 return stream_->SendTelephoneEvent(payload_type, payload_freq, event,
912 duration_ms);
Fredrik Solenbergb5727682015-12-04 15:22:19 +0100913 }
914
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800915 void SetSend(bool send) {
916 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
917 send_ = send;
918 UpdateSendState();
919 }
920
solenberg94218532016-06-16 10:53:22 -0700921 void SetMuted(bool muted) {
922 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
923 RTC_DCHECK(stream_);
924 stream_->SetMuted(muted);
925 muted_ = muted;
926 }
927
928 bool muted() const {
929 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
930 return muted_;
931 }
932
solenberg3a941542015-11-16 07:34:50 -0800933 webrtc::AudioSendStream::Stats GetStats() const {
934 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
935 RTC_DCHECK(stream_);
936 return stream_->GetStats();
937 }
938
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800939 // Starts the sending by setting ourselves as a sink to the AudioSource to
940 // get data callbacks.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000941 // This method is called on the libjingle worker thread.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000942 // TODO(xians): Make sure Start() is called only once.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800943 void SetSource(AudioSource* source) {
solenberg566ef242015-11-06 15:34:49 -0800944 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800945 RTC_DCHECK(source);
946 if (source_) {
947 RTC_DCHECK(source_ == source);
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000948 return;
949 }
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800950 source->SetSink(this);
951 source_ = source;
952 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000953 }
954
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800955 // Stops sending by setting the sink of the AudioSource to nullptr. No data
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000956 // callback will be received after this method.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000957 // This method is called on the libjingle worker thread.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800958 void ClearSource() {
solenberg566ef242015-11-06 15:34:49 -0800959 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800960 if (source_) {
961 source_->SetSink(nullptr);
962 source_ = nullptr;
solenberg98c68862015-10-09 03:27:14 -0700963 }
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800964 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000965 }
966
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800967 // AudioSource::Sink implementation.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000968 // This method is called on the audio thread.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000969 void OnData(const void* audio_data,
970 int bits_per_sample,
971 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -0800972 size_t number_of_channels,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700973 size_t number_of_frames) override {
solenberg347ec5c2016-09-23 04:21:47 -0700974 RTC_CHECK_RUNS_SERIALIZED(&audio_capture_race_checker_);
solenbergc96df772015-10-21 13:01:53 -0700975 RTC_DCHECK(voe_audio_transport_);
maxmorin1aee0b52016-08-15 11:46:19 -0700976 voe_audio_transport_->PushCaptureData(config_.voe_channel_id, audio_data,
977 bits_per_sample, sample_rate,
978 number_of_channels, number_of_frames);
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000979 }
980
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800981 // Callback from the |source_| when it is going away. In case Start() has
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000982 // never been called, this callback won't be triggered.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000983 void OnClose() override {
solenberg566ef242015-11-06 15:34:49 -0800984 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800985 // Set |source_| to nullptr to make sure no more callback will get into
986 // the source.
987 source_ = nullptr;
988 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000989 }
990
991 // Accessor to the VoE channel ID.
solenberg85a04962015-10-27 03:35:21 -0700992 int channel() const {
solenberg566ef242015-11-06 15:34:49 -0800993 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7add0582015-11-20 09:59:34 -0800994 return config_.voe_channel_id;
solenberg85a04962015-10-27 03:35:21 -0700995 }
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000996
skvlade0d46372016-04-07 22:59:22 -0700997 const webrtc::RtpParameters& rtp_parameters() const {
998 return rtp_parameters_;
999 }
1000
deadbeeffb2aced2017-01-06 23:05:37 -08001001 bool ValidateRtpParameters(const webrtc::RtpParameters& rtp_parameters) {
1002 if (rtp_parameters.encodings.size() != 1) {
1003 LOG(LS_ERROR)
1004 << "Attempted to set RtpParameters without exactly one encoding";
1005 return false;
1006 }
1007 if (rtp_parameters.encodings[0].ssrc != rtp_parameters_.encodings[0].ssrc) {
1008 LOG(LS_ERROR) << "Attempted to set RtpParameters with modified SSRC";
1009 return false;
1010 }
1011 return true;
1012 }
1013
minyue7a973442016-10-20 03:27:12 -07001014 bool SetRtpParameters(const webrtc::RtpParameters& parameters) {
deadbeeffb2aced2017-01-06 23:05:37 -08001015 if (!ValidateRtpParameters(parameters)) {
1016 return false;
1017 }
ossu20a4b3f2017-04-27 02:08:52 -07001018
1019 rtc::Optional<int> send_rate;
1020 if (audio_codec_spec_) {
1021 send_rate = ComputeSendBitrate(max_send_bitrate_bps_,
1022 parameters.encodings[0].max_bitrate_bps,
1023 *audio_codec_spec_);
1024 if (!send_rate) {
1025 return false;
1026 }
minyue7a973442016-10-20 03:27:12 -07001027 }
1028
minyuececec102017-03-27 13:04:25 -07001029 const rtc::Optional<int> old_rtp_max_bitrate =
1030 rtp_parameters_.encodings[0].max_bitrate_bps;
1031
skvlade0d46372016-04-07 22:59:22 -07001032 rtp_parameters_ = parameters;
minyue7a973442016-10-20 03:27:12 -07001033
minyuececec102017-03-27 13:04:25 -07001034 if (rtp_parameters_.encodings[0].max_bitrate_bps != old_rtp_max_bitrate) {
ossu20a4b3f2017-04-27 02:08:52 -07001035 // Reconfigure AudioSendStream with new bit rate.
1036 if (send_rate) {
1037 config_.send_codec_spec->target_bitrate_bps = send_rate;
1038 }
1039 UpdateAllowedBitrateRange();
1040 ReconfigureAudioSendStream();
minyue7a973442016-10-20 03:27:12 -07001041 } else {
1042 // parameters.encodings[0].active could have changed.
1043 UpdateSendState();
1044 }
1045 return true;
skvlade0d46372016-04-07 22:59:22 -07001046 }
1047
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001048 private:
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001049 void UpdateSendState() {
1050 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1051 RTC_DCHECK(stream_);
Taylor Brandstetter55dd7082016-05-03 13:50:11 -07001052 RTC_DCHECK_EQ(1UL, rtp_parameters_.encodings.size());
1053 if (send_ && source_ != nullptr && rtp_parameters_.encodings[0].active) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001054 stream_->Start();
1055 } else { // !send || source_ = nullptr
1056 stream_->Stop();
1057 }
1058 }
1059
ossu20a4b3f2017-04-27 02:08:52 -07001060 void UpdateAllowedBitrateRange() {
michaelt53fe19d2016-10-18 09:39:22 -07001061 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
ossu20a4b3f2017-04-27 02:08:52 -07001062 const bool is_opus =
1063 config_.send_codec_spec &&
1064 !STR_CASE_CMP(config_.send_codec_spec->format.name.c_str(),
1065 kOpusCodecName);
1066 if (is_opus && webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe")) {
stefane9f36d52017-01-24 08:18:45 -08001067 config_.min_bitrate_bps = kOpusMinBitrateBps;
minyuececec102017-03-27 13:04:25 -07001068
1069 // This means that when RtpParameters is reset, we may change the
ossu20a4b3f2017-04-27 02:08:52 -07001070 // encoder's bit rate immediately (through ReconfigureAudioSendStream()),
minyuececec102017-03-27 13:04:25 -07001071 // meanwhile change the cap to the output of BWE.
1072 config_.max_bitrate_bps =
1073 rtp_parameters_.encodings[0].max_bitrate_bps
1074 ? *rtp_parameters_.encodings[0].max_bitrate_bps
1075 : kOpusBitrateFbBps;
1076
michaelt53fe19d2016-10-18 09:39:22 -07001077 // TODO(mflodman): Keep testing this and set proper values.
1078 // Note: This is an early experiment currently only supported by Opus.
elad.alon0fe12162017-01-31 05:48:37 -08001079 if (send_side_bwe_with_overhead_) {
ossu20a4b3f2017-04-27 02:08:52 -07001080 const int max_packet_size_ms =
1081 WEBRTC_OPUS_SUPPORT_120MS_PTIME ? 120 : 60;
michaelt6672b262017-01-11 10:17:59 -08001082
ossu20a4b3f2017-04-27 02:08:52 -07001083 // OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12)
1084 constexpr int kOverheadPerPacket = 20 + 8 + 10 + 12;
michaelt6672b262017-01-11 10:17:59 -08001085
ossu20a4b3f2017-04-27 02:08:52 -07001086 int min_overhead_bps =
1087 kOverheadPerPacket * 8 * 1000 / max_packet_size_ms;
michaelt6672b262017-01-11 10:17:59 -08001088
ossu20a4b3f2017-04-27 02:08:52 -07001089 // We assume that |config_.max_bitrate_bps| before the next line is
1090 // a hard limit on the payload bitrate, so we add min_overhead_bps to
1091 // it to ensure that, when overhead is deducted, the payload rate
1092 // never goes beyond the limit.
1093 // Note: this also means that if a higher overhead is forced, we
1094 // cannot reach the limit.
1095 // TODO(minyue): Reconsider this when the signaling to BWE is done
1096 // through a dedicated API.
1097 config_.max_bitrate_bps += min_overhead_bps;
michaelt6672b262017-01-11 10:17:59 -08001098
ossu20a4b3f2017-04-27 02:08:52 -07001099 // In contrast to max_bitrate_bps, we let min_bitrate_bps always be
1100 // reachable.
1101 config_.min_bitrate_bps += min_overhead_bps;
michaelt6672b262017-01-11 10:17:59 -08001102 }
michaelt53fe19d2016-10-18 09:39:22 -07001103 }
ossu20a4b3f2017-04-27 02:08:52 -07001104 }
1105
1106 void UpdateSendCodecSpec(
1107 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) {
1108 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1109 config_.rtp.nack.rtp_history_ms =
1110 send_codec_spec.nack_enabled ? kNackRtpHistoryMs : 0;
1111 config_.send_codec_spec =
1112 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>(
1113 send_codec_spec);
1114 auto info =
1115 config_.encoder_factory->QueryAudioEncoder(send_codec_spec.format);
1116 RTC_DCHECK(info);
1117 // If a specific target bitrate has been set for the stream, use that as
1118 // the new default bitrate when computing send bitrate.
1119 if (send_codec_spec.target_bitrate_bps) {
1120 info->default_bitrate_bps = std::max(
1121 info->min_bitrate_bps,
1122 std::min(info->max_bitrate_bps, *send_codec_spec.target_bitrate_bps));
1123 }
1124
1125 audio_codec_spec_.emplace(
1126 webrtc::AudioCodecSpec{send_codec_spec.format, *info});
1127
1128 config_.send_codec_spec->target_bitrate_bps = ComputeSendBitrate(
1129 max_send_bitrate_bps_, rtp_parameters_.encodings[0].max_bitrate_bps,
1130 *audio_codec_spec_);
1131
1132 UpdateAllowedBitrateRange();
1133 }
1134
1135 void ReconfigureAudioSendStream() {
1136 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1137 RTC_DCHECK(stream_);
1138 stream_->Reconfigure(config_);
michaelt53fe19d2016-10-18 09:39:22 -07001139 }
1140
solenberg566ef242015-11-06 15:34:49 -08001141 rtc::ThreadChecker worker_thread_checker_;
solenberg347ec5c2016-09-23 04:21:47 -07001142 rtc::RaceChecker audio_capture_race_checker_;
solenbergc96df772015-10-21 13:01:53 -07001143 webrtc::AudioTransport* const voe_audio_transport_ = nullptr;
1144 webrtc::Call* call_ = nullptr;
solenberg3a941542015-11-16 07:34:50 -08001145 webrtc::AudioSendStream::Config config_;
elad.alon0fe12162017-01-31 05:48:37 -08001146 const bool send_side_bwe_with_overhead_;
solenberg3a941542015-11-16 07:34:50 -08001147 // The stream is owned by WebRtcAudioSendStream and may be reallocated if
1148 // configuration changes.
solenbergc96df772015-10-21 13:01:53 -07001149 webrtc::AudioSendStream* stream_ = nullptr;
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001150
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001151 // Raw pointer to AudioSource owned by LocalAudioTrackHandler.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001152 // PeerConnection will make sure invalidating the pointer before the object
1153 // goes away.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001154 AudioSource* source_ = nullptr;
1155 bool send_ = false;
solenberg94218532016-06-16 10:53:22 -07001156 bool muted_ = false;
minyue7a973442016-10-20 03:27:12 -07001157 int max_send_bitrate_bps_;
skvlade0d46372016-04-07 22:59:22 -07001158 webrtc::RtpParameters rtp_parameters_;
ossu20a4b3f2017-04-27 02:08:52 -07001159 rtc::Optional<webrtc::AudioCodecSpec> audio_codec_spec_;
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00001160
solenbergc96df772015-10-21 13:01:53 -07001161 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream);
1162};
1163
1164class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
1165 public:
ossu29b1a8d2016-06-13 07:34:51 -07001166 WebRtcAudioReceiveStream(
1167 int ch,
1168 uint32_t remote_ssrc,
1169 uint32_t local_ssrc,
1170 bool use_transport_cc,
solenberg8189b022016-06-14 12:13:00 -07001171 bool use_nack,
ossu29b1a8d2016-06-13 07:34:51 -07001172 const std::string& sync_group,
1173 const std::vector<webrtc::RtpExtension>& extensions,
1174 webrtc::Call* call,
1175 webrtc::Transport* rtcp_send_transport,
kwiberg1c07c702017-03-27 07:15:49 -07001176 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
1177 const std::map<int, webrtc::SdpAudioFormat>& decoder_map)
stefanba4c0e42016-02-04 04:12:24 -08001178 : call_(call), config_() {
solenberg7add0582015-11-20 09:59:34 -08001179 RTC_DCHECK_GE(ch, 0);
1180 RTC_DCHECK(call);
1181 config_.rtp.remote_ssrc = remote_ssrc;
kwibergd32bf752017-01-19 07:03:59 -08001182 config_.rtp.local_ssrc = local_ssrc;
1183 config_.rtp.transport_cc = use_transport_cc;
1184 config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0;
1185 config_.rtp.extensions = extensions;
solenberg31fec402016-05-06 02:13:12 -07001186 config_.rtcp_send_transport = rtcp_send_transport;
solenberg7add0582015-11-20 09:59:34 -08001187 config_.voe_channel_id = ch;
1188 config_.sync_group = sync_group;
ossu29b1a8d2016-06-13 07:34:51 -07001189 config_.decoder_factory = decoder_factory;
kwiberg1c07c702017-03-27 07:15:49 -07001190 config_.decoder_map = decoder_map;
kwibergd32bf752017-01-19 07:03:59 -08001191 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001192 }
solenbergc96df772015-10-21 13:01:53 -07001193
solenberg7add0582015-11-20 09:59:34 -08001194 ~WebRtcAudioReceiveStream() {
1195 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1196 call_->DestroyAudioReceiveStream(stream_);
1197 }
1198
solenberg4a0f7b52016-06-16 13:07:33 -07001199 void RecreateAudioReceiveStream(uint32_t local_ssrc) {
solenberg7add0582015-11-20 09:59:34 -08001200 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001201 config_.rtp.local_ssrc = local_ssrc;
1202 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001203 }
solenberg8189b022016-06-14 12:13:00 -07001204
1205 void RecreateAudioReceiveStream(bool use_transport_cc, bool use_nack) {
solenberg7add0582015-11-20 09:59:34 -08001206 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001207 config_.rtp.transport_cc = use_transport_cc;
1208 config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0;
1209 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001210 }
1211
solenberg4a0f7b52016-06-16 13:07:33 -07001212 void RecreateAudioReceiveStream(
1213 const std::vector<webrtc::RtpExtension>& extensions) {
1214 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001215 config_.rtp.extensions = extensions;
1216 RecreateAudioReceiveStream();
1217 }
1218
deadbeefcb383672017-04-26 16:28:42 -07001219 // Set a new payload type -> decoder map.
kwibergd32bf752017-01-19 07:03:59 -08001220 void RecreateAudioReceiveStream(
1221 const std::map<int, webrtc::SdpAudioFormat>& decoder_map) {
1222 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001223 config_.decoder_map = decoder_map;
1224 RecreateAudioReceiveStream();
solenberg4a0f7b52016-06-16 13:07:33 -07001225 }
1226
solenberg4904fb62017-02-17 12:01:14 -08001227 void MaybeRecreateAudioReceiveStream(const std::string& sync_group) {
1228 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1229 if (config_.sync_group != sync_group) {
1230 config_.sync_group = sync_group;
1231 RecreateAudioReceiveStream();
1232 }
1233 }
1234
solenberg7add0582015-11-20 09:59:34 -08001235 webrtc::AudioReceiveStream::Stats GetStats() const {
1236 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1237 RTC_DCHECK(stream_);
1238 return stream_->GetStats();
1239 }
1240
solenberg796b8f92017-03-01 17:02:23 -08001241 int GetOutputLevel() const {
1242 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1243 RTC_DCHECK(stream_);
1244 return stream_->GetOutputLevel();
1245 }
1246
solenberg7add0582015-11-20 09:59:34 -08001247 int channel() const {
1248 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1249 return config_.voe_channel_id;
1250 }
solenbergc96df772015-10-21 13:01:53 -07001251
kwiberg686a8ef2016-02-26 03:00:35 -08001252 void SetRawAudioSink(std::unique_ptr<webrtc::AudioSinkInterface> sink) {
Tommif888bb52015-12-12 01:37:01 +01001253 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwiberg686a8ef2016-02-26 03:00:35 -08001254 stream_->SetSink(std::move(sink));
Tommif888bb52015-12-12 01:37:01 +01001255 }
1256
solenberg217fb662016-06-17 08:30:54 -07001257 void SetOutputVolume(double volume) {
1258 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1259 stream_->SetGain(volume);
1260 }
1261
aleloi84ef6152016-08-04 05:28:21 -07001262 void SetPlayout(bool playout) {
1263 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1264 RTC_DCHECK(stream_);
1265 if (playout) {
1266 LOG(LS_INFO) << "Starting playout for channel #" << channel();
1267 stream_->Start();
1268 } else {
1269 LOG(LS_INFO) << "Stopping playout for channel #" << channel();
1270 stream_->Stop();
1271 }
aleloi18e0b672016-10-04 02:45:47 -07001272 playout_ = playout;
aleloi84ef6152016-08-04 05:28:21 -07001273 }
1274
hbos8d609f62017-04-10 07:39:05 -07001275 std::vector<webrtc::RtpSource> GetSources() {
1276 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1277 RTC_DCHECK(stream_);
1278 return stream_->GetSources();
1279 }
1280
solenbergc96df772015-10-21 13:01:53 -07001281 private:
kwibergd32bf752017-01-19 07:03:59 -08001282 void RecreateAudioReceiveStream() {
solenberg7add0582015-11-20 09:59:34 -08001283 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1284 if (stream_) {
1285 call_->DestroyAudioReceiveStream(stream_);
solenberg7add0582015-11-20 09:59:34 -08001286 }
solenberg7add0582015-11-20 09:59:34 -08001287 stream_ = call_->CreateAudioReceiveStream(config_);
1288 RTC_CHECK(stream_);
aleloi18e0b672016-10-04 02:45:47 -07001289 SetPlayout(playout_);
solenberg7add0582015-11-20 09:59:34 -08001290 }
1291
1292 rtc::ThreadChecker worker_thread_checker_;
1293 webrtc::Call* call_ = nullptr;
1294 webrtc::AudioReceiveStream::Config config_;
1295 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if
1296 // configuration changes.
1297 webrtc::AudioReceiveStream* stream_ = nullptr;
aleloi18e0b672016-10-04 02:45:47 -07001298 bool playout_ = false;
solenbergc96df772015-10-21 13:01:53 -07001299
1300 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioReceiveStream);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001301};
1302
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001303WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine,
nisse51542be2016-02-12 02:27:06 -08001304 const MediaConfig& config,
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001305 const AudioOptions& options,
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001306 webrtc::Call* call)
nisse51542be2016-02-12 02:27:06 -08001307 : VoiceMediaChannel(config), engine_(engine), call_(call) {
solenberg0a617e22015-10-20 15:49:38 -07001308 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel";
solenberg566ef242015-11-06 15:34:49 -08001309 RTC_DCHECK(call);
solenberg0a617e22015-10-20 15:49:38 -07001310 engine->RegisterChannel(this);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001311 SetOptions(options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001312}
1313
1314WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() {
solenberg566ef242015-11-06 15:34:49 -08001315 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg0a617e22015-10-20 15:49:38 -07001316 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel";
solenberg7add0582015-11-20 09:59:34 -08001317 // TODO(solenberg): Should be able to delete the streams directly, without
1318 // going through RemoveNnStream(), once stream objects handle
1319 // all (de)configuration.
solenbergc96df772015-10-21 13:01:53 -07001320 while (!send_streams_.empty()) {
1321 RemoveSendStream(send_streams_.begin()->first);
solenbergd97ec302015-10-07 01:40:33 -07001322 }
solenberg7add0582015-11-20 09:59:34 -08001323 while (!recv_streams_.empty()) {
1324 RemoveRecvStream(recv_streams_.begin()->first);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001325 }
solenberg0a617e22015-10-20 15:49:38 -07001326 engine()->UnregisterChannel(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001327}
1328
nisse51542be2016-02-12 02:27:06 -08001329rtc::DiffServCodePoint WebRtcVoiceMediaChannel::PreferredDscp() const {
1330 return kAudioDscpValue;
1331}
1332
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001333bool WebRtcVoiceMediaChannel::SetSendParameters(
1334 const AudioSendParameters& params) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001335 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetSendParameters");
solenberg566ef242015-11-06 15:34:49 -08001336 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7e4e01a2015-12-02 08:05:01 -08001337 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendParameters: "
1338 << params.ToString();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001339 // TODO(pthatcher): Refactor this to be more clean now that we have
1340 // all the information at once.
solenberg3a941542015-11-16 07:34:50 -08001341
1342 if (!SetSendCodecs(params.codecs)) {
1343 return false;
1344 }
1345
solenberg7e4e01a2015-12-02 08:05:01 -08001346 if (!ValidateRtpExtensions(params.extensions)) {
1347 return false;
1348 }
1349 std::vector<webrtc::RtpExtension> filtered_extensions =
1350 FilterRtpExtensions(params.extensions,
1351 webrtc::RtpExtension::IsSupportedForAudio, true);
1352 if (send_rtp_extensions_ != filtered_extensions) {
1353 send_rtp_extensions_.swap(filtered_extensions);
solenberg3a941542015-11-16 07:34:50 -08001354 for (auto& it : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001355 it.second->SetRtpExtensions(send_rtp_extensions_);
solenberg3a941542015-11-16 07:34:50 -08001356 }
1357 }
1358
deadbeef80346142016-04-27 14:17:10 -07001359 if (!SetMaxSendBitrate(params.max_bandwidth_bps)) {
solenberg3a941542015-11-16 07:34:50 -08001360 return false;
1361 }
1362 return SetOptions(params.options);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001363}
1364
1365bool WebRtcVoiceMediaChannel::SetRecvParameters(
1366 const AudioRecvParameters& params) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001367 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetRecvParameters");
solenberg566ef242015-11-06 15:34:49 -08001368 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7e4e01a2015-12-02 08:05:01 -08001369 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetRecvParameters: "
1370 << params.ToString();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001371 // TODO(pthatcher): Refactor this to be more clean now that we have
1372 // all the information at once.
solenberg7add0582015-11-20 09:59:34 -08001373
1374 if (!SetRecvCodecs(params.codecs)) {
1375 return false;
1376 }
1377
solenberg7e4e01a2015-12-02 08:05:01 -08001378 if (!ValidateRtpExtensions(params.extensions)) {
1379 return false;
1380 }
1381 std::vector<webrtc::RtpExtension> filtered_extensions =
1382 FilterRtpExtensions(params.extensions,
1383 webrtc::RtpExtension::IsSupportedForAudio, false);
1384 if (recv_rtp_extensions_ != filtered_extensions) {
1385 recv_rtp_extensions_.swap(filtered_extensions);
solenberg7add0582015-11-20 09:59:34 -08001386 for (auto& it : recv_streams_) {
1387 it.second->RecreateAudioReceiveStream(recv_rtp_extensions_);
1388 }
1389 }
solenberg7add0582015-11-20 09:59:34 -08001390 return true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001391}
1392
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001393webrtc::RtpParameters WebRtcVoiceMediaChannel::GetRtpSendParameters(
skvlade0d46372016-04-07 22:59:22 -07001394 uint32_t ssrc) const {
1395 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1396 auto it = send_streams_.find(ssrc);
1397 if (it == send_streams_.end()) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001398 LOG(LS_WARNING) << "Attempting to get RTP send parameters for stream "
1399 << "with ssrc " << ssrc << " which doesn't exist.";
skvlade0d46372016-04-07 22:59:22 -07001400 return webrtc::RtpParameters();
1401 }
1402
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001403 webrtc::RtpParameters rtp_params = it->second->rtp_parameters();
1404 // Need to add the common list of codecs to the send stream-specific
1405 // RTP parameters.
1406 for (const AudioCodec& codec : send_codecs_) {
1407 rtp_params.codecs.push_back(codec.ToCodecParameters());
1408 }
1409 return rtp_params;
skvlade0d46372016-04-07 22:59:22 -07001410}
1411
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001412bool WebRtcVoiceMediaChannel::SetRtpSendParameters(
skvlade0d46372016-04-07 22:59:22 -07001413 uint32_t ssrc,
1414 const webrtc::RtpParameters& parameters) {
1415 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
skvlade0d46372016-04-07 22:59:22 -07001416 auto it = send_streams_.find(ssrc);
1417 if (it == send_streams_.end()) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001418 LOG(LS_WARNING) << "Attempting to set RTP send parameters for stream "
1419 << "with ssrc " << ssrc << " which doesn't exist.";
skvlade0d46372016-04-07 22:59:22 -07001420 return false;
1421 }
1422
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001423 // TODO(deadbeef): Handle setting parameters with a list of codecs in a
1424 // different order (which should change the send codec).
1425 webrtc::RtpParameters current_parameters = GetRtpSendParameters(ssrc);
1426 if (current_parameters.codecs != parameters.codecs) {
1427 LOG(LS_ERROR) << "Using SetParameters to change the set of codecs "
1428 << "is not currently supported.";
1429 return false;
1430 }
1431
minyue7a973442016-10-20 03:27:12 -07001432 // TODO(minyue): The following legacy actions go into
1433 // |WebRtcAudioSendStream::SetRtpParameters()| which is called at the end,
1434 // though there are two difference:
1435 // 1. |WebRtcVoiceMediaChannel::SetChannelSendParameters()| only calls
1436 // |SetSendCodec| while |WebRtcAudioSendStream::SetRtpParameters()| calls
1437 // |SetSendCodecs|. The outcome should be the same.
1438 // 2. AudioSendStream can be recreated.
1439
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001440 // Codecs are handled at the WebRtcVoiceMediaChannel level.
1441 webrtc::RtpParameters reduced_params = parameters;
1442 reduced_params.codecs.clear();
minyue7a973442016-10-20 03:27:12 -07001443 return it->second->SetRtpParameters(reduced_params);
skvlade0d46372016-04-07 22:59:22 -07001444}
1445
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001446webrtc::RtpParameters WebRtcVoiceMediaChannel::GetRtpReceiveParameters(
1447 uint32_t ssrc) const {
1448 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef3bc15102017-04-20 19:25:07 -07001449 webrtc::RtpParameters rtp_params;
1450 // SSRC of 0 represents the default receive stream.
1451 if (ssrc == 0) {
1452 if (!default_sink_) {
1453 LOG(LS_WARNING) << "Attempting to get RTP parameters for the default, "
1454 "unsignaled audio receive stream, but not yet "
1455 "configured to receive such a stream.";
1456 return rtp_params;
1457 }
1458 rtp_params.encodings.emplace_back();
1459 } else {
1460 auto it = recv_streams_.find(ssrc);
1461 if (it == recv_streams_.end()) {
1462 LOG(LS_WARNING) << "Attempting to get RTP receive parameters for stream "
1463 << "with ssrc " << ssrc << " which doesn't exist.";
1464 return webrtc::RtpParameters();
1465 }
1466 rtp_params.encodings.emplace_back();
1467 // TODO(deadbeef): Return stream-specific parameters.
1468 rtp_params.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001469 }
1470
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001471 for (const AudioCodec& codec : recv_codecs_) {
1472 rtp_params.codecs.push_back(codec.ToCodecParameters());
1473 }
1474 return rtp_params;
1475}
1476
1477bool WebRtcVoiceMediaChannel::SetRtpReceiveParameters(
1478 uint32_t ssrc,
1479 const webrtc::RtpParameters& parameters) {
1480 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef3bc15102017-04-20 19:25:07 -07001481 // SSRC of 0 represents the default receive stream.
1482 if (ssrc == 0) {
1483 if (!default_sink_) {
1484 LOG(LS_WARNING) << "Attempting to set RTP parameters for the default, "
1485 "unsignaled audio receive stream, but not yet "
1486 "configured to receive such a stream.";
1487 return false;
1488 }
1489 } else {
1490 auto it = recv_streams_.find(ssrc);
1491 if (it == recv_streams_.end()) {
1492 LOG(LS_WARNING) << "Attempting to set RTP receive parameters for stream "
1493 << "with ssrc " << ssrc << " which doesn't exist.";
1494 return false;
1495 }
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001496 }
1497
1498 webrtc::RtpParameters current_parameters = GetRtpReceiveParameters(ssrc);
1499 if (current_parameters != parameters) {
1500 LOG(LS_ERROR) << "Changing the RTP receive parameters is currently "
1501 << "unsupported.";
1502 return false;
1503 }
1504 return true;
1505}
1506
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001507bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
solenberg566ef242015-11-06 15:34:49 -08001508 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001509 LOG(LS_INFO) << "Setting voice channel options: "
1510 << options.ToString();
1511
1512 // We retain all of the existing options, and apply the given ones
1513 // on top. This means there is no way to "clear" options such that
1514 // they go back to the engine default.
1515 options_.SetAll(options);
solenberg246b8172015-12-08 09:50:23 -08001516 if (!engine()->ApplyOptions(options_)) {
1517 LOG(LS_WARNING) <<
1518 "Failed to apply engine options during channel SetOptions.";
1519 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001520 }
minyue6b825df2016-10-31 04:08:32 -07001521
ossu20a4b3f2017-04-27 02:08:52 -07001522 rtc::Optional<std::string> audio_network_adaptor_config =
minyue6b825df2016-10-31 04:08:32 -07001523 GetAudioNetworkAdaptorConfig(options_);
1524 for (auto& it : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001525 it.second->SetAudioNetworkAdaptorConfig(audio_network_adaptor_config);
minyue6b825df2016-10-31 04:08:32 -07001526 }
1527
solenberg76377c52017-02-21 00:54:31 -08001528 LOG(LS_INFO) << "Set voice channel options. Current options: "
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001529 << options_.ToString();
1530 return true;
1531}
1532
1533bool WebRtcVoiceMediaChannel::SetRecvCodecs(
1534 const std::vector<AudioCodec>& codecs) {
solenberg566ef242015-11-06 15:34:49 -08001535 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg8fb30c32015-10-13 03:06:58 -07001536
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001537 // Set the payload types to be used for incoming media.
solenberg0b675462015-10-09 01:37:09 -07001538 LOG(LS_INFO) << "Setting receive voice codecs.";
solenberg0b675462015-10-09 01:37:09 -07001539
1540 if (!VerifyUniquePayloadTypes(codecs)) {
1541 LOG(LS_ERROR) << "Codec payload types overlap.";
1542 return false;
1543 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001544
kwibergd32bf752017-01-19 07:03:59 -08001545 // Create a payload type -> SdpAudioFormat map with all the decoders. Fail
1546 // unless the factory claims to support all decoders.
1547 std::map<int, webrtc::SdpAudioFormat> decoder_map;
1548 for (const AudioCodec& codec : codecs) {
deadbeefcb383672017-04-26 16:28:42 -07001549 // Log a warning if a codec's payload type is changing. This used to be
1550 // treated as an error. It's abnormal, but not really illegal.
1551 AudioCodec old_codec;
1552 if (FindCodec(recv_codecs_, codec, &old_codec) &&
1553 old_codec.id != codec.id) {
1554 LOG(LS_WARNING) << codec.name << " mapped to a second payload type ("
1555 << codec.id << ", was already mapped to " << old_codec.id
1556 << ")";
1557 }
kwibergd32bf752017-01-19 07:03:59 -08001558 auto format = AudioCodecToSdpAudioFormat(codec);
1559 if (!IsCodec(codec, "cn") && !IsCodec(codec, "telephone-event") &&
1560 !engine()->decoder_factory_->IsSupportedDecoder(format)) {
1561 LOG(LS_ERROR) << "Unsupported codec: " << format;
1562 return false;
1563 }
deadbeefcb383672017-04-26 16:28:42 -07001564 // We allow adding new codecs but don't allow changing the payload type of
1565 // codecs that are already configured since we might already be receiving
1566 // packets with that payload type. See RFC3264, Section 8.3.2.
1567 // TODO(deadbeef): Also need to check for clashes with previously mapped
1568 // payload types, and not just currently mapped ones. For example, this
1569 // should be illegal:
1570 // 1. {100: opus/48000/2, 101: ISAC/16000}
1571 // 2. {100: opus/48000/2}
1572 // 3. {100: opus/48000/2, 101: ISAC/32000}
1573 // Though this check really should happen at a higher level, since this
1574 // conflict could happen between audio and video codecs.
1575 auto existing = decoder_map_.find(codec.id);
1576 if (existing != decoder_map_.end() && !existing->second.Matches(format)) {
1577 LOG(LS_ERROR) << "Attempting to use payload type " << codec.id << " for "
1578 << codec.name << ", but it is already used for "
1579 << existing->second.name;
1580 return false;
1581 }
kwibergd32bf752017-01-19 07:03:59 -08001582 decoder_map.insert({codec.id, std::move(format)});
1583 }
1584
deadbeefcb383672017-04-26 16:28:42 -07001585 if (decoder_map == decoder_map_) {
1586 // There's nothing new to configure.
1587 return true;
1588 }
1589
kwiberg37b8b112016-11-03 02:46:53 -07001590 if (playout_) {
1591 // Receive codecs can not be changed while playing. So we temporarily
1592 // pause playout.
1593 ChangePlayout(false);
1594 }
1595
kwiberg1c07c702017-03-27 07:15:49 -07001596 decoder_map_ = std::move(decoder_map);
kwibergd32bf752017-01-19 07:03:59 -08001597 for (auto& kv : recv_streams_) {
kwiberg1c07c702017-03-27 07:15:49 -07001598 kv.second->RecreateAudioReceiveStream(decoder_map_);
solenberg26c8c912015-11-27 04:00:25 -08001599 }
kwibergd32bf752017-01-19 07:03:59 -08001600 recv_codecs_ = codecs;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001601
kwiberg37b8b112016-11-03 02:46:53 -07001602 if (desired_playout_ && !playout_) {
1603 ChangePlayout(desired_playout_);
1604 }
kwibergd32bf752017-01-19 07:03:59 -08001605 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001606}
1607
solenberg72e29d22016-03-08 06:35:16 -08001608// Utility function called from SetSendParameters() to extract current send
1609// codec settings from the given list of codecs (originally from SDP). Both send
1610// and receive streams may be reconfigured based on the new settings.
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001611bool WebRtcVoiceMediaChannel::SetSendCodecs(
1612 const std::vector<AudioCodec>& codecs) {
solenberg566ef242015-11-06 15:34:49 -08001613 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenbergb5727682015-12-04 15:22:19 +01001614 dtmf_payload_type_ = rtc::Optional<int>();
solenbergffbbcac2016-11-17 05:25:37 -08001615 dtmf_payload_freq_ = -1;
1616
1617 // Validate supplied codecs list.
1618 for (const AudioCodec& codec : codecs) {
1619 // TODO(solenberg): Validate more aspects of input - that payload types
1620 // don't overlap, remove redundant/unsupported codecs etc -
1621 // the same way it is done for RtpHeaderExtensions.
1622 if (codec.id < kMinPayloadType || codec.id > kMaxPayloadType) {
1623 LOG(LS_WARNING) << "Codec payload type out of range: " << ToString(codec);
1624 return false;
1625 }
1626 }
1627
1628 // Find PT of telephone-event codec with lowest clockrate, as a fallback, in
1629 // case we don't have a DTMF codec with a rate matching the send codec's, or
1630 // if this function returns early.
1631 std::vector<AudioCodec> dtmf_codecs;
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02001632 for (const AudioCodec& codec : codecs) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02001633 if (IsCodec(codec, kDtmfCodecName)) {
solenbergffbbcac2016-11-17 05:25:37 -08001634 dtmf_codecs.push_back(codec);
1635 if (!dtmf_payload_type_ || codec.clockrate < dtmf_payload_freq_) {
1636 dtmf_payload_type_ = rtc::Optional<int>(codec.id);
1637 dtmf_payload_freq_ = codec.clockrate;
solenberg31642aa2016-03-14 08:00:37 -07001638 }
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001639 }
1640 }
1641
ossu20a4b3f2017-04-27 02:08:52 -07001642 // Scan through the list to figure out the codec to use for sending.
1643 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec> send_codec_spec;
stefan1ccf73f2017-03-27 03:51:18 -07001644 webrtc::Call::Config::BitrateConfig bitrate_config;
ossu20a4b3f2017-04-27 02:08:52 -07001645 rtc::Optional<webrtc::AudioCodecInfo> voice_codec_info;
1646 for (const AudioCodec& voice_codec : codecs) {
1647 if (!(IsCodec(voice_codec, kCnCodecName) ||
1648 IsCodec(voice_codec, kDtmfCodecName) ||
1649 IsCodec(voice_codec, kRedCodecName))) {
1650 webrtc::SdpAudioFormat format(voice_codec.name, voice_codec.clockrate,
1651 voice_codec.channels, voice_codec.params);
solenberg72e29d22016-03-08 06:35:16 -08001652
ossu20a4b3f2017-04-27 02:08:52 -07001653 voice_codec_info = engine()->encoder_factory_->QueryAudioEncoder(format);
1654 if (!voice_codec_info) {
1655 LOG(LS_WARNING) << "Unknown codec " << ToString(voice_codec);
solenberg72e29d22016-03-08 06:35:16 -08001656 continue;
1657 }
1658
ossu20a4b3f2017-04-27 02:08:52 -07001659 send_codec_spec =
1660 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>(
1661 {voice_codec.id, format});
1662 if (voice_codec.bitrate > 0) {
1663 send_codec_spec->target_bitrate_bps =
1664 rtc::Optional<int>(voice_codec.bitrate);
1665 }
1666 send_codec_spec->transport_cc_enabled = HasTransportCc(voice_codec);
1667 send_codec_spec->nack_enabled = HasNack(voice_codec);
1668 bitrate_config = GetBitrateConfigForCodec(voice_codec);
1669 break;
1670 }
1671 }
1672
1673 if (!send_codec_spec) {
1674 return false;
1675 }
1676
1677 RTC_DCHECK(voice_codec_info);
1678 if (voice_codec_info->allow_comfort_noise) {
1679 // Loop through the codecs list again to find the CN codec.
1680 // TODO(solenberg): Break out into a separate function?
1681 for (const AudioCodec& cn_codec : codecs) {
ossu0c4b8492017-03-02 11:03:25 -08001682 if (IsCodec(cn_codec, kCnCodecName) &&
ossu20a4b3f2017-04-27 02:08:52 -07001683 cn_codec.clockrate == send_codec_spec->format.clockrate_hz) {
ossu0c4b8492017-03-02 11:03:25 -08001684 switch (cn_codec.clockrate) {
solenberg72e29d22016-03-08 06:35:16 -08001685 case 8000:
1686 case 16000:
1687 case 32000:
ossu20a4b3f2017-04-27 02:08:52 -07001688 send_codec_spec->cng_payload_type = rtc::Optional<int>(cn_codec.id);
solenberg72e29d22016-03-08 06:35:16 -08001689 break;
1690 default:
ossu0c4b8492017-03-02 11:03:25 -08001691 LOG(LS_WARNING) << "CN frequency " << cn_codec.clockrate
solenberg72e29d22016-03-08 06:35:16 -08001692 << " not supported.";
ossu20a4b3f2017-04-27 02:08:52 -07001693 break;
solenberg72e29d22016-03-08 06:35:16 -08001694 }
solenberg72e29d22016-03-08 06:35:16 -08001695 break;
1696 }
1697 }
solenbergffbbcac2016-11-17 05:25:37 -08001698
1699 // Find the telephone-event PT exactly matching the preferred send codec.
1700 for (const AudioCodec& dtmf_codec : dtmf_codecs) {
ossu20a4b3f2017-04-27 02:08:52 -07001701 if (dtmf_codec.clockrate == send_codec_spec->format.clockrate_hz) {
solenbergffbbcac2016-11-17 05:25:37 -08001702 dtmf_payload_type_ = rtc::Optional<int>(dtmf_codec.id);
1703 dtmf_payload_freq_ = dtmf_codec.clockrate;
1704 break;
1705 }
1706 }
solenberg72e29d22016-03-08 06:35:16 -08001707 }
1708
solenberg971cab02016-06-14 10:02:41 -07001709 if (send_codec_spec_ != send_codec_spec) {
1710 send_codec_spec_ = std::move(send_codec_spec);
stefan13f1a0a2016-11-30 07:22:58 -08001711 // Apply new settings to all streams.
solenberg971cab02016-06-14 10:02:41 -07001712 for (const auto& kv : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001713 kv.second->SetSendCodecSpec(*send_codec_spec_);
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001714 }
stefan13f1a0a2016-11-30 07:22:58 -08001715 } else {
1716 // If the codec isn't changing, set the start bitrate to -1 which means
1717 // "unchanged" so that BWE isn't affected.
stefan1ccf73f2017-03-27 03:51:18 -07001718 bitrate_config.start_bitrate_bps = -1;
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001719 }
stefan1ccf73f2017-03-27 03:51:18 -07001720 call_->SetBitrateConfig(bitrate_config);
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001721
solenberg8189b022016-06-14 12:13:00 -07001722 // Check if the transport cc feedback or NACK status has changed on the
1723 // preferred send codec, and in that case reconfigure all receive streams.
ossu20a4b3f2017-04-27 02:08:52 -07001724 if (recv_transport_cc_enabled_ != send_codec_spec_->transport_cc_enabled ||
1725 recv_nack_enabled_ != send_codec_spec_->nack_enabled) {
solenberg72e29d22016-03-08 06:35:16 -08001726 LOG(LS_INFO) << "Recreate all the receive streams because the send "
1727 "codec has changed.";
ossu20a4b3f2017-04-27 02:08:52 -07001728 recv_transport_cc_enabled_ = send_codec_spec_->transport_cc_enabled;
1729 recv_nack_enabled_ = send_codec_spec_->nack_enabled;
solenberg72e29d22016-03-08 06:35:16 -08001730 for (auto& kv : recv_streams_) {
solenberg8189b022016-06-14 12:13:00 -07001731 kv.second->RecreateAudioReceiveStream(recv_transport_cc_enabled_,
1732 recv_nack_enabled_);
solenberg72e29d22016-03-08 06:35:16 -08001733 }
1734 }
1735
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001736 send_codecs_ = codecs;
solenberg72e29d22016-03-08 06:35:16 -08001737 return true;
1738}
1739
aleloi84ef6152016-08-04 05:28:21 -07001740void WebRtcVoiceMediaChannel::SetPlayout(bool playout) {
kwiberg37b8b112016-11-03 02:46:53 -07001741 desired_playout_ = playout;
1742 return ChangePlayout(desired_playout_);
1743}
1744
1745void WebRtcVoiceMediaChannel::ChangePlayout(bool playout) {
1746 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::ChangePlayout");
solenberg566ef242015-11-06 15:34:49 -08001747 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001748 if (playout_ == playout) {
aleloi84ef6152016-08-04 05:28:21 -07001749 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001750 }
1751
aleloi84ef6152016-08-04 05:28:21 -07001752 for (const auto& kv : recv_streams_) {
1753 kv.second->SetPlayout(playout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001754 }
solenberg1ac56142015-10-13 03:58:19 -07001755 playout_ = playout;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001756}
1757
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001758void WebRtcVoiceMediaChannel::SetSend(bool send) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001759 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetSend");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001760 if (send_ == send) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001761 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001762 }
1763
solenbergd53a3f92016-04-14 13:56:37 -07001764 // Apply channel specific options, and initialize the ADM for recording (this
1765 // may take time on some platforms, e.g. Android).
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001766 if (send) {
solenberg63b34542015-09-29 06:06:31 -07001767 engine()->ApplyOptions(options_);
solenbergd53a3f92016-04-14 13:56:37 -07001768
1769 // InitRecording() may return an error if the ADM is already recording.
1770 if (!engine()->adm()->RecordingIsInitialized() &&
1771 !engine()->adm()->Recording()) {
1772 if (engine()->adm()->InitRecording() != 0) {
1773 LOG(LS_WARNING) << "Failed to initialize recording";
1774 }
1775 }
solenberg63b34542015-09-29 06:06:31 -07001776 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001777
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001778 // Change the settings on each send channel.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001779 for (auto& kv : send_streams_) {
1780 kv.second->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001781 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001782
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001783 send_ = send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001784}
1785
Peter Boström0c4e06b2015-10-07 12:23:21 +02001786bool WebRtcVoiceMediaChannel::SetAudioSend(uint32_t ssrc,
1787 bool enable,
solenberg1dd98f32015-09-10 01:57:14 -07001788 const AudioOptions* options,
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001789 AudioSource* source) {
solenberg566ef242015-11-06 15:34:49 -08001790 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg1dd98f32015-09-10 01:57:14 -07001791 // TODO(solenberg): The state change should be fully rolled back if any one of
1792 // these calls fail.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001793 if (!SetLocalSource(ssrc, source)) {
solenberg1dd98f32015-09-10 01:57:14 -07001794 return false;
1795 }
solenbergdfc8f4f2015-10-01 02:31:10 -07001796 if (!MuteStream(ssrc, !enable)) {
solenberg1dd98f32015-09-10 01:57:14 -07001797 return false;
1798 }
solenbergdfc8f4f2015-10-01 02:31:10 -07001799 if (enable && options) {
solenberg1dd98f32015-09-10 01:57:14 -07001800 return SetOptions(*options);
1801 }
1802 return true;
1803}
1804
solenberg0a617e22015-10-20 15:49:38 -07001805int WebRtcVoiceMediaChannel::CreateVoEChannel() {
1806 int id = engine()->CreateVoEChannel();
1807 if (id == -1) {
1808 LOG_RTCERR0(CreateVoEChannel);
1809 return -1;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001810 }
mflodman3d7db262016-04-29 00:57:13 -07001811
solenberg0a617e22015-10-20 15:49:38 -07001812 return id;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001813}
1814
solenberg7add0582015-11-20 09:59:34 -08001815bool WebRtcVoiceMediaChannel::DeleteVoEChannel(int channel) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001816 if (engine()->voe()->base()->DeleteChannel(channel) == -1) {
1817 LOG_RTCERR1(DeleteChannel, channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001818 return false;
1819 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001820 return true;
1821}
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001822
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001823bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001824 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::AddSendStream");
solenberg566ef242015-11-06 15:34:49 -08001825 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg0a617e22015-10-20 15:49:38 -07001826 LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
1827
1828 uint32_t ssrc = sp.first_ssrc();
1829 RTC_DCHECK(0 != ssrc);
1830
1831 if (GetSendChannelId(ssrc) != -1) {
1832 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001833 return false;
1834 }
1835
solenberg0a617e22015-10-20 15:49:38 -07001836 // Create a new channel for sending audio data.
1837 int channel = CreateVoEChannel();
1838 if (channel == -1) {
1839 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001840 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001841
solenbergc96df772015-10-21 13:01:53 -07001842 // Save the channel to send_streams_, so that RemoveSendStream() can still
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001843 // delete the channel in case failure happens below.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001844 webrtc::AudioTransport* audio_transport =
1845 engine()->voe()->base()->audio_transport();
mflodman3d7db262016-04-29 00:57:13 -07001846
minyue6b825df2016-10-31 04:08:32 -07001847 rtc::Optional<std::string> audio_network_adaptor_config =
1848 GetAudioNetworkAdaptorConfig(options_);
skvlade0d46372016-04-07 22:59:22 -07001849 WebRtcAudioSendStream* stream = new WebRtcAudioSendStream(
solenberg971cab02016-06-14 10:02:41 -07001850 channel, audio_transport, ssrc, sp.cname, send_codec_spec_,
minyue6b825df2016-10-31 04:08:32 -07001851 send_rtp_extensions_, max_send_bitrate_bps_, audio_network_adaptor_config,
ossu20a4b3f2017-04-27 02:08:52 -07001852 call_, this, engine()->encoder_factory_);
skvlade0d46372016-04-07 22:59:22 -07001853 send_streams_.insert(std::make_pair(ssrc, stream));
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001854
solenberg4a0f7b52016-06-16 13:07:33 -07001855 // At this point the stream's local SSRC has been updated. If it is the first
1856 // send stream, make sure that all the receive streams are updated with the
1857 // same SSRC in order to send receiver reports.
solenbergc96df772015-10-21 13:01:53 -07001858 if (send_streams_.size() == 1) {
solenberg0a617e22015-10-20 15:49:38 -07001859 receiver_reports_ssrc_ = ssrc;
solenberg4a0f7b52016-06-16 13:07:33 -07001860 for (const auto& kv : recv_streams_) {
1861 // TODO(solenberg): Allow applications to set the RTCP SSRC of receive
1862 // streams instead, so we can avoid recreating the streams here.
1863 kv.second->RecreateAudioReceiveStream(ssrc);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001864 }
1865 }
1866
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001867 send_streams_[ssrc]->SetSend(send_);
1868 return true;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001869}
1870
Peter Boström0c4e06b2015-10-07 12:23:21 +02001871bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001872 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::RemoveSendStream");
solenberg566ef242015-11-06 15:34:49 -08001873 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg3a941542015-11-16 07:34:50 -08001874 LOG(LS_INFO) << "RemoveSendStream: " << ssrc;
1875
solenbergc96df772015-10-21 13:01:53 -07001876 auto it = send_streams_.find(ssrc);
1877 if (it == send_streams_.end()) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001878 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
1879 << " which doesn't exist.";
1880 return false;
1881 }
1882
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001883 it->second->SetSend(false);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001884
solenberg7602aab2016-11-14 11:30:07 -08001885 // TODO(solenberg): If we're removing the receiver_reports_ssrc_ stream, find
1886 // the first active send stream and use that instead, reassociating receive
1887 // streams.
1888
solenberg7add0582015-11-20 09:59:34 -08001889 // Clean up and delete the send stream+channel.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001890 int channel = it->second->channel();
solenberg0a617e22015-10-20 15:49:38 -07001891 LOG(LS_INFO) << "Removing audio send stream " << ssrc
1892 << " with VoiceEngine channel #" << channel << ".";
solenberg7add0582015-11-20 09:59:34 -08001893 delete it->second;
1894 send_streams_.erase(it);
1895 if (!DeleteVoEChannel(channel)) {
solenberg0a617e22015-10-20 15:49:38 -07001896 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001897 }
solenbergc96df772015-10-21 13:01:53 -07001898 if (send_streams_.empty()) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001899 SetSend(false);
solenberg0a617e22015-10-20 15:49:38 -07001900 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001901 return true;
1902}
1903
1904bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001905 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::AddRecvStream");
solenberg566ef242015-11-06 15:34:49 -08001906 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergd97ec302015-10-07 01:40:33 -07001907 LOG(LS_INFO) << "AddRecvStream: " << sp.ToString();
1908
solenberg0b675462015-10-09 01:37:09 -07001909 if (!ValidateStreamParams(sp)) {
wu@webrtc.org78187522013-10-07 23:32:02 +00001910 return false;
1911 }
1912
solenberg7add0582015-11-20 09:59:34 -08001913 const uint32_t ssrc = sp.first_ssrc();
solenberg0b675462015-10-09 01:37:09 -07001914 if (ssrc == 0) {
1915 LOG(LS_WARNING) << "AddRecvStream with ssrc==0 is not supported.";
1916 return false;
1917 }
1918
solenberg2100c0b2017-03-01 11:29:29 -08001919 // If this stream was previously received unsignaled, we promote it, possibly
1920 // recreating the AudioReceiveStream, if sync_label has changed.
1921 if (MaybeDeregisterUnsignaledRecvStream(ssrc)) {
solenberg4904fb62017-02-17 12:01:14 -08001922 recv_streams_[ssrc]->MaybeRecreateAudioReceiveStream(sp.sync_label);
solenberg4904fb62017-02-17 12:01:14 -08001923 return true;
solenberg1ac56142015-10-13 03:58:19 -07001924 }
solenberg0b675462015-10-09 01:37:09 -07001925
solenberg7add0582015-11-20 09:59:34 -08001926 if (GetReceiveChannelId(ssrc) != -1) {
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001927 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001928 return false;
1929 }
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02001930
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001931 // Create a new channel for receiving audio data.
solenberg7add0582015-11-20 09:59:34 -08001932 const int channel = CreateVoEChannel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001933 if (channel == -1) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001934 return false;
1935 }
Minyue2013aec2015-05-13 14:14:42 +02001936
stefanba4c0e42016-02-04 04:12:24 -08001937 recv_streams_.insert(std::make_pair(
kwiberg1c07c702017-03-27 07:15:49 -07001938 ssrc,
1939 new WebRtcAudioReceiveStream(
1940 channel, ssrc, receiver_reports_ssrc_, recv_transport_cc_enabled_,
1941 recv_nack_enabled_, sp.sync_label, recv_rtp_extensions_, call_, this,
1942 engine()->decoder_factory_, decoder_map_)));
aleloi84ef6152016-08-04 05:28:21 -07001943 recv_streams_[ssrc]->SetPlayout(playout_);
solenberg7add0582015-11-20 09:59:34 -08001944
solenberg1ac56142015-10-13 03:58:19 -07001945 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001946}
1947
Peter Boström0c4e06b2015-10-07 12:23:21 +02001948bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001949 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::RemoveRecvStream");
solenberg566ef242015-11-06 15:34:49 -08001950 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergd97ec302015-10-07 01:40:33 -07001951 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
1952
solenberg7add0582015-11-20 09:59:34 -08001953 const auto it = recv_streams_.find(ssrc);
1954 if (it == recv_streams_.end()) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001955 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
1956 << " which doesn't exist.";
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001957 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001958 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001959
solenberg2100c0b2017-03-01 11:29:29 -08001960 MaybeDeregisterUnsignaledRecvStream(ssrc);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001961
solenberg7add0582015-11-20 09:59:34 -08001962 const int channel = it->second->channel();
1963
1964 // Clean up and delete the receive stream+channel.
1965 LOG(LS_INFO) << "Removing audio receive stream " << ssrc
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001966 << " with VoiceEngine channel #" << channel << ".";
Tommif888bb52015-12-12 01:37:01 +01001967 it->second->SetRawAudioSink(nullptr);
solenberg7add0582015-11-20 09:59:34 -08001968 delete it->second;
1969 recv_streams_.erase(it);
1970 return DeleteVoEChannel(channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001971}
1972
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001973bool WebRtcVoiceMediaChannel::SetLocalSource(uint32_t ssrc,
1974 AudioSource* source) {
solenbergc96df772015-10-21 13:01:53 -07001975 auto it = send_streams_.find(ssrc);
1976 if (it == send_streams_.end()) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001977 if (source) {
1978 // Return an error if trying to set a valid source with an invalid ssrc.
1979 LOG(LS_ERROR) << "SetLocalSource failed with ssrc " << ssrc;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001980 return false;
1981 }
1982
1983 // The channel likely has gone away, do nothing.
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001984 return true;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001985 }
1986
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001987 if (source) {
1988 it->second->SetSource(source);
solenberg1ac56142015-10-13 03:58:19 -07001989 } else {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001990 it->second->ClearSource();
solenberg1ac56142015-10-13 03:58:19 -07001991 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001992
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001993 return true;
1994}
1995
solenberg796b8f92017-03-01 17:02:23 -08001996// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001997bool WebRtcVoiceMediaChannel::GetActiveStreams(
1998 AudioInfo::StreamList* actives) {
solenberg566ef242015-11-06 15:34:49 -08001999 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002000 actives->clear();
solenberg7add0582015-11-20 09:59:34 -08002001 for (const auto& ch : recv_streams_) {
solenberg796b8f92017-03-01 17:02:23 -08002002 int level = ch.second->GetOutputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002003 if (level > 0) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02002004 actives->push_back(std::make_pair(ch.first, level));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002005 }
2006 }
2007 return true;
2008}
2009
solenberg796b8f92017-03-01 17:02:23 -08002010// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002011int WebRtcVoiceMediaChannel::GetOutputLevel() {
solenberg566ef242015-11-06 15:34:49 -08002012 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg1ac56142015-10-13 03:58:19 -07002013 int highest = 0;
solenberg7add0582015-11-20 09:59:34 -08002014 for (const auto& ch : recv_streams_) {
solenberg796b8f92017-03-01 17:02:23 -08002015 highest = std::max(ch.second->GetOutputLevel(), highest);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002016 }
2017 return highest;
2018}
2019
solenberg4bac9c52015-10-09 02:32:53 -07002020bool WebRtcVoiceMediaChannel::SetOutputVolume(uint32_t ssrc, double volume) {
solenberg566ef242015-11-06 15:34:49 -08002021 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg2100c0b2017-03-01 11:29:29 -08002022 std::vector<uint32_t> ssrcs(1, ssrc);
deadbeef3bc15102017-04-20 19:25:07 -07002023 // SSRC of 0 represents the default receive stream.
solenberg1ac56142015-10-13 03:58:19 -07002024 if (ssrc == 0) {
2025 default_recv_volume_ = volume;
solenberg2100c0b2017-03-01 11:29:29 -08002026 ssrcs = unsignaled_recv_ssrcs_;
2027 }
2028 for (uint32_t ssrc : ssrcs) {
2029 const auto it = recv_streams_.find(ssrc);
2030 if (it == recv_streams_.end()) {
2031 LOG(LS_WARNING) << "SetOutputVolume: no recv stream " << ssrc;
2032 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002033 }
solenberg2100c0b2017-03-01 11:29:29 -08002034 it->second->SetOutputVolume(volume);
2035 LOG(LS_INFO) << "SetOutputVolume() to " << volume
2036 << " for recv stream with ssrc " << ssrc;
solenberg1ac56142015-10-13 03:58:19 -07002037 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002038 return true;
2039}
2040
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002041bool WebRtcVoiceMediaChannel::CanInsertDtmf() {
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002042 return dtmf_payload_type_ ? true : false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002043}
2044
solenberg1d63dd02015-12-02 12:35:09 -08002045bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, int event,
2046 int duration) {
solenberg566ef242015-11-06 15:34:49 -08002047 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002048 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::InsertDtmf";
2049 if (!dtmf_payload_type_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002050 return false;
2051 }
2052
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002053 // Figure out which WebRtcAudioSendStream to send the event on.
2054 auto it = ssrc != 0 ? send_streams_.find(ssrc) : send_streams_.begin();
2055 if (it == send_streams_.end()) {
2056 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
solenberg1d63dd02015-12-02 12:35:09 -08002057 return false;
2058 }
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002059 if (event < kMinTelephoneEventCode ||
2060 event > kMaxTelephoneEventCode) {
2061 LOG(LS_WARNING) << "DTMF event code " << event << " out of range.";
solenberg1d63dd02015-12-02 12:35:09 -08002062 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002063 }
solenbergffbbcac2016-11-17 05:25:37 -08002064 RTC_DCHECK_NE(-1, dtmf_payload_freq_);
2065 return it->second->SendTelephoneEvent(*dtmf_payload_type_, dtmf_payload_freq_,
2066 event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002067}
2068
wu@webrtc.orga9890802013-12-13 00:21:03 +00002069void WebRtcVoiceMediaChannel::OnPacketReceived(
jbaucheec21bd2016-03-20 06:15:43 -07002070 rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
solenberg566ef242015-11-06 15:34:49 -08002071 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02002072
mflodman3d7db262016-04-29 00:57:13 -07002073 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
2074 packet_time.not_before);
2075 webrtc::PacketReceiver::DeliveryStatus delivery_result =
2076 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
2077 packet->cdata(), packet->size(),
2078 webrtc_packet_time);
mflodman3d7db262016-04-29 00:57:13 -07002079 if (delivery_result != webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC) {
2080 return;
2081 }
2082
solenberg2100c0b2017-03-01 11:29:29 -08002083 // Create an unsignaled receive stream for this previously not received ssrc.
2084 // If there already is N unsignaled receive streams, delete the oldest.
mflodman3d7db262016-04-29 00:57:13 -07002085 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5208
solenberg1ac56142015-10-13 03:58:19 -07002086 uint32_t ssrc = 0;
jbaucheec21bd2016-03-20 06:15:43 -07002087 if (!GetRtpSsrc(packet->cdata(), packet->size(), &ssrc)) {
solenberg1ac56142015-10-13 03:58:19 -07002088 return;
2089 }
solenberg2100c0b2017-03-01 11:29:29 -08002090 RTC_DCHECK(std::find(unsignaled_recv_ssrcs_.begin(),
2091 unsignaled_recv_ssrcs_.end(), ssrc) == unsignaled_recv_ssrcs_.end());
solenberg1ac56142015-10-13 03:58:19 -07002092
solenberg2100c0b2017-03-01 11:29:29 -08002093 // Add new stream.
mflodman3d7db262016-04-29 00:57:13 -07002094 StreamParams sp;
2095 sp.ssrcs.push_back(ssrc);
solenberg2100c0b2017-03-01 11:29:29 -08002096 LOG(LS_INFO) << "Creating unsignaled receive stream for SSRC=" << ssrc;
mflodman3d7db262016-04-29 00:57:13 -07002097 if (!AddRecvStream(sp)) {
solenberg2100c0b2017-03-01 11:29:29 -08002098 LOG(LS_WARNING) << "Could not create unsignaled receive stream.";
mflodman3d7db262016-04-29 00:57:13 -07002099 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002100 }
solenberg2100c0b2017-03-01 11:29:29 -08002101 unsignaled_recv_ssrcs_.push_back(ssrc);
2102 RTC_HISTOGRAM_COUNTS_LINEAR(
2103 "WebRTC.Audio.NumOfUnsignaledStreams", unsignaled_recv_ssrcs_.size(), 1,
2104 100, 101);
solenbergf748ca42017-02-06 13:03:19 -08002105
solenberg2100c0b2017-03-01 11:29:29 -08002106 // Remove oldest unsignaled stream, if we have too many.
2107 if (unsignaled_recv_ssrcs_.size() > kMaxUnsignaledRecvStreams) {
2108 uint32_t remove_ssrc = unsignaled_recv_ssrcs_.front();
2109 LOG(LS_INFO) << "Removing unsignaled receive stream with SSRC="
2110 << remove_ssrc;
2111 RemoveRecvStream(remove_ssrc);
2112 }
2113 RTC_DCHECK_GE(kMaxUnsignaledRecvStreams, unsignaled_recv_ssrcs_.size());
2114
2115 SetOutputVolume(ssrc, default_recv_volume_);
2116
2117 // The default sink can only be attached to one stream at a time, so we hook
2118 // it up to the *latest* unsignaled stream we've seen, in order to support the
2119 // case where the SSRC of one unsignaled stream changes.
mflodman3d7db262016-04-29 00:57:13 -07002120 if (default_sink_) {
solenberg2100c0b2017-03-01 11:29:29 -08002121 for (uint32_t drop_ssrc : unsignaled_recv_ssrcs_) {
2122 auto it = recv_streams_.find(drop_ssrc);
2123 it->second->SetRawAudioSink(nullptr);
2124 }
mflodman3d7db262016-04-29 00:57:13 -07002125 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
2126 new ProxySink(default_sink_.get()));
solenberg2100c0b2017-03-01 11:29:29 -08002127 SetRawAudioSink(ssrc, std::move(proxy_sink));
mflodman3d7db262016-04-29 00:57:13 -07002128 }
solenberg2100c0b2017-03-01 11:29:29 -08002129
mflodman3d7db262016-04-29 00:57:13 -07002130 delivery_result = call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
2131 packet->cdata(),
2132 packet->size(),
2133 webrtc_packet_time);
2134 RTC_DCHECK_NE(webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC, delivery_result);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002135}
2136
wu@webrtc.orga9890802013-12-13 00:21:03 +00002137void WebRtcVoiceMediaChannel::OnRtcpReceived(
jbaucheec21bd2016-03-20 06:15:43 -07002138 rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
solenberg566ef242015-11-06 15:34:49 -08002139 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02002140
Fredrik Solenberg709ed672015-09-15 12:26:33 +02002141 // Forward packet to Call as well.
2142 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
2143 packet_time.not_before);
2144 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
jbaucheec21bd2016-03-20 06:15:43 -07002145 packet->cdata(), packet->size(), webrtc_packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002146}
2147
Honghai Zhangcc411c02016-03-29 17:27:21 -07002148void WebRtcVoiceMediaChannel::OnNetworkRouteChanged(
2149 const std::string& transport_name,
Honghai Zhang0e533ef2016-04-19 15:41:36 -07002150 const rtc::NetworkRoute& network_route) {
2151 call_->OnNetworkRouteChanged(transport_name, network_route);
Honghai Zhangcc411c02016-03-29 17:27:21 -07002152}
2153
Peter Boström0c4e06b2015-10-07 12:23:21 +02002154bool WebRtcVoiceMediaChannel::MuteStream(uint32_t ssrc, bool muted) {
solenberg566ef242015-11-06 15:34:49 -08002155 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg94218532016-06-16 10:53:22 -07002156 const auto it = send_streams_.find(ssrc);
2157 if (it == send_streams_.end()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002158 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
2159 return false;
2160 }
solenberg94218532016-06-16 10:53:22 -07002161 it->second->SetMuted(muted);
2162
2163 // TODO(solenberg):
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002164 // We set the AGC to mute state only when all the channels are muted.
2165 // This implementation is not ideal, instead we should signal the AGC when
2166 // the mic channel is muted/unmuted. We can't do it today because there
2167 // is no good way to know which stream is mapping to the mic channel.
2168 bool all_muted = muted;
solenberg94218532016-06-16 10:53:22 -07002169 for (const auto& kv : send_streams_) {
2170 all_muted = all_muted && kv.second->muted();
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002171 }
solenberg059fb442016-10-26 05:12:24 -07002172 engine()->apm()->set_output_will_be_muted(all_muted);
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002173
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002174 return true;
2175}
2176
deadbeef80346142016-04-27 14:17:10 -07002177bool WebRtcVoiceMediaChannel::SetMaxSendBitrate(int bps) {
2178 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetMaxSendBitrate.";
2179 max_send_bitrate_bps_ = bps;
minyue7a973442016-10-20 03:27:12 -07002180 bool success = true;
skvlade0d46372016-04-07 22:59:22 -07002181 for (const auto& kv : send_streams_) {
minyue7a973442016-10-20 03:27:12 -07002182 if (!kv.second->SetMaxSendBitrate(max_send_bitrate_bps_)) {
2183 success = false;
skvlade0d46372016-04-07 22:59:22 -07002184 }
2185 }
minyue7a973442016-10-20 03:27:12 -07002186 return success;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002187}
2188
skvlad7a43d252016-03-22 15:32:27 -07002189void WebRtcVoiceMediaChannel::OnReadyToSend(bool ready) {
2190 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2191 LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
2192 call_->SignalChannelNetworkState(
2193 webrtc::MediaType::AUDIO,
2194 ready ? webrtc::kNetworkUp : webrtc::kNetworkDown);
2195}
2196
michaelt79e05882016-11-08 02:50:09 -08002197void WebRtcVoiceMediaChannel::OnTransportOverheadChanged(
2198 int transport_overhead_per_packet) {
2199 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2200 call_->OnTransportOverheadChanged(webrtc::MediaType::AUDIO,
2201 transport_overhead_per_packet);
2202}
2203
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002204bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
Peter Boströmca8b4042016-03-08 14:24:13 -08002205 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::GetStats");
solenberg566ef242015-11-06 15:34:49 -08002206 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg85a04962015-10-27 03:35:21 -07002207 RTC_DCHECK(info);
solenbergd97ec302015-10-07 01:40:33 -07002208
solenberg85a04962015-10-27 03:35:21 -07002209 // Get SSRC and stats for each sender.
hbos1acfbd22016-11-17 23:43:29 -08002210 RTC_DCHECK_EQ(info->senders.size(), 0U);
solenberg85a04962015-10-27 03:35:21 -07002211 for (const auto& stream : send_streams_) {
2212 webrtc::AudioSendStream::Stats stats = stream.second->GetStats();
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002213 VoiceSenderInfo sinfo;
solenberg85a04962015-10-27 03:35:21 -07002214 sinfo.add_ssrc(stats.local_ssrc);
2215 sinfo.bytes_sent = stats.bytes_sent;
2216 sinfo.packets_sent = stats.packets_sent;
2217 sinfo.packets_lost = stats.packets_lost;
2218 sinfo.fraction_lost = stats.fraction_lost;
2219 sinfo.codec_name = stats.codec_name;
hbos1acfbd22016-11-17 23:43:29 -08002220 sinfo.codec_payload_type = stats.codec_payload_type;
solenberg85a04962015-10-27 03:35:21 -07002221 sinfo.ext_seqnum = stats.ext_seqnum;
2222 sinfo.jitter_ms = stats.jitter_ms;
2223 sinfo.rtt_ms = stats.rtt_ms;
2224 sinfo.audio_level = stats.audio_level;
2225 sinfo.aec_quality_min = stats.aec_quality_min;
2226 sinfo.echo_delay_median_ms = stats.echo_delay_median_ms;
2227 sinfo.echo_delay_std_ms = stats.echo_delay_std_ms;
2228 sinfo.echo_return_loss = stats.echo_return_loss;
2229 sinfo.echo_return_loss_enhancement = stats.echo_return_loss_enhancement;
ivoc8c63a822016-10-21 04:10:03 -07002230 sinfo.residual_echo_likelihood = stats.residual_echo_likelihood;
ivoc4e477a12017-01-15 08:29:46 -08002231 sinfo.residual_echo_likelihood_recent_max =
2232 stats.residual_echo_likelihood_recent_max;
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002233 sinfo.typing_noise_detected = (send_ ? stats.typing_noise_detected : false);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002234 info->senders.push_back(sinfo);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002235 }
2236
solenberg85a04962015-10-27 03:35:21 -07002237 // Get SSRC and stats for each receiver.
hbos1acfbd22016-11-17 23:43:29 -08002238 RTC_DCHECK_EQ(info->receivers.size(), 0U);
solenberg7add0582015-11-20 09:59:34 -08002239 for (const auto& stream : recv_streams_) {
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002240 webrtc::AudioReceiveStream::Stats stats = stream.second->GetStats();
2241 VoiceReceiverInfo rinfo;
2242 rinfo.add_ssrc(stats.remote_ssrc);
2243 rinfo.bytes_rcvd = stats.bytes_rcvd;
2244 rinfo.packets_rcvd = stats.packets_rcvd;
2245 rinfo.packets_lost = stats.packets_lost;
2246 rinfo.fraction_lost = stats.fraction_lost;
2247 rinfo.codec_name = stats.codec_name;
hbos1acfbd22016-11-17 23:43:29 -08002248 rinfo.codec_payload_type = stats.codec_payload_type;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002249 rinfo.ext_seqnum = stats.ext_seqnum;
2250 rinfo.jitter_ms = stats.jitter_ms;
2251 rinfo.jitter_buffer_ms = stats.jitter_buffer_ms;
2252 rinfo.jitter_buffer_preferred_ms = stats.jitter_buffer_preferred_ms;
2253 rinfo.delay_estimate_ms = stats.delay_estimate_ms;
2254 rinfo.audio_level = stats.audio_level;
2255 rinfo.expand_rate = stats.expand_rate;
2256 rinfo.speech_expand_rate = stats.speech_expand_rate;
2257 rinfo.secondary_decoded_rate = stats.secondary_decoded_rate;
2258 rinfo.accelerate_rate = stats.accelerate_rate;
2259 rinfo.preemptive_expand_rate = stats.preemptive_expand_rate;
2260 rinfo.decoding_calls_to_silence_generator =
2261 stats.decoding_calls_to_silence_generator;
2262 rinfo.decoding_calls_to_neteq = stats.decoding_calls_to_neteq;
2263 rinfo.decoding_normal = stats.decoding_normal;
2264 rinfo.decoding_plc = stats.decoding_plc;
2265 rinfo.decoding_cng = stats.decoding_cng;
2266 rinfo.decoding_plc_cng = stats.decoding_plc_cng;
henrik.lundin63489782016-09-20 01:47:12 -07002267 rinfo.decoding_muted_output = stats.decoding_muted_output;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002268 rinfo.capture_start_ntp_time_ms = stats.capture_start_ntp_time_ms;
2269 info->receivers.push_back(rinfo);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002270 }
2271
hbos1acfbd22016-11-17 23:43:29 -08002272 // Get codec info
2273 for (const AudioCodec& codec : send_codecs_) {
2274 webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
2275 info->send_codecs.insert(
2276 std::make_pair(codec_params.payload_type, std::move(codec_params)));
2277 }
2278 for (const AudioCodec& codec : recv_codecs_) {
2279 webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
2280 info->receive_codecs.insert(
2281 std::make_pair(codec_params.payload_type, std::move(codec_params)));
2282 }
2283
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002284 return true;
2285}
2286
Tommif888bb52015-12-12 01:37:01 +01002287void WebRtcVoiceMediaChannel::SetRawAudioSink(
2288 uint32_t ssrc,
kwiberg686a8ef2016-02-26 03:00:35 -08002289 std::unique_ptr<webrtc::AudioSinkInterface> sink) {
Tommif888bb52015-12-12 01:37:01 +01002290 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef884f5852016-01-15 09:20:04 -08002291 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::SetRawAudioSink: ssrc:" << ssrc
2292 << " " << (sink ? "(ptr)" : "NULL");
2293 if (ssrc == 0) {
solenberg2100c0b2017-03-01 11:29:29 -08002294 if (!unsignaled_recv_ssrcs_.empty()) {
kwiberg686a8ef2016-02-26 03:00:35 -08002295 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
deadbeef884f5852016-01-15 09:20:04 -08002296 sink ? new ProxySink(sink.get()) : nullptr);
solenberg2100c0b2017-03-01 11:29:29 -08002297 SetRawAudioSink(unsignaled_recv_ssrcs_.back(), std::move(proxy_sink));
deadbeef884f5852016-01-15 09:20:04 -08002298 }
2299 default_sink_ = std::move(sink);
2300 return;
2301 }
Tommif888bb52015-12-12 01:37:01 +01002302 const auto it = recv_streams_.find(ssrc);
2303 if (it == recv_streams_.end()) {
solenberg2100c0b2017-03-01 11:29:29 -08002304 LOG(LS_WARNING) << "SetRawAudioSink: no recv stream " << ssrc;
Tommif888bb52015-12-12 01:37:01 +01002305 return;
2306 }
deadbeef2d110be2016-01-13 12:00:26 -08002307 it->second->SetRawAudioSink(std::move(sink));
Tommif888bb52015-12-12 01:37:01 +01002308}
2309
hbos8d609f62017-04-10 07:39:05 -07002310std::vector<webrtc::RtpSource> WebRtcVoiceMediaChannel::GetSources(
2311 uint32_t ssrc) const {
2312 auto it = recv_streams_.find(ssrc);
2313 RTC_DCHECK(it != recv_streams_.end())
2314 << "Attempting to get contributing sources for SSRC:" << ssrc
2315 << " which doesn't exist.";
2316 return it->second->GetSources();
2317}
2318
Peter Boström0c4e06b2015-10-07 12:23:21 +02002319int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
solenberg566ef242015-11-06 15:34:49 -08002320 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7add0582015-11-20 09:59:34 -08002321 const auto it = recv_streams_.find(ssrc);
2322 if (it != recv_streams_.end()) {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002323 return it->second->channel();
solenberg8fb30c32015-10-13 03:06:58 -07002324 }
solenberg1ac56142015-10-13 03:58:19 -07002325 return -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002326}
2327
Peter Boström0c4e06b2015-10-07 12:23:21 +02002328int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const {
solenberg566ef242015-11-06 15:34:49 -08002329 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergc96df772015-10-21 13:01:53 -07002330 const auto it = send_streams_.find(ssrc);
2331 if (it != send_streams_.end()) {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002332 return it->second->channel();
solenberg8fb30c32015-10-13 03:06:58 -07002333 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002334 return -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002335}
solenberg2100c0b2017-03-01 11:29:29 -08002336
2337bool WebRtcVoiceMediaChannel::
2338 MaybeDeregisterUnsignaledRecvStream(uint32_t ssrc) {
2339 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2340 auto it = std::find(unsignaled_recv_ssrcs_.begin(),
2341 unsignaled_recv_ssrcs_.end(),
2342 ssrc);
2343 if (it != unsignaled_recv_ssrcs_.end()) {
2344 unsignaled_recv_ssrcs_.erase(it);
2345 return true;
2346 }
2347 return false;
2348}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002349} // namespace cricket
2350
2351#endif // HAVE_WEBRTC_VOICE