blob: d202106be09025ed3215525b70eae77c055e2388 [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"
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -080022#include "webrtc/media/base/audiosource.h"
kjellanderf4752772016-03-02 05:42:30 -080023#include "webrtc/media/base/mediaconstants.h"
kjellandera96e2d72016-02-04 23:52:28 -080024#include "webrtc/media/base/streamparams.h"
solenberg9a5f032222017-03-15 06:14:12 -070025#include "webrtc/media/engine/adm_helpers.h"
solenberg76377c52017-02-21 00:54:31 -080026#include "webrtc/media/engine/apm_helpers.h"
ossuc54071d2016-08-17 02:45:41 -070027#include "webrtc/media/engine/payload_type_mapper.h"
kjellander@webrtc.org5ad12972016-02-12 06:39:40 +010028#include "webrtc/media/engine/webrtcmediaengine.h"
29#include "webrtc/media/engine/webrtcvoe.h"
aleloi10111bc2016-11-17 06:48:48 -080030#include "webrtc/modules/audio_mixer/audio_mixer_impl.h"
aleloi048cbdd2017-05-29 02:56:27 -070031#include "webrtc/modules/audio_processing/aec_dump/aec_dump_factory.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000032#include "webrtc/modules/audio_processing/include/audio_processing.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020033#include "webrtc/rtc_base/arraysize.h"
34#include "webrtc/rtc_base/base64.h"
35#include "webrtc/rtc_base/byteorder.h"
36#include "webrtc/rtc_base/constructormagic.h"
37#include "webrtc/rtc_base/helpers.h"
38#include "webrtc/rtc_base/logging.h"
39#include "webrtc/rtc_base/race_checker.h"
40#include "webrtc/rtc_base/stringencode.h"
41#include "webrtc/rtc_base/stringutils.h"
42#include "webrtc/rtc_base/trace_event.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
peahb1c9d1d2017-07-25 15:45:24 -0700604 webrtc::AudioProcessing::Config apm_config = apm()->GetConfig();
605
peaha3333bf2016-06-30 00:02:34 -0700606 LOG(LS_INFO) << "Level control: "
607 << (!!level_control_ ? *level_control_ : -1);
608 if (level_control_) {
peahb1c9d1d2017-07-25 15:45:24 -0700609 apm_config.level_controller.enabled = *level_control_;
aleloie33c5d92016-10-20 01:53:27 -0700610 if (options.level_control_initial_peak_level_dbfs) {
peahb1c9d1d2017-07-25 15:45:24 -0700611 apm_config.level_controller.initial_peak_level_dbfs =
aleloie33c5d92016-10-20 01:53:27 -0700612 *options.level_control_initial_peak_level_dbfs;
613 }
peaha3333bf2016-06-30 00:02:34 -0700614 }
615
peah8271d042016-11-22 07:24:52 -0800616 if (options.highpass_filter) {
peahb1c9d1d2017-07-25 15:45:24 -0700617 apm_config.high_pass_filter.enabled = *options.highpass_filter;
peah8271d042016-11-22 07:24:52 -0800618 }
619
ivoc4ca18692017-02-10 05:11:09 -0800620 if (options.residual_echo_detector) {
peahb1c9d1d2017-07-25 15:45:24 -0700621 apm_config.residual_echo_detector.enabled = *options.residual_echo_detector;
ivoc4ca18692017-02-10 05:11:09 -0800622 }
623
solenberg059fb442016-10-26 05:12:24 -0700624 apm()->SetExtraOptions(config);
peahb1c9d1d2017-07-25 15:45:24 -0700625 apm()->ApplyConfig(apm_config);
buildbot@webrtc.org1f8a2372014-08-28 10:52:44 +0000626
kwiberg102c6a62015-10-30 02:47:38 -0700627 if (options.recording_sample_rate) {
628 LOG(LS_INFO) << "Recording sample rate is "
629 << *options.recording_sample_rate;
solenberg5b5129a2016-04-08 05:35:48 -0700630 if (adm()->SetRecordingSampleRate(*options.recording_sample_rate)) {
kwiberg102c6a62015-10-30 02:47:38 -0700631 LOG_RTCERR1(SetRecordingSampleRate, *options.recording_sample_rate);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000632 }
633 }
634
kwiberg102c6a62015-10-30 02:47:38 -0700635 if (options.playout_sample_rate) {
636 LOG(LS_INFO) << "Playout sample rate is " << *options.playout_sample_rate;
solenberg5b5129a2016-04-08 05:35:48 -0700637 if (adm()->SetPlayoutSampleRate(*options.playout_sample_rate)) {
kwiberg102c6a62015-10-30 02:47:38 -0700638 LOG_RTCERR1(SetPlayoutSampleRate, *options.playout_sample_rate);
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000639 }
640 }
buildbot@webrtc.org13d67762014-05-02 17:33:29 +0000641 return true;
642}
643
solenberg796b8f92017-03-01 17:02:23 -0800644// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000645int WebRtcVoiceEngine::GetInputLevel() {
solenberg566ef242015-11-06 15:34:49 -0800646 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg796b8f92017-03-01 17:02:23 -0800647 int8_t level = transmit_mixer()->AudioLevel();
648 RTC_DCHECK_LE(0, level);
649 return level;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000650}
651
ossudedfd282016-06-14 07:12:39 -0700652const std::vector<AudioCodec>& WebRtcVoiceEngine::send_codecs() const {
653 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
ossuc54071d2016-08-17 02:45:41 -0700654 return send_codecs_;
ossudedfd282016-06-14 07:12:39 -0700655}
656
657const std::vector<AudioCodec>& WebRtcVoiceEngine::recv_codecs() const {
solenberg566ef242015-11-06 15:34:49 -0800658 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
ossuc54071d2016-08-17 02:45:41 -0700659 return recv_codecs_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000660}
661
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100662RtpCapabilities WebRtcVoiceEngine::GetCapabilities() const {
solenberg566ef242015-11-06 15:34:49 -0800663 RTC_DCHECK(signal_thread_checker_.CalledOnValidThread());
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100664 RtpCapabilities capabilities;
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100665 capabilities.header_extensions.push_back(
isheriff6f8d6862016-05-26 11:24:55 -0700666 webrtc::RtpExtension(webrtc::RtpExtension::kAudioLevelUri,
667 webrtc::RtpExtension::kAudioLevelDefaultId));
sprangc1b57a12017-02-28 08:50:47 -0800668 if (webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe")) {
isheriff6f8d6862016-05-26 11:24:55 -0700669 capabilities.header_extensions.push_back(webrtc::RtpExtension(
670 webrtc::RtpExtension::kTransportSequenceNumberUri,
671 webrtc::RtpExtension::kTransportSequenceNumberDefaultId));
stefanba4c0e42016-02-04 04:12:24 -0800672 }
Stefan Holmer9d69c3f2015-12-07 10:45:43 +0100673 return capabilities;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000674}
675
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000676int WebRtcVoiceEngine::GetLastEngineError() {
solenberg566ef242015-11-06 15:34:49 -0800677 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000678 return voe_wrapper_->error();
679}
680
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000681void WebRtcVoiceEngine::Print(webrtc::TraceLevel level, const char* trace,
682 int length) {
solenberg566ef242015-11-06 15:34:49 -0800683 // Note: This callback can happen on any thread!
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000684 rtc::LoggingSeverity sev = rtc::LS_VERBOSE;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000685 if (level == webrtc::kTraceError || level == webrtc::kTraceCritical)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000686 sev = rtc::LS_ERROR;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000687 else if (level == webrtc::kTraceWarning)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000688 sev = rtc::LS_WARNING;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000689 else if (level == webrtc::kTraceStateInfo || level == webrtc::kTraceInfo)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000690 sev = rtc::LS_INFO;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000691 else if (level == webrtc::kTraceTerseInfo)
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000692 sev = rtc::LS_INFO;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000693
solenberg72e29d22016-03-08 06:35:16 -0800694 // Skip past boilerplate prefix text.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000695 if (length < 72) {
696 std::string msg(trace, length);
697 LOG(LS_ERROR) << "Malformed webrtc log message: ";
698 LOG_V(sev) << msg;
699 } else {
700 std::string msg(trace + 71, length - 72);
Peter Boströmd5c75b12015-09-23 13:24:32 +0200701 LOG_V(sev) << "webrtc: " << msg;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000702 }
703}
704
solenberg63b34542015-09-29 06:06:31 -0700705void WebRtcVoiceEngine::RegisterChannel(WebRtcVoiceMediaChannel* channel) {
solenberg566ef242015-11-06 15:34:49 -0800706 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
707 RTC_DCHECK(channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000708 channels_.push_back(channel);
709}
710
solenberg63b34542015-09-29 06:06:31 -0700711void WebRtcVoiceEngine::UnregisterChannel(WebRtcVoiceMediaChannel* channel) {
solenberg566ef242015-11-06 15:34:49 -0800712 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg63b34542015-09-29 06:06:31 -0700713 auto it = std::find(channels_.begin(), channels_.end(), channel);
solenberg566ef242015-11-06 15:34:49 -0800714 RTC_DCHECK(it != channels_.end());
715 channels_.erase(it);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000716}
717
ivocd66b44d2016-01-15 03:06:36 -0800718bool WebRtcVoiceEngine::StartAecDump(rtc::PlatformFile file,
719 int64_t max_size_bytes) {
solenberg566ef242015-11-06 15:34:49 -0800720 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeefeb02c032017-06-15 08:29:25 -0700721 auto aec_dump = webrtc::AecDumpFactory::Create(
722 file, max_size_bytes, low_priority_worker_queue_.get());
aleloi048cbdd2017-05-29 02:56:27 -0700723 if (!aec_dump) {
wu@webrtc.orga8910d22014-01-23 22:12:45 +0000724 return false;
725 }
aleloi048cbdd2017-05-29 02:56:27 -0700726 apm()->AttachAecDump(std::move(aec_dump));
wu@webrtc.orga9890802013-12-13 00:21:03 +0000727 return true;
wu@webrtc.orga9890802013-12-13 00:21:03 +0000728}
729
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000730void WebRtcVoiceEngine::StartAecDump(const std::string& filename) {
solenberg566ef242015-11-06 15:34:49 -0800731 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
aleloi048cbdd2017-05-29 02:56:27 -0700732
deadbeefeb02c032017-06-15 08:29:25 -0700733 auto aec_dump = webrtc::AecDumpFactory::Create(
734 filename, -1, low_priority_worker_queue_.get());
aleloi048cbdd2017-05-29 02:56:27 -0700735 if (aec_dump) {
736 apm()->AttachAecDump(std::move(aec_dump));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000737 }
738}
739
740void WebRtcVoiceEngine::StopAecDump() {
solenberg566ef242015-11-06 15:34:49 -0800741 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
aleloi048cbdd2017-05-29 02:56:27 -0700742 apm()->DetachAecDump();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000743}
744
solenberg0a617e22015-10-20 15:49:38 -0700745int WebRtcVoiceEngine::CreateVoEChannel() {
solenberg566ef242015-11-06 15:34:49 -0800746 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg88499ec2016-09-07 07:34:41 -0700747 return voe_wrapper_->base()->CreateChannel(channel_config_);
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000748}
749
solenberg5b5129a2016-04-08 05:35:48 -0700750webrtc::AudioDeviceModule* WebRtcVoiceEngine::adm() {
751 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
752 RTC_DCHECK(adm_);
753 return adm_;
754}
755
peahb1c9d1d2017-07-25 15:45:24 -0700756webrtc::AudioProcessing* WebRtcVoiceEngine::apm() const {
solenberg059fb442016-10-26 05:12:24 -0700757 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
peaha9cc40b2017-06-29 08:32:09 -0700758 return apm_.get();
solenberg059fb442016-10-26 05:12:24 -0700759}
760
solenberg76377c52017-02-21 00:54:31 -0800761webrtc::voe::TransmitMixer* WebRtcVoiceEngine::transmit_mixer() {
762 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
763 RTC_DCHECK(transmit_mixer_);
764 return transmit_mixer_;
765}
766
ossu20a4b3f2017-04-27 02:08:52 -0700767AudioCodecs WebRtcVoiceEngine::CollectCodecs(
768 const std::vector<webrtc::AudioCodecSpec>& specs) const {
ossuc54071d2016-08-17 02:45:41 -0700769 PayloadTypeMapper mapper;
770 AudioCodecs out;
ossuc54071d2016-08-17 02:45:41 -0700771
solenberg2779bab2016-11-17 04:45:19 -0800772 // Only generate CN payload types for these clockrates:
ossuc54071d2016-08-17 02:45:41 -0700773 std::map<int, bool, std::greater<int>> generate_cn = {{ 8000, false },
774 { 16000, false },
775 { 32000, false }};
solenberg2779bab2016-11-17 04:45:19 -0800776 // Only generate telephone-event payload types for these clockrates:
777 std::map<int, bool, std::greater<int>> generate_dtmf = {{ 8000, false },
778 { 16000, false },
779 { 32000, false },
780 { 48000, false }};
ossuc54071d2016-08-17 02:45:41 -0700781
ossu9def8002017-02-09 05:14:32 -0800782 auto map_format = [&mapper](const webrtc::SdpAudioFormat& format,
783 AudioCodecs* out) {
ossuc54071d2016-08-17 02:45:41 -0700784 rtc::Optional<AudioCodec> opt_codec = mapper.ToAudioCodec(format);
ossu9def8002017-02-09 05:14:32 -0800785 if (opt_codec) {
786 if (out) {
787 out->push_back(*opt_codec);
788 }
789 } else {
ossuc54071d2016-08-17 02:45:41 -0700790 LOG(LS_ERROR) << "Unable to assign payload type to format: " << format;
ossuc54071d2016-08-17 02:45:41 -0700791 }
792
ossu9def8002017-02-09 05:14:32 -0800793 return opt_codec;
ossuc54071d2016-08-17 02:45:41 -0700794 };
795
ossud4e9f622016-08-18 02:01:17 -0700796 for (const auto& spec : specs) {
ossu9def8002017-02-09 05:14:32 -0800797 // We need to do some extra stuff before adding the main codecs to out.
798 rtc::Optional<AudioCodec> opt_codec = map_format(spec.format, nullptr);
799 if (opt_codec) {
800 AudioCodec& codec = *opt_codec;
ossua1a040a2017-04-06 10:03:21 -0700801 if (spec.info.supports_network_adaption) {
ossu9def8002017-02-09 05:14:32 -0800802 codec.AddFeedbackParam(
803 FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty));
804 }
805
ossua1a040a2017-04-06 10:03:21 -0700806 if (spec.info.allow_comfort_noise) {
solenberg2779bab2016-11-17 04:45:19 -0800807 // Generate a CN entry if the decoder allows it and we support the
808 // clockrate.
809 auto cn = generate_cn.find(spec.format.clockrate_hz);
810 if (cn != generate_cn.end()) {
811 cn->second = true;
812 }
813 }
814
815 // Generate a telephone-event entry if we support the clockrate.
816 auto dtmf = generate_dtmf.find(spec.format.clockrate_hz);
817 if (dtmf != generate_dtmf.end()) {
818 dtmf->second = true;
ossuc54071d2016-08-17 02:45:41 -0700819 }
ossu9def8002017-02-09 05:14:32 -0800820
821 out.push_back(codec);
ossuc54071d2016-08-17 02:45:41 -0700822 }
823 }
824
solenberg2779bab2016-11-17 04:45:19 -0800825 // Add CN codecs after "proper" audio codecs.
ossuc54071d2016-08-17 02:45:41 -0700826 for (const auto& cn : generate_cn) {
827 if (cn.second) {
ossu9def8002017-02-09 05:14:32 -0800828 map_format({kCnCodecName, cn.first, 1}, &out);
ossuc54071d2016-08-17 02:45:41 -0700829 }
830 }
831
solenberg2779bab2016-11-17 04:45:19 -0800832 // Add telephone-event codecs last.
833 for (const auto& dtmf : generate_dtmf) {
834 if (dtmf.second) {
ossu9def8002017-02-09 05:14:32 -0800835 map_format({kDtmfCodecName, dtmf.first, 1}, &out);
solenberg2779bab2016-11-17 04:45:19 -0800836 }
837 }
ossuc54071d2016-08-17 02:45:41 -0700838
839 return out;
840}
841
solenbergc96df772015-10-21 13:01:53 -0700842class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800843 : public AudioSource::Sink {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000844 public:
minyue7a973442016-10-20 03:27:12 -0700845 WebRtcAudioSendStream(
846 int ch,
847 webrtc::AudioTransport* voe_audio_transport,
848 uint32_t ssrc,
849 const std::string& c_name,
ossu20a4b3f2017-04-27 02:08:52 -0700850 const rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>&
851 send_codec_spec,
minyue7a973442016-10-20 03:27:12 -0700852 const std::vector<webrtc::RtpExtension>& extensions,
853 int max_send_bitrate_bps,
minyue6b825df2016-10-31 04:08:32 -0700854 const rtc::Optional<std::string>& audio_network_adaptor_config,
minyue7a973442016-10-20 03:27:12 -0700855 webrtc::Call* call,
ossu20a4b3f2017-04-27 02:08:52 -0700856 webrtc::Transport* send_transport,
857 const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory)
solenberg7add0582015-11-20 09:59:34 -0800858 : voe_audio_transport_(voe_audio_transport),
solenberg3a941542015-11-16 07:34:50 -0800859 call_(call),
mflodman3d7db262016-04-29 00:57:13 -0700860 config_(send_transport),
sprangc1b57a12017-02-28 08:50:47 -0800861 send_side_bwe_with_overhead_(
862 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
minyue7a973442016-10-20 03:27:12 -0700863 max_send_bitrate_bps_(max_send_bitrate_bps),
skvlade0d46372016-04-07 22:59:22 -0700864 rtp_parameters_(CreateRtpParametersWithOneEncoding()) {
solenberg85a04962015-10-27 03:35:21 -0700865 RTC_DCHECK_GE(ch, 0);
866 // TODO(solenberg): Once we're not using FakeWebRtcVoiceEngine anymore:
867 // RTC_DCHECK(voe_audio_transport);
solenbergc96df772015-10-21 13:01:53 -0700868 RTC_DCHECK(call);
ossu20a4b3f2017-04-27 02:08:52 -0700869 RTC_DCHECK(encoder_factory);
solenberg3a941542015-11-16 07:34:50 -0800870 config_.rtp.ssrc = ssrc;
871 config_.rtp.c_name = c_name;
872 config_.voe_channel_id = ch;
solenberg971cab02016-06-14 10:02:41 -0700873 config_.rtp.extensions = extensions;
minyue6b825df2016-10-31 04:08:32 -0700874 config_.audio_network_adaptor_config = audio_network_adaptor_config;
ossu20a4b3f2017-04-27 02:08:52 -0700875 config_.encoder_factory = encoder_factory;
deadbeefcb443432016-12-12 11:12:36 -0800876 rtp_parameters_.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
ossu20a4b3f2017-04-27 02:08:52 -0700877
878 if (send_codec_spec) {
879 UpdateSendCodecSpec(*send_codec_spec);
880 }
881
882 stream_ = call_->CreateAudioSendStream(config_);
solenbergc96df772015-10-21 13:01:53 -0700883 }
solenberg3a941542015-11-16 07:34:50 -0800884
solenbergc96df772015-10-21 13:01:53 -0700885 ~WebRtcAudioSendStream() override {
solenberg566ef242015-11-06 15:34:49 -0800886 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800887 ClearSource();
solenbergc96df772015-10-21 13:01:53 -0700888 call_->DestroyAudioSendStream(stream_);
889 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000890
ossu20a4b3f2017-04-27 02:08:52 -0700891 void SetSendCodecSpec(
minyue7a973442016-10-20 03:27:12 -0700892 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) {
ossu20a4b3f2017-04-27 02:08:52 -0700893 UpdateSendCodecSpec(send_codec_spec);
894 ReconfigureAudioSendStream();
solenberg971cab02016-06-14 10:02:41 -0700895 }
896
ossu20a4b3f2017-04-27 02:08:52 -0700897 void SetRtpExtensions(const std::vector<webrtc::RtpExtension>& extensions) {
solenberg3a941542015-11-16 07:34:50 -0800898 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg3a941542015-11-16 07:34:50 -0800899 config_.rtp.extensions = extensions;
ossu20a4b3f2017-04-27 02:08:52 -0700900 ReconfigureAudioSendStream();
solenberg3a941542015-11-16 07:34:50 -0800901 }
902
ossu20a4b3f2017-04-27 02:08:52 -0700903 void SetAudioNetworkAdaptorConfig(
minyue6b825df2016-10-31 04:08:32 -0700904 const rtc::Optional<std::string>& audio_network_adaptor_config) {
905 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
906 if (config_.audio_network_adaptor_config == audio_network_adaptor_config) {
907 return;
908 }
909 config_.audio_network_adaptor_config = audio_network_adaptor_config;
ossu20a4b3f2017-04-27 02:08:52 -0700910 UpdateAllowedBitrateRange();
911 ReconfigureAudioSendStream();
minyue6b825df2016-10-31 04:08:32 -0700912 }
913
minyue7a973442016-10-20 03:27:12 -0700914 bool SetMaxSendBitrate(int bps) {
915 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
ossu20a4b3f2017-04-27 02:08:52 -0700916 RTC_DCHECK(config_.send_codec_spec);
917 RTC_DCHECK(audio_codec_spec_);
918 auto send_rate = ComputeSendBitrate(
919 bps, rtp_parameters_.encodings[0].max_bitrate_bps, *audio_codec_spec_);
920
minyue7a973442016-10-20 03:27:12 -0700921 if (!send_rate) {
922 return false;
923 }
924
925 max_send_bitrate_bps_ = bps;
926
ossu20a4b3f2017-04-27 02:08:52 -0700927 if (send_rate != config_.send_codec_spec->target_bitrate_bps) {
928 config_.send_codec_spec->target_bitrate_bps = send_rate;
929 ReconfigureAudioSendStream();
minyue7a973442016-10-20 03:27:12 -0700930 }
931 return true;
932 }
933
solenbergffbbcac2016-11-17 05:25:37 -0800934 bool SendTelephoneEvent(int payload_type, int payload_freq, int event,
935 int duration_ms) {
Fredrik Solenbergb5727682015-12-04 15:22:19 +0100936 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
937 RTC_DCHECK(stream_);
solenbergffbbcac2016-11-17 05:25:37 -0800938 return stream_->SendTelephoneEvent(payload_type, payload_freq, event,
939 duration_ms);
Fredrik Solenbergb5727682015-12-04 15:22:19 +0100940 }
941
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800942 void SetSend(bool send) {
943 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
944 send_ = send;
945 UpdateSendState();
946 }
947
solenberg94218532016-06-16 10:53:22 -0700948 void SetMuted(bool muted) {
949 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
950 RTC_DCHECK(stream_);
951 stream_->SetMuted(muted);
952 muted_ = muted;
953 }
954
955 bool muted() const {
956 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
957 return muted_;
958 }
959
solenberg3a941542015-11-16 07:34:50 -0800960 webrtc::AudioSendStream::Stats GetStats() const {
961 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
962 RTC_DCHECK(stream_);
963 return stream_->GetStats();
964 }
965
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800966 // Starts the sending by setting ourselves as a sink to the AudioSource to
967 // get data callbacks.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000968 // This method is called on the libjingle worker thread.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000969 // TODO(xians): Make sure Start() is called only once.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800970 void SetSource(AudioSource* source) {
solenberg566ef242015-11-06 15:34:49 -0800971 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800972 RTC_DCHECK(source);
973 if (source_) {
974 RTC_DCHECK(source_ == source);
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000975 return;
976 }
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800977 source->SetSink(this);
978 source_ = source;
979 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000980 }
981
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800982 // Stops sending by setting the sink of the AudioSource to nullptr. No data
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000983 // callback will be received after this method.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000984 // This method is called on the libjingle worker thread.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800985 void ClearSource() {
solenberg566ef242015-11-06 15:34:49 -0800986 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800987 if (source_) {
988 source_->SetSink(nullptr);
989 source_ = nullptr;
solenberg98c68862015-10-09 03:27:14 -0700990 }
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800991 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +0000992 }
993
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -0800994 // AudioSource::Sink implementation.
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000995 // This method is called on the audio thread.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000996 void OnData(const void* audio_data,
997 int bits_per_sample,
998 int sample_rate,
Peter Kasting69558702016-01-12 16:26:35 -0800999 size_t number_of_channels,
Peter Kastingdce40cf2015-08-24 14:52:23 -07001000 size_t number_of_frames) override {
solenberg347ec5c2016-09-23 04:21:47 -07001001 RTC_CHECK_RUNS_SERIALIZED(&audio_capture_race_checker_);
solenbergc96df772015-10-21 13:01:53 -07001002 RTC_DCHECK(voe_audio_transport_);
maxmorin1aee0b52016-08-15 11:46:19 -07001003 voe_audio_transport_->PushCaptureData(config_.voe_channel_id, audio_data,
1004 bits_per_sample, sample_rate,
1005 number_of_channels, number_of_frames);
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00001006 }
1007
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001008 // Callback from the |source_| when it is going away. In case Start() has
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00001009 // never been called, this callback won't be triggered.
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001010 void OnClose() override {
solenberg566ef242015-11-06 15:34:49 -08001011 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001012 // Set |source_| to nullptr to make sure no more callback will get into
1013 // the source.
1014 source_ = nullptr;
1015 UpdateSendState();
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001016 }
1017
1018 // Accessor to the VoE channel ID.
solenberg85a04962015-10-27 03:35:21 -07001019 int channel() const {
solenberg566ef242015-11-06 15:34:49 -08001020 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7add0582015-11-20 09:59:34 -08001021 return config_.voe_channel_id;
solenberg85a04962015-10-27 03:35:21 -07001022 }
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001023
skvlade0d46372016-04-07 22:59:22 -07001024 const webrtc::RtpParameters& rtp_parameters() const {
1025 return rtp_parameters_;
1026 }
1027
deadbeeffb2aced2017-01-06 23:05:37 -08001028 bool ValidateRtpParameters(const webrtc::RtpParameters& rtp_parameters) {
1029 if (rtp_parameters.encodings.size() != 1) {
1030 LOG(LS_ERROR)
1031 << "Attempted to set RtpParameters without exactly one encoding";
1032 return false;
1033 }
1034 if (rtp_parameters.encodings[0].ssrc != rtp_parameters_.encodings[0].ssrc) {
1035 LOG(LS_ERROR) << "Attempted to set RtpParameters with modified SSRC";
1036 return false;
1037 }
1038 return true;
1039 }
1040
minyue7a973442016-10-20 03:27:12 -07001041 bool SetRtpParameters(const webrtc::RtpParameters& parameters) {
deadbeeffb2aced2017-01-06 23:05:37 -08001042 if (!ValidateRtpParameters(parameters)) {
1043 return false;
1044 }
ossu20a4b3f2017-04-27 02:08:52 -07001045
1046 rtc::Optional<int> send_rate;
1047 if (audio_codec_spec_) {
1048 send_rate = ComputeSendBitrate(max_send_bitrate_bps_,
1049 parameters.encodings[0].max_bitrate_bps,
1050 *audio_codec_spec_);
1051 if (!send_rate) {
1052 return false;
1053 }
minyue7a973442016-10-20 03:27:12 -07001054 }
1055
minyuececec102017-03-27 13:04:25 -07001056 const rtc::Optional<int> old_rtp_max_bitrate =
1057 rtp_parameters_.encodings[0].max_bitrate_bps;
1058
skvlade0d46372016-04-07 22:59:22 -07001059 rtp_parameters_ = parameters;
minyue7a973442016-10-20 03:27:12 -07001060
minyuececec102017-03-27 13:04:25 -07001061 if (rtp_parameters_.encodings[0].max_bitrate_bps != old_rtp_max_bitrate) {
ossu20a4b3f2017-04-27 02:08:52 -07001062 // Reconfigure AudioSendStream with new bit rate.
1063 if (send_rate) {
1064 config_.send_codec_spec->target_bitrate_bps = send_rate;
1065 }
1066 UpdateAllowedBitrateRange();
1067 ReconfigureAudioSendStream();
minyue7a973442016-10-20 03:27:12 -07001068 } else {
1069 // parameters.encodings[0].active could have changed.
1070 UpdateSendState();
1071 }
1072 return true;
skvlade0d46372016-04-07 22:59:22 -07001073 }
1074
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001075 private:
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001076 void UpdateSendState() {
1077 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1078 RTC_DCHECK(stream_);
Taylor Brandstetter55dd7082016-05-03 13:50:11 -07001079 RTC_DCHECK_EQ(1UL, rtp_parameters_.encodings.size());
1080 if (send_ && source_ != nullptr && rtp_parameters_.encodings[0].active) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001081 stream_->Start();
1082 } else { // !send || source_ = nullptr
1083 stream_->Stop();
1084 }
1085 }
1086
ossu20a4b3f2017-04-27 02:08:52 -07001087 void UpdateAllowedBitrateRange() {
michaelt53fe19d2016-10-18 09:39:22 -07001088 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
ossu20a4b3f2017-04-27 02:08:52 -07001089 const bool is_opus =
1090 config_.send_codec_spec &&
1091 !STR_CASE_CMP(config_.send_codec_spec->format.name.c_str(),
1092 kOpusCodecName);
1093 if (is_opus && webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe")) {
stefane9f36d52017-01-24 08:18:45 -08001094 config_.min_bitrate_bps = kOpusMinBitrateBps;
minyuececec102017-03-27 13:04:25 -07001095
1096 // This means that when RtpParameters is reset, we may change the
ossu20a4b3f2017-04-27 02:08:52 -07001097 // encoder's bit rate immediately (through ReconfigureAudioSendStream()),
minyuececec102017-03-27 13:04:25 -07001098 // meanwhile change the cap to the output of BWE.
1099 config_.max_bitrate_bps =
1100 rtp_parameters_.encodings[0].max_bitrate_bps
1101 ? *rtp_parameters_.encodings[0].max_bitrate_bps
1102 : kOpusBitrateFbBps;
1103
michaelt53fe19d2016-10-18 09:39:22 -07001104 // TODO(mflodman): Keep testing this and set proper values.
1105 // Note: This is an early experiment currently only supported by Opus.
elad.alon0fe12162017-01-31 05:48:37 -08001106 if (send_side_bwe_with_overhead_) {
ossu20a4b3f2017-04-27 02:08:52 -07001107 const int max_packet_size_ms =
1108 WEBRTC_OPUS_SUPPORT_120MS_PTIME ? 120 : 60;
michaelt6672b262017-01-11 10:17:59 -08001109
ossu20a4b3f2017-04-27 02:08:52 -07001110 // OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12)
1111 constexpr int kOverheadPerPacket = 20 + 8 + 10 + 12;
michaelt6672b262017-01-11 10:17:59 -08001112
ossu20a4b3f2017-04-27 02:08:52 -07001113 int min_overhead_bps =
1114 kOverheadPerPacket * 8 * 1000 / max_packet_size_ms;
michaelt6672b262017-01-11 10:17:59 -08001115
ossu20a4b3f2017-04-27 02:08:52 -07001116 // We assume that |config_.max_bitrate_bps| before the next line is
1117 // a hard limit on the payload bitrate, so we add min_overhead_bps to
1118 // it to ensure that, when overhead is deducted, the payload rate
1119 // never goes beyond the limit.
1120 // Note: this also means that if a higher overhead is forced, we
1121 // cannot reach the limit.
1122 // TODO(minyue): Reconsider this when the signaling to BWE is done
1123 // through a dedicated API.
1124 config_.max_bitrate_bps += min_overhead_bps;
michaelt6672b262017-01-11 10:17:59 -08001125
ossu20a4b3f2017-04-27 02:08:52 -07001126 // In contrast to max_bitrate_bps, we let min_bitrate_bps always be
1127 // reachable.
1128 config_.min_bitrate_bps += min_overhead_bps;
michaelt6672b262017-01-11 10:17:59 -08001129 }
michaelt53fe19d2016-10-18 09:39:22 -07001130 }
ossu20a4b3f2017-04-27 02:08:52 -07001131 }
1132
1133 void UpdateSendCodecSpec(
1134 const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) {
1135 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1136 config_.rtp.nack.rtp_history_ms =
1137 send_codec_spec.nack_enabled ? kNackRtpHistoryMs : 0;
1138 config_.send_codec_spec =
1139 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>(
1140 send_codec_spec);
1141 auto info =
1142 config_.encoder_factory->QueryAudioEncoder(send_codec_spec.format);
1143 RTC_DCHECK(info);
1144 // If a specific target bitrate has been set for the stream, use that as
1145 // the new default bitrate when computing send bitrate.
1146 if (send_codec_spec.target_bitrate_bps) {
1147 info->default_bitrate_bps = std::max(
1148 info->min_bitrate_bps,
1149 std::min(info->max_bitrate_bps, *send_codec_spec.target_bitrate_bps));
1150 }
1151
1152 audio_codec_spec_.emplace(
1153 webrtc::AudioCodecSpec{send_codec_spec.format, *info});
1154
1155 config_.send_codec_spec->target_bitrate_bps = ComputeSendBitrate(
1156 max_send_bitrate_bps_, rtp_parameters_.encodings[0].max_bitrate_bps,
1157 *audio_codec_spec_);
1158
1159 UpdateAllowedBitrateRange();
1160 }
1161
1162 void ReconfigureAudioSendStream() {
1163 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1164 RTC_DCHECK(stream_);
1165 stream_->Reconfigure(config_);
michaelt53fe19d2016-10-18 09:39:22 -07001166 }
1167
solenberg566ef242015-11-06 15:34:49 -08001168 rtc::ThreadChecker worker_thread_checker_;
solenberg347ec5c2016-09-23 04:21:47 -07001169 rtc::RaceChecker audio_capture_race_checker_;
solenbergc96df772015-10-21 13:01:53 -07001170 webrtc::AudioTransport* const voe_audio_transport_ = nullptr;
1171 webrtc::Call* call_ = nullptr;
solenberg3a941542015-11-16 07:34:50 -08001172 webrtc::AudioSendStream::Config config_;
elad.alon0fe12162017-01-31 05:48:37 -08001173 const bool send_side_bwe_with_overhead_;
solenberg3a941542015-11-16 07:34:50 -08001174 // The stream is owned by WebRtcAudioSendStream and may be reallocated if
1175 // configuration changes.
solenbergc96df772015-10-21 13:01:53 -07001176 webrtc::AudioSendStream* stream_ = nullptr;
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001177
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001178 // Raw pointer to AudioSource owned by LocalAudioTrackHandler.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001179 // PeerConnection will make sure invalidating the pointer before the object
1180 // goes away.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001181 AudioSource* source_ = nullptr;
1182 bool send_ = false;
solenberg94218532016-06-16 10:53:22 -07001183 bool muted_ = false;
minyue7a973442016-10-20 03:27:12 -07001184 int max_send_bitrate_bps_;
skvlade0d46372016-04-07 22:59:22 -07001185 webrtc::RtpParameters rtp_parameters_;
ossu20a4b3f2017-04-27 02:08:52 -07001186 rtc::Optional<webrtc::AudioCodecSpec> audio_codec_spec_;
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00001187
solenbergc96df772015-10-21 13:01:53 -07001188 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream);
1189};
1190
1191class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
1192 public:
ossu29b1a8d2016-06-13 07:34:51 -07001193 WebRtcAudioReceiveStream(
1194 int ch,
1195 uint32_t remote_ssrc,
1196 uint32_t local_ssrc,
1197 bool use_transport_cc,
solenberg8189b022016-06-14 12:13:00 -07001198 bool use_nack,
ossu29b1a8d2016-06-13 07:34:51 -07001199 const std::string& sync_group,
1200 const std::vector<webrtc::RtpExtension>& extensions,
1201 webrtc::Call* call,
1202 webrtc::Transport* rtcp_send_transport,
kwiberg1c07c702017-03-27 07:15:49 -07001203 const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
1204 const std::map<int, webrtc::SdpAudioFormat>& decoder_map)
stefanba4c0e42016-02-04 04:12:24 -08001205 : call_(call), config_() {
solenberg7add0582015-11-20 09:59:34 -08001206 RTC_DCHECK_GE(ch, 0);
1207 RTC_DCHECK(call);
1208 config_.rtp.remote_ssrc = remote_ssrc;
kwibergd32bf752017-01-19 07:03:59 -08001209 config_.rtp.local_ssrc = local_ssrc;
1210 config_.rtp.transport_cc = use_transport_cc;
1211 config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0;
1212 config_.rtp.extensions = extensions;
solenberg31fec402016-05-06 02:13:12 -07001213 config_.rtcp_send_transport = rtcp_send_transport;
solenberg7add0582015-11-20 09:59:34 -08001214 config_.voe_channel_id = ch;
1215 config_.sync_group = sync_group;
ossu29b1a8d2016-06-13 07:34:51 -07001216 config_.decoder_factory = decoder_factory;
kwiberg1c07c702017-03-27 07:15:49 -07001217 config_.decoder_map = decoder_map;
kwibergd32bf752017-01-19 07:03:59 -08001218 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001219 }
solenbergc96df772015-10-21 13:01:53 -07001220
solenberg7add0582015-11-20 09:59:34 -08001221 ~WebRtcAudioReceiveStream() {
1222 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1223 call_->DestroyAudioReceiveStream(stream_);
1224 }
1225
solenberg4a0f7b52016-06-16 13:07:33 -07001226 void RecreateAudioReceiveStream(uint32_t local_ssrc) {
solenberg7add0582015-11-20 09:59:34 -08001227 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001228 config_.rtp.local_ssrc = local_ssrc;
1229 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001230 }
solenberg8189b022016-06-14 12:13:00 -07001231
1232 void RecreateAudioReceiveStream(bool use_transport_cc, bool use_nack) {
solenberg7add0582015-11-20 09:59:34 -08001233 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001234 config_.rtp.transport_cc = use_transport_cc;
1235 config_.rtp.nack.rtp_history_ms = use_nack ? kNackRtpHistoryMs : 0;
1236 RecreateAudioReceiveStream();
solenberg7add0582015-11-20 09:59:34 -08001237 }
1238
solenberg4a0f7b52016-06-16 13:07:33 -07001239 void RecreateAudioReceiveStream(
1240 const std::vector<webrtc::RtpExtension>& extensions) {
1241 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001242 config_.rtp.extensions = extensions;
1243 RecreateAudioReceiveStream();
1244 }
1245
deadbeefcb383672017-04-26 16:28:42 -07001246 // Set a new payload type -> decoder map.
kwibergd32bf752017-01-19 07:03:59 -08001247 void RecreateAudioReceiveStream(
1248 const std::map<int, webrtc::SdpAudioFormat>& decoder_map) {
1249 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwibergd32bf752017-01-19 07:03:59 -08001250 config_.decoder_map = decoder_map;
1251 RecreateAudioReceiveStream();
solenberg4a0f7b52016-06-16 13:07:33 -07001252 }
1253
solenberg4904fb62017-02-17 12:01:14 -08001254 void MaybeRecreateAudioReceiveStream(const std::string& sync_group) {
1255 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1256 if (config_.sync_group != sync_group) {
1257 config_.sync_group = sync_group;
1258 RecreateAudioReceiveStream();
1259 }
1260 }
1261
solenberg7add0582015-11-20 09:59:34 -08001262 webrtc::AudioReceiveStream::Stats GetStats() const {
1263 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1264 RTC_DCHECK(stream_);
1265 return stream_->GetStats();
1266 }
1267
solenberg796b8f92017-03-01 17:02:23 -08001268 int GetOutputLevel() const {
1269 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1270 RTC_DCHECK(stream_);
1271 return stream_->GetOutputLevel();
1272 }
1273
solenberg7add0582015-11-20 09:59:34 -08001274 int channel() const {
1275 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1276 return config_.voe_channel_id;
1277 }
solenbergc96df772015-10-21 13:01:53 -07001278
kwiberg686a8ef2016-02-26 03:00:35 -08001279 void SetRawAudioSink(std::unique_ptr<webrtc::AudioSinkInterface> sink) {
Tommif888bb52015-12-12 01:37:01 +01001280 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
kwiberg686a8ef2016-02-26 03:00:35 -08001281 stream_->SetSink(std::move(sink));
Tommif888bb52015-12-12 01:37:01 +01001282 }
1283
solenberg217fb662016-06-17 08:30:54 -07001284 void SetOutputVolume(double volume) {
1285 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1286 stream_->SetGain(volume);
1287 }
1288
aleloi84ef6152016-08-04 05:28:21 -07001289 void SetPlayout(bool playout) {
1290 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1291 RTC_DCHECK(stream_);
1292 if (playout) {
1293 LOG(LS_INFO) << "Starting playout for channel #" << channel();
1294 stream_->Start();
1295 } else {
1296 LOG(LS_INFO) << "Stopping playout for channel #" << channel();
1297 stream_->Stop();
1298 }
aleloi18e0b672016-10-04 02:45:47 -07001299 playout_ = playout;
aleloi84ef6152016-08-04 05:28:21 -07001300 }
1301
hbos8d609f62017-04-10 07:39:05 -07001302 std::vector<webrtc::RtpSource> GetSources() {
1303 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1304 RTC_DCHECK(stream_);
1305 return stream_->GetSources();
1306 }
1307
solenbergc96df772015-10-21 13:01:53 -07001308 private:
kwibergd32bf752017-01-19 07:03:59 -08001309 void RecreateAudioReceiveStream() {
solenberg7add0582015-11-20 09:59:34 -08001310 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1311 if (stream_) {
1312 call_->DestroyAudioReceiveStream(stream_);
solenberg7add0582015-11-20 09:59:34 -08001313 }
solenberg7add0582015-11-20 09:59:34 -08001314 stream_ = call_->CreateAudioReceiveStream(config_);
1315 RTC_CHECK(stream_);
aleloi18e0b672016-10-04 02:45:47 -07001316 SetPlayout(playout_);
solenberg7add0582015-11-20 09:59:34 -08001317 }
1318
1319 rtc::ThreadChecker worker_thread_checker_;
1320 webrtc::Call* call_ = nullptr;
1321 webrtc::AudioReceiveStream::Config config_;
1322 // The stream is owned by WebRtcAudioReceiveStream and may be reallocated if
1323 // configuration changes.
1324 webrtc::AudioReceiveStream* stream_ = nullptr;
aleloi18e0b672016-10-04 02:45:47 -07001325 bool playout_ = false;
solenbergc96df772015-10-21 13:01:53 -07001326
1327 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioReceiveStream);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001328};
1329
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001330WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine,
nisse51542be2016-02-12 02:27:06 -08001331 const MediaConfig& config,
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001332 const AudioOptions& options,
Fredrik Solenberg709ed672015-09-15 12:26:33 +02001333 webrtc::Call* call)
nisse51542be2016-02-12 02:27:06 -08001334 : VoiceMediaChannel(config), engine_(engine), call_(call) {
solenberg0a617e22015-10-20 15:49:38 -07001335 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel";
solenberg566ef242015-11-06 15:34:49 -08001336 RTC_DCHECK(call);
solenberg0a617e22015-10-20 15:49:38 -07001337 engine->RegisterChannel(this);
Fredrik Solenbergb071a192015-09-17 16:42:56 +02001338 SetOptions(options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001339}
1340
1341WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() {
solenberg566ef242015-11-06 15:34:49 -08001342 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg0a617e22015-10-20 15:49:38 -07001343 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel";
solenberg7add0582015-11-20 09:59:34 -08001344 // TODO(solenberg): Should be able to delete the streams directly, without
1345 // going through RemoveNnStream(), once stream objects handle
1346 // all (de)configuration.
solenbergc96df772015-10-21 13:01:53 -07001347 while (!send_streams_.empty()) {
1348 RemoveSendStream(send_streams_.begin()->first);
solenbergd97ec302015-10-07 01:40:33 -07001349 }
solenberg7add0582015-11-20 09:59:34 -08001350 while (!recv_streams_.empty()) {
1351 RemoveRecvStream(recv_streams_.begin()->first);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001352 }
solenberg0a617e22015-10-20 15:49:38 -07001353 engine()->UnregisterChannel(this);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001354}
1355
nisse51542be2016-02-12 02:27:06 -08001356rtc::DiffServCodePoint WebRtcVoiceMediaChannel::PreferredDscp() const {
1357 return kAudioDscpValue;
1358}
1359
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001360bool WebRtcVoiceMediaChannel::SetSendParameters(
1361 const AudioSendParameters& params) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001362 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetSendParameters");
solenberg566ef242015-11-06 15:34:49 -08001363 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7e4e01a2015-12-02 08:05:01 -08001364 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetSendParameters: "
1365 << params.ToString();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001366 // TODO(pthatcher): Refactor this to be more clean now that we have
1367 // all the information at once.
solenberg3a941542015-11-16 07:34:50 -08001368
1369 if (!SetSendCodecs(params.codecs)) {
1370 return false;
1371 }
1372
solenberg7e4e01a2015-12-02 08:05:01 -08001373 if (!ValidateRtpExtensions(params.extensions)) {
1374 return false;
1375 }
1376 std::vector<webrtc::RtpExtension> filtered_extensions =
1377 FilterRtpExtensions(params.extensions,
1378 webrtc::RtpExtension::IsSupportedForAudio, true);
1379 if (send_rtp_extensions_ != filtered_extensions) {
1380 send_rtp_extensions_.swap(filtered_extensions);
solenberg3a941542015-11-16 07:34:50 -08001381 for (auto& it : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001382 it.second->SetRtpExtensions(send_rtp_extensions_);
solenberg3a941542015-11-16 07:34:50 -08001383 }
1384 }
1385
deadbeef80346142016-04-27 14:17:10 -07001386 if (!SetMaxSendBitrate(params.max_bandwidth_bps)) {
solenberg3a941542015-11-16 07:34:50 -08001387 return false;
1388 }
1389 return SetOptions(params.options);
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001390}
1391
1392bool WebRtcVoiceMediaChannel::SetRecvParameters(
1393 const AudioRecvParameters& params) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001394 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetRecvParameters");
solenberg566ef242015-11-06 15:34:49 -08001395 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7e4e01a2015-12-02 08:05:01 -08001396 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetRecvParameters: "
1397 << params.ToString();
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001398 // TODO(pthatcher): Refactor this to be more clean now that we have
1399 // all the information at once.
solenberg7add0582015-11-20 09:59:34 -08001400
1401 if (!SetRecvCodecs(params.codecs)) {
1402 return false;
1403 }
1404
solenberg7e4e01a2015-12-02 08:05:01 -08001405 if (!ValidateRtpExtensions(params.extensions)) {
1406 return false;
1407 }
1408 std::vector<webrtc::RtpExtension> filtered_extensions =
1409 FilterRtpExtensions(params.extensions,
1410 webrtc::RtpExtension::IsSupportedForAudio, false);
1411 if (recv_rtp_extensions_ != filtered_extensions) {
1412 recv_rtp_extensions_.swap(filtered_extensions);
solenberg7add0582015-11-20 09:59:34 -08001413 for (auto& it : recv_streams_) {
1414 it.second->RecreateAudioReceiveStream(recv_rtp_extensions_);
1415 }
1416 }
solenberg7add0582015-11-20 09:59:34 -08001417 return true;
Peter Thatcherc2ee2c82015-08-07 16:05:34 -07001418}
1419
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001420webrtc::RtpParameters WebRtcVoiceMediaChannel::GetRtpSendParameters(
skvlade0d46372016-04-07 22:59:22 -07001421 uint32_t ssrc) const {
1422 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
1423 auto it = send_streams_.find(ssrc);
1424 if (it == send_streams_.end()) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001425 LOG(LS_WARNING) << "Attempting to get RTP send parameters for stream "
1426 << "with ssrc " << ssrc << " which doesn't exist.";
skvlade0d46372016-04-07 22:59:22 -07001427 return webrtc::RtpParameters();
1428 }
1429
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001430 webrtc::RtpParameters rtp_params = it->second->rtp_parameters();
1431 // Need to add the common list of codecs to the send stream-specific
1432 // RTP parameters.
1433 for (const AudioCodec& codec : send_codecs_) {
1434 rtp_params.codecs.push_back(codec.ToCodecParameters());
1435 }
1436 return rtp_params;
skvlade0d46372016-04-07 22:59:22 -07001437}
1438
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001439bool WebRtcVoiceMediaChannel::SetRtpSendParameters(
skvlade0d46372016-04-07 22:59:22 -07001440 uint32_t ssrc,
1441 const webrtc::RtpParameters& parameters) {
1442 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
skvlade0d46372016-04-07 22:59:22 -07001443 auto it = send_streams_.find(ssrc);
1444 if (it == send_streams_.end()) {
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001445 LOG(LS_WARNING) << "Attempting to set RTP send parameters for stream "
1446 << "with ssrc " << ssrc << " which doesn't exist.";
skvlade0d46372016-04-07 22:59:22 -07001447 return false;
1448 }
1449
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001450 // TODO(deadbeef): Handle setting parameters with a list of codecs in a
1451 // different order (which should change the send codec).
1452 webrtc::RtpParameters current_parameters = GetRtpSendParameters(ssrc);
1453 if (current_parameters.codecs != parameters.codecs) {
1454 LOG(LS_ERROR) << "Using SetParameters to change the set of codecs "
1455 << "is not currently supported.";
1456 return false;
1457 }
1458
minyue7a973442016-10-20 03:27:12 -07001459 // TODO(minyue): The following legacy actions go into
1460 // |WebRtcAudioSendStream::SetRtpParameters()| which is called at the end,
1461 // though there are two difference:
1462 // 1. |WebRtcVoiceMediaChannel::SetChannelSendParameters()| only calls
1463 // |SetSendCodec| while |WebRtcAudioSendStream::SetRtpParameters()| calls
1464 // |SetSendCodecs|. The outcome should be the same.
1465 // 2. AudioSendStream can be recreated.
1466
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001467 // Codecs are handled at the WebRtcVoiceMediaChannel level.
1468 webrtc::RtpParameters reduced_params = parameters;
1469 reduced_params.codecs.clear();
minyue7a973442016-10-20 03:27:12 -07001470 return it->second->SetRtpParameters(reduced_params);
skvlade0d46372016-04-07 22:59:22 -07001471}
1472
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001473webrtc::RtpParameters WebRtcVoiceMediaChannel::GetRtpReceiveParameters(
1474 uint32_t ssrc) const {
1475 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef3bc15102017-04-20 19:25:07 -07001476 webrtc::RtpParameters rtp_params;
1477 // SSRC of 0 represents the default receive stream.
1478 if (ssrc == 0) {
1479 if (!default_sink_) {
1480 LOG(LS_WARNING) << "Attempting to get RTP parameters for the default, "
1481 "unsignaled audio receive stream, but not yet "
1482 "configured to receive such a stream.";
1483 return rtp_params;
1484 }
1485 rtp_params.encodings.emplace_back();
1486 } else {
1487 auto it = recv_streams_.find(ssrc);
1488 if (it == recv_streams_.end()) {
1489 LOG(LS_WARNING) << "Attempting to get RTP receive parameters for stream "
1490 << "with ssrc " << ssrc << " which doesn't exist.";
1491 return webrtc::RtpParameters();
1492 }
1493 rtp_params.encodings.emplace_back();
1494 // TODO(deadbeef): Return stream-specific parameters.
1495 rtp_params.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001496 }
1497
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001498 for (const AudioCodec& codec : recv_codecs_) {
1499 rtp_params.codecs.push_back(codec.ToCodecParameters());
1500 }
1501 return rtp_params;
1502}
1503
1504bool WebRtcVoiceMediaChannel::SetRtpReceiveParameters(
1505 uint32_t ssrc,
1506 const webrtc::RtpParameters& parameters) {
1507 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef3bc15102017-04-20 19:25:07 -07001508 // SSRC of 0 represents the default receive stream.
1509 if (ssrc == 0) {
1510 if (!default_sink_) {
1511 LOG(LS_WARNING) << "Attempting to set RTP parameters for the default, "
1512 "unsignaled audio receive stream, but not yet "
1513 "configured to receive such a stream.";
1514 return false;
1515 }
1516 } else {
1517 auto it = recv_streams_.find(ssrc);
1518 if (it == recv_streams_.end()) {
1519 LOG(LS_WARNING) << "Attempting to set RTP receive parameters for stream "
1520 << "with ssrc " << ssrc << " which doesn't exist.";
1521 return false;
1522 }
Taylor Brandstetterdb0cd9e2016-05-16 11:40:30 -07001523 }
1524
1525 webrtc::RtpParameters current_parameters = GetRtpReceiveParameters(ssrc);
1526 if (current_parameters != parameters) {
1527 LOG(LS_ERROR) << "Changing the RTP receive parameters is currently "
1528 << "unsupported.";
1529 return false;
1530 }
1531 return true;
1532}
1533
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001534bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
solenberg566ef242015-11-06 15:34:49 -08001535 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001536 LOG(LS_INFO) << "Setting voice channel options: "
1537 << options.ToString();
1538
1539 // We retain all of the existing options, and apply the given ones
1540 // on top. This means there is no way to "clear" options such that
1541 // they go back to the engine default.
1542 options_.SetAll(options);
solenberg246b8172015-12-08 09:50:23 -08001543 if (!engine()->ApplyOptions(options_)) {
1544 LOG(LS_WARNING) <<
1545 "Failed to apply engine options during channel SetOptions.";
1546 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001547 }
minyue6b825df2016-10-31 04:08:32 -07001548
ossu20a4b3f2017-04-27 02:08:52 -07001549 rtc::Optional<std::string> audio_network_adaptor_config =
minyue6b825df2016-10-31 04:08:32 -07001550 GetAudioNetworkAdaptorConfig(options_);
1551 for (auto& it : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001552 it.second->SetAudioNetworkAdaptorConfig(audio_network_adaptor_config);
minyue6b825df2016-10-31 04:08:32 -07001553 }
1554
solenberg76377c52017-02-21 00:54:31 -08001555 LOG(LS_INFO) << "Set voice channel options. Current options: "
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001556 << options_.ToString();
1557 return true;
1558}
1559
1560bool WebRtcVoiceMediaChannel::SetRecvCodecs(
1561 const std::vector<AudioCodec>& codecs) {
solenberg566ef242015-11-06 15:34:49 -08001562 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg8fb30c32015-10-13 03:06:58 -07001563
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001564 // Set the payload types to be used for incoming media.
solenberg0b675462015-10-09 01:37:09 -07001565 LOG(LS_INFO) << "Setting receive voice codecs.";
solenberg0b675462015-10-09 01:37:09 -07001566
1567 if (!VerifyUniquePayloadTypes(codecs)) {
1568 LOG(LS_ERROR) << "Codec payload types overlap.";
1569 return false;
1570 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001571
kwibergd32bf752017-01-19 07:03:59 -08001572 // Create a payload type -> SdpAudioFormat map with all the decoders. Fail
1573 // unless the factory claims to support all decoders.
1574 std::map<int, webrtc::SdpAudioFormat> decoder_map;
1575 for (const AudioCodec& codec : codecs) {
deadbeefcb383672017-04-26 16:28:42 -07001576 // Log a warning if a codec's payload type is changing. This used to be
1577 // treated as an error. It's abnormal, but not really illegal.
1578 AudioCodec old_codec;
1579 if (FindCodec(recv_codecs_, codec, &old_codec) &&
1580 old_codec.id != codec.id) {
1581 LOG(LS_WARNING) << codec.name << " mapped to a second payload type ("
1582 << codec.id << ", was already mapped to " << old_codec.id
1583 << ")";
1584 }
kwibergd32bf752017-01-19 07:03:59 -08001585 auto format = AudioCodecToSdpAudioFormat(codec);
1586 if (!IsCodec(codec, "cn") && !IsCodec(codec, "telephone-event") &&
1587 !engine()->decoder_factory_->IsSupportedDecoder(format)) {
1588 LOG(LS_ERROR) << "Unsupported codec: " << format;
1589 return false;
1590 }
deadbeefcb383672017-04-26 16:28:42 -07001591 // We allow adding new codecs but don't allow changing the payload type of
1592 // codecs that are already configured since we might already be receiving
1593 // packets with that payload type. See RFC3264, Section 8.3.2.
1594 // TODO(deadbeef): Also need to check for clashes with previously mapped
1595 // payload types, and not just currently mapped ones. For example, this
1596 // should be illegal:
1597 // 1. {100: opus/48000/2, 101: ISAC/16000}
1598 // 2. {100: opus/48000/2}
1599 // 3. {100: opus/48000/2, 101: ISAC/32000}
1600 // Though this check really should happen at a higher level, since this
1601 // conflict could happen between audio and video codecs.
1602 auto existing = decoder_map_.find(codec.id);
1603 if (existing != decoder_map_.end() && !existing->second.Matches(format)) {
1604 LOG(LS_ERROR) << "Attempting to use payload type " << codec.id << " for "
1605 << codec.name << ", but it is already used for "
1606 << existing->second.name;
1607 return false;
1608 }
kwibergd32bf752017-01-19 07:03:59 -08001609 decoder_map.insert({codec.id, std::move(format)});
1610 }
1611
deadbeefcb383672017-04-26 16:28:42 -07001612 if (decoder_map == decoder_map_) {
1613 // There's nothing new to configure.
1614 return true;
1615 }
1616
kwiberg37b8b112016-11-03 02:46:53 -07001617 if (playout_) {
1618 // Receive codecs can not be changed while playing. So we temporarily
1619 // pause playout.
1620 ChangePlayout(false);
1621 }
1622
kwiberg1c07c702017-03-27 07:15:49 -07001623 decoder_map_ = std::move(decoder_map);
kwibergd32bf752017-01-19 07:03:59 -08001624 for (auto& kv : recv_streams_) {
kwiberg1c07c702017-03-27 07:15:49 -07001625 kv.second->RecreateAudioReceiveStream(decoder_map_);
solenberg26c8c912015-11-27 04:00:25 -08001626 }
kwibergd32bf752017-01-19 07:03:59 -08001627 recv_codecs_ = codecs;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001628
kwiberg37b8b112016-11-03 02:46:53 -07001629 if (desired_playout_ && !playout_) {
1630 ChangePlayout(desired_playout_);
1631 }
kwibergd32bf752017-01-19 07:03:59 -08001632 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001633}
1634
solenberg72e29d22016-03-08 06:35:16 -08001635// Utility function called from SetSendParameters() to extract current send
1636// codec settings from the given list of codecs (originally from SDP). Both send
1637// and receive streams may be reconfigured based on the new settings.
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001638bool WebRtcVoiceMediaChannel::SetSendCodecs(
1639 const std::vector<AudioCodec>& codecs) {
solenberg566ef242015-11-06 15:34:49 -08001640 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenbergb5727682015-12-04 15:22:19 +01001641 dtmf_payload_type_ = rtc::Optional<int>();
solenbergffbbcac2016-11-17 05:25:37 -08001642 dtmf_payload_freq_ = -1;
1643
1644 // Validate supplied codecs list.
1645 for (const AudioCodec& codec : codecs) {
1646 // TODO(solenberg): Validate more aspects of input - that payload types
1647 // don't overlap, remove redundant/unsupported codecs etc -
1648 // the same way it is done for RtpHeaderExtensions.
1649 if (codec.id < kMinPayloadType || codec.id > kMaxPayloadType) {
1650 LOG(LS_WARNING) << "Codec payload type out of range: " << ToString(codec);
1651 return false;
1652 }
1653 }
1654
1655 // Find PT of telephone-event codec with lowest clockrate, as a fallback, in
1656 // case we don't have a DTMF codec with a rate matching the send codec's, or
1657 // if this function returns early.
1658 std::vector<AudioCodec> dtmf_codecs;
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02001659 for (const AudioCodec& codec : codecs) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02001660 if (IsCodec(codec, kDtmfCodecName)) {
solenbergffbbcac2016-11-17 05:25:37 -08001661 dtmf_codecs.push_back(codec);
1662 if (!dtmf_payload_type_ || codec.clockrate < dtmf_payload_freq_) {
1663 dtmf_payload_type_ = rtc::Optional<int>(codec.id);
1664 dtmf_payload_freq_ = codec.clockrate;
solenberg31642aa2016-03-14 08:00:37 -07001665 }
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001666 }
1667 }
1668
ossu20a4b3f2017-04-27 02:08:52 -07001669 // Scan through the list to figure out the codec to use for sending.
1670 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec> send_codec_spec;
stefan1ccf73f2017-03-27 03:51:18 -07001671 webrtc::Call::Config::BitrateConfig bitrate_config;
ossu20a4b3f2017-04-27 02:08:52 -07001672 rtc::Optional<webrtc::AudioCodecInfo> voice_codec_info;
1673 for (const AudioCodec& voice_codec : codecs) {
1674 if (!(IsCodec(voice_codec, kCnCodecName) ||
1675 IsCodec(voice_codec, kDtmfCodecName) ||
1676 IsCodec(voice_codec, kRedCodecName))) {
1677 webrtc::SdpAudioFormat format(voice_codec.name, voice_codec.clockrate,
1678 voice_codec.channels, voice_codec.params);
solenberg72e29d22016-03-08 06:35:16 -08001679
ossu20a4b3f2017-04-27 02:08:52 -07001680 voice_codec_info = engine()->encoder_factory_->QueryAudioEncoder(format);
1681 if (!voice_codec_info) {
1682 LOG(LS_WARNING) << "Unknown codec " << ToString(voice_codec);
solenberg72e29d22016-03-08 06:35:16 -08001683 continue;
1684 }
1685
ossu20a4b3f2017-04-27 02:08:52 -07001686 send_codec_spec =
1687 rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>(
1688 {voice_codec.id, format});
1689 if (voice_codec.bitrate > 0) {
1690 send_codec_spec->target_bitrate_bps =
1691 rtc::Optional<int>(voice_codec.bitrate);
1692 }
1693 send_codec_spec->transport_cc_enabled = HasTransportCc(voice_codec);
1694 send_codec_spec->nack_enabled = HasNack(voice_codec);
1695 bitrate_config = GetBitrateConfigForCodec(voice_codec);
1696 break;
1697 }
1698 }
1699
1700 if (!send_codec_spec) {
1701 return false;
1702 }
1703
1704 RTC_DCHECK(voice_codec_info);
1705 if (voice_codec_info->allow_comfort_noise) {
1706 // Loop through the codecs list again to find the CN codec.
1707 // TODO(solenberg): Break out into a separate function?
1708 for (const AudioCodec& cn_codec : codecs) {
ossu0c4b8492017-03-02 11:03:25 -08001709 if (IsCodec(cn_codec, kCnCodecName) &&
ossu20a4b3f2017-04-27 02:08:52 -07001710 cn_codec.clockrate == send_codec_spec->format.clockrate_hz) {
ossu0c4b8492017-03-02 11:03:25 -08001711 switch (cn_codec.clockrate) {
solenberg72e29d22016-03-08 06:35:16 -08001712 case 8000:
1713 case 16000:
1714 case 32000:
ossu20a4b3f2017-04-27 02:08:52 -07001715 send_codec_spec->cng_payload_type = rtc::Optional<int>(cn_codec.id);
solenberg72e29d22016-03-08 06:35:16 -08001716 break;
1717 default:
ossu0c4b8492017-03-02 11:03:25 -08001718 LOG(LS_WARNING) << "CN frequency " << cn_codec.clockrate
solenberg72e29d22016-03-08 06:35:16 -08001719 << " not supported.";
ossu20a4b3f2017-04-27 02:08:52 -07001720 break;
solenberg72e29d22016-03-08 06:35:16 -08001721 }
solenberg72e29d22016-03-08 06:35:16 -08001722 break;
1723 }
1724 }
solenbergffbbcac2016-11-17 05:25:37 -08001725
1726 // Find the telephone-event PT exactly matching the preferred send codec.
1727 for (const AudioCodec& dtmf_codec : dtmf_codecs) {
ossu20a4b3f2017-04-27 02:08:52 -07001728 if (dtmf_codec.clockrate == send_codec_spec->format.clockrate_hz) {
solenbergffbbcac2016-11-17 05:25:37 -08001729 dtmf_payload_type_ = rtc::Optional<int>(dtmf_codec.id);
1730 dtmf_payload_freq_ = dtmf_codec.clockrate;
1731 break;
1732 }
1733 }
solenberg72e29d22016-03-08 06:35:16 -08001734 }
1735
solenberg971cab02016-06-14 10:02:41 -07001736 if (send_codec_spec_ != send_codec_spec) {
1737 send_codec_spec_ = std::move(send_codec_spec);
stefan13f1a0a2016-11-30 07:22:58 -08001738 // Apply new settings to all streams.
solenberg971cab02016-06-14 10:02:41 -07001739 for (const auto& kv : send_streams_) {
ossu20a4b3f2017-04-27 02:08:52 -07001740 kv.second->SetSendCodecSpec(*send_codec_spec_);
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001741 }
stefan13f1a0a2016-11-30 07:22:58 -08001742 } else {
1743 // If the codec isn't changing, set the start bitrate to -1 which means
1744 // "unchanged" so that BWE isn't affected.
stefan1ccf73f2017-03-27 03:51:18 -07001745 bitrate_config.start_bitrate_bps = -1;
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001746 }
stefan1ccf73f2017-03-27 03:51:18 -07001747 call_->SetBitrateConfig(bitrate_config);
wu@webrtc.orgcadf9042013-08-30 21:24:16 +00001748
solenberg8189b022016-06-14 12:13:00 -07001749 // Check if the transport cc feedback or NACK status has changed on the
1750 // preferred send codec, and in that case reconfigure all receive streams.
ossu20a4b3f2017-04-27 02:08:52 -07001751 if (recv_transport_cc_enabled_ != send_codec_spec_->transport_cc_enabled ||
1752 recv_nack_enabled_ != send_codec_spec_->nack_enabled) {
solenberg72e29d22016-03-08 06:35:16 -08001753 LOG(LS_INFO) << "Recreate all the receive streams because the send "
1754 "codec has changed.";
ossu20a4b3f2017-04-27 02:08:52 -07001755 recv_transport_cc_enabled_ = send_codec_spec_->transport_cc_enabled;
1756 recv_nack_enabled_ = send_codec_spec_->nack_enabled;
solenberg72e29d22016-03-08 06:35:16 -08001757 for (auto& kv : recv_streams_) {
solenberg8189b022016-06-14 12:13:00 -07001758 kv.second->RecreateAudioReceiveStream(recv_transport_cc_enabled_,
1759 recv_nack_enabled_);
solenberg72e29d22016-03-08 06:35:16 -08001760 }
1761 }
1762
Taylor Brandstetter0cd086b2016-04-20 16:23:10 -07001763 send_codecs_ = codecs;
solenberg72e29d22016-03-08 06:35:16 -08001764 return true;
1765}
1766
aleloi84ef6152016-08-04 05:28:21 -07001767void WebRtcVoiceMediaChannel::SetPlayout(bool playout) {
kwiberg37b8b112016-11-03 02:46:53 -07001768 desired_playout_ = playout;
1769 return ChangePlayout(desired_playout_);
1770}
1771
1772void WebRtcVoiceMediaChannel::ChangePlayout(bool playout) {
1773 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::ChangePlayout");
solenberg566ef242015-11-06 15:34:49 -08001774 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001775 if (playout_ == playout) {
aleloi84ef6152016-08-04 05:28:21 -07001776 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001777 }
1778
aleloi84ef6152016-08-04 05:28:21 -07001779 for (const auto& kv : recv_streams_) {
1780 kv.second->SetPlayout(playout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001781 }
solenberg1ac56142015-10-13 03:58:19 -07001782 playout_ = playout;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001783}
1784
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001785void WebRtcVoiceMediaChannel::SetSend(bool send) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001786 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetSend");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001787 if (send_ == send) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001788 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001789 }
1790
solenbergd53a3f92016-04-14 13:56:37 -07001791 // Apply channel specific options, and initialize the ADM for recording (this
1792 // may take time on some platforms, e.g. Android).
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001793 if (send) {
solenberg63b34542015-09-29 06:06:31 -07001794 engine()->ApplyOptions(options_);
solenbergd53a3f92016-04-14 13:56:37 -07001795
1796 // InitRecording() may return an error if the ADM is already recording.
1797 if (!engine()->adm()->RecordingIsInitialized() &&
1798 !engine()->adm()->Recording()) {
1799 if (engine()->adm()->InitRecording() != 0) {
1800 LOG(LS_WARNING) << "Failed to initialize recording";
1801 }
1802 }
solenberg63b34542015-09-29 06:06:31 -07001803 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001804
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001805 // Change the settings on each send channel.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001806 for (auto& kv : send_streams_) {
1807 kv.second->SetSend(send);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001808 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001809
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001810 send_ = send;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001811}
1812
Peter Boström0c4e06b2015-10-07 12:23:21 +02001813bool WebRtcVoiceMediaChannel::SetAudioSend(uint32_t ssrc,
1814 bool enable,
solenberg1dd98f32015-09-10 01:57:14 -07001815 const AudioOptions* options,
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001816 AudioSource* source) {
solenberg566ef242015-11-06 15:34:49 -08001817 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg1dd98f32015-09-10 01:57:14 -07001818 // TODO(solenberg): The state change should be fully rolled back if any one of
1819 // these calls fail.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001820 if (!SetLocalSource(ssrc, source)) {
solenberg1dd98f32015-09-10 01:57:14 -07001821 return false;
1822 }
solenbergdfc8f4f2015-10-01 02:31:10 -07001823 if (!MuteStream(ssrc, !enable)) {
solenberg1dd98f32015-09-10 01:57:14 -07001824 return false;
1825 }
solenbergdfc8f4f2015-10-01 02:31:10 -07001826 if (enable && options) {
solenberg1dd98f32015-09-10 01:57:14 -07001827 return SetOptions(*options);
1828 }
1829 return true;
1830}
1831
solenberg0a617e22015-10-20 15:49:38 -07001832int WebRtcVoiceMediaChannel::CreateVoEChannel() {
1833 int id = engine()->CreateVoEChannel();
1834 if (id == -1) {
1835 LOG_RTCERR0(CreateVoEChannel);
1836 return -1;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001837 }
mflodman3d7db262016-04-29 00:57:13 -07001838
solenberg0a617e22015-10-20 15:49:38 -07001839 return id;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001840}
1841
solenberg7add0582015-11-20 09:59:34 -08001842bool WebRtcVoiceMediaChannel::DeleteVoEChannel(int channel) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001843 if (engine()->voe()->base()->DeleteChannel(channel) == -1) {
1844 LOG_RTCERR1(DeleteChannel, channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001845 return false;
1846 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001847 return true;
1848}
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001849
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001850bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001851 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::AddSendStream");
solenberg566ef242015-11-06 15:34:49 -08001852 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg0a617e22015-10-20 15:49:38 -07001853 LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
1854
1855 uint32_t ssrc = sp.first_ssrc();
1856 RTC_DCHECK(0 != ssrc);
1857
1858 if (GetSendChannelId(ssrc) != -1) {
1859 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001860 return false;
1861 }
1862
solenberg0a617e22015-10-20 15:49:38 -07001863 // Create a new channel for sending audio data.
1864 int channel = CreateVoEChannel();
1865 if (channel == -1) {
1866 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001867 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001868
solenbergc96df772015-10-21 13:01:53 -07001869 // Save the channel to send_streams_, so that RemoveSendStream() can still
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001870 // delete the channel in case failure happens below.
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001871 webrtc::AudioTransport* audio_transport =
1872 engine()->voe()->base()->audio_transport();
mflodman3d7db262016-04-29 00:57:13 -07001873
minyue6b825df2016-10-31 04:08:32 -07001874 rtc::Optional<std::string> audio_network_adaptor_config =
1875 GetAudioNetworkAdaptorConfig(options_);
skvlade0d46372016-04-07 22:59:22 -07001876 WebRtcAudioSendStream* stream = new WebRtcAudioSendStream(
solenberg971cab02016-06-14 10:02:41 -07001877 channel, audio_transport, ssrc, sp.cname, send_codec_spec_,
minyue6b825df2016-10-31 04:08:32 -07001878 send_rtp_extensions_, max_send_bitrate_bps_, audio_network_adaptor_config,
ossu20a4b3f2017-04-27 02:08:52 -07001879 call_, this, engine()->encoder_factory_);
skvlade0d46372016-04-07 22:59:22 -07001880 send_streams_.insert(std::make_pair(ssrc, stream));
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001881
solenberg4a0f7b52016-06-16 13:07:33 -07001882 // At this point the stream's local SSRC has been updated. If it is the first
1883 // send stream, make sure that all the receive streams are updated with the
1884 // same SSRC in order to send receiver reports.
solenbergc96df772015-10-21 13:01:53 -07001885 if (send_streams_.size() == 1) {
solenberg0a617e22015-10-20 15:49:38 -07001886 receiver_reports_ssrc_ = ssrc;
solenberg4a0f7b52016-06-16 13:07:33 -07001887 for (const auto& kv : recv_streams_) {
1888 // TODO(solenberg): Allow applications to set the RTCP SSRC of receive
1889 // streams instead, so we can avoid recreating the streams here.
1890 kv.second->RecreateAudioReceiveStream(ssrc);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001891 }
1892 }
1893
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001894 send_streams_[ssrc]->SetSend(send_);
1895 return true;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001896}
1897
Peter Boström0c4e06b2015-10-07 12:23:21 +02001898bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32_t ssrc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001899 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::RemoveSendStream");
solenberg566ef242015-11-06 15:34:49 -08001900 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg3a941542015-11-16 07:34:50 -08001901 LOG(LS_INFO) << "RemoveSendStream: " << ssrc;
1902
solenbergc96df772015-10-21 13:01:53 -07001903 auto it = send_streams_.find(ssrc);
1904 if (it == send_streams_.end()) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001905 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
1906 << " which doesn't exist.";
1907 return false;
1908 }
1909
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001910 it->second->SetSend(false);
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001911
solenberg7602aab2016-11-14 11:30:07 -08001912 // TODO(solenberg): If we're removing the receiver_reports_ssrc_ stream, find
1913 // the first active send stream and use that instead, reassociating receive
1914 // streams.
1915
solenberg7add0582015-11-20 09:59:34 -08001916 // Clean up and delete the send stream+channel.
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001917 int channel = it->second->channel();
solenberg0a617e22015-10-20 15:49:38 -07001918 LOG(LS_INFO) << "Removing audio send stream " << ssrc
1919 << " with VoiceEngine channel #" << channel << ".";
solenberg7add0582015-11-20 09:59:34 -08001920 delete it->second;
1921 send_streams_.erase(it);
1922 if (!DeleteVoEChannel(channel)) {
solenberg0a617e22015-10-20 15:49:38 -07001923 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001924 }
solenbergc96df772015-10-21 13:01:53 -07001925 if (send_streams_.empty()) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08001926 SetSend(false);
solenberg0a617e22015-10-20 15:49:38 -07001927 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001928 return true;
1929}
1930
1931bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001932 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::AddRecvStream");
solenberg566ef242015-11-06 15:34:49 -08001933 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergd97ec302015-10-07 01:40:33 -07001934 LOG(LS_INFO) << "AddRecvStream: " << sp.ToString();
1935
solenberg0b675462015-10-09 01:37:09 -07001936 if (!ValidateStreamParams(sp)) {
wu@webrtc.org78187522013-10-07 23:32:02 +00001937 return false;
1938 }
1939
solenberg7add0582015-11-20 09:59:34 -08001940 const uint32_t ssrc = sp.first_ssrc();
solenberg0b675462015-10-09 01:37:09 -07001941 if (ssrc == 0) {
1942 LOG(LS_WARNING) << "AddRecvStream with ssrc==0 is not supported.";
1943 return false;
1944 }
1945
solenberg2100c0b2017-03-01 11:29:29 -08001946 // If this stream was previously received unsignaled, we promote it, possibly
1947 // recreating the AudioReceiveStream, if sync_label has changed.
1948 if (MaybeDeregisterUnsignaledRecvStream(ssrc)) {
solenberg4904fb62017-02-17 12:01:14 -08001949 recv_streams_[ssrc]->MaybeRecreateAudioReceiveStream(sp.sync_label);
solenberg4904fb62017-02-17 12:01:14 -08001950 return true;
solenberg1ac56142015-10-13 03:58:19 -07001951 }
solenberg0b675462015-10-09 01:37:09 -07001952
solenberg7add0582015-11-20 09:59:34 -08001953 if (GetReceiveChannelId(ssrc) != -1) {
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001954 LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001955 return false;
1956 }
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02001957
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001958 // Create a new channel for receiving audio data.
solenberg7add0582015-11-20 09:59:34 -08001959 const int channel = CreateVoEChannel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001960 if (channel == -1) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001961 return false;
1962 }
Minyue2013aec2015-05-13 14:14:42 +02001963
stefanba4c0e42016-02-04 04:12:24 -08001964 recv_streams_.insert(std::make_pair(
kwiberg1c07c702017-03-27 07:15:49 -07001965 ssrc,
1966 new WebRtcAudioReceiveStream(
1967 channel, ssrc, receiver_reports_ssrc_, recv_transport_cc_enabled_,
1968 recv_nack_enabled_, sp.sync_label, recv_rtp_extensions_, call_, this,
1969 engine()->decoder_factory_, decoder_map_)));
aleloi84ef6152016-08-04 05:28:21 -07001970 recv_streams_[ssrc]->SetPlayout(playout_);
solenberg7add0582015-11-20 09:59:34 -08001971
solenberg1ac56142015-10-13 03:58:19 -07001972 return true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001973}
1974
Peter Boström0c4e06b2015-10-07 12:23:21 +02001975bool WebRtcVoiceMediaChannel::RemoveRecvStream(uint32_t ssrc) {
Peter Boströmca8b4042016-03-08 14:24:13 -08001976 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::RemoveRecvStream");
solenberg566ef242015-11-06 15:34:49 -08001977 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergd97ec302015-10-07 01:40:33 -07001978 LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
1979
solenberg7add0582015-11-20 09:59:34 -08001980 const auto it = recv_streams_.find(ssrc);
1981 if (it == recv_streams_.end()) {
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001982 LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc
1983 << " which doesn't exist.";
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001984 return false;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00001985 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001986
solenberg2100c0b2017-03-01 11:29:29 -08001987 MaybeDeregisterUnsignaledRecvStream(ssrc);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001988
solenberg7add0582015-11-20 09:59:34 -08001989 const int channel = it->second->channel();
1990
1991 // Clean up and delete the receive stream+channel.
1992 LOG(LS_INFO) << "Removing audio receive stream " << ssrc
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001993 << " with VoiceEngine channel #" << channel << ".";
Tommif888bb52015-12-12 01:37:01 +01001994 it->second->SetRawAudioSink(nullptr);
solenberg7add0582015-11-20 09:59:34 -08001995 delete it->second;
1996 recv_streams_.erase(it);
1997 return DeleteVoEChannel(channel);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001998}
1999
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002000bool WebRtcVoiceMediaChannel::SetLocalSource(uint32_t ssrc,
2001 AudioSource* source) {
solenbergc96df772015-10-21 13:01:53 -07002002 auto it = send_streams_.find(ssrc);
2003 if (it == send_streams_.end()) {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002004 if (source) {
2005 // Return an error if trying to set a valid source with an invalid ssrc.
2006 LOG(LS_ERROR) << "SetLocalSource failed with ssrc " << ssrc;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002007 return false;
2008 }
2009
2010 // The channel likely has gone away, do nothing.
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002011 return true;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002012 }
2013
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002014 if (source) {
2015 it->second->SetSource(source);
solenberg1ac56142015-10-13 03:58:19 -07002016 } else {
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002017 it->second->ClearSource();
solenberg1ac56142015-10-13 03:58:19 -07002018 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002019
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002020 return true;
2021}
2022
solenberg796b8f92017-03-01 17:02:23 -08002023// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002024bool WebRtcVoiceMediaChannel::GetActiveStreams(
2025 AudioInfo::StreamList* actives) {
solenberg566ef242015-11-06 15:34:49 -08002026 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002027 actives->clear();
solenberg7add0582015-11-20 09:59:34 -08002028 for (const auto& ch : recv_streams_) {
solenberg796b8f92017-03-01 17:02:23 -08002029 int level = ch.second->GetOutputLevel();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002030 if (level > 0) {
Fredrik Solenbergaf9fb212015-08-26 10:45:53 +02002031 actives->push_back(std::make_pair(ch.first, level));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002032 }
2033 }
2034 return true;
2035}
2036
solenberg796b8f92017-03-01 17:02:23 -08002037// TODO(solenberg): Remove, once AudioMonitor is gone.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002038int WebRtcVoiceMediaChannel::GetOutputLevel() {
solenberg566ef242015-11-06 15:34:49 -08002039 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg1ac56142015-10-13 03:58:19 -07002040 int highest = 0;
solenberg7add0582015-11-20 09:59:34 -08002041 for (const auto& ch : recv_streams_) {
solenberg796b8f92017-03-01 17:02:23 -08002042 highest = std::max(ch.second->GetOutputLevel(), highest);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002043 }
2044 return highest;
2045}
2046
solenberg4bac9c52015-10-09 02:32:53 -07002047bool WebRtcVoiceMediaChannel::SetOutputVolume(uint32_t ssrc, double volume) {
solenberg566ef242015-11-06 15:34:49 -08002048 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg2100c0b2017-03-01 11:29:29 -08002049 std::vector<uint32_t> ssrcs(1, ssrc);
deadbeef3bc15102017-04-20 19:25:07 -07002050 // SSRC of 0 represents the default receive stream.
solenberg1ac56142015-10-13 03:58:19 -07002051 if (ssrc == 0) {
2052 default_recv_volume_ = volume;
solenberg2100c0b2017-03-01 11:29:29 -08002053 ssrcs = unsignaled_recv_ssrcs_;
2054 }
2055 for (uint32_t ssrc : ssrcs) {
2056 const auto it = recv_streams_.find(ssrc);
2057 if (it == recv_streams_.end()) {
2058 LOG(LS_WARNING) << "SetOutputVolume: no recv stream " << ssrc;
2059 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002060 }
solenberg2100c0b2017-03-01 11:29:29 -08002061 it->second->SetOutputVolume(volume);
2062 LOG(LS_INFO) << "SetOutputVolume() to " << volume
2063 << " for recv stream with ssrc " << ssrc;
solenberg1ac56142015-10-13 03:58:19 -07002064 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002065 return true;
2066}
2067
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002068bool WebRtcVoiceMediaChannel::CanInsertDtmf() {
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002069 return dtmf_payload_type_ ? true : false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002070}
2071
solenberg1d63dd02015-12-02 12:35:09 -08002072bool WebRtcVoiceMediaChannel::InsertDtmf(uint32_t ssrc, int event,
2073 int duration) {
solenberg566ef242015-11-06 15:34:49 -08002074 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002075 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::InsertDtmf";
2076 if (!dtmf_payload_type_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002077 return false;
2078 }
2079
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002080 // Figure out which WebRtcAudioSendStream to send the event on.
2081 auto it = ssrc != 0 ? send_streams_.find(ssrc) : send_streams_.begin();
2082 if (it == send_streams_.end()) {
2083 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
solenberg1d63dd02015-12-02 12:35:09 -08002084 return false;
2085 }
Fredrik Solenbergb5727682015-12-04 15:22:19 +01002086 if (event < kMinTelephoneEventCode ||
2087 event > kMaxTelephoneEventCode) {
2088 LOG(LS_WARNING) << "DTMF event code " << event << " out of range.";
solenberg1d63dd02015-12-02 12:35:09 -08002089 return false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002090 }
solenbergffbbcac2016-11-17 05:25:37 -08002091 RTC_DCHECK_NE(-1, dtmf_payload_freq_);
2092 return it->second->SendTelephoneEvent(*dtmf_payload_type_, dtmf_payload_freq_,
2093 event, duration);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002094}
2095
wu@webrtc.orga9890802013-12-13 00:21:03 +00002096void WebRtcVoiceMediaChannel::OnPacketReceived(
jbaucheec21bd2016-03-20 06:15:43 -07002097 rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
solenberg566ef242015-11-06 15:34:49 -08002098 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02002099
mflodman3d7db262016-04-29 00:57:13 -07002100 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
2101 packet_time.not_before);
2102 webrtc::PacketReceiver::DeliveryStatus delivery_result =
2103 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
2104 packet->cdata(), packet->size(),
2105 webrtc_packet_time);
mflodman3d7db262016-04-29 00:57:13 -07002106 if (delivery_result != webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC) {
2107 return;
2108 }
2109
solenberg2100c0b2017-03-01 11:29:29 -08002110 // Create an unsignaled receive stream for this previously not received ssrc.
2111 // If there already is N unsignaled receive streams, delete the oldest.
mflodman3d7db262016-04-29 00:57:13 -07002112 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5208
solenberg1ac56142015-10-13 03:58:19 -07002113 uint32_t ssrc = 0;
jbaucheec21bd2016-03-20 06:15:43 -07002114 if (!GetRtpSsrc(packet->cdata(), packet->size(), &ssrc)) {
solenberg1ac56142015-10-13 03:58:19 -07002115 return;
2116 }
solenberg2100c0b2017-03-01 11:29:29 -08002117 RTC_DCHECK(std::find(unsignaled_recv_ssrcs_.begin(),
2118 unsignaled_recv_ssrcs_.end(), ssrc) == unsignaled_recv_ssrcs_.end());
solenberg1ac56142015-10-13 03:58:19 -07002119
solenberg2100c0b2017-03-01 11:29:29 -08002120 // Add new stream.
mflodman3d7db262016-04-29 00:57:13 -07002121 StreamParams sp;
2122 sp.ssrcs.push_back(ssrc);
solenberg2100c0b2017-03-01 11:29:29 -08002123 LOG(LS_INFO) << "Creating unsignaled receive stream for SSRC=" << ssrc;
mflodman3d7db262016-04-29 00:57:13 -07002124 if (!AddRecvStream(sp)) {
solenberg2100c0b2017-03-01 11:29:29 -08002125 LOG(LS_WARNING) << "Could not create unsignaled receive stream.";
mflodman3d7db262016-04-29 00:57:13 -07002126 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002127 }
solenberg2100c0b2017-03-01 11:29:29 -08002128 unsignaled_recv_ssrcs_.push_back(ssrc);
2129 RTC_HISTOGRAM_COUNTS_LINEAR(
2130 "WebRTC.Audio.NumOfUnsignaledStreams", unsignaled_recv_ssrcs_.size(), 1,
2131 100, 101);
solenbergf748ca42017-02-06 13:03:19 -08002132
solenberg2100c0b2017-03-01 11:29:29 -08002133 // Remove oldest unsignaled stream, if we have too many.
2134 if (unsignaled_recv_ssrcs_.size() > kMaxUnsignaledRecvStreams) {
2135 uint32_t remove_ssrc = unsignaled_recv_ssrcs_.front();
2136 LOG(LS_INFO) << "Removing unsignaled receive stream with SSRC="
2137 << remove_ssrc;
2138 RemoveRecvStream(remove_ssrc);
2139 }
2140 RTC_DCHECK_GE(kMaxUnsignaledRecvStreams, unsignaled_recv_ssrcs_.size());
2141
2142 SetOutputVolume(ssrc, default_recv_volume_);
2143
2144 // The default sink can only be attached to one stream at a time, so we hook
2145 // it up to the *latest* unsignaled stream we've seen, in order to support the
2146 // case where the SSRC of one unsignaled stream changes.
mflodman3d7db262016-04-29 00:57:13 -07002147 if (default_sink_) {
solenberg2100c0b2017-03-01 11:29:29 -08002148 for (uint32_t drop_ssrc : unsignaled_recv_ssrcs_) {
2149 auto it = recv_streams_.find(drop_ssrc);
2150 it->second->SetRawAudioSink(nullptr);
2151 }
mflodman3d7db262016-04-29 00:57:13 -07002152 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
2153 new ProxySink(default_sink_.get()));
solenberg2100c0b2017-03-01 11:29:29 -08002154 SetRawAudioSink(ssrc, std::move(proxy_sink));
mflodman3d7db262016-04-29 00:57:13 -07002155 }
solenberg2100c0b2017-03-01 11:29:29 -08002156
mflodman3d7db262016-04-29 00:57:13 -07002157 delivery_result = call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
2158 packet->cdata(),
2159 packet->size(),
2160 webrtc_packet_time);
2161 RTC_DCHECK_NE(webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC, delivery_result);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002162}
2163
wu@webrtc.orga9890802013-12-13 00:21:03 +00002164void WebRtcVoiceMediaChannel::OnRtcpReceived(
jbaucheec21bd2016-03-20 06:15:43 -07002165 rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
solenberg566ef242015-11-06 15:34:49 -08002166 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Fredrik Solenberg4b60c732015-05-07 14:07:48 +02002167
Fredrik Solenberg709ed672015-09-15 12:26:33 +02002168 // Forward packet to Call as well.
2169 const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
2170 packet_time.not_before);
2171 call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
jbaucheec21bd2016-03-20 06:15:43 -07002172 packet->cdata(), packet->size(), webrtc_packet_time);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002173}
2174
Honghai Zhangcc411c02016-03-29 17:27:21 -07002175void WebRtcVoiceMediaChannel::OnNetworkRouteChanged(
2176 const std::string& transport_name,
Honghai Zhang0e533ef2016-04-19 15:41:36 -07002177 const rtc::NetworkRoute& network_route) {
2178 call_->OnNetworkRouteChanged(transport_name, network_route);
Honghai Zhangcc411c02016-03-29 17:27:21 -07002179}
2180
Peter Boström0c4e06b2015-10-07 12:23:21 +02002181bool WebRtcVoiceMediaChannel::MuteStream(uint32_t ssrc, bool muted) {
solenberg566ef242015-11-06 15:34:49 -08002182 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg94218532016-06-16 10:53:22 -07002183 const auto it = send_streams_.find(ssrc);
2184 if (it == send_streams_.end()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002185 LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use.";
2186 return false;
2187 }
solenberg94218532016-06-16 10:53:22 -07002188 it->second->SetMuted(muted);
2189
2190 // TODO(solenberg):
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002191 // We set the AGC to mute state only when all the channels are muted.
2192 // This implementation is not ideal, instead we should signal the AGC when
2193 // the mic channel is muted/unmuted. We can't do it today because there
2194 // is no good way to know which stream is mapping to the mic channel.
2195 bool all_muted = muted;
solenberg94218532016-06-16 10:53:22 -07002196 for (const auto& kv : send_streams_) {
2197 all_muted = all_muted && kv.second->muted();
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002198 }
solenberg059fb442016-10-26 05:12:24 -07002199 engine()->apm()->set_output_will_be_muted(all_muted);
buildbot@webrtc.org6b21b712014-07-31 15:08:53 +00002200
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002201 return true;
2202}
2203
deadbeef80346142016-04-27 14:17:10 -07002204bool WebRtcVoiceMediaChannel::SetMaxSendBitrate(int bps) {
2205 LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetMaxSendBitrate.";
2206 max_send_bitrate_bps_ = bps;
minyue7a973442016-10-20 03:27:12 -07002207 bool success = true;
skvlade0d46372016-04-07 22:59:22 -07002208 for (const auto& kv : send_streams_) {
minyue7a973442016-10-20 03:27:12 -07002209 if (!kv.second->SetMaxSendBitrate(max_send_bitrate_bps_)) {
2210 success = false;
skvlade0d46372016-04-07 22:59:22 -07002211 }
2212 }
minyue7a973442016-10-20 03:27:12 -07002213 return success;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002214}
2215
skvlad7a43d252016-03-22 15:32:27 -07002216void WebRtcVoiceMediaChannel::OnReadyToSend(bool ready) {
2217 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2218 LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
2219 call_->SignalChannelNetworkState(
2220 webrtc::MediaType::AUDIO,
2221 ready ? webrtc::kNetworkUp : webrtc::kNetworkDown);
2222}
2223
michaelt79e05882016-11-08 02:50:09 -08002224void WebRtcVoiceMediaChannel::OnTransportOverheadChanged(
2225 int transport_overhead_per_packet) {
2226 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2227 call_->OnTransportOverheadChanged(webrtc::MediaType::AUDIO,
2228 transport_overhead_per_packet);
2229}
2230
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002231bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
Peter Boströmca8b4042016-03-08 14:24:13 -08002232 TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::GetStats");
solenberg566ef242015-11-06 15:34:49 -08002233 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg85a04962015-10-27 03:35:21 -07002234 RTC_DCHECK(info);
solenbergd97ec302015-10-07 01:40:33 -07002235
solenberg85a04962015-10-27 03:35:21 -07002236 // Get SSRC and stats for each sender.
hbos1acfbd22016-11-17 23:43:29 -08002237 RTC_DCHECK_EQ(info->senders.size(), 0U);
solenberg85a04962015-10-27 03:35:21 -07002238 for (const auto& stream : send_streams_) {
2239 webrtc::AudioSendStream::Stats stats = stream.second->GetStats();
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002240 VoiceSenderInfo sinfo;
solenberg85a04962015-10-27 03:35:21 -07002241 sinfo.add_ssrc(stats.local_ssrc);
2242 sinfo.bytes_sent = stats.bytes_sent;
2243 sinfo.packets_sent = stats.packets_sent;
2244 sinfo.packets_lost = stats.packets_lost;
2245 sinfo.fraction_lost = stats.fraction_lost;
2246 sinfo.codec_name = stats.codec_name;
hbos1acfbd22016-11-17 23:43:29 -08002247 sinfo.codec_payload_type = stats.codec_payload_type;
solenberg85a04962015-10-27 03:35:21 -07002248 sinfo.ext_seqnum = stats.ext_seqnum;
2249 sinfo.jitter_ms = stats.jitter_ms;
2250 sinfo.rtt_ms = stats.rtt_ms;
2251 sinfo.audio_level = stats.audio_level;
zsteine76bd3a2017-07-14 12:17:49 -07002252 sinfo.total_input_energy = stats.total_input_energy;
2253 sinfo.total_input_duration = stats.total_input_duration;
solenberg85a04962015-10-27 03:35:21 -07002254 sinfo.aec_quality_min = stats.aec_quality_min;
2255 sinfo.echo_delay_median_ms = stats.echo_delay_median_ms;
2256 sinfo.echo_delay_std_ms = stats.echo_delay_std_ms;
2257 sinfo.echo_return_loss = stats.echo_return_loss;
2258 sinfo.echo_return_loss_enhancement = stats.echo_return_loss_enhancement;
ivoc8c63a822016-10-21 04:10:03 -07002259 sinfo.residual_echo_likelihood = stats.residual_echo_likelihood;
ivoc4e477a12017-01-15 08:29:46 -08002260 sinfo.residual_echo_likelihood_recent_max =
2261 stats.residual_echo_likelihood_recent_max;
Taylor Brandstetter1a018dc2016-03-08 12:37:39 -08002262 sinfo.typing_noise_detected = (send_ ? stats.typing_noise_detected : false);
ivoce1198e02017-09-08 08:13:19 -07002263 sinfo.ana_statistics = stats.ana_statistics;
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002264 info->senders.push_back(sinfo);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002265 }
2266
solenberg85a04962015-10-27 03:35:21 -07002267 // Get SSRC and stats for each receiver.
hbos1acfbd22016-11-17 23:43:29 -08002268 RTC_DCHECK_EQ(info->receivers.size(), 0U);
solenberg7add0582015-11-20 09:59:34 -08002269 for (const auto& stream : recv_streams_) {
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002270 webrtc::AudioReceiveStream::Stats stats = stream.second->GetStats();
2271 VoiceReceiverInfo rinfo;
2272 rinfo.add_ssrc(stats.remote_ssrc);
2273 rinfo.bytes_rcvd = stats.bytes_rcvd;
2274 rinfo.packets_rcvd = stats.packets_rcvd;
2275 rinfo.packets_lost = stats.packets_lost;
2276 rinfo.fraction_lost = stats.fraction_lost;
2277 rinfo.codec_name = stats.codec_name;
hbos1acfbd22016-11-17 23:43:29 -08002278 rinfo.codec_payload_type = stats.codec_payload_type;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002279 rinfo.ext_seqnum = stats.ext_seqnum;
2280 rinfo.jitter_ms = stats.jitter_ms;
2281 rinfo.jitter_buffer_ms = stats.jitter_buffer_ms;
2282 rinfo.jitter_buffer_preferred_ms = stats.jitter_buffer_preferred_ms;
2283 rinfo.delay_estimate_ms = stats.delay_estimate_ms;
2284 rinfo.audio_level = stats.audio_level;
zsteine76bd3a2017-07-14 12:17:49 -07002285 rinfo.total_output_energy = stats.total_output_energy;
Steve Anton2dbc69f2017-08-24 17:15:13 -07002286 rinfo.total_samples_received = stats.total_samples_received;
zsteine76bd3a2017-07-14 12:17:49 -07002287 rinfo.total_output_duration = stats.total_output_duration;
Steve Anton2dbc69f2017-08-24 17:15:13 -07002288 rinfo.concealed_samples = stats.concealed_samples;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002289 rinfo.expand_rate = stats.expand_rate;
2290 rinfo.speech_expand_rate = stats.speech_expand_rate;
2291 rinfo.secondary_decoded_rate = stats.secondary_decoded_rate;
minyue-webrtc0e320ec2017-08-28 13:51:27 +02002292 rinfo.secondary_discarded_rate = stats.secondary_discarded_rate;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002293 rinfo.accelerate_rate = stats.accelerate_rate;
2294 rinfo.preemptive_expand_rate = stats.preemptive_expand_rate;
2295 rinfo.decoding_calls_to_silence_generator =
2296 stats.decoding_calls_to_silence_generator;
2297 rinfo.decoding_calls_to_neteq = stats.decoding_calls_to_neteq;
2298 rinfo.decoding_normal = stats.decoding_normal;
2299 rinfo.decoding_plc = stats.decoding_plc;
2300 rinfo.decoding_cng = stats.decoding_cng;
2301 rinfo.decoding_plc_cng = stats.decoding_plc_cng;
henrik.lundin63489782016-09-20 01:47:12 -07002302 rinfo.decoding_muted_output = stats.decoding_muted_output;
Fredrik Solenberg4f4ec0a2015-10-22 10:49:27 +02002303 rinfo.capture_start_ntp_time_ms = stats.capture_start_ntp_time_ms;
2304 info->receivers.push_back(rinfo);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002305 }
2306
hbos1acfbd22016-11-17 23:43:29 -08002307 // Get codec info
2308 for (const AudioCodec& codec : send_codecs_) {
2309 webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
2310 info->send_codecs.insert(
2311 std::make_pair(codec_params.payload_type, std::move(codec_params)));
2312 }
2313 for (const AudioCodec& codec : recv_codecs_) {
2314 webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
2315 info->receive_codecs.insert(
2316 std::make_pair(codec_params.payload_type, std::move(codec_params)));
2317 }
2318
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002319 return true;
2320}
2321
Tommif888bb52015-12-12 01:37:01 +01002322void WebRtcVoiceMediaChannel::SetRawAudioSink(
2323 uint32_t ssrc,
kwiberg686a8ef2016-02-26 03:00:35 -08002324 std::unique_ptr<webrtc::AudioSinkInterface> sink) {
Tommif888bb52015-12-12 01:37:01 +01002325 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
deadbeef884f5852016-01-15 09:20:04 -08002326 LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::SetRawAudioSink: ssrc:" << ssrc
2327 << " " << (sink ? "(ptr)" : "NULL");
2328 if (ssrc == 0) {
solenberg2100c0b2017-03-01 11:29:29 -08002329 if (!unsignaled_recv_ssrcs_.empty()) {
kwiberg686a8ef2016-02-26 03:00:35 -08002330 std::unique_ptr<webrtc::AudioSinkInterface> proxy_sink(
deadbeef884f5852016-01-15 09:20:04 -08002331 sink ? new ProxySink(sink.get()) : nullptr);
solenberg2100c0b2017-03-01 11:29:29 -08002332 SetRawAudioSink(unsignaled_recv_ssrcs_.back(), std::move(proxy_sink));
deadbeef884f5852016-01-15 09:20:04 -08002333 }
2334 default_sink_ = std::move(sink);
2335 return;
2336 }
Tommif888bb52015-12-12 01:37:01 +01002337 const auto it = recv_streams_.find(ssrc);
2338 if (it == recv_streams_.end()) {
solenberg2100c0b2017-03-01 11:29:29 -08002339 LOG(LS_WARNING) << "SetRawAudioSink: no recv stream " << ssrc;
Tommif888bb52015-12-12 01:37:01 +01002340 return;
2341 }
deadbeef2d110be2016-01-13 12:00:26 -08002342 it->second->SetRawAudioSink(std::move(sink));
Tommif888bb52015-12-12 01:37:01 +01002343}
2344
hbos8d609f62017-04-10 07:39:05 -07002345std::vector<webrtc::RtpSource> WebRtcVoiceMediaChannel::GetSources(
2346 uint32_t ssrc) const {
2347 auto it = recv_streams_.find(ssrc);
2348 RTC_DCHECK(it != recv_streams_.end())
2349 << "Attempting to get contributing sources for SSRC:" << ssrc
2350 << " which doesn't exist.";
2351 return it->second->GetSources();
2352}
2353
Peter Boström0c4e06b2015-10-07 12:23:21 +02002354int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
solenberg566ef242015-11-06 15:34:49 -08002355 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenberg7add0582015-11-20 09:59:34 -08002356 const auto it = recv_streams_.find(ssrc);
2357 if (it != recv_streams_.end()) {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002358 return it->second->channel();
solenberg8fb30c32015-10-13 03:06:58 -07002359 }
solenberg1ac56142015-10-13 03:58:19 -07002360 return -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002361}
2362
Peter Boström0c4e06b2015-10-07 12:23:21 +02002363int WebRtcVoiceMediaChannel::GetSendChannelId(uint32_t ssrc) const {
solenberg566ef242015-11-06 15:34:49 -08002364 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
solenbergc96df772015-10-21 13:01:53 -07002365 const auto it = send_streams_.find(ssrc);
2366 if (it != send_streams_.end()) {
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002367 return it->second->channel();
solenberg8fb30c32015-10-13 03:06:58 -07002368 }
wu@webrtc.org9dba5252013-08-05 20:36:57 +00002369 return -1;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002370}
solenberg2100c0b2017-03-01 11:29:29 -08002371
2372bool WebRtcVoiceMediaChannel::
2373 MaybeDeregisterUnsignaledRecvStream(uint32_t ssrc) {
2374 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
2375 auto it = std::find(unsignaled_recv_ssrcs_.begin(),
2376 unsignaled_recv_ssrcs_.end(),
2377 ssrc);
2378 if (it != unsignaled_recv_ssrcs_.end()) {
2379 unsignaled_recv_ssrcs_.erase(it);
2380 return true;
2381 }
2382 return false;
2383}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002384} // namespace cricket
2385
2386#endif // HAVE_WEBRTC_VOICE