blob: 1f9794944ead90d562286e1ab8080b854629f466 [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,
peaha9cc40b2017-06-29 08:32:09 -0700166 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
167 rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing) {
solenberg566ef242015-11-06 15:34:49 -0800168 webrtc::AudioState::Config config;
169 config.voice_engine = voe_wrapper->engine();
gyzhou95aa9642016-12-13 14:06:26 -0800170 if (audio_mixer) {
171 config.audio_mixer = audio_mixer;
172 } else {
173 config.audio_mixer = webrtc::AudioMixerImpl::Create();
174 }
peaha9cc40b2017-06-29 08:32:09 -0700175 config.audio_processing = audio_processing;
solenberg566ef242015-11-06 15:34:49 -0800176 return config;
177}
178
deadbeefe702b302017-02-04 12:09:01 -0800179// |max_send_bitrate_bps| is the bitrate from "b=" in SDP.
180// |rtp_max_bitrate_bps| is the bitrate from RtpSender::SetParameters.
minyue7a973442016-10-20 03:27:12 -0700181rtc::Optional<int> ComputeSendBitrate(int max_send_bitrate_bps,
deadbeefe702b302017-02-04 12:09:01 -0800182 rtc::Optional<int> rtp_max_bitrate_bps,
ossu20a4b3f2017-04-27 02:08:52 -0700183 const webrtc::AudioCodecSpec& spec) {
deadbeefe702b302017-02-04 12:09:01 -0800184 // If application-configured bitrate is set, take minimum of that and SDP
185 // bitrate.
zsteina5e0df62017-06-14 11:41:48 -0700186 const int bps =
187 rtp_max_bitrate_bps
188 ? webrtc::MinPositive(max_send_bitrate_bps, *rtp_max_bitrate_bps)
189 : max_send_bitrate_bps;
minyue7a973442016-10-20 03:27:12 -0700190 if (bps <= 0) {
ossu20a4b3f2017-04-27 02:08:52 -0700191 return rtc::Optional<int>(spec.info.default_bitrate_bps);
solenberg971cab02016-06-14 10:02:41 -0700192 }
minyue7a973442016-10-20 03:27:12 -0700193
ossu20a4b3f2017-04-27 02:08:52 -0700194 if (bps < spec.info.min_bitrate_bps) {
minyue7a973442016-10-20 03:27:12 -0700195 // If codec is not multi-rate and |bps| is less than the fixed bitrate then
196 // fail. If codec is not multi-rate and |bps| exceeds or equal the fixed
197 // bitrate then ignore.
ossu20a4b3f2017-04-27 02:08:52 -0700198 LOG(LS_ERROR) << "Failed to set codec " << spec.format.name
minyue7a973442016-10-20 03:27:12 -0700199 << " to bitrate " << bps << " bps"
ossu20a4b3f2017-04-27 02:08:52 -0700200 << ", requires at least " << spec.info.min_bitrate_bps
201 << " bps.";
minyue7a973442016-10-20 03:27:12 -0700202 return rtc::Optional<int>();
solenberg971cab02016-06-14 10:02:41 -0700203 }
ossu20a4b3f2017-04-27 02:08:52 -0700204
205 if (spec.info.HasFixedBitrate()) {
206 return rtc::Optional<int>(spec.info.default_bitrate_bps);
207 } else {
208 // If codec is multi-rate then just set the bitrate.
209 return rtc::Optional<int>(std::min(bps, spec.info.max_bitrate_bps));
210 }
solenberg971cab02016-06-14 10:02:41 -0700211}
212
solenberg76377c52017-02-21 00:54:31 -0800213} // namespace
solenberg971cab02016-06-14 10:02:41 -0700214
ossu29b1a8d2016-06-13 07:34:51 -0700215WebRtcVoiceEngine::WebRtcVoiceEngine(
216 webrtc::AudioDeviceModule* adm,
ossueb1fde42017-05-02 06:46:30 -0700217 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -0800218 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
peaha9cc40b2017-06-29 08:32:09 -0700219 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
220 rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing)
ossueb1fde42017-05-02 06:46:30 -0700221 : WebRtcVoiceEngine(adm,
222 encoder_factory,
223 decoder_factory,
224 audio_mixer,
peaha9cc40b2017-06-29 08:32:09 -0700225 audio_processing,
deadbeefeb02c032017-06-15 08:29:25 -0700226 nullptr) {}
solenberg26c8c912015-11-27 04:00:25 -0800227
ossu29b1a8d2016-06-13 07:34:51 -0700228WebRtcVoiceEngine::WebRtcVoiceEngine(
229 webrtc::AudioDeviceModule* adm,
ossueb1fde42017-05-02 06:46:30 -0700230 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory,
ossu29b1a8d2016-06-13 07:34:51 -0700231 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
gyzhou95aa9642016-12-13 14:06:26 -0800232 rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
peaha9cc40b2017-06-29 08:32:09 -0700233 rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing,
ossu29b1a8d2016-06-13 07:34:51 -0700234 VoEWrapper* voe_wrapper)
deadbeefeb02c032017-06-15 08:29:25 -0700235 : adm_(adm),
ossueb1fde42017-05-02 06:46:30 -0700236 encoder_factory_(encoder_factory),
ossu20a4b3f2017-04-27 02:08:52 -0700237 decoder_factory_(decoder_factory),
deadbeefeb02c032017-06-15 08:29:25 -0700238 audio_mixer_(audio_mixer),
peaha9cc40b2017-06-29 08:32:09 -0700239 apm_(audio_processing),
ossu20a4b3f2017-04-27 02:08:52 -0700240 voe_wrapper_(voe_wrapper) {
deadbeefeb02c032017-06-15 08:29:25 -0700241 // This may be called from any thread, so detach thread checkers.
242 worker_thread_checker_.DetachFromThread();
solenberg26c8c912015-11-27 04:00:25 -0800243 signal_thread_checker_.DetachFromThread();
deadbeefeb02c032017-06-15 08:29:25 -0700244 LOG(LS_INFO) << "WebRtcVoiceEngine::WebRtcVoiceEngine";
245 RTC_DCHECK(decoder_factory);
246 RTC_DCHECK(encoder_factory);
peaha9cc40b2017-06-29 08:32:09 -0700247 RTC_DCHECK(audio_processing);
deadbeefeb02c032017-06-15 08:29:25 -0700248 // The rest of our initialization will happen in Init.
249}
250
251WebRtcVoiceEngine::~WebRtcVoiceEngine() {
252 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
253 LOG(LS_INFO) << "WebRtcVoiceEngine::~WebRtcVoiceEngine";
254 if (initialized_) {
255 StopAecDump();
256 voe_wrapper_->base()->Terminate();
257 webrtc::Trace::SetTraceCallback(nullptr);
258 }
259}
260
261void WebRtcVoiceEngine::Init() {
262 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
263 LOG(LS_INFO) << "WebRtcVoiceEngine::Init";
264
265 // TaskQueue expects to be created/destroyed on the same thread.
266 low_priority_worker_queue_.reset(
267 new rtc::TaskQueue("rtc-low-prio", rtc::TaskQueue::Priority::LOW));
268
269 // VoEWrapper needs to be created on the worker thread. It's expected to be
270 // null here unless it's being injected for testing.
271 if (!voe_wrapper_) {
272 voe_wrapper_.reset(new VoEWrapper());
273 }
solenberg26c8c912015-11-27 04:00:25 -0800274
ossueb1fde42017-05-02 06:46:30 -0700275 // Load our audio codec lists.
ossuc54071d2016-08-17 02:45:41 -0700276 LOG(LS_INFO) << "Supported send codecs in order of preference:";
ossu20a4b3f2017-04-27 02:08:52 -0700277 send_codecs_ = CollectCodecs(encoder_factory_->GetSupportedEncoders());
ossuc54071d2016-08-17 02:45:41 -0700278 for (const AudioCodec& codec : send_codecs_) {
279 LOG(LS_INFO) << ToString(codec);
280 }
281
282 LOG(LS_INFO) << "Supported recv codecs in order of preference:";
ossu20a4b3f2017-04-27 02:08:52 -0700283 recv_codecs_ = CollectCodecs(decoder_factory_->GetSupportedDecoders());
ossuc54071d2016-08-17 02:45:41 -0700284 for (const AudioCodec& codec : recv_codecs_) {
solenbergff976312016-03-30 23:28:51 -0700285 LOG(LS_INFO) << ToString(codec);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000286 }
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000287
solenberg88499ec2016-09-07 07:34:41 -0700288 channel_config_.enable_voice_pacing = true;
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000289
solenbergff976312016-03-30 23:28:51 -0700290 // Temporarily turn logging level up for the Init() call.
291 webrtc::Trace::SetTraceCallback(this);
solenbergbd138382015-11-20 16:08:07 -0800292 webrtc::Trace::set_level_filter(kElevatedTraceFilter);
solenberg2515af22015-12-02 06:19:36 -0800293 LOG(LS_INFO) << webrtc::VoiceEngine::GetVersionString();
peaha9cc40b2017-06-29 08:32:09 -0700294 RTC_CHECK_EQ(0,
295 voe_wrapper_->base()->Init(adm_.get(), apm(), decoder_factory_));
solenbergbd138382015-11-20 16:08:07 -0800296 webrtc::Trace::set_level_filter(kDefaultTraceFilter);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000297
solenbergff976312016-03-30 23:28:51 -0700298 // No ADM supplied? Get the default one from VoE.
299 if (!adm_) {
300 adm_ = voe_wrapper_->base()->audio_device_module();
301 }
302 RTC_DCHECK(adm_);
303
solenberg76377c52017-02-21 00:54:31 -0800304 transmit_mixer_ = voe_wrapper_->base()->transmit_mixer();
305 RTC_DCHECK(transmit_mixer_);
306
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000307 // Save the default AGC configuration settings. This must happen before
solenberg246b8172015-12-08 09:50:23 -0800308 // calling ApplyOptions or the default will be overwritten.
peaha9cc40b2017-06-29 08:32:09 -0700309 default_agc_config_ = webrtc::apm_helpers::GetAgcConfig(apm());
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000310
solenberg0f7d2932016-01-15 01:40:39 -0800311 // Set default engine options.
312 {
313 AudioOptions options;
314 options.echo_cancellation = rtc::Optional<bool>(true);
315 options.auto_gain_control = rtc::Optional<bool>(true);
316 options.noise_suppression = rtc::Optional<bool>(true);
317 options.highpass_filter = rtc::Optional<bool>(true);
318 options.stereo_swapping = rtc::Optional<bool>(false);
319 options.audio_jitter_buffer_max_packets = rtc::Optional<int>(50);
320 options.audio_jitter_buffer_fast_accelerate = rtc::Optional<bool>(false);
321 options.typing_detection = rtc::Optional<bool>(true);
322 options.adjust_agc_delta = rtc::Optional<int>(0);
323 options.experimental_agc = rtc::Optional<bool>(false);
324 options.extended_filter_aec = rtc::Optional<bool>(false);
325 options.delay_agnostic_aec = rtc::Optional<bool>(false);
326 options.experimental_ns = rtc::Optional<bool>(false);
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700327 options.intelligibility_enhancer = rtc::Optional<bool>(false);
peaha3333bf2016-06-30 00:02:34 -0700328 options.level_control = rtc::Optional<bool>(false);
ivocb829d9f2016-11-15 02:34:47 -0800329 options.residual_echo_detector = rtc::Optional<bool>(true);
solenbergff976312016-03-30 23:28:51 -0700330 bool error = ApplyOptions(options);
331 RTC_DCHECK(error);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000332 }
333
solenberg9a5f032222017-03-15 06:14:12 -0700334 // Set default audio devices.
335#if !defined(WEBRTC_IOS)
336 webrtc::adm_helpers::SetRecordingDevice(adm_);
337 apm()->Initialize();
338 webrtc::adm_helpers::SetPlayoutDevice(adm_);
339#endif // !WEBRTC_IOS
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000340
deadbeefeb02c032017-06-15 08:29:25 -0700341 // May be null for VoE injected for testing.
342 if (voe()->engine()) {
peaha9cc40b2017-06-29 08:32:09 -0700343 audio_state_ = webrtc::AudioState::Create(
344 MakeAudioStateConfig(voe(), audio_mixer_, apm_));
deadbeefeb02c032017-06-15 08:29:25 -0700345 }
346
347 initialized_ = true;
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000348}
349
solenberg566ef242015-11-06 15:34:49 -0800350rtc::scoped_refptr<webrtc::AudioState>
351 WebRtcVoiceEngine::GetAudioState() const {
352 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
353 return audio_state_;
354}
355
nisse51542be2016-02-12 02:27:06 -0800356VoiceMediaChannel* WebRtcVoiceEngine::CreateChannel(
357 webrtc::Call* call,
358 const MediaConfig& config,
Jelena Marusicc28a8962015-05-29 15:05:44 +0200359 const AudioOptions& options) {
solenberg566ef242015-11-06 15:34:49 -0800360 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
nisse51542be2016-02-12 02:27:06 -0800361 return new WebRtcVoiceMediaChannel(this, config, options, call);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000362}
363
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000364bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) {
solenberg566ef242015-11-06 15:34:49 -0800365 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergff976312016-03-30 23:28:51 -0700366 LOG(LS_INFO) << "WebRtcVoiceEngine::ApplyOptions: " << options_in.ToString();
solenberg0f7d2932016-01-15 01:40:39 -0800367 AudioOptions options = options_in; // The options are modified below.
solenberg246b8172015-12-08 09:50:23 -0800368
peah8a8ebd92017-05-22 15:48:47 -0700369 // Set and adjust echo canceller options.
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000370 // kEcConference is AEC with high suppression.
371 webrtc::EcModes ec_mode = webrtc::kEcConference;
kwiberg102c6a62015-10-30 02:47:38 -0700372 if (options.aecm_generate_comfort_noise) {
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000373 LOG(LS_VERBOSE) << "Comfort noise explicitly set to "
kwiberg102c6a62015-10-30 02:47:38 -0700374 << *options.aecm_generate_comfort_noise
375 << " (default is false).";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000376 }
377
kjellanderfcfc8042016-01-14 11:01:09 -0800378#if defined(WEBRTC_IOS)
peah8a8ebd92017-05-22 15:48:47 -0700379 // On iOS, VPIO provides built-in EC.
Karl Wibergbe579832015-11-10 22:34:18 +0100380 options.echo_cancellation = rtc::Optional<bool>(false);
peah8a8ebd92017-05-22 15:48:47 -0700381 options.extended_filter_aec = rtc::Optional<bool>(false);
382 LOG(LS_INFO) << "Always disable AEC on iOS. Use built-in instead.";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000383#elif defined(ANDROID)
384 ec_mode = webrtc::kEcAecm;
Karl Wibergbe579832015-11-10 22:34:18 +0100385 options.extended_filter_aec = rtc::Optional<bool>(false);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000386#endif
387
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100388 // Delay Agnostic AEC automatically turns on EC if not set except on iOS
389 // where the feature is not supported.
390 bool use_delay_agnostic_aec = false;
kjellanderfcfc8042016-01-14 11:01:09 -0800391#if !defined(WEBRTC_IOS)
kwiberg102c6a62015-10-30 02:47:38 -0700392 if (options.delay_agnostic_aec) {
393 use_delay_agnostic_aec = *options.delay_agnostic_aec;
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100394 if (use_delay_agnostic_aec) {
Karl Wibergbe579832015-11-10 22:34:18 +0100395 options.echo_cancellation = rtc::Optional<bool>(true);
396 options.extended_filter_aec = rtc::Optional<bool>(true);
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100397 ec_mode = webrtc::kEcConference;
398 }
399 }
400#endif
401
peah8a8ebd92017-05-22 15:48:47 -0700402// Set and adjust noise suppressor options.
403#if defined(WEBRTC_IOS)
404 // On iOS, VPIO provides built-in NS.
405 options.noise_suppression = rtc::Optional<bool>(false);
406 options.typing_detection = rtc::Optional<bool>(false);
407 options.experimental_ns = rtc::Optional<bool>(false);
408 LOG(LS_INFO) << "Always disable NS on iOS. Use built-in instead.";
409#elif defined(ANDROID)
410 options.typing_detection = rtc::Optional<bool>(false);
411 options.experimental_ns = rtc::Optional<bool>(false);
412#endif
413
414// Set and adjust gain control options.
415#if defined(WEBRTC_IOS)
416 // On iOS, VPIO provides built-in AGC.
417 options.auto_gain_control = rtc::Optional<bool>(false);
418 options.experimental_agc = rtc::Optional<bool>(false);
419 LOG(LS_INFO) << "Always disable AGC on iOS. Use built-in instead.";
420#elif defined(ANDROID)
421 options.experimental_agc = rtc::Optional<bool>(false);
422#endif
423
424#if defined(WEBRTC_IOS) || defined(WEBRTC_ANDROID)
425 // 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).
426 if (webrtc::field_trial::IsEnabled(
427 "WebRTC-Audio-MinimizeResamplingOnMobile")) {
428 options.auto_gain_control = rtc::Optional<bool>(false);
429 LOG(LS_INFO) << "Disable AGC according to field trial.";
430 if (!(options.noise_suppression.value_or(false) or
431 options.echo_cancellation.value_or(false))) {
432 // If possible, turn off the high-pass filter.
433 LOG(LS_INFO) << "Disable high-pass filter in response to field trial.";
434 options.highpass_filter = rtc::Optional<bool>(false);
435 }
436 }
437#endif
438
peah1bcfce52016-08-26 07:16:04 -0700439#if (WEBRTC_INTELLIGIBILITY_ENHANCER == 0)
440 // Hardcode the intelligibility enhancer to be off.
441 options.intelligibility_enhancer = rtc::Optional<bool>(false);
442#endif
443
kwiberg102c6a62015-10-30 02:47:38 -0700444 if (options.echo_cancellation) {
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000445 // Check if platform supports built-in EC. Currently only supported on
446 // Android and in combination with Java based audio layer.
447 // TODO(henrika): investigate possibility to support built-in EC also
448 // in combination with Open SL ES audio.
solenberg5b5129a2016-04-08 05:35:48 -0700449 const bool built_in_aec = adm()->BuiltInAECIsAvailable();
Bjorn Volcker73f72102015-06-03 14:50:15 +0200450 if (built_in_aec) {
Bjorn Volckerccfc9392015-05-07 07:43:17 +0200451 // Built-in EC exists on this device and use_delay_agnostic_aec is not
452 // overriding it. Enable/Disable it according to the echo_cancellation
453 // audio option.
Bjorn Volcker73f72102015-06-03 14:50:15 +0200454 const bool enable_built_in_aec =
kwiberg102c6a62015-10-30 02:47:38 -0700455 *options.echo_cancellation && !use_delay_agnostic_aec;
solenberg5b5129a2016-04-08 05:35:48 -0700456 if (adm()->EnableBuiltInAEC(enable_built_in_aec) == 0 &&
Bjorn Volcker73f72102015-06-03 14:50:15 +0200457 enable_built_in_aec) {
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100458 // Disable internal software EC if built-in EC is enabled,
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000459 // i.e., replace the software EC with the built-in EC.
Karl Wibergbe579832015-11-10 22:34:18 +0100460 options.echo_cancellation = rtc::Optional<bool>(false);
henrika@webrtc.orga954c072014-12-09 16:22:09 +0000461 LOG(LS_INFO) << "Disabling EC since built-in EC will be used instead";
462 }
463 }
solenberg76377c52017-02-21 00:54:31 -0800464 webrtc::apm_helpers::SetEcStatus(
465 apm(), *options.echo_cancellation, ec_mode);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000466#if !defined(ANDROID)
solenberg76377c52017-02-21 00:54:31 -0800467 webrtc::apm_helpers::SetEcMetricsStatus(apm(), *options.echo_cancellation);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000468#endif
469 if (ec_mode == webrtc::kEcAecm) {
kwiberg102c6a62015-10-30 02:47:38 -0700470 bool cn = options.aecm_generate_comfort_noise.value_or(false);
solenberg76377c52017-02-21 00:54:31 -0800471 webrtc::apm_helpers::SetAecmMode(apm(), cn);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000472 }
473 }
474
kwiberg102c6a62015-10-30 02:47:38 -0700475 if (options.auto_gain_control) {
peah72a56452016-08-22 12:08:55 -0700476 bool built_in_agc_avaliable = adm()->BuiltInAGCIsAvailable();
477 if (built_in_agc_avaliable) {
solenberg5b5129a2016-04-08 05:35:48 -0700478 if (adm()->EnableBuiltInAGC(*options.auto_gain_control) == 0 &&
kwiberg102c6a62015-10-30 02:47:38 -0700479 *options.auto_gain_control) {
henrikac14f5ff2015-09-23 14:08:33 +0200480 // Disable internal software AGC if built-in AGC is enabled,
481 // i.e., replace the software AGC with the built-in AGC.
Karl Wibergbe579832015-11-10 22:34:18 +0100482 options.auto_gain_control = rtc::Optional<bool>(false);
henrikac14f5ff2015-09-23 14:08:33 +0200483 LOG(LS_INFO) << "Disabling AGC since built-in AGC will be used instead";
484 }
485 }
solenberg22818a52017-03-16 01:20:23 -0700486 webrtc::apm_helpers::SetAgcStatus(apm(), adm(), *options.auto_gain_control);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000487 }
488
kwiberg102c6a62015-10-30 02:47:38 -0700489 if (options.tx_agc_target_dbov || options.tx_agc_digital_compression_gain ||
solenberg76377c52017-02-21 00:54:31 -0800490 options.tx_agc_limiter || options.adjust_agc_delta) {
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000491 // Override default_agc_config_. Generally, an unset option means "leave
492 // the VoE bits alone" in this function, so we want whatever is set to be
493 // stored as the new "default". If we didn't, then setting e.g.
494 // tx_agc_target_dbov would reset digital compression gain and limiter
495 // settings.
496 // Also, if we don't update default_agc_config_, then adjust_agc_delta
497 // would be an offset from the original values, and not whatever was set
498 // explicitly.
kwiberg102c6a62015-10-30 02:47:38 -0700499 default_agc_config_.targetLeveldBOv = options.tx_agc_target_dbov.value_or(
500 default_agc_config_.targetLeveldBOv);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000501 default_agc_config_.digitalCompressionGaindB =
kwiberg102c6a62015-10-30 02:47:38 -0700502 options.tx_agc_digital_compression_gain.value_or(
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000503 default_agc_config_.digitalCompressionGaindB);
504 default_agc_config_.limiterEnable =
kwiberg102c6a62015-10-30 02:47:38 -0700505 options.tx_agc_limiter.value_or(default_agc_config_.limiterEnable);
solenberg76377c52017-02-21 00:54:31 -0800506
507 webrtc::AgcConfig config = default_agc_config_;
508 if (options.adjust_agc_delta) {
509 config.targetLeveldBOv -= *options.adjust_agc_delta;
510 LOG(LS_INFO) << "Adjusting AGC level from default -"
511 << default_agc_config_.targetLeveldBOv << "dB to -"
512 << config.targetLeveldBOv << "dB";
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000513 }
peaha9cc40b2017-06-29 08:32:09 -0700514 webrtc::apm_helpers::SetAgcConfig(apm(), config);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000515 }
516
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700517 if (options.intelligibility_enhancer) {
518 intelligibility_enhancer_ = options.intelligibility_enhancer;
519 }
520 if (intelligibility_enhancer_ && *intelligibility_enhancer_) {
521 LOG(LS_INFO) << "Enabling NS when Intelligibility Enhancer is active.";
522 options.noise_suppression = intelligibility_enhancer_;
523 }
524
kwiberg102c6a62015-10-30 02:47:38 -0700525 if (options.noise_suppression) {
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700526 if (adm()->BuiltInNSIsAvailable()) {
527 bool builtin_ns =
528 *options.noise_suppression &&
529 !(intelligibility_enhancer_ && *intelligibility_enhancer_);
530 if (adm()->EnableBuiltInNS(builtin_ns) == 0 && builtin_ns) {
henrikac14f5ff2015-09-23 14:08:33 +0200531 // Disable internal software NS if built-in NS is enabled,
532 // i.e., replace the software NS with the built-in NS.
Karl Wibergbe579832015-11-10 22:34:18 +0100533 options.noise_suppression = rtc::Optional<bool>(false);
henrikac14f5ff2015-09-23 14:08:33 +0200534 LOG(LS_INFO) << "Disabling NS since built-in NS will be used instead";
535 }
536 }
solenberg76377c52017-02-21 00:54:31 -0800537 webrtc::apm_helpers::SetNsStatus(apm(), *options.noise_suppression);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000538 }
539
kwiberg102c6a62015-10-30 02:47:38 -0700540 if (options.stereo_swapping) {
541 LOG(LS_INFO) << "Stereo swapping enabled? " << *options.stereo_swapping;
solenberg76377c52017-02-21 00:54:31 -0800542 transmit_mixer()->EnableStereoChannelSwapping(*options.stereo_swapping);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000543 }
544
kwiberg102c6a62015-10-30 02:47:38 -0700545 if (options.audio_jitter_buffer_max_packets) {
546 LOG(LS_INFO) << "NetEq capacity is "
547 << *options.audio_jitter_buffer_max_packets;
solenberg88499ec2016-09-07 07:34:41 -0700548 channel_config_.acm_config.neteq_config.max_packets_in_buffer =
549 std::max(20, *options.audio_jitter_buffer_max_packets);
Henrik Lundin64dad832015-05-11 12:44:23 +0200550 }
kwiberg102c6a62015-10-30 02:47:38 -0700551 if (options.audio_jitter_buffer_fast_accelerate) {
552 LOG(LS_INFO) << "NetEq fast mode? "
553 << *options.audio_jitter_buffer_fast_accelerate;
solenberg88499ec2016-09-07 07:34:41 -0700554 channel_config_.acm_config.neteq_config.enable_fast_accelerate =
555 *options.audio_jitter_buffer_fast_accelerate;
Henrik Lundin5263b3c2015-06-01 10:29:41 +0200556 }
557
kwiberg102c6a62015-10-30 02:47:38 -0700558 if (options.typing_detection) {
559 LOG(LS_INFO) << "Typing detection is enabled? "
560 << *options.typing_detection;
solenberg76377c52017-02-21 00:54:31 -0800561 webrtc::apm_helpers::SetTypingDetectionStatus(
562 apm(), *options.typing_detection);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000563 }
564
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000565 webrtc::Config config;
566
kwiberg102c6a62015-10-30 02:47:38 -0700567 if (options.delay_agnostic_aec)
568 delay_agnostic_aec_ = options.delay_agnostic_aec;
569 if (delay_agnostic_aec_) {
570 LOG(LS_INFO) << "Delay agnostic aec is enabled? " << *delay_agnostic_aec_;
henrik.lundin0f133b92015-07-02 00:17:55 -0700571 config.Set<webrtc::DelayAgnostic>(
kwiberg102c6a62015-10-30 02:47:38 -0700572 new webrtc::DelayAgnostic(*delay_agnostic_aec_));
Bjorn Volckerbf395c12015-03-25 22:45:56 +0100573 }
574
kwiberg102c6a62015-10-30 02:47:38 -0700575 if (options.extended_filter_aec) {
576 extended_filter_aec_ = options.extended_filter_aec;
577 }
578 if (extended_filter_aec_) {
579 LOG(LS_INFO) << "Extended filter aec is enabled? " << *extended_filter_aec_;
Henrik Lundin441f6342015-06-09 16:03:13 +0200580 config.Set<webrtc::ExtendedFilter>(
kwiberg102c6a62015-10-30 02:47:38 -0700581 new webrtc::ExtendedFilter(*extended_filter_aec_));
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000582 }
583
kwiberg102c6a62015-10-30 02:47:38 -0700584 if (options.experimental_ns) {
585 experimental_ns_ = options.experimental_ns;
586 }
587 if (experimental_ns_) {
588 LOG(LS_INFO) << "Experimental ns is enabled? " << *experimental_ns_;
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000589 config.Set<webrtc::ExperimentalNs>(
kwiberg102c6a62015-10-30 02:47:38 -0700590 new webrtc::ExperimentalNs(*experimental_ns_));
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000591 }
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000592
Alejandro Luebsc9b0c262016-05-16 15:32:38 -0700593 if (intelligibility_enhancer_) {
594 LOG(LS_INFO) << "Intelligibility Enhancer is enabled? "
595 << *intelligibility_enhancer_;
596 config.Set<webrtc::Intelligibility>(
597 new webrtc::Intelligibility(*intelligibility_enhancer_));
598 }
599
peaha3333bf2016-06-30 00:02:34 -0700600 if (options.level_control) {
601 level_control_ = options.level_control;
602 }
603
604 LOG(LS_INFO) << "Level control: "
605 << (!!level_control_ ? *level_control_ : -1);
606 if (level_control_) {
peah64d6ff72016-11-21 06:28:14 -0800607 apm_config_.level_controller.enabled = *level_control_;
aleloie33c5d92016-10-20 01:53:27 -0700608 if (options.level_control_initial_peak_level_dbfs) {
peah64d6ff72016-11-21 06:28:14 -0800609 apm_config_.level_controller.initial_peak_level_dbfs =
aleloie33c5d92016-10-20 01:53:27 -0700610 *options.level_control_initial_peak_level_dbfs;
611 }
peaha3333bf2016-06-30 00:02:34 -0700612 }
613
peah8271d042016-11-22 07:24:52 -0800614 if (options.highpass_filter) {
615 apm_config_.high_pass_filter.enabled = *options.highpass_filter;
616 }
617
ivoc4ca18692017-02-10 05:11:09 -0800618 if (options.residual_echo_detector) {
619 apm_config_.residual_echo_detector.enabled =
620 *options.residual_echo_detector;
621 }
622
solenberg059fb442016-10-26 05:12:24 -0700623 apm()->SetExtraOptions(config);
peah64d6ff72016-11-21 06:28:14 -0800624 apm()->ApplyConfig(apm_config_);
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000625
kwiberg102c6a62015-10-30 02:47:38 -0700626 if (options.recording_sample_rate) {
627 LOG(LS_INFO) << "Recording sample rate is "
628 << *options.recording_sample_rate;
solenberg5b5129a2016-04-08 05:35:48 -0700629 if (adm()->SetRecordingSampleRate(*options.recording_sample_rate)) {
kwiberg102c6a62015-10-30 02:47:38 -0700630 LOG_RTCERR1(SetRecordingSampleRate, *options.recording_sample_rate);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000631 }
632 }
633
kwiberg102c6a62015-10-30 02:47:38 -0700634 if (options.playout_sample_rate) {
635 LOG(LS_INFO) << "Playout sample rate is " << *options.playout_sample_rate;
solenberg5b5129a2016-04-08 05:35:48 -0700636 if (adm()->SetPlayoutSampleRate(*options.playout_sample_rate)) {
kwiberg102c6a62015-10-30 02:47:38 -0700637 LOG_RTCERR1(SetPlayoutSampleRate, *options.playout_sample_rate);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000638 }
639 }
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000640 return true;
641}
642
solenberg796b8f92017-03-01 17:02:23 -0800643// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000644int WebRtcVoiceEngine::GetInputLevel() {
solenberg566ef242015-11-06 15:34:49 -0800645 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg796b8f92017-03-01 17:02:23 -0800646 int8_t level = transmit_mixer()->AudioLevel();
647 RTC_DCHECK_LE(0, level);
648 return level;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000649}
650
ossudedfd282016-06-14 07:12:39 -0700651const std::vector<AudioCodec>& WebRtcVoiceEngine::send_codecs() const {
652 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
ossuc54071d2016-08-17 02:45:41 -0700653 return send_codecs_;
ossudedfd282016-06-14 07:12:39 -0700654}
655
656const std::vector<AudioCodec>& WebRtcVoiceEngine::recv_codecs() const {
solenberg566ef242015-11-06 15:34:49 -0800657 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
ossuc54071d2016-08-17 02:45:41 -0700658 return recv_codecs_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000659}
660
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100661RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const {
solenberg566ef242015-11-06 15:34:49 -0800662 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100663 RtpCapabilities capabilities;
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100664 capabilities.header_extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -0700665 webrtc::RtpExtension(webrtc::RtpExtension::kAudioLevelUri,
666 webrtc::RtpExtension::kAudioLevelDefaultId));
sprangc1b57a12017-02-28 08:50:47 -0800667 if (webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe")) {
isheriff6f8d6862016-05-26 11:24:55 -0700668 capabilities.header_extensions.push_back(webrtc::RtpExtension(
669 webrtc::RtpExtension::kTransportSequenceNumberUri,
670 webrtc::RtpExtension::kTransportSequenceNumberDefaultId));
stefanba4c0e42016-02-04 04:12:24 -0800671 }
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100672 return capabilities;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000673}
674
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000675int WebRtcVoiceEngine::GetLastEngineError() {
solenberg566ef242015-11-06 15:34:49 -0800676 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000677 return voe_wrapper_->error();
678}
679
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000680void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
681 int length) {
solenberg566ef242015-11-06 15:34:49 -0800682 // Note: This callback can happen on any thread!
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000683 rtc::LoggingSeverity sev = rtc::LS_VERBOSE;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000684 if (level == webrtc::kTraceError || level == webrtc::kTraceCritical)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000685 sev = rtc::LS_ERROR;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000686 else if (level == webrtc::kTraceWarning)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000687 sev = rtc::LS_WARNING;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000688 else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000689 sev = rtc::LS_INFO;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000690 else if (level == webrtc::kTraceTerseInfo)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000691 sev = rtc::LS_INFO;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000692
solenberg72e29d22016-03-08 06:35:16 -0800693 // Skip past boilerplate prefix text.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000694 if (length < 72) {
695 std::string msg(trace, length);
696 LOG(LS_ERROR) << "Malformed webrtc log message: ";
697 LOG_V(sev) << msg;
698 } else {
699 std::string msg(trace + 71, length - 72);
Peter Boströmd5c75b12015-09-23 13:24:32 +0200700 LOG_V(sev) << "webrtc: " << msg;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000701 }
702}
703
solenberg63b34542015-09-29 06:06:31 -0700704void WebRtcVoiceEngine::RegisterChannel(WebRtcVoiceMediaChannel* channel) {
solenberg566ef242015-11-06 15:34:49 -0800705 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
706 RTC_DCHECK(channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000707 channels_.push_back(channel);
708}
709
solenberg63b34542015-09-29 06:06:31 -0700710void WebRtcVoiceEngine::UnregisterChannel(WebRtcVoiceMediaChannel* channel) {
solenberg566ef242015-11-06 15:34:49 -0800711 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg63b34542015-09-29 06:06:31 -0700712 auto it = std::find(channels_.begin(), channels_.end(), channel);
solenberg566ef242015-11-06 15:34:49 -0800713 RTC_DCHECK(it != channels_.end());
714 channels_.erase(it);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000715}
716
ivocd66b44d2016-01-15 03:06:36 -0800717bool WebRtcVoiceEngine::StartAecDump(rtc::PlatformFile file,
718 int64_t max_size_bytes) {
solenberg566ef242015-11-06 15:34:49 -0800719 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeefeb02c032017-06-15 08:29:25 -0700720 auto aec_dump = webrtc::AecDumpFactory::Create(
721 file, max_size_bytes, low_priority_worker_queue_.get());
aleloi048cbdd2017-05-29 02:56:27 -0700722 if (!aec_dump) {
wu@webrtc.orga8910d22014-01-23 22:12:45 +0000723 return false;
724 }
aleloi048cbdd2017-05-29 02:56:27 -0700725 apm()->AttachAecDump(std::move(aec_dump));
wu@webrtc.orga9890802013-12-13 00:21:03 +0000726 return true;
wu@webrtc.orga9890802013-12-13 00:21:03 +0000727}
728
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000729void WebRtcVoiceEngine::StartAecDump(const std::string& filename) {
solenberg566ef242015-11-06 15:34:49 -0800730 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
aleloi048cbdd2017-05-29 02:56:27 -0700731
deadbeefeb02c032017-06-15 08:29:25 -0700732 auto aec_dump = webrtc::AecDumpFactory::Create(
733 filename, -1, low_priority_worker_queue_.get());
aleloi048cbdd2017-05-29 02:56:27 -0700734 if (aec_dump) {
735 apm()->AttachAecDump(std::move(aec_dump));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000736 }
737}
738
739void WebRtcVoiceEngine::StopAecDump() {
solenberg566ef242015-11-06 15:34:49 -0800740 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
aleloi048cbdd2017-05-29 02:56:27 -0700741 apm()->DetachAecDump();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000742}
743
solenberg0a617e22015-10-20 15:49:38 -0700744int WebRtcVoiceEngine::CreateVoEChannel() {
solenberg566ef242015-11-06 15:34:49 -0800745 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg88499ec2016-09-07 07:34:41 -0700746 return voe_wrapper_->base()->CreateChannel(channel_config_);
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000747}
748
solenberg5b5129a2016-04-08 05:35:48 -0700749webrtc::AudioDeviceModule* WebRtcVoiceEngine::adm() {
750 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
751 RTC_DCHECK(adm_);
752 return adm_;
753}
754
solenberg059fb442016-10-26 05:12:24 -0700755webrtc::AudioProcessing* WebRtcVoiceEngine::apm() {
756 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
peaha9cc40b2017-06-29 08:32:09 -0700757 return apm_.get();
solenberg059fb442016-10-26 05:12:24 -0700758}
759
solenberg76377c52017-02-21 00:54:31 -0800760webrtc::voe::TransmitMixer* WebRtcVoiceEngine::transmit_mixer() {
761 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
762 RTC_DCHECK(transmit_mixer_);
763 return transmit_mixer_;
764}
765
ossu20a4b3f2017-04-27 02:08:52 -0700766AudioCodecs WebRtcVoiceEngine::CollectCodecs(
767 const std::vector<webrtc::AudioCodecSpec>& specs) const {
ossuc54071d2016-08-17 02:45:41 -0700768 PayloadTypeMapper mapper;
769 AudioCodecs out;
ossuc54071d2016-08-17 02:45:41 -0700770
solenberg2779bab2016-11-17 04:45:19 -0800771 // Only generate CN payload types for these clockrates:
ossuc54071d2016-08-17 02:45:41 -0700772 std::map<int, bool, std::greater<int>> generate_cn = {{ 8000, false },
773 { 16000, false },
774 { 32000, false }};
solenberg2779bab2016-11-17 04:45:19 -0800775 // Only generate telephone-event payload types for these clockrates:
776 std::map<int, bool, std::greater<int>> generate_dtmf = {{ 8000, false },
777 { 16000, false },
778 { 32000, false },
779 { 48000, false }};
ossuc54071d2016-08-17 02:45:41 -0700780
ossu9def8002017-02-09 05:14:32 -0800781 auto map_format = [&mapper](const webrtc::SdpAudioFormat& format,
782 AudioCodecs* out) {
ossuc54071d2016-08-17 02:45:41 -0700783 rtc::Optional<AudioCodec> opt_codec = mapper.ToAudioCodec(format);
ossu9def8002017-02-09 05:14:32 -0800784 if (opt_codec) {
785 if (out) {
786 out->push_back(*opt_codec);
787 }
788 } else {
ossuc54071d2016-08-17 02:45:41 -0700789 LOG(LS_ERROR) << "Unable to assign payload type to format: " << format;
ossuc54071d2016-08-17 02:45:41 -0700790 }
791
ossu9def8002017-02-09 05:14:32 -0800792 return opt_codec;
ossuc54071d2016-08-17 02:45:41 -0700793 };
794
ossud4e9f622016-08-18 02:01:17 -0700795 for (const auto& spec : specs) {
ossu9def8002017-02-09 05:14:32 -0800796 // We need to do some extra stuff before adding the main codecs to out.
797 rtc::Optional<AudioCodec> opt_codec = map_format(spec.format, nullptr);
798 if (opt_codec) {
799 AudioCodec& codec = *opt_codec;
ossua1a040a2017-04-06 10:03:21 -0700800 if (spec.info.supports_network_adaption) {
ossu9def8002017-02-09 05:14:32 -0800801 codec.AddFeedbackParam(
802 FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty));
803 }
804
ossua1a040a2017-04-06 10:03:21 -0700805 if (spec.info.allow_comfort_noise) {
solenberg2779bab2016-11-17 04:45:19 -0800806 // Generate a CN entry if the decoder allows it and we support the
807 // clockrate.
808 auto cn = generate_cn.find(spec.format.clockrate_hz);
809 if (cn != generate_cn.end()) {
810 cn->second = true;
811 }
812 }
813
814 // Generate a telephone-event entry if we support the clockrate.
815 auto dtmf = generate_dtmf.find(spec.format.clockrate_hz);
816 if (dtmf != generate_dtmf.end()) {
817 dtmf->second = true;
ossuc54071d2016-08-17 02:45:41 -0700818 }
ossu9def8002017-02-09 05:14:32 -0800819
820 out.push_back(codec);
ossuc54071d2016-08-17 02:45:41 -0700821 }
822 }
823
solenberg2779bab2016-11-17 04:45:19 -0800824 // Add CN codecs after "proper" audio codecs.
ossuc54071d2016-08-17 02:45:41 -0700825 for (const auto& cn : generate_cn) {
826 if (cn.second) {
ossu9def8002017-02-09 05:14:32 -0800827 map_format({kCnCodecName, cn.first, 1}, &out);
ossuc54071d2016-08-17 02:45:41 -0700828 }
829 }
830
solenberg2779bab2016-11-17 04:45:19 -0800831 // Add telephone-event codecs last.
832 for (const auto& dtmf : generate_dtmf) {
833 if (dtmf.second) {
ossu9def8002017-02-09 05:14:32 -0800834 map_format({kDtmfCodecName, dtmf.first, 1}, &out);
solenberg2779bab2016-11-17 04:45:19 -0800835 }
836 }
ossuc54071d2016-08-17 02:45:41 -0700837
838 return out;
839}
840
solenbergc96df772015-10-21 13:01:53 -0700841class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800842 : public AudioSource::Sink {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000843 public:
minyue7a973442016-10-20 03:27:12 -0700844 WebRtcAudioSendStream(
845 int ch,
846 webrtc::AudioTransport* voe_audio_transport,
847 uint32_t ssrc,
848 const std::string& c_name,
ossu20a4b3f2017-04-27 02:08:52 -0700849 const rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>&
850 send_codec_spec,
minyue7a973442016-10-20 03:27:12 -0700851 const std::vector<webrtc::RtpExtension>& extensions,
852 int max_send_bitrate_bps,
minyue6b825df2016-10-31 04:08:32 -0700853 const rtc::Optional<std::string>& audio_network_adaptor_config,
minyue7a973442016-10-20 03:27:12 -0700854 webrtc::Call* call,
ossu20a4b3f2017-04-27 02:08:52 -0700855 webrtc::Transport* send_transport,
856 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory)
solenberg7add0582015-11-20 09:59:34 -0800857 : voe_audio_transport_(voe_audio_transport),
solenberg3a941542015-11-16 07:34:50 -0800858 call_(call),
mflodman3d7db262016-04-29 00:57:13 -0700859 config_(send_transport),
sprangc1b57a12017-02-28 08:50:47 -0800860 send_side_bwe_with_overhead_(
861 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
minyue7a973442016-10-20 03:27:12 -0700862 max_send_bitrate_bps_(max_send_bitrate_bps),
skvlade0d46372016-04-07 22:59:22 -0700863 rtp_parameters_(CreateRtpParametersWithOneEncoding()) {
solenberg85a04962015-10-27 03:35:21 -0700864 RTC_DCHECK_GE(ch, 0);
865 // TODO(solenberg): Once we're not using FakeWebRtcVoiceEngine anymore:
866 // RTC_DCHECK(voe_audio_transport);
solenbergc96df772015-10-21 13:01:53 -0700867 RTC_DCHECK(call);
ossu20a4b3f2017-04-27 02:08:52 -0700868 RTC_DCHECK(encoder_factory);
solenberg3a941542015-11-16 07:34:50 -0800869 config_.rtp.ssrc = ssrc;
870 config_.rtp.c_name = c_name;
871 config_.voe_channel_id = ch;
solenberg971cab02016-06-14 10:02:41 -0700872 config_.rtp.extensions = extensions;
minyue6b825df2016-10-31 04:08:32 -0700873 config_.audio_network_adaptor_config = audio_network_adaptor_config;
ossu20a4b3f2017-04-27 02:08:52 -0700874 config_.encoder_factory = encoder_factory;
deadbeefcb443432016-12-12 11:12:36 -0800875 rtp_parameters_.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
ossu20a4b3f2017-04-27 02:08:52 -0700876
877 if (send_codec_spec) {
878 UpdateSendCodecSpec(*send_codec_spec);
879 }
880
881 stream_ = call_->CreateAudioSendStream(config_);
solenbergc96df772015-10-21 13:01:53 -0700882 }
solenberg3a941542015-11-16 07:34:50 -0800883
solenbergc96df772015-10-21 13:01:53 -0700884 ~WebRtcAudioSendStream() override {
solenberg566ef242015-11-06 15:34:49 -0800885 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800886 ClearSource();
solenbergc96df772015-10-21 13:01:53 -0700887 call_->DestroyAudioSendStream(stream_);
888 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000889
ossu20a4b3f2017-04-27 02:08:52 -0700890 void SetSendCodecSpec(
minyue7a973442016-10-20 03:27:12 -0700891 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) {
ossu20a4b3f2017-04-27 02:08:52 -0700892 UpdateSendCodecSpec(send_codec_spec);
893 ReconfigureAudioSendStream();
solenberg971cab02016-06-14 10:02:41 -0700894 }
895
ossu20a4b3f2017-04-27 02:08:52 -0700896 void SetRtpExtensions(const std::vector<webrtc::RtpExtension>& extensions) {
solenberg3a941542015-11-16 07:34:50 -0800897 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg3a941542015-11-16 07:34:50 -0800898 config_.rtp.extensions = extensions;
ossu20a4b3f2017-04-27 02:08:52 -0700899 ReconfigureAudioSendStream();
solenberg3a941542015-11-16 07:34:50 -0800900 }
901
ossu20a4b3f2017-04-27 02:08:52 -0700902 void SetAudioNetworkAdaptorConfig(
minyue6b825df2016-10-31 04:08:32 -0700903 const rtc::Optional<std::string>& audio_network_adaptor_config) {
904 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
905 if (config_.audio_network_adaptor_config == audio_network_adaptor_config) {
906 return;
907 }
908 config_.audio_network_adaptor_config = audio_network_adaptor_config;
ossu20a4b3f2017-04-27 02:08:52 -0700909 UpdateAllowedBitrateRange();
910 ReconfigureAudioSendStream();
minyue6b825df2016-10-31 04:08:32 -0700911 }
912
minyue7a973442016-10-20 03:27:12 -0700913 bool SetMaxSendBitrate(int bps) {
914 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
ossu20a4b3f2017-04-27 02:08:52 -0700915 RTC_DCHECK(config_.send_codec_spec);
916 RTC_DCHECK(audio_codec_spec_);
917 auto send_rate = ComputeSendBitrate(
918 bps, rtp_parameters_.encodings[0].max_bitrate_bps, *audio_codec_spec_);
919
minyue7a973442016-10-20 03:27:12 -0700920 if (!send_rate) {
921 return false;
922 }
923
924 max_send_bitrate_bps_ = bps;
925
ossu20a4b3f2017-04-27 02:08:52 -0700926 if (send_rate != config_.send_codec_spec->target_bitrate_bps) {
927 config_.send_codec_spec->target_bitrate_bps = send_rate;
928 ReconfigureAudioSendStream();
minyue7a973442016-10-20 03:27:12 -0700929 }
930 return true;
931 }
932
solenbergffbbcac2016-11-17 05:25:37 -0800933 bool SendTelephoneEvent(int payload_type, int payload_freq, int event,
934 int duration_ms) {
Fredrik Solenbergb5727682015-12-04 15:22:19 +0100935 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
936 RTC_DCHECK(stream_);
solenbergffbbcac2016-11-17 05:25:37 -0800937 return stream_->SendTelephoneEvent(payload_type, payload_freq, event,
938 duration_ms);
Fredrik Solenbergb5727682015-12-04 15:22:19 +0100939 }
940
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800941 void SetSend(bool send) {
942 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
943 send_ = send;
944 UpdateSendState();
945 }
946
solenberg94218532016-06-16 10:53:22 -0700947 void SetMuted(bool muted) {
948 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
949 RTC_DCHECK(stream_);
950 stream_->SetMuted(muted);
951 muted_ = muted;
952 }
953
954 bool muted() const {
955 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
956 return muted_;
957 }
958
solenberg3a941542015-11-16 07:34:50 -0800959 webrtc::AudioSendStream::Stats GetStats() const {
960 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
961 RTC_DCHECK(stream_);
962 return stream_->GetStats();
963 }
964
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800965 // Starts the sending by setting ourselves as a sink to the AudioSource to
966 // get data callbacks.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000967 // This method is called on the libjingle worker thread.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000968 // TODO(xians): Make sure Start() is called only once.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800969 void SetSource(AudioSource* source) {
solenberg566ef242015-11-06 15:34:49 -0800970 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800971 RTC_DCHECK(source);
972 if (source_) {
973 RTC_DCHECK(source_ == source);
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000974 return;
975 }
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800976 source->SetSink(this);
977 source_ = source;
978 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000979 }
980
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800981 // Stops sending by setting the sink of the AudioSource to nullptr. No data
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000982 // callback will be received after this method.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000983 // This method is called on the libjingle worker thread.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800984 void ClearSource() {
solenberg566ef242015-11-06 15:34:49 -0800985 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800986 if (source_) {
987 source_->SetSink(nullptr);
988 source_ = nullptr;
solenberg98c68862015-10-09 03:27:14 -0700989 }
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800990 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000991 }
992
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800993 // AudioSource::Sink implementation.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000994 // This method is called on the audio thread.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000995 void OnData(const void* audio_data,
996 int bits_per_sample,
997 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -0800998 size_t number_of_channels,
Peter Kastingdce40cf2015-08-24 14:52:23 -0700999 size_t number_of_frames) override {
solenberg347ec5c2016-09-23 04:21:47 -07001000 RTC_CHECK_RUNS_SERIALIZED(&audio_capture_race_checker_);
solenbergc96df772015-10-21 13:01:53 -07001001 RTC_DCHECK(voe_audio_transport_);
maxmorin1aee0b52016-08-15 11:46:19 -07001002 voe_audio_transport_->PushCaptureData(config_.voe_channel_id, audio_data,
1003 bits_per_sample, sample_rate,
1004 number_of_channels, number_of_frames);
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00001005 }
1006
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001007 // Callback from the |source_| when it is going away. In case Start() has
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00001008 // never been called, this callback won't be triggered.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001009 void OnClose() override {
solenberg566ef242015-11-06 15:34:49 -08001010 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001011 // Set |source_| to nullptr to make sure no more callback will get into
1012 // the source.
1013 source_ = nullptr;
1014 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001015 }
1016
1017 // Accessor to the VoE channel ID.
solenberg85a04962015-10-27 03:35:21 -07001018 int channel() const {
solenberg566ef242015-11-06 15:34:49 -08001019 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7add0582015-11-20 09:59:34 -08001020 return config_.voe_channel_id;
solenberg85a04962015-10-27 03:35:21 -07001021 }
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001022
skvlade0d46372016-04-07 22:59:22 -07001023 const webrtc::RtpParameters& rtp_parameters() const {
1024 return rtp_parameters_;
1025 }
1026
deadbeeffb2aced2017-01-06 23:05:37 -08001027 bool ValidateRtpParameters(const webrtc::RtpParameters& rtp_parameters) {
1028 if (rtp_parameters.encodings.size() != 1) {
1029 LOG(LS_ERROR)
1030 << "Attempted to set RtpParameters without exactly one encoding";
1031 return false;
1032 }
1033 if (rtp_parameters.encodings[0].ssrc != rtp_parameters_.encodings[0].ssrc) {
1034 LOG(LS_ERROR) << "Attempted to set RtpParameters with modified SSRC";
1035 return false;
1036 }
1037 return true;
1038 }
1039
minyue7a973442016-10-20 03:27:12 -07001040 bool SetRtpParameters(const webrtc::RtpParameters& parameters) {
deadbeeffb2aced2017-01-06 23:05:37 -08001041 if (!ValidateRtpParameters(parameters)) {
1042 return false;
1043 }
ossu20a4b3f2017-04-27 02:08:52 -07001044
1045 rtc::Optional<int> send_rate;
1046 if (audio_codec_spec_) {
1047 send_rate = ComputeSendBitrate(max_send_bitrate_bps_,
1048 parameters.encodings[0].max_bitrate_bps,
1049 *audio_codec_spec_);
1050 if (!send_rate) {
1051 return false;
1052 }
minyue7a973442016-10-20 03:27:12 -07001053 }
1054
minyuececec102017-03-27 13:04:25 -07001055 const rtc::Optional<int> old_rtp_max_bitrate =
1056 rtp_parameters_.encodings[0].max_bitrate_bps;
1057
skvlade0d46372016-04-07 22:59:22 -07001058 rtp_parameters_ = parameters;
minyue7a973442016-10-20 03:27:12 -07001059
minyuececec102017-03-27 13:04:25 -07001060 if (rtp_parameters_.encodings[0].max_bitrate_bps != old_rtp_max_bitrate) {
ossu20a4b3f2017-04-27 02:08:52 -07001061 // Reconfigure AudioSendStream with new bit rate.
1062 if (send_rate) {
1063 config_.send_codec_spec->target_bitrate_bps = send_rate;
1064 }
1065 UpdateAllowedBitrateRange();
1066 ReconfigureAudioSendStream();
minyue7a973442016-10-20 03:27:12 -07001067 } else {
1068 // parameters.encodings[0].active could have changed.
1069 UpdateSendState();
1070 }
1071 return true;
skvlade0d46372016-04-07 22:59:22 -07001072 }
1073
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001074 private:
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001075 void UpdateSendState() {
1076 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1077 RTC_DCHECK(stream_);
Taylor Brandstetter55dd7082016-05-03 13:50:11 -07001078 RTC_DCHECK_EQ(1UL, rtp_parameters_.encodings.size());
1079 if (send_ && source_ != nullptr && rtp_parameters_.encodings[0].active) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001080 stream_->Start();
1081 } else { // !send || source_ = nullptr
1082 stream_->Stop();
1083 }
1084 }
1085
ossu20a4b3f2017-04-27 02:08:52 -07001086 void UpdateAllowedBitrateRange() {
michaelt53fe19d2016-10-18 09:39:22 -07001087 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
ossu20a4b3f2017-04-27 02:08:52 -07001088 const bool is_opus =
1089 config_.send_codec_spec &&
1090 !STR_CASE_CMP(config_.send_codec_spec->format.name.c_str(),
1091 kOpusCodecName);
1092 if (is_opus && webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe")) {
stefane9f36d52017-01-24 08:18:45 -08001093 config_.min_bitrate_bps = kOpusMinBitrateBps;
minyuececec102017-03-27 13:04:25 -07001094
1095 // This means that when RtpParameters is reset, we may change the
ossu20a4b3f2017-04-27 02:08:52 -07001096 // encoder's bit rate immediately (through ReconfigureAudioSendStream()),
minyuececec102017-03-27 13:04:25 -07001097 // meanwhile change the cap to the output of BWE.
1098 config_.max_bitrate_bps =
1099 rtp_parameters_.encodings[0].max_bitrate_bps
1100 ? *rtp_parameters_.encodings[0].max_bitrate_bps
1101 : kOpusBitrateFbBps;
1102
michaelt53fe19d2016-10-18 09:39:22 -07001103 // TODO(mflodman): Keep testing this and set proper values.
1104 // Note: This is an early experiment currently only supported by Opus.
elad.alon0fe12162017-01-31 05:48:37 -08001105 if (send_side_bwe_with_overhead_) {
ossu20a4b3f2017-04-27 02:08:52 -07001106 const int max_packet_size_ms =
1107 WEBRTC_OPUS_SUPPORT_120MS_PTIME ? 120 : 60;
michaelt6672b262017-01-11 10:17:59 -08001108
ossu20a4b3f2017-04-27 02:08:52 -07001109 // OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12)
1110 constexpr int kOverheadPerPacket = 20 + 8 + 10 + 12;
michaelt6672b262017-01-11 10:17:59 -08001111
ossu20a4b3f2017-04-27 02:08:52 -07001112 int min_overhead_bps =
1113 kOverheadPerPacket * 8 * 1000 / max_packet_size_ms;
michaelt6672b262017-01-11 10:17:59 -08001114
ossu20a4b3f2017-04-27 02:08:52 -07001115 // We assume that |config_.max_bitrate_bps| before the next line is
1116 // a hard limit on the payload bitrate, so we add min_overhead_bps to
1117 // it to ensure that, when overhead is deducted, the payload rate
1118 // never goes beyond the limit.
1119 // Note: this also means that if a higher overhead is forced, we
1120 // cannot reach the limit.
1121 // TODO(minyue): Reconsider this when the signaling to BWE is done
1122 // through a dedicated API.
1123 config_.max_bitrate_bps += min_overhead_bps;
michaelt6672b262017-01-11 10:17:59 -08001124
ossu20a4b3f2017-04-27 02:08:52 -07001125 // In contrast to max_bitrate_bps, we let min_bitrate_bps always be
1126 // reachable.
1127 config_.min_bitrate_bps += min_overhead_bps;
michaelt6672b262017-01-11 10:17:59 -08001128 }
michaelt53fe19d2016-10-18 09:39:22 -07001129 }
ossu20a4b3f2017-04-27 02:08:52 -07001130 }
1131
1132 void UpdateSendCodecSpec(
1133 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) {
1134 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1135 config_.rtp.nack.rtp_history_ms =
1136 send_codec_spec.nack_enabled ? kNackRtpHistoryMs : 0;
1137 config_.send_codec_spec =
1138 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>(
1139 send_codec_spec);
1140 auto info =
1141 config_.encoder_factory->QueryAudioEncoder(send_codec_spec.format);
1142 RTC_DCHECK(info);
1143 // If a specific target bitrate has been set for the stream, use that as
1144 // the new default bitrate when computing send bitrate.
1145 if (send_codec_spec.target_bitrate_bps) {
1146 info->default_bitrate_bps = std::max(
1147 info->min_bitrate_bps,
1148 std::min(info->max_bitrate_bps, *send_codec_spec.target_bitrate_bps));
1149 }
1150
1151 audio_codec_spec_.emplace(
1152 webrtc::AudioCodecSpec{send_codec_spec.format, *info});
1153
1154 config_.send_codec_spec->target_bitrate_bps = ComputeSendBitrate(
1155 max_send_bitrate_bps_, rtp_parameters_.encodings[0].max_bitrate_bps,
1156 *audio_codec_spec_);
1157
1158 UpdateAllowedBitrateRange();
1159 }
1160
1161 void ReconfigureAudioSendStream() {
1162 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1163 RTC_DCHECK(stream_);
1164 stream_->Reconfigure(config_);
michaelt53fe19d2016-10-18 09:39:22 -07001165 }
1166
solenberg566ef242015-11-06 15:34:49 -08001167 rtc::ThreadChecker worker_thread_checker_;
solenberg347ec5c2016-09-23 04:21:47 -07001168 rtc::RaceChecker audio_capture_race_checker_;
solenbergc96df772015-10-21 13:01:53 -07001169 webrtc::AudioTransport* const voe_audio_transport_ = nullptr;
1170 webrtc::Call* call_ = nullptr;
solenberg3a941542015-11-16 07:34:50 -08001171 webrtc::AudioSendStream::Config config_;
elad.alon0fe12162017-01-31 05:48:37 -08001172 const bool send_side_bwe_with_overhead_;
solenberg3a941542015-11-16 07:34:50 -08001173 // The stream is owned by WebRtcAudioSendStream and may be reallocated if
1174 // configuration changes.
solenbergc96df772015-10-21 13:01:53 -07001175 webrtc::AudioSendStream* stream_ = nullptr;
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001176
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001177 // Raw pointer to AudioSource owned by LocalAudioTrackHandler.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001178 // PeerConnection will make sure invalidating the pointer before the object
1179 // goes away.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001180 AudioSource* source_ = nullptr;
1181 bool send_ = false;
solenberg94218532016-06-16 10:53:22 -07001182 bool muted_ = false;
minyue7a973442016-10-20 03:27:12 -07001183 int max_send_bitrate_bps_;
skvlade0d46372016-04-07 22:59:22 -07001184 webrtc::RtpParameters rtp_parameters_;
ossu20a4b3f2017-04-27 02:08:52 -07001185 rtc::Optional<webrtc::AudioCodecSpec> audio_codec_spec_;
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00001186
solenbergc96df772015-10-21 13:01:53 -07001187 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream);
1188};
1189
1190class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
1191 public:
ossu29b1a8d2016-06-13 07:34:51 -07001192 WebRtcAudioReceiveStream(
1193 int ch,
1194 uint32_t remote_ssrc,
1195 uint32_t local_ssrc,
1196 bool use_transport_cc,
solenberg8189b022016-06-14 12:13:00 -07001197 bool use_nack,
ossu29b1a8d2016-06-13 07:34:51 -07001198 const std::string& sync_group,
1199 const std::vector<webrtc::RtpExtension>& extensions,
1200 webrtc::Call* call,
1201 webrtc::Transport* rtcp_send_transport,
kwiberg1c07c702017-03-27 07:15:49 -07001202 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
1203 const std::map<int, webrtc::SdpAudioFormat>& decoder_map)
stefanba4c0e42016-02-04 04:12:24 -08001204 : call_(call), config_() {
solenberg7add0582015-11-20 09:59:34 -08001205 RTC_DCHECK_GE(ch, 0);
1206 RTC_DCHECK(call);
1207 config_.rtp.remote_ssrc = remote_ssrc;
kwibergd32bf752017-01-19 07:03:59 -08001208 config_.rtp.local_ssrc = local_ssrc;
1209 config_.rtp.transport_cc = use_transport_cc;
1210 config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0;
1211 config_.rtp.extensions = extensions;
solenberg31fec402016-05-06 02:13:12 -07001212 config_.rtcp_send_transport = rtcp_send_transport;
solenberg7add0582015-11-20 09:59:34 -08001213 config_.voe_channel_id = ch;
1214 config_.sync_group = sync_group;
ossu29b1a8d2016-06-13 07:34:51 -07001215 config_.decoder_factory = decoder_factory;
kwiberg1c07c702017-03-27 07:15:49 -07001216 config_.decoder_map = decoder_map;
kwibergd32bf752017-01-19 07:03:59 -08001217 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001218 }
solenbergc96df772015-10-21 13:01:53 -07001219
solenberg7add0582015-11-20 09:59:34 -08001220 ~WebRtcAudioReceiveStream() {
1221 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1222 call_->DestroyAudioReceiveStream(stream_);
1223 }
1224
solenberg4a0f7b52016-06-16 13:07:33 -07001225 void RecreateAudioReceiveStream(uint32_t local_ssrc) {
solenberg7add0582015-11-20 09:59:34 -08001226 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001227 config_.rtp.local_ssrc = local_ssrc;
1228 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001229 }
solenberg8189b022016-06-14 12:13:00 -07001230
1231 void RecreateAudioReceiveStream(bool use_transport_cc, bool use_nack) {
solenberg7add0582015-11-20 09:59:34 -08001232 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001233 config_.rtp.transport_cc = use_transport_cc;
1234 config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0;
1235 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001236 }
1237
solenberg4a0f7b52016-06-16 13:07:33 -07001238 void RecreateAudioReceiveStream(
1239 const std::vector<webrtc::RtpExtension>& extensions) {
1240 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001241 config_.rtp.extensions = extensions;
1242 RecreateAudioReceiveStream();
1243 }
1244
deadbeefcb383672017-04-26 16:28:42 -07001245 // Set a new payload type -> decoder map.
kwibergd32bf752017-01-19 07:03:59 -08001246 void RecreateAudioReceiveStream(
1247 const std::map<int, webrtc::SdpAudioFormat>& decoder_map) {
1248 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001249 config_.decoder_map = decoder_map;
1250 RecreateAudioReceiveStream();
solenberg4a0f7b52016-06-16 13:07:33 -07001251 }
1252
solenberg4904fb62017-02-17 12:01:14 -08001253 void MaybeRecreateAudioReceiveStream(const std::string& sync_group) {
1254 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1255 if (config_.sync_group != sync_group) {
1256 config_.sync_group = sync_group;
1257 RecreateAudioReceiveStream();
1258 }
1259 }
1260
solenberg7add0582015-11-20 09:59:34 -08001261 webrtc::AudioReceiveStream::Stats GetStats() const {
1262 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1263 RTC_DCHECK(stream_);
1264 return stream_->GetStats();
1265 }
1266
solenberg796b8f92017-03-01 17:02:23 -08001267 int GetOutputLevel() const {
1268 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1269 RTC_DCHECK(stream_);
1270 return stream_->GetOutputLevel();
1271 }
1272
solenberg7add0582015-11-20 09:59:34 -08001273 int channel() const {
1274 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1275 return config_.voe_channel_id;
1276 }
solenbergc96df772015-10-21 13:01:53 -07001277
kwiberg686a8ef2016-02-26 03:00:35 -08001278 void SetRawAudioSink(std::unique_ptr<webrtc::AudioSinkInterface> sink) {
Tommif888bb52015-12-12 01:37:01 +01001279 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwiberg686a8ef2016-02-26 03:00:35 -08001280 stream_->SetSink(std::move(sink));
Tommif888bb52015-12-12 01:37:01 +01001281 }
1282
solenberg217fb662016-06-17 08:30:54 -07001283 void SetOutputVolume(double volume) {
1284 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1285 stream_->SetGain(volume);
1286 }
1287
aleloi84ef6152016-08-04 05:28:21 -07001288 void SetPlayout(bool playout) {
1289 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1290 RTC_DCHECK(stream_);
1291 if (playout) {
1292 LOG(LS_INFO) << "Starting playout for channel #" << channel();
1293 stream_->Start();
1294 } else {
1295 LOG(LS_INFO) << "Stopping playout for channel #" << channel();
1296 stream_->Stop();
1297 }
aleloi18e0b672016-10-04 02:45:47 -07001298 playout_ = playout;
aleloi84ef6152016-08-04 05:28:21 -07001299 }
1300
hbos8d609f62017-04-10 07:39:05 -07001301 std::vector<webrtc::RtpSource> GetSources() {
1302 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1303 RTC_DCHECK(stream_);
1304 return stream_->GetSources();
1305 }
1306
solenbergc96df772015-10-21 13:01:53 -07001307 private:
kwibergd32bf752017-01-19 07:03:59 -08001308 void RecreateAudioReceiveStream() {
solenberg7add0582015-11-20 09:59:34 -08001309 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1310 if (stream_) {
1311 call_->DestroyAudioReceiveStream(stream_);
solenberg7add0582015-11-20 09:59:34 -08001312 }
solenberg7add0582015-11-20 09:59:34 -08001313 stream_ = call_->CreateAudioReceiveStream(config_);
1314 RTC_CHECK(stream_);
aleloi18e0b672016-10-04 02:45:47 -07001315 SetPlayout(playout_);
solenberg7add0582015-11-20 09:59:34 -08001316 }
1317
1318 rtc::ThreadChecker worker_thread_checker_;
1319 webrtc::Call* call_ = nullptr;
1320 webrtc::AudioReceiveStream::Config config_;
1321 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if
1322 // configuration changes.
1323 webrtc::AudioReceiveStream* stream_ = nullptr;
aleloi18e0b672016-10-04 02:45:47 -07001324 bool playout_ = false;
solenbergc96df772015-10-21 13:01:53 -07001325
1326 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioReceiveStream);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001327};
1328
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001329WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine,
nisse51542be2016-02-12 02:27:06 -08001330 const MediaConfig& config,
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001331 const AudioOptions& options,
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001332 webrtc::Call* call)
nisse51542be2016-02-12 02:27:06 -08001333 : VoiceMediaChannel(config), engine_(engine), call_(call) {
solenberg0a617e22015-10-20 15:49:38 -07001334 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel";
solenberg566ef242015-11-06 15:34:49 -08001335 RTC_DCHECK(call);
solenberg0a617e22015-10-20 15:49:38 -07001336 engine->RegisterChannel(this);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001337 SetOptions(options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001338}
1339
1340WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() {
solenberg566ef242015-11-06 15:34:49 -08001341 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg0a617e22015-10-20 15:49:38 -07001342 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel";
solenberg7add0582015-11-20 09:59:34 -08001343 // TODO(solenberg): Should be able to delete the streams directly, without
1344 // going through RemoveNnStream(), once stream objects handle
1345 // all (de)configuration.
solenbergc96df772015-10-21 13:01:53 -07001346 while (!send_streams_.empty()) {
1347 RemoveSendStream(send_streams_.begin()->first);
solenbergd97ec302015-10-07 01:40:33 -07001348 }
solenberg7add0582015-11-20 09:59:34 -08001349 while (!recv_streams_.empty()) {
1350 RemoveRecvStream(recv_streams_.begin()->first);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001351 }
solenberg0a617e22015-10-20 15:49:38 -07001352 engine()->UnregisterChannel(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001353}
1354
nisse51542be2016-02-12 02:27:06 -08001355rtc::DiffServCodePoint WebRtcVoiceMediaChannel::PreferredDscp() const {
1356 return kAudioDscpValue;
1357}
1358
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001359bool WebRtcVoiceMediaChannel::SetSendParameters(
1360 const AudioSendParameters& params) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001361 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetSendParameters");
solenberg566ef242015-11-06 15:34:49 -08001362 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7e4e01a2015-12-02 08:05:01 -08001363 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendParameters: "
1364 << params.ToString();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001365 // TODO(pthatcher): Refactor this to be more clean now that we have
1366 // all the information at once.
solenberg3a941542015-11-16 07:34:50 -08001367
1368 if (!SetSendCodecs(params.codecs)) {
1369 return false;
1370 }
1371
solenberg7e4e01a2015-12-02 08:05:01 -08001372 if (!ValidateRtpExtensions(params.extensions)) {
1373 return false;
1374 }
1375 std::vector<webrtc::RtpExtension> filtered_extensions =
1376 FilterRtpExtensions(params.extensions,
1377 webrtc::RtpExtension::IsSupportedForAudio, true);
1378 if (send_rtp_extensions_ != filtered_extensions) {
1379 send_rtp_extensions_.swap(filtered_extensions);
solenberg3a941542015-11-16 07:34:50 -08001380 for (auto& it : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001381 it.second->SetRtpExtensions(send_rtp_extensions_);
solenberg3a941542015-11-16 07:34:50 -08001382 }
1383 }
1384
deadbeef80346142016-04-27 14:17:10 -07001385 if (!SetMaxSendBitrate(params.max_bandwidth_bps)) {
solenberg3a941542015-11-16 07:34:50 -08001386 return false;
1387 }
1388 return SetOptions(params.options);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001389}
1390
1391bool WebRtcVoiceMediaChannel::SetRecvParameters(
1392 const AudioRecvParameters& params) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001393 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetRecvParameters");
solenberg566ef242015-11-06 15:34:49 -08001394 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7e4e01a2015-12-02 08:05:01 -08001395 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetRecvParameters: "
1396 << params.ToString();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001397 // TODO(pthatcher): Refactor this to be more clean now that we have
1398 // all the information at once.
solenberg7add0582015-11-20 09:59:34 -08001399
1400 if (!SetRecvCodecs(params.codecs)) {
1401 return false;
1402 }
1403
solenberg7e4e01a2015-12-02 08:05:01 -08001404 if (!ValidateRtpExtensions(params.extensions)) {
1405 return false;
1406 }
1407 std::vector<webrtc::RtpExtension> filtered_extensions =
1408 FilterRtpExtensions(params.extensions,
1409 webrtc::RtpExtension::IsSupportedForAudio, false);
1410 if (recv_rtp_extensions_ != filtered_extensions) {
1411 recv_rtp_extensions_.swap(filtered_extensions);
solenberg7add0582015-11-20 09:59:34 -08001412 for (auto& it : recv_streams_) {
1413 it.second->RecreateAudioReceiveStream(recv_rtp_extensions_);
1414 }
1415 }
solenberg7add0582015-11-20 09:59:34 -08001416 return true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001417}
1418
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001419webrtc::RtpParameters WebRtcVoiceMediaChannel::GetRtpSendParameters(
skvlade0d46372016-04-07 22:59:22 -07001420 uint32_t ssrc) const {
1421 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1422 auto it = send_streams_.find(ssrc);
1423 if (it == send_streams_.end()) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001424 LOG(LS_WARNING) << "Attempting to get RTP send parameters for stream "
1425 << "with ssrc " << ssrc << " which doesn't exist.";
skvlade0d46372016-04-07 22:59:22 -07001426 return webrtc::RtpParameters();
1427 }
1428
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001429 webrtc::RtpParameters rtp_params = it->second->rtp_parameters();
1430 // Need to add the common list of codecs to the send stream-specific
1431 // RTP parameters.
1432 for (const AudioCodec& codec : send_codecs_) {
1433 rtp_params.codecs.push_back(codec.ToCodecParameters());
1434 }
1435 return rtp_params;
skvlade0d46372016-04-07 22:59:22 -07001436}
1437
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001438bool WebRtcVoiceMediaChannel::SetRtpSendParameters(
skvlade0d46372016-04-07 22:59:22 -07001439 uint32_t ssrc,
1440 const webrtc::RtpParameters& parameters) {
1441 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
skvlade0d46372016-04-07 22:59:22 -07001442 auto it = send_streams_.find(ssrc);
1443 if (it == send_streams_.end()) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001444 LOG(LS_WARNING) << "Attempting to set RTP send parameters for stream "
1445 << "with ssrc " << ssrc << " which doesn't exist.";
skvlade0d46372016-04-07 22:59:22 -07001446 return false;
1447 }
1448
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001449 // TODO(deadbeef): Handle setting parameters with a list of codecs in a
1450 // different order (which should change the send codec).
1451 webrtc::RtpParameters current_parameters = GetRtpSendParameters(ssrc);
1452 if (current_parameters.codecs != parameters.codecs) {
1453 LOG(LS_ERROR) << "Using SetParameters to change the set of codecs "
1454 << "is not currently supported.";
1455 return false;
1456 }
1457
minyue7a973442016-10-20 03:27:12 -07001458 // TODO(minyue): The following legacy actions go into
1459 // |WebRtcAudioSendStream::SetRtpParameters()| which is called at the end,
1460 // though there are two difference:
1461 // 1. |WebRtcVoiceMediaChannel::SetChannelSendParameters()| only calls
1462 // |SetSendCodec| while |WebRtcAudioSendStream::SetRtpParameters()| calls
1463 // |SetSendCodecs|. The outcome should be the same.
1464 // 2. AudioSendStream can be recreated.
1465
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001466 // Codecs are handled at the WebRtcVoiceMediaChannel level.
1467 webrtc::RtpParameters reduced_params = parameters;
1468 reduced_params.codecs.clear();
minyue7a973442016-10-20 03:27:12 -07001469 return it->second->SetRtpParameters(reduced_params);
skvlade0d46372016-04-07 22:59:22 -07001470}
1471
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001472webrtc::RtpParameters WebRtcVoiceMediaChannel::GetRtpReceiveParameters(
1473 uint32_t ssrc) const {
1474 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef3bc15102017-04-20 19:25:07 -07001475 webrtc::RtpParameters rtp_params;
1476 // SSRC of 0 represents the default receive stream.
1477 if (ssrc == 0) {
1478 if (!default_sink_) {
1479 LOG(LS_WARNING) << "Attempting to get RTP parameters for the default, "
1480 "unsignaled audio receive stream, but not yet "
1481 "configured to receive such a stream.";
1482 return rtp_params;
1483 }
1484 rtp_params.encodings.emplace_back();
1485 } else {
1486 auto it = recv_streams_.find(ssrc);
1487 if (it == recv_streams_.end()) {
1488 LOG(LS_WARNING) << "Attempting to get RTP receive parameters for stream "
1489 << "with ssrc " << ssrc << " which doesn't exist.";
1490 return webrtc::RtpParameters();
1491 }
1492 rtp_params.encodings.emplace_back();
1493 // TODO(deadbeef): Return stream-specific parameters.
1494 rtp_params.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001495 }
1496
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001497 for (const AudioCodec& codec : recv_codecs_) {
1498 rtp_params.codecs.push_back(codec.ToCodecParameters());
1499 }
1500 return rtp_params;
1501}
1502
1503bool WebRtcVoiceMediaChannel::SetRtpReceiveParameters(
1504 uint32_t ssrc,
1505 const webrtc::RtpParameters& parameters) {
1506 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef3bc15102017-04-20 19:25:07 -07001507 // SSRC of 0 represents the default receive stream.
1508 if (ssrc == 0) {
1509 if (!default_sink_) {
1510 LOG(LS_WARNING) << "Attempting to set RTP parameters for the default, "
1511 "unsignaled audio receive stream, but not yet "
1512 "configured to receive such a stream.";
1513 return false;
1514 }
1515 } else {
1516 auto it = recv_streams_.find(ssrc);
1517 if (it == recv_streams_.end()) {
1518 LOG(LS_WARNING) << "Attempting to set RTP receive parameters for stream "
1519 << "with ssrc " << ssrc << " which doesn't exist.";
1520 return false;
1521 }
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001522 }
1523
1524 webrtc::RtpParameters current_parameters = GetRtpReceiveParameters(ssrc);
1525 if (current_parameters != parameters) {
1526 LOG(LS_ERROR) << "Changing the RTP receive parameters is currently "
1527 << "unsupported.";
1528 return false;
1529 }
1530 return true;
1531}
1532
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001533bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
solenberg566ef242015-11-06 15:34:49 -08001534 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001535 LOG(LS_INFO) << "Setting voice channel options: "
1536 << options.ToString();
1537
1538 // We retain all of the existing options, and apply the given ones
1539 // on top. This means there is no way to "clear" options such that
1540 // they go back to the engine default.
1541 options_.SetAll(options);
solenberg246b8172015-12-08 09:50:23 -08001542 if (!engine()->ApplyOptions(options_)) {
1543 LOG(LS_WARNING) <<
1544 "Failed to apply engine options during channel SetOptions.";
1545 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001546 }
minyue6b825df2016-10-31 04:08:32 -07001547
ossu20a4b3f2017-04-27 02:08:52 -07001548 rtc::Optional<std::string> audio_network_adaptor_config =
minyue6b825df2016-10-31 04:08:32 -07001549 GetAudioNetworkAdaptorConfig(options_);
1550 for (auto& it : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001551 it.second->SetAudioNetworkAdaptorConfig(audio_network_adaptor_config);
minyue6b825df2016-10-31 04:08:32 -07001552 }
1553
solenberg76377c52017-02-21 00:54:31 -08001554 LOG(LS_INFO) << "Set voice channel options. Current options: "
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001555 << options_.ToString();
1556 return true;
1557}
1558
1559bool WebRtcVoiceMediaChannel::SetRecvCodecs(
1560 const std::vector<AudioCodec>& codecs) {
solenberg566ef242015-11-06 15:34:49 -08001561 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg8fb30c32015-10-13 03:06:58 -07001562
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001563 // Set the payload types to be used for incoming media.
solenberg0b675462015-10-09 01:37:09 -07001564 LOG(LS_INFO) << "Setting receive voice codecs.";
solenberg0b675462015-10-09 01:37:09 -07001565
1566 if (!VerifyUniquePayloadTypes(codecs)) {
1567 LOG(LS_ERROR) << "Codec payload types overlap.";
1568 return false;
1569 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001570
kwibergd32bf752017-01-19 07:03:59 -08001571 // Create a payload type -> SdpAudioFormat map with all the decoders. Fail
1572 // unless the factory claims to support all decoders.
1573 std::map<int, webrtc::SdpAudioFormat> decoder_map;
1574 for (const AudioCodec& codec : codecs) {
deadbeefcb383672017-04-26 16:28:42 -07001575 // Log a warning if a codec's payload type is changing. This used to be
1576 // treated as an error. It's abnormal, but not really illegal.
1577 AudioCodec old_codec;
1578 if (FindCodec(recv_codecs_, codec, &old_codec) &&
1579 old_codec.id != codec.id) {
1580 LOG(LS_WARNING) << codec.name << " mapped to a second payload type ("
1581 << codec.id << ", was already mapped to " << old_codec.id
1582 << ")";
1583 }
kwibergd32bf752017-01-19 07:03:59 -08001584 auto format = AudioCodecToSdpAudioFormat(codec);
1585 if (!IsCodec(codec, "cn") && !IsCodec(codec, "telephone-event") &&
1586 !engine()->decoder_factory_->IsSupportedDecoder(format)) {
1587 LOG(LS_ERROR) << "Unsupported codec: " << format;
1588 return false;
1589 }
deadbeefcb383672017-04-26 16:28:42 -07001590 // We allow adding new codecs but don't allow changing the payload type of
1591 // codecs that are already configured since we might already be receiving
1592 // packets with that payload type. See RFC3264, Section 8.3.2.
1593 // TODO(deadbeef): Also need to check for clashes with previously mapped
1594 // payload types, and not just currently mapped ones. For example, this
1595 // should be illegal:
1596 // 1. {100: opus/48000/2, 101: ISAC/16000}
1597 // 2. {100: opus/48000/2}
1598 // 3. {100: opus/48000/2, 101: ISAC/32000}
1599 // Though this check really should happen at a higher level, since this
1600 // conflict could happen between audio and video codecs.
1601 auto existing = decoder_map_.find(codec.id);
1602 if (existing != decoder_map_.end() && !existing->second.Matches(format)) {
1603 LOG(LS_ERROR) << "Attempting to use payload type " << codec.id << " for "
1604 << codec.name << ", but it is already used for "
1605 << existing->second.name;
1606 return false;
1607 }
kwibergd32bf752017-01-19 07:03:59 -08001608 decoder_map.insert({codec.id, std::move(format)});
1609 }
1610
deadbeefcb383672017-04-26 16:28:42 -07001611 if (decoder_map == decoder_map_) {
1612 // There's nothing new to configure.
1613 return true;
1614 }
1615
kwiberg37b8b112016-11-03 02:46:53 -07001616 if (playout_) {
1617 // Receive codecs can not be changed while playing. So we temporarily
1618 // pause playout.
1619 ChangePlayout(false);
1620 }
1621
kwiberg1c07c702017-03-27 07:15:49 -07001622 decoder_map_ = std::move(decoder_map);
kwibergd32bf752017-01-19 07:03:59 -08001623 for (auto& kv : recv_streams_) {
kwiberg1c07c702017-03-27 07:15:49 -07001624 kv.second->RecreateAudioReceiveStream(decoder_map_);
solenberg26c8c912015-11-27 04:00:25 -08001625 }
kwibergd32bf752017-01-19 07:03:59 -08001626 recv_codecs_ = codecs;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001627
kwiberg37b8b112016-11-03 02:46:53 -07001628 if (desired_playout_ && !playout_) {
1629 ChangePlayout(desired_playout_);
1630 }
kwibergd32bf752017-01-19 07:03:59 -08001631 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001632}
1633
solenberg72e29d22016-03-08 06:35:16 -08001634// Utility function called from SetSendParameters() to extract current send
1635// codec settings from the given list of codecs (originally from SDP). Both send
1636// and receive streams may be reconfigured based on the new settings.
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001637bool WebRtcVoiceMediaChannel::SetSendCodecs(
1638 const std::vector<AudioCodec>& codecs) {
solenberg566ef242015-11-06 15:34:49 -08001639 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenbergb5727682015-12-04 15:22:19 +01001640 dtmf_payload_type_ = rtc::Optional<int>();
solenbergffbbcac2016-11-17 05:25:37 -08001641 dtmf_payload_freq_ = -1;
1642
1643 // Validate supplied codecs list.
1644 for (const AudioCodec& codec : codecs) {
1645 // TODO(solenberg): Validate more aspects of input - that payload types
1646 // don't overlap, remove redundant/unsupported codecs etc -
1647 // the same way it is done for RtpHeaderExtensions.
1648 if (codec.id < kMinPayloadType || codec.id > kMaxPayloadType) {
1649 LOG(LS_WARNING) << "Codec payload type out of range: " << ToString(codec);
1650 return false;
1651 }
1652 }
1653
1654 // Find PT of telephone-event codec with lowest clockrate, as a fallback, in
1655 // case we don't have a DTMF codec with a rate matching the send codec's, or
1656 // if this function returns early.
1657 std::vector<AudioCodec> dtmf_codecs;
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02001658 for (const AudioCodec& codec : codecs) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02001659 if (IsCodec(codec, kDtmfCodecName)) {
solenbergffbbcac2016-11-17 05:25:37 -08001660 dtmf_codecs.push_back(codec);
1661 if (!dtmf_payload_type_ || codec.clockrate < dtmf_payload_freq_) {
1662 dtmf_payload_type_ = rtc::Optional<int>(codec.id);
1663 dtmf_payload_freq_ = codec.clockrate;
solenberg31642aa2016-03-14 08:00:37 -07001664 }
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001665 }
1666 }
1667
ossu20a4b3f2017-04-27 02:08:52 -07001668 // Scan through the list to figure out the codec to use for sending.
1669 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec> send_codec_spec;
stefan1ccf73f2017-03-27 03:51:18 -07001670 webrtc::Call::Config::BitrateConfig bitrate_config;
ossu20a4b3f2017-04-27 02:08:52 -07001671 rtc::Optional<webrtc::AudioCodecInfo> voice_codec_info;
1672 for (const AudioCodec& voice_codec : codecs) {
1673 if (!(IsCodec(voice_codec, kCnCodecName) ||
1674 IsCodec(voice_codec, kDtmfCodecName) ||
1675 IsCodec(voice_codec, kRedCodecName))) {
1676 webrtc::SdpAudioFormat format(voice_codec.name, voice_codec.clockrate,
1677 voice_codec.channels, voice_codec.params);
solenberg72e29d22016-03-08 06:35:16 -08001678
ossu20a4b3f2017-04-27 02:08:52 -07001679 voice_codec_info = engine()->encoder_factory_->QueryAudioEncoder(format);
1680 if (!voice_codec_info) {
1681 LOG(LS_WARNING) << "Unknown codec " << ToString(voice_codec);
solenberg72e29d22016-03-08 06:35:16 -08001682 continue;
1683 }
1684
ossu20a4b3f2017-04-27 02:08:52 -07001685 send_codec_spec =
1686 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>(
1687 {voice_codec.id, format});
1688 if (voice_codec.bitrate > 0) {
1689 send_codec_spec->target_bitrate_bps =
1690 rtc::Optional<int>(voice_codec.bitrate);
1691 }
1692 send_codec_spec->transport_cc_enabled = HasTransportCc(voice_codec);
1693 send_codec_spec->nack_enabled = HasNack(voice_codec);
1694 bitrate_config = GetBitrateConfigForCodec(voice_codec);
1695 break;
1696 }
1697 }
1698
1699 if (!send_codec_spec) {
1700 return false;
1701 }
1702
1703 RTC_DCHECK(voice_codec_info);
1704 if (voice_codec_info->allow_comfort_noise) {
1705 // Loop through the codecs list again to find the CN codec.
1706 // TODO(solenberg): Break out into a separate function?
1707 for (const AudioCodec& cn_codec : codecs) {
ossu0c4b8492017-03-02 11:03:25 -08001708 if (IsCodec(cn_codec, kCnCodecName) &&
ossu20a4b3f2017-04-27 02:08:52 -07001709 cn_codec.clockrate == send_codec_spec->format.clockrate_hz) {
ossu0c4b8492017-03-02 11:03:25 -08001710 switch (cn_codec.clockrate) {
solenberg72e29d22016-03-08 06:35:16 -08001711 case 8000:
1712 case 16000:
1713 case 32000:
ossu20a4b3f2017-04-27 02:08:52 -07001714 send_codec_spec->cng_payload_type = rtc::Optional<int>(cn_codec.id);
solenberg72e29d22016-03-08 06:35:16 -08001715 break;
1716 default:
ossu0c4b8492017-03-02 11:03:25 -08001717 LOG(LS_WARNING) << "CN frequency " << cn_codec.clockrate
solenberg72e29d22016-03-08 06:35:16 -08001718 << " not supported.";
ossu20a4b3f2017-04-27 02:08:52 -07001719 break;
solenberg72e29d22016-03-08 06:35:16 -08001720 }
solenberg72e29d22016-03-08 06:35:16 -08001721 break;
1722 }
1723 }
solenbergffbbcac2016-11-17 05:25:37 -08001724
1725 // Find the telephone-event PT exactly matching the preferred send codec.
1726 for (const AudioCodec& dtmf_codec : dtmf_codecs) {
ossu20a4b3f2017-04-27 02:08:52 -07001727 if (dtmf_codec.clockrate == send_codec_spec->format.clockrate_hz) {
solenbergffbbcac2016-11-17 05:25:37 -08001728 dtmf_payload_type_ = rtc::Optional<int>(dtmf_codec.id);
1729 dtmf_payload_freq_ = dtmf_codec.clockrate;
1730 break;
1731 }
1732 }
solenberg72e29d22016-03-08 06:35:16 -08001733 }
1734
solenberg971cab02016-06-14 10:02:41 -07001735 if (send_codec_spec_ != send_codec_spec) {
1736 send_codec_spec_ = std::move(send_codec_spec);
stefan13f1a0a2016-11-30 07:22:58 -08001737 // Apply new settings to all streams.
solenberg971cab02016-06-14 10:02:41 -07001738 for (const auto& kv : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001739 kv.second->SetSendCodecSpec(*send_codec_spec_);
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001740 }
stefan13f1a0a2016-11-30 07:22:58 -08001741 } else {
1742 // If the codec isn't changing, set the start bitrate to -1 which means
1743 // "unchanged" so that BWE isn't affected.
stefan1ccf73f2017-03-27 03:51:18 -07001744 bitrate_config.start_bitrate_bps = -1;
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001745 }
stefan1ccf73f2017-03-27 03:51:18 -07001746 call_->SetBitrateConfig(bitrate_config);
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001747
solenberg8189b022016-06-14 12:13:00 -07001748 // Check if the transport cc feedback or NACK status has changed on the
1749 // preferred send codec, and in that case reconfigure all receive streams.
ossu20a4b3f2017-04-27 02:08:52 -07001750 if (recv_transport_cc_enabled_ != send_codec_spec_->transport_cc_enabled ||
1751 recv_nack_enabled_ != send_codec_spec_->nack_enabled) {
solenberg72e29d22016-03-08 06:35:16 -08001752 LOG(LS_INFO) << "Recreate all the receive streams because the send "
1753 "codec has changed.";
ossu20a4b3f2017-04-27 02:08:52 -07001754 recv_transport_cc_enabled_ = send_codec_spec_->transport_cc_enabled;
1755 recv_nack_enabled_ = send_codec_spec_->nack_enabled;
solenberg72e29d22016-03-08 06:35:16 -08001756 for (auto& kv : recv_streams_) {
solenberg8189b022016-06-14 12:13:00 -07001757 kv.second->RecreateAudioReceiveStream(recv_transport_cc_enabled_,
1758 recv_nack_enabled_);
solenberg72e29d22016-03-08 06:35:16 -08001759 }
1760 }
1761
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001762 send_codecs_ = codecs;
solenberg72e29d22016-03-08 06:35:16 -08001763 return true;
1764}
1765
aleloi84ef6152016-08-04 05:28:21 -07001766void WebRtcVoiceMediaChannel::SetPlayout(bool playout) {
kwiberg37b8b112016-11-03 02:46:53 -07001767 desired_playout_ = playout;
1768 return ChangePlayout(desired_playout_);
1769}
1770
1771void WebRtcVoiceMediaChannel::ChangePlayout(bool playout) {
1772 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::ChangePlayout");
solenberg566ef242015-11-06 15:34:49 -08001773 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001774 if (playout_ == playout) {
aleloi84ef6152016-08-04 05:28:21 -07001775 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001776 }
1777
aleloi84ef6152016-08-04 05:28:21 -07001778 for (const auto& kv : recv_streams_) {
1779 kv.second->SetPlayout(playout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001780 }
solenberg1ac56142015-10-13 03:58:19 -07001781 playout_ = playout;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001782}
1783
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001784void WebRtcVoiceMediaChannel::SetSend(bool send) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001785 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetSend");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001786 if (send_ == send) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001787 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001788 }
1789
solenbergd53a3f92016-04-14 13:56:37 -07001790 // Apply channel specific options, and initialize the ADM for recording (this
1791 // may take time on some platforms, e.g. Android).
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001792 if (send) {
solenberg63b34542015-09-29 06:06:31 -07001793 engine()->ApplyOptions(options_);
solenbergd53a3f92016-04-14 13:56:37 -07001794
1795 // InitRecording() may return an error if the ADM is already recording.
1796 if (!engine()->adm()->RecordingIsInitialized() &&
1797 !engine()->adm()->Recording()) {
1798 if (engine()->adm()->InitRecording() != 0) {
1799 LOG(LS_WARNING) << "Failed to initialize recording";
1800 }
1801 }
solenberg63b34542015-09-29 06:06:31 -07001802 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001803
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001804 // Change the settings on each send channel.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001805 for (auto& kv : send_streams_) {
1806 kv.second->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001807 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001808
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001809 send_ = send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001810}
1811
Peter Boström0c4e06b2015-10-07 12:23:21 +02001812bool WebRtcVoiceMediaChannel::SetAudioSend(uint32_t ssrc,
1813 bool enable,
solenberg1dd98f32015-09-10 01:57:14 -07001814 const AudioOptions* options,
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001815 AudioSource* source) {
solenberg566ef242015-11-06 15:34:49 -08001816 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg1dd98f32015-09-10 01:57:14 -07001817 // TODO(solenberg): The state change should be fully rolled back if any one of
1818 // these calls fail.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001819 if (!SetLocalSource(ssrc, source)) {
solenberg1dd98f32015-09-10 01:57:14 -07001820 return false;
1821 }
solenbergdfc8f4f2015-10-01 02:31:10 -07001822 if (!MuteStream(ssrc, !enable)) {
solenberg1dd98f32015-09-10 01:57:14 -07001823 return false;
1824 }
solenbergdfc8f4f2015-10-01 02:31:10 -07001825 if (enable && options) {
solenberg1dd98f32015-09-10 01:57:14 -07001826 return SetOptions(*options);
1827 }
1828 return true;
1829}
1830
solenberg0a617e22015-10-20 15:49:38 -07001831int WebRtcVoiceMediaChannel::CreateVoEChannel() {
1832 int id = engine()->CreateVoEChannel();
1833 if (id == -1) {
1834 LOG_RTCERR0(CreateVoEChannel);
1835 return -1;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001836 }
mflodman3d7db262016-04-29 00:57:13 -07001837
solenberg0a617e22015-10-20 15:49:38 -07001838 return id;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001839}
1840
solenberg7add0582015-11-20 09:59:34 -08001841bool WebRtcVoiceMediaChannel::DeleteVoEChannel(int channel) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001842 if (engine()->voe()->base()->DeleteChannel(channel) == -1) {
1843 LOG_RTCERR1(DeleteChannel, channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001844 return false;
1845 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001846 return true;
1847}
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001848
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001849bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001850 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::AddSendStream");
solenberg566ef242015-11-06 15:34:49 -08001851 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg0a617e22015-10-20 15:49:38 -07001852 LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
1853
1854 uint32_t ssrc = sp.first_ssrc();
1855 RTC_DCHECK(0 != ssrc);
1856
1857 if (GetSendChannelId(ssrc) != -1) {
1858 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001859 return false;
1860 }
1861
solenberg0a617e22015-10-20 15:49:38 -07001862 // Create a new channel for sending audio data.
1863 int channel = CreateVoEChannel();
1864 if (channel == -1) {
1865 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001866 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001867
solenbergc96df772015-10-21 13:01:53 -07001868 // Save the channel to send_streams_, so that RemoveSendStream() can still
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001869 // delete the channel in case failure happens below.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001870 webrtc::AudioTransport* audio_transport =
1871 engine()->voe()->base()->audio_transport();
mflodman3d7db262016-04-29 00:57:13 -07001872
minyue6b825df2016-10-31 04:08:32 -07001873 rtc::Optional<std::string> audio_network_adaptor_config =
1874 GetAudioNetworkAdaptorConfig(options_);
skvlade0d46372016-04-07 22:59:22 -07001875 WebRtcAudioSendStream* stream = new WebRtcAudioSendStream(
solenberg971cab02016-06-14 10:02:41 -07001876 channel, audio_transport, ssrc, sp.cname, send_codec_spec_,
minyue6b825df2016-10-31 04:08:32 -07001877 send_rtp_extensions_, max_send_bitrate_bps_, audio_network_adaptor_config,
ossu20a4b3f2017-04-27 02:08:52 -07001878 call_, this, engine()->encoder_factory_);
skvlade0d46372016-04-07 22:59:22 -07001879 send_streams_.insert(std::make_pair(ssrc, stream));
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001880
solenberg4a0f7b52016-06-16 13:07:33 -07001881 // At this point the stream's local SSRC has been updated. If it is the first
1882 // send stream, make sure that all the receive streams are updated with the
1883 // same SSRC in order to send receiver reports.
solenbergc96df772015-10-21 13:01:53 -07001884 if (send_streams_.size() == 1) {
solenberg0a617e22015-10-20 15:49:38 -07001885 receiver_reports_ssrc_ = ssrc;
solenberg4a0f7b52016-06-16 13:07:33 -07001886 for (const auto& kv : recv_streams_) {
1887 // TODO(solenberg): Allow applications to set the RTCP SSRC of receive
1888 // streams instead, so we can avoid recreating the streams here.
1889 kv.second->RecreateAudioReceiveStream(ssrc);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001890 }
1891 }
1892
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001893 send_streams_[ssrc]->SetSend(send_);
1894 return true;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001895}
1896
Peter Boström0c4e06b2015-10-07 12:23:21 +02001897bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001898 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::RemoveSendStream");
solenberg566ef242015-11-06 15:34:49 -08001899 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg3a941542015-11-16 07:34:50 -08001900 LOG(LS_INFO) << "RemoveSendStream: " << ssrc;
1901
solenbergc96df772015-10-21 13:01:53 -07001902 auto it = send_streams_.find(ssrc);
1903 if (it == send_streams_.end()) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001904 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
1905 << " which doesn't exist.";
1906 return false;
1907 }
1908
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001909 it->second->SetSend(false);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001910
solenberg7602aab2016-11-14 11:30:07 -08001911 // TODO(solenberg): If we're removing the receiver_reports_ssrc_ stream, find
1912 // the first active send stream and use that instead, reassociating receive
1913 // streams.
1914
solenberg7add0582015-11-20 09:59:34 -08001915 // Clean up and delete the send stream+channel.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001916 int channel = it->second->channel();
solenberg0a617e22015-10-20 15:49:38 -07001917 LOG(LS_INFO) << "Removing audio send stream " << ssrc
1918 << " with VoiceEngine channel #" << channel << ".";
solenberg7add0582015-11-20 09:59:34 -08001919 delete it->second;
1920 send_streams_.erase(it);
1921 if (!DeleteVoEChannel(channel)) {
solenberg0a617e22015-10-20 15:49:38 -07001922 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001923 }
solenbergc96df772015-10-21 13:01:53 -07001924 if (send_streams_.empty()) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001925 SetSend(false);
solenberg0a617e22015-10-20 15:49:38 -07001926 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001927 return true;
1928}
1929
1930bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001931 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::AddRecvStream");
solenberg566ef242015-11-06 15:34:49 -08001932 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergd97ec302015-10-07 01:40:33 -07001933 LOG(LS_INFO) << "AddRecvStream: " << sp.ToString();
1934
solenberg0b675462015-10-09 01:37:09 -07001935 if (!ValidateStreamParams(sp)) {
wu@webrtc.org78187522013-10-07 23:32:02 +00001936 return false;
1937 }
1938
solenberg7add0582015-11-20 09:59:34 -08001939 const uint32_t ssrc = sp.first_ssrc();
solenberg0b675462015-10-09 01:37:09 -07001940 if (ssrc == 0) {
1941 LOG(LS_WARNING) << "AddRecvStream with ssrc==0 is not supported.";
1942 return false;
1943 }
1944
solenberg2100c0b2017-03-01 11:29:29 -08001945 // If this stream was previously received unsignaled, we promote it, possibly
1946 // recreating the AudioReceiveStream, if sync_label has changed.
1947 if (MaybeDeregisterUnsignaledRecvStream(ssrc)) {
solenberg4904fb62017-02-17 12:01:14 -08001948 recv_streams_[ssrc]->MaybeRecreateAudioReceiveStream(sp.sync_label);
solenberg4904fb62017-02-17 12:01:14 -08001949 return true;
solenberg1ac56142015-10-13 03:58:19 -07001950 }
solenberg0b675462015-10-09 01:37:09 -07001951
solenberg7add0582015-11-20 09:59:34 -08001952 if (GetReceiveChannelId(ssrc) != -1) {
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001953 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001954 return false;
1955 }
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02001956
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001957 // Create a new channel for receiving audio data.
solenberg7add0582015-11-20 09:59:34 -08001958 const int channel = CreateVoEChannel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001959 if (channel == -1) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001960 return false;
1961 }
Minyue2013aec2015-05-13 14:14:42 +02001962
stefanba4c0e42016-02-04 04:12:24 -08001963 recv_streams_.insert(std::make_pair(
kwiberg1c07c702017-03-27 07:15:49 -07001964 ssrc,
1965 new WebRtcAudioReceiveStream(
1966 channel, ssrc, receiver_reports_ssrc_, recv_transport_cc_enabled_,
1967 recv_nack_enabled_, sp.sync_label, recv_rtp_extensions_, call_, this,
1968 engine()->decoder_factory_, decoder_map_)));
aleloi84ef6152016-08-04 05:28:21 -07001969 recv_streams_[ssrc]->SetPlayout(playout_);
solenberg7add0582015-11-20 09:59:34 -08001970
solenberg1ac56142015-10-13 03:58:19 -07001971 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001972}
1973
Peter Boström0c4e06b2015-10-07 12:23:21 +02001974bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001975 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::RemoveRecvStream");
solenberg566ef242015-11-06 15:34:49 -08001976 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergd97ec302015-10-07 01:40:33 -07001977 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
1978
solenberg7add0582015-11-20 09:59:34 -08001979 const auto it = recv_streams_.find(ssrc);
1980 if (it == recv_streams_.end()) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001981 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
1982 << " which doesn't exist.";
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001983 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001984 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001985
solenberg2100c0b2017-03-01 11:29:29 -08001986 MaybeDeregisterUnsignaledRecvStream(ssrc);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001987
solenberg7add0582015-11-20 09:59:34 -08001988 const int channel = it->second->channel();
1989
1990 // Clean up and delete the receive stream+channel.
1991 LOG(LS_INFO) << "Removing audio receive stream " << ssrc
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001992 << " with VoiceEngine channel #" << channel << ".";
Tommif888bb52015-12-12 01:37:01 +01001993 it->second->SetRawAudioSink(nullptr);
solenberg7add0582015-11-20 09:59:34 -08001994 delete it->second;
1995 recv_streams_.erase(it);
1996 return DeleteVoEChannel(channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001997}
1998
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001999bool WebRtcVoiceMediaChannel::SetLocalSource(uint32_t ssrc,
2000 AudioSource* source) {
solenbergc96df772015-10-21 13:01:53 -07002001 auto it = send_streams_.find(ssrc);
2002 if (it == send_streams_.end()) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002003 if (source) {
2004 // Return an error if trying to set a valid source with an invalid ssrc.
2005 LOG(LS_ERROR) << "SetLocalSource failed with ssrc " << ssrc;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002006 return false;
2007 }
2008
2009 // The channel likely has gone away, do nothing.
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002010 return true;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002011 }
2012
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002013 if (source) {
2014 it->second->SetSource(source);
solenberg1ac56142015-10-13 03:58:19 -07002015 } else {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002016 it->second->ClearSource();
solenberg1ac56142015-10-13 03:58:19 -07002017 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002018
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002019 return true;
2020}
2021
solenberg796b8f92017-03-01 17:02:23 -08002022// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002023bool WebRtcVoiceMediaChannel::GetActiveStreams(
2024 AudioInfo::StreamList* actives) {
solenberg566ef242015-11-06 15:34:49 -08002025 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002026 actives->clear();
solenberg7add0582015-11-20 09:59:34 -08002027 for (const auto& ch : recv_streams_) {
solenberg796b8f92017-03-01 17:02:23 -08002028 int level = ch.second->GetOutputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002029 if (level > 0) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02002030 actives->push_back(std::make_pair(ch.first, level));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002031 }
2032 }
2033 return true;
2034}
2035
solenberg796b8f92017-03-01 17:02:23 -08002036// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002037int WebRtcVoiceMediaChannel::GetOutputLevel() {
solenberg566ef242015-11-06 15:34:49 -08002038 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg1ac56142015-10-13 03:58:19 -07002039 int highest = 0;
solenberg7add0582015-11-20 09:59:34 -08002040 for (const auto& ch : recv_streams_) {
solenberg796b8f92017-03-01 17:02:23 -08002041 highest = std::max(ch.second->GetOutputLevel(), highest);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002042 }
2043 return highest;
2044}
2045
solenberg4bac9c52015-10-09 02:32:53 -07002046bool WebRtcVoiceMediaChannel::SetOutputVolume(uint32_t ssrc, double volume) {
solenberg566ef242015-11-06 15:34:49 -08002047 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg2100c0b2017-03-01 11:29:29 -08002048 std::vector<uint32_t> ssrcs(1, ssrc);
deadbeef3bc15102017-04-20 19:25:07 -07002049 // SSRC of 0 represents the default receive stream.
solenberg1ac56142015-10-13 03:58:19 -07002050 if (ssrc == 0) {
2051 default_recv_volume_ = volume;
solenberg2100c0b2017-03-01 11:29:29 -08002052 ssrcs = unsignaled_recv_ssrcs_;
2053 }
2054 for (uint32_t ssrc : ssrcs) {
2055 const auto it = recv_streams_.find(ssrc);
2056 if (it == recv_streams_.end()) {
2057 LOG(LS_WARNING) << "SetOutputVolume: no recv stream " << ssrc;
2058 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002059 }
solenberg2100c0b2017-03-01 11:29:29 -08002060 it->second->SetOutputVolume(volume);
2061 LOG(LS_INFO) << "SetOutputVolume() to " << volume
2062 << " for recv stream with ssrc " << ssrc;
solenberg1ac56142015-10-13 03:58:19 -07002063 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002064 return true;
2065}
2066
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002067bool WebRtcVoiceMediaChannel::CanInsertDtmf() {
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002068 return dtmf_payload_type_ ? true : false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002069}
2070
solenberg1d63dd02015-12-02 12:35:09 -08002071bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, int event,
2072 int duration) {
solenberg566ef242015-11-06 15:34:49 -08002073 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002074 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::InsertDtmf";
2075 if (!dtmf_payload_type_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002076 return false;
2077 }
2078
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002079 // Figure out which WebRtcAudioSendStream to send the event on.
2080 auto it = ssrc != 0 ? send_streams_.find(ssrc) : send_streams_.begin();
2081 if (it == send_streams_.end()) {
2082 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
solenberg1d63dd02015-12-02 12:35:09 -08002083 return false;
2084 }
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002085 if (event < kMinTelephoneEventCode ||
2086 event > kMaxTelephoneEventCode) {
2087 LOG(LS_WARNING) << "DTMF event code " << event << " out of range.";
solenberg1d63dd02015-12-02 12:35:09 -08002088 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002089 }
solenbergffbbcac2016-11-17 05:25:37 -08002090 RTC_DCHECK_NE(-1, dtmf_payload_freq_);
2091 return it->second->SendTelephoneEvent(*dtmf_payload_type_, dtmf_payload_freq_,
2092 event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002093}
2094
wu@webrtc.orga9890802013-12-13 00:21:03 +00002095void WebRtcVoiceMediaChannel::OnPacketReceived(
jbaucheec21bd2016-03-20 06:15:43 -07002096 rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
solenberg566ef242015-11-06 15:34:49 -08002097 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02002098
mflodman3d7db262016-04-29 00:57:13 -07002099 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
2100 packet_time.not_before);
2101 webrtc::PacketReceiver::DeliveryStatus delivery_result =
2102 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
2103 packet->cdata(), packet->size(),
2104 webrtc_packet_time);
mflodman3d7db262016-04-29 00:57:13 -07002105 if (delivery_result != webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC) {
2106 return;
2107 }
2108
solenberg2100c0b2017-03-01 11:29:29 -08002109 // Create an unsignaled receive stream for this previously not received ssrc.
2110 // If there already is N unsignaled receive streams, delete the oldest.
mflodman3d7db262016-04-29 00:57:13 -07002111 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5208
solenberg1ac56142015-10-13 03:58:19 -07002112 uint32_t ssrc = 0;
jbaucheec21bd2016-03-20 06:15:43 -07002113 if (!GetRtpSsrc(packet->cdata(), packet->size(), &ssrc)) {
solenberg1ac56142015-10-13 03:58:19 -07002114 return;
2115 }
solenberg2100c0b2017-03-01 11:29:29 -08002116 RTC_DCHECK(std::find(unsignaled_recv_ssrcs_.begin(),
2117 unsignaled_recv_ssrcs_.end(), ssrc) == unsignaled_recv_ssrcs_.end());
solenberg1ac56142015-10-13 03:58:19 -07002118
solenberg2100c0b2017-03-01 11:29:29 -08002119 // Add new stream.
mflodman3d7db262016-04-29 00:57:13 -07002120 StreamParams sp;
2121 sp.ssrcs.push_back(ssrc);
solenberg2100c0b2017-03-01 11:29:29 -08002122 LOG(LS_INFO) << "Creating unsignaled receive stream for SSRC=" << ssrc;
mflodman3d7db262016-04-29 00:57:13 -07002123 if (!AddRecvStream(sp)) {
solenberg2100c0b2017-03-01 11:29:29 -08002124 LOG(LS_WARNING) << "Could not create unsignaled receive stream.";
mflodman3d7db262016-04-29 00:57:13 -07002125 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002126 }
solenberg2100c0b2017-03-01 11:29:29 -08002127 unsignaled_recv_ssrcs_.push_back(ssrc);
2128 RTC_HISTOGRAM_COUNTS_LINEAR(
2129 "WebRTC.Audio.NumOfUnsignaledStreams", unsignaled_recv_ssrcs_.size(), 1,
2130 100, 101);
solenbergf748ca42017-02-06 13:03:19 -08002131
solenberg2100c0b2017-03-01 11:29:29 -08002132 // Remove oldest unsignaled stream, if we have too many.
2133 if (unsignaled_recv_ssrcs_.size() > kMaxUnsignaledRecvStreams) {
2134 uint32_t remove_ssrc = unsignaled_recv_ssrcs_.front();
2135 LOG(LS_INFO) << "Removing unsignaled receive stream with SSRC="
2136 << remove_ssrc;
2137 RemoveRecvStream(remove_ssrc);
2138 }
2139 RTC_DCHECK_GE(kMaxUnsignaledRecvStreams, unsignaled_recv_ssrcs_.size());
2140
2141 SetOutputVolume(ssrc, default_recv_volume_);
2142
2143 // The default sink can only be attached to one stream at a time, so we hook
2144 // it up to the *latest* unsignaled stream we've seen, in order to support the
2145 // case where the SSRC of one unsignaled stream changes.
mflodman3d7db262016-04-29 00:57:13 -07002146 if (default_sink_) {
solenberg2100c0b2017-03-01 11:29:29 -08002147 for (uint32_t drop_ssrc : unsignaled_recv_ssrcs_) {
2148 auto it = recv_streams_.find(drop_ssrc);
2149 it->second->SetRawAudioSink(nullptr);
2150 }
mflodman3d7db262016-04-29 00:57:13 -07002151 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
2152 new ProxySink(default_sink_.get()));
solenberg2100c0b2017-03-01 11:29:29 -08002153 SetRawAudioSink(ssrc, std::move(proxy_sink));
mflodman3d7db262016-04-29 00:57:13 -07002154 }
solenberg2100c0b2017-03-01 11:29:29 -08002155
mflodman3d7db262016-04-29 00:57:13 -07002156 delivery_result = call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
2157 packet->cdata(),
2158 packet->size(),
2159 webrtc_packet_time);
2160 RTC_DCHECK_NE(webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC, delivery_result);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002161}
2162
wu@webrtc.orga9890802013-12-13 00:21:03 +00002163void WebRtcVoiceMediaChannel::OnRtcpReceived(
jbaucheec21bd2016-03-20 06:15:43 -07002164 rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
solenberg566ef242015-11-06 15:34:49 -08002165 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02002166
Fredrik Solenberg709ed672015-09-15 12:26:33 +02002167 // Forward packet to Call as well.
2168 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
2169 packet_time.not_before);
2170 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
jbaucheec21bd2016-03-20 06:15:43 -07002171 packet->cdata(), packet->size(), webrtc_packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002172}
2173
Honghai Zhangcc411c02016-03-29 17:27:21 -07002174void WebRtcVoiceMediaChannel::OnNetworkRouteChanged(
2175 const std::string& transport_name,
Honghai Zhang0e533ef2016-04-19 15:41:36 -07002176 const rtc::NetworkRoute& network_route) {
2177 call_->OnNetworkRouteChanged(transport_name, network_route);
Honghai Zhangcc411c02016-03-29 17:27:21 -07002178}
2179
Peter Boström0c4e06b2015-10-07 12:23:21 +02002180bool WebRtcVoiceMediaChannel::MuteStream(uint32_t ssrc, bool muted) {
solenberg566ef242015-11-06 15:34:49 -08002181 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg94218532016-06-16 10:53:22 -07002182 const auto it = send_streams_.find(ssrc);
2183 if (it == send_streams_.end()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002184 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
2185 return false;
2186 }
solenberg94218532016-06-16 10:53:22 -07002187 it->second->SetMuted(muted);
2188
2189 // TODO(solenberg):
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002190 // We set the AGC to mute state only when all the channels are muted.
2191 // This implementation is not ideal, instead we should signal the AGC when
2192 // the mic channel is muted/unmuted. We can't do it today because there
2193 // is no good way to know which stream is mapping to the mic channel.
2194 bool all_muted = muted;
solenberg94218532016-06-16 10:53:22 -07002195 for (const auto& kv : send_streams_) {
2196 all_muted = all_muted && kv.second->muted();
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002197 }
solenberg059fb442016-10-26 05:12:24 -07002198 engine()->apm()->set_output_will_be_muted(all_muted);
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002199
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002200 return true;
2201}
2202
deadbeef80346142016-04-27 14:17:10 -07002203bool WebRtcVoiceMediaChannel::SetMaxSendBitrate(int bps) {
2204 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetMaxSendBitrate.";
2205 max_send_bitrate_bps_ = bps;
minyue7a973442016-10-20 03:27:12 -07002206 bool success = true;
skvlade0d46372016-04-07 22:59:22 -07002207 for (const auto& kv : send_streams_) {
minyue7a973442016-10-20 03:27:12 -07002208 if (!kv.second->SetMaxSendBitrate(max_send_bitrate_bps_)) {
2209 success = false;
skvlade0d46372016-04-07 22:59:22 -07002210 }
2211 }
minyue7a973442016-10-20 03:27:12 -07002212 return success;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002213}
2214
skvlad7a43d252016-03-22 15:32:27 -07002215void WebRtcVoiceMediaChannel::OnReadyToSend(bool ready) {
2216 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2217 LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
2218 call_->SignalChannelNetworkState(
2219 webrtc::MediaType::AUDIO,
2220 ready ? webrtc::kNetworkUp : webrtc::kNetworkDown);
2221}
2222
michaelt79e05882016-11-08 02:50:09 -08002223void WebRtcVoiceMediaChannel::OnTransportOverheadChanged(
2224 int transport_overhead_per_packet) {
2225 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2226 call_->OnTransportOverheadChanged(webrtc::MediaType::AUDIO,
2227 transport_overhead_per_packet);
2228}
2229
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002230bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
Peter Boströmca8b4042016-03-08 14:24:13 -08002231 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::GetStats");
solenberg566ef242015-11-06 15:34:49 -08002232 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg85a04962015-10-27 03:35:21 -07002233 RTC_DCHECK(info);
solenbergd97ec302015-10-07 01:40:33 -07002234
solenberg85a04962015-10-27 03:35:21 -07002235 // Get SSRC and stats for each sender.
hbos1acfbd22016-11-17 23:43:29 -08002236 RTC_DCHECK_EQ(info->senders.size(), 0U);
solenberg85a04962015-10-27 03:35:21 -07002237 for (const auto& stream : send_streams_) {
2238 webrtc::AudioSendStream::Stats stats = stream.second->GetStats();
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002239 VoiceSenderInfo sinfo;
solenberg85a04962015-10-27 03:35:21 -07002240 sinfo.add_ssrc(stats.local_ssrc);
2241 sinfo.bytes_sent = stats.bytes_sent;
2242 sinfo.packets_sent = stats.packets_sent;
2243 sinfo.packets_lost = stats.packets_lost;
2244 sinfo.fraction_lost = stats.fraction_lost;
2245 sinfo.codec_name = stats.codec_name;
hbos1acfbd22016-11-17 23:43:29 -08002246 sinfo.codec_payload_type = stats.codec_payload_type;
solenberg85a04962015-10-27 03:35:21 -07002247 sinfo.ext_seqnum = stats.ext_seqnum;
2248 sinfo.jitter_ms = stats.jitter_ms;
2249 sinfo.rtt_ms = stats.rtt_ms;
2250 sinfo.audio_level = stats.audio_level;
2251 sinfo.aec_quality_min = stats.aec_quality_min;
2252 sinfo.echo_delay_median_ms = stats.echo_delay_median_ms;
2253 sinfo.echo_delay_std_ms = stats.echo_delay_std_ms;
2254 sinfo.echo_return_loss = stats.echo_return_loss;
2255 sinfo.echo_return_loss_enhancement = stats.echo_return_loss_enhancement;
ivoc8c63a822016-10-21 04:10:03 -07002256 sinfo.residual_echo_likelihood = stats.residual_echo_likelihood;
ivoc4e477a12017-01-15 08:29:46 -08002257 sinfo.residual_echo_likelihood_recent_max =
2258 stats.residual_echo_likelihood_recent_max;
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002259 sinfo.typing_noise_detected = (send_ ? stats.typing_noise_detected : false);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002260 info->senders.push_back(sinfo);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002261 }
2262
solenberg85a04962015-10-27 03:35:21 -07002263 // Get SSRC and stats for each receiver.
hbos1acfbd22016-11-17 23:43:29 -08002264 RTC_DCHECK_EQ(info->receivers.size(), 0U);
solenberg7add0582015-11-20 09:59:34 -08002265 for (const auto& stream : recv_streams_) {
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002266 webrtc::AudioReceiveStream::Stats stats = stream.second->GetStats();
2267 VoiceReceiverInfo rinfo;
2268 rinfo.add_ssrc(stats.remote_ssrc);
2269 rinfo.bytes_rcvd = stats.bytes_rcvd;
2270 rinfo.packets_rcvd = stats.packets_rcvd;
2271 rinfo.packets_lost = stats.packets_lost;
2272 rinfo.fraction_lost = stats.fraction_lost;
2273 rinfo.codec_name = stats.codec_name;
hbos1acfbd22016-11-17 23:43:29 -08002274 rinfo.codec_payload_type = stats.codec_payload_type;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002275 rinfo.ext_seqnum = stats.ext_seqnum;
2276 rinfo.jitter_ms = stats.jitter_ms;
2277 rinfo.jitter_buffer_ms = stats.jitter_buffer_ms;
2278 rinfo.jitter_buffer_preferred_ms = stats.jitter_buffer_preferred_ms;
2279 rinfo.delay_estimate_ms = stats.delay_estimate_ms;
2280 rinfo.audio_level = stats.audio_level;
2281 rinfo.expand_rate = stats.expand_rate;
2282 rinfo.speech_expand_rate = stats.speech_expand_rate;
2283 rinfo.secondary_decoded_rate = stats.secondary_decoded_rate;
2284 rinfo.accelerate_rate = stats.accelerate_rate;
2285 rinfo.preemptive_expand_rate = stats.preemptive_expand_rate;
2286 rinfo.decoding_calls_to_silence_generator =
2287 stats.decoding_calls_to_silence_generator;
2288 rinfo.decoding_calls_to_neteq = stats.decoding_calls_to_neteq;
2289 rinfo.decoding_normal = stats.decoding_normal;
2290 rinfo.decoding_plc = stats.decoding_plc;
2291 rinfo.decoding_cng = stats.decoding_cng;
2292 rinfo.decoding_plc_cng = stats.decoding_plc_cng;
henrik.lundin63489782016-09-20 01:47:12 -07002293 rinfo.decoding_muted_output = stats.decoding_muted_output;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002294 rinfo.capture_start_ntp_time_ms = stats.capture_start_ntp_time_ms;
2295 info->receivers.push_back(rinfo);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002296 }
2297
hbos1acfbd22016-11-17 23:43:29 -08002298 // Get codec info
2299 for (const AudioCodec& codec : send_codecs_) {
2300 webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
2301 info->send_codecs.insert(
2302 std::make_pair(codec_params.payload_type, std::move(codec_params)));
2303 }
2304 for (const AudioCodec& codec : recv_codecs_) {
2305 webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
2306 info->receive_codecs.insert(
2307 std::make_pair(codec_params.payload_type, std::move(codec_params)));
2308 }
2309
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002310 return true;
2311}
2312
Tommif888bb52015-12-12 01:37:01 +01002313void WebRtcVoiceMediaChannel::SetRawAudioSink(
2314 uint32_t ssrc,
kwiberg686a8ef2016-02-26 03:00:35 -08002315 std::unique_ptr<webrtc::AudioSinkInterface> sink) {
Tommif888bb52015-12-12 01:37:01 +01002316 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef884f5852016-01-15 09:20:04 -08002317 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::SetRawAudioSink: ssrc:" << ssrc
2318 << " " << (sink ? "(ptr)" : "NULL");
2319 if (ssrc == 0) {
solenberg2100c0b2017-03-01 11:29:29 -08002320 if (!unsignaled_recv_ssrcs_.empty()) {
kwiberg686a8ef2016-02-26 03:00:35 -08002321 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
deadbeef884f5852016-01-15 09:20:04 -08002322 sink ? new ProxySink(sink.get()) : nullptr);
solenberg2100c0b2017-03-01 11:29:29 -08002323 SetRawAudioSink(unsignaled_recv_ssrcs_.back(), std::move(proxy_sink));
deadbeef884f5852016-01-15 09:20:04 -08002324 }
2325 default_sink_ = std::move(sink);
2326 return;
2327 }
Tommif888bb52015-12-12 01:37:01 +01002328 const auto it = recv_streams_.find(ssrc);
2329 if (it == recv_streams_.end()) {
solenberg2100c0b2017-03-01 11:29:29 -08002330 LOG(LS_WARNING) << "SetRawAudioSink: no recv stream " << ssrc;
Tommif888bb52015-12-12 01:37:01 +01002331 return;
2332 }
deadbeef2d110be2016-01-13 12:00:26 -08002333 it->second->SetRawAudioSink(std::move(sink));
Tommif888bb52015-12-12 01:37:01 +01002334}
2335
hbos8d609f62017-04-10 07:39:05 -07002336std::vector<webrtc::RtpSource> WebRtcVoiceMediaChannel::GetSources(
2337 uint32_t ssrc) const {
2338 auto it = recv_streams_.find(ssrc);
2339 RTC_DCHECK(it != recv_streams_.end())
2340 << "Attempting to get contributing sources for SSRC:" << ssrc
2341 << " which doesn't exist.";
2342 return it->second->GetSources();
2343}
2344
Peter Boström0c4e06b2015-10-07 12:23:21 +02002345int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
solenberg566ef242015-11-06 15:34:49 -08002346 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7add0582015-11-20 09:59:34 -08002347 const auto it = recv_streams_.find(ssrc);
2348 if (it != recv_streams_.end()) {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002349 return it->second->channel();
solenberg8fb30c32015-10-13 03:06:58 -07002350 }
solenberg1ac56142015-10-13 03:58:19 -07002351 return -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002352}
2353
Peter Boström0c4e06b2015-10-07 12:23:21 +02002354int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const {
solenberg566ef242015-11-06 15:34:49 -08002355 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergc96df772015-10-21 13:01:53 -07002356 const auto it = send_streams_.find(ssrc);
2357 if (it != send_streams_.end()) {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002358 return it->second->channel();
solenberg8fb30c32015-10-13 03:06:58 -07002359 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002360 return -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002361}
solenberg2100c0b2017-03-01 11:29:29 -08002362
2363bool WebRtcVoiceMediaChannel::
2364 MaybeDeregisterUnsignaledRecvStream(uint32_t ssrc) {
2365 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2366 auto it = std::find(unsignaled_recv_ssrcs_.begin(),
2367 unsignaled_recv_ssrcs_.end(),
2368 ssrc);
2369 if (it != unsignaled_recv_ssrcs_.end()) {
2370 unsignaled_recv_ssrcs_.erase(it);
2371 return true;
2372 }
2373 return false;
2374}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002375} // namespace cricket
2376
2377#endif // HAVE_WEBRTC_VOICE